웹개발 수업/Server

[Day +78 / Server]웹사이트(공지사항)

Chole Woo 2021. 10. 14. 20:12
211014 목

 

1. lib(라이브러리)에 jstl-1.2.jar 파일 넣어주기

why? jstl을 이 프로젝트에서도 쓰고 싶어서

 

2. menubar.jsp : 카테고리의 공지사항 클릭시 출력 용도

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="member.model.vo.Member"%>
    
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
<%
	// session 객체에 담긴 loginUser 정보를 변수에 담아두기
	Member loginUser = (Member)session.getAttribute("loginUser");
	// *임포트 처리해줘야 위의 빨간줄 사라짐
%>
    
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>menubar</title>
<!-- 구글 웹폰트 -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@700&display=swap" rel="stylesheet">
<!-- 외부 스타일 시트 -->
<link href="<%= request.getContextPath() %>/resources/css/menubar-style.css" rel="stylesheet">

<%-- session에 담긴 message 있을 경우 alert하는 script --%>
<% if(session.getAttribute("message") != null) {%>
<script>
	alert(' <%= session.getAttribute("message") %>');
</script>
<%
	session.removeAttribute("message");
} %>



</head>
<body>
<!-- page의 application의 contextPath -->
<c:set var="contextPath" value="${ pageContext.servletContext.contextPath }"
scope="application"/>
<!-- pageContext라고하는 내장객체로 부터.. contextPath값 요청 = getContextPath와 같음 
application : 어느 페이지에서든 쓸 수 있음-->

<div class="wrapper">
   <header id="header">
      <!-- 로고 이미지를 클릭하면 첫 화면으로 -->
      <a href="<%= request.getContextPath() %>">
      <%-- request.getContextPath() => jsp --%>
         <img class="logo" src="<%= request.getContextPath() %>/resources/images/logo.jpg">
      </a>
      <div class="btnArea">
      
      <!-- 로긴 했을 떄와 안했을때의 차이를 두기 위한 조건식 세우기 -->
      	<% if(loginUser == null) { %>
         <a href="<%= request.getContextPath() %>/memberJoin">회원가입</a>|
         <a href="<%= request.getContextPath() %>/login">로그인</a>
         
         <% } else { %>
         <a href ="<%= request.getContextPath()%>/memberModify">정보수정</a>
         <a href ="<%= request.getContextPath()%>/logout">로그아웃</a>
         <!-- href방식은 무조건 get방식 -->
         <% } %>
      </div>
   </header>
   <nav id="nav">
      <ul>
         <li><a href="<%= request.getContextPath() %>">HOME</a></li>
         <li><a href="${ contextPath }/notice/list">공지사항</a></li>

         <li><a href="#">게시판</a></li>
         <li><a href="#">사진게시판</a></li>
      </ul>
   </nav>
</div>
</body>
</html>

 <ul>
         <li><a href="<%= request.getContextPath() %>">HOME</a></li>
         <li><a href="${ contextPath }/notice/list">공지사항</a></li>

         <li><a href="#">게시판</a></li>
         <li><a href="#">사진게시판</a></li>
</ul>
1) 경로 작성 방법 변경됨
jstl 사용 전에는 <%= request.getContextPath() %>">HOME 이런 식으로 경로를 써줬으나,

jstl 사용 후에는 "${ contextPath }/notice/list"만 써줘도 됨
2) /notice/list로 NoticeServlet.java와 매핑
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
=> 상단에 어떤 접두사를 쓸건지와 그 접두사에 맞는 uri를 넣어줘야 실행됨

 

3. loginCheckFilter.java

package filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

import member.model.vo.Member;

/**
 * Servlet Filter implementation class LoginCheckFilter
 */
@WebFilter("/*")
public class LoginCheckFilter implements Filter {
	
	private List<String> permitList;
	// 로그인이 안되어 있어도 볼 수 있는 리스트
	private List<String> resourceList;
	// css 하위..
	// => init 메소드 안에 저 값들 초기화 하기
	
	
    /**
     * Default constructor. 
     */
    public LoginCheckFilter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest)request;
		String uri = req.getRequestURI();
		// 요청한 주소가 뭔지
		// System.out.println(uri);
		
		/* 로그인 없이 요청이 허가된 요청 값 리스트에 현재 요청이 포함되지 않았을 때 */
		   if(!permitList.contains(uri)) {
		         boolean isResourceFile = false;
		         /* 요청 안에 "/resources/" 라는 문자열을 포함하고 있는지 확인 */
		         for(String str : resourceList) {
		            if(uri.contains(str)) {
		               isResourceFile = true;
		               break;
		            }
		         }

			/* 허가 리스트에도 없는 요청이면서 리소스 파일도 아닌 경우 ex) /jsp/memberModify*/
			if(!isResourceFile) {
				/*로그인 상태 확인*/
				Member loginUser = (Member)req.getSession().getAttribute("loginUser");
				if(loginUser == null) {
					req.setAttribute("message", "올바르지 않은 요청입니다.");
					req.getRequestDispatcher("/WEB-INF/views/common/errorpage.jsp").forward(request, response);
					return;
				}
			}
		}
		
		// pass the request along the filter chain
		chain.doFilter(request, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		permitList = new ArrayList<String>();
		permitList.add("/jsp/");
		permitList.add("/jsp/login");
		permitList.add("/jsp/memberJoin");
		permitList.add("/jsp/notice/list");
		
		
		resourceList = new ArrayList<String>();
		resourceList.add("/resources/");
	}

}
public void init(FilterConfig fConfig) throws ServletException {
permitList = new ArrayList<String>();
permitList.add("/jsp/");
permitList.add("/jsp/login");
permitList.add("/jsp/memberJoin");
permitList.add("/jsp/notice/list");

resourceList = new ArrayList<String>();
resourceList.add("/resources/");
}
-비회원 상태에서도 접근가능한 사이트 목록에 notice/list 추가해주기

 

4. NoticeListServlet.java

package notice.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import notice.model.vo.Notice;
import notice.model.service.NoticeService;

/**
 * Servlet implementation class NoticeListServlet
 */
@WebServlet("/notice/list")
public class NoticeListServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NoticeListServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 공지사항 목록 조회 요청(넘어온 데이터 없으므로 추출할 값 없는 상태)
		
		List<Notice> noticeList = new NoticeService().selectList();
		System.out.println(noticeList);
		
		request.setAttribute("noticeList", noticeList);
		request.getRequestDispatcher("/WEB-INF/views/notice/noticeListView.jsp").forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	}

}
@WebServlet("/notice/list")
-menubar.jsp와 연결
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 공지사항 목록 조회 요청(넘어온 데이터 없으므로 추출할 값 없는 상태)

List<Notice> noticeList = new NoticeService().selectList();
System.out.println(noticeList);

request.setAttribute("noticeList", noticeList);
request.getRequestDispatcher("/WEB-INF/views/notice/noticeListView.jsp").forward(request, response);
}
1) href로 연결하면 보통 바로 doGet과 연결됨
2) List<Notice> noticeList = new NoticeService().selectList(); 만들어서 NoticeService와 연결

 

5. NoticeService.java

package notice.model.service;

import java.sql.Connection;
import java.util.List;
import static common.JDBCTemplate.*;

import notice.model.dao.NoticeDao;
import notice.model.vo.Notice;

public class NoticeService {
   
   private NoticeDao noticeDao = new NoticeDao();

   public List<Notice> selectList() {
      Connection conn = getConnection();
      
      List<Notice> noticeList = noticeDao.selectList(conn);
      
      close(conn);
      
      return noticeList;
   }

}
 public List<Notice> selectList() {
      Connection conn = getConnection();
      
      List<Notice> noticeList = noticeDao.selectList(conn);
      
      close(conn);
      
      return noticeList;
   }
-Servlet과 연결되는 List selectList()만들기
Connection conn = getConnection();

-이미 JDBCTemplate에 만들어 놓은 Conn객체 불러오기




*Connection의 역할 : DB와의 연결
private NoticeDao noticeDao = new NoticeDao();
-NoticeDao와 연결
 List<Notice> noticeList = noticeDao.selectList(conn);
-noticeList를 Dao와 연결해서 쿼리 정보 불러오기 

 

6. NoticeDao.java

package notice.model.dao;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.InvalidPropertiesFormatException;
import java.util.List;
import java.util.Properties;
import static common.JDBCTemplate.close;

import notice.model.vo.Notice;

public class NoticeDao {

	private Properties noticeQuery = new Properties();
	// Properties : 맵 타입의 일종, 키와 밸류가 하나의 엔트리가 되..
	// 키와 밸류가 모두 String 타입이다.
	
	public NoticeDao() {
		String fileName = NoticeDao.class.getResource("/sql/notice/notice-query.xml").getPath();
		
		
			try {
				noticeQuery.loadFromXML(new FileInputStream(fileName));
			} catch (IOException e) {
				e.printStackTrace();
			}
			// IO는 항상 exception이 발생할 위험이 있으므로 try/catch로 감싸준다
		
	}
	
	
	public List<Notice> selectList(Connection conn) {
		
		
		
		PreparedStatement pstmt=null;
		ResultSet rset = null;
		List<Notice> noticeList = new ArrayList<>();
		
		String sql= noticeQuery.getProperty("selectList");
		
		try {
			pstmt = conn.prepareStatement(sql);
			
			rset = pstmt.executeQuery();
			// return 값은 resultset..
			
			while(rset.next()) {
				noticeList.add(new Notice(rset.getInt("nno")
										, rset.getString("ntitle")
										, rset.getString("ncontent")
										, rset.getString("nwriter")
										, rset.getInt("ncount")
										, rset.getDate("ndate")
										, rset.getString("status")));
			} 
			
			
		} catch (SQLException e) {
			e.printStackTrace();
		}	finally{
			close(rset);
			close(pstmt);
		} // 임포트로 close 오류 없애기
		
		
		
		
		return noticeList;
		
	}

}
String fileName = NoticeDao.class.getResource("/sql/notice/notice-query.xml").getPath();
-notice.query.xml에서 경로 얻어오기

 

7. notice-query.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM
"http://java.sun.com/dtd/properties.dtd">
<properties>
 
 	<entry key="selectList">
 		SELECT
 			  NNO
 			, NTITLE
 			, NCONTENT
 			, NWRITER
 			, NCOUNT
 			, NDATE
 			, STATUS
 		FROM NOTICE
 	  WHERE STATUS = 'Y'
 	  ORDER BY NNO DESC
 	</entry>
 	
   
</properties>
  WHERE STATUS = 'Y'
    ORDER BY NNO DESC
1) STATUS = 'Y' : 로그인이 되어있을 경우라는 의미
2) NNO DESC : NO를 내림차순으로 불러오겠다는 의미

 

8. NoticeDao.java

public List<Notice> selectList(Connection conn) {



PreparedStatement pstmt=null;
ResultSet rset = null;
List<Notice> noticeList = new ArrayList<>();

String sql= noticeQuery.getProperty("selectList");

try {
pstmt = conn.prepareStatement(sql);

rset = pstmt.executeQuery();
// return 값은 resultset..

while(rset.next()) {
noticeList.add(new Notice(rset.getInt("nno")
, rset.getString("ntitle")
, rset.getString("ncontent")
, rset.getString("nwriter")
, rset.getInt("ncount")
, rset.getDate("ndate")
, rset.getString("status")));



} catch (SQLException e) {
e.printStackTrace();
} finally{
close(rset);
close(pstmt);
} // 임포트로 close 오류 없애기




return noticeList;

}
-이 부분 잘 모르겠음
-결국 noticeList를 NoticeService로 반환

 

9. NoticeService.java

 List<Notice> noticeList = noticeDao.selectList(conn);
      
      close(conn);
      
      return noticeList;
-쓴 conn객체 닫아주기
-Dao에서 반환받은 noticeService를 NoticeListServlet으로 돌려줌

 

10. NoticeListServlet.java

System.out.println(noticeList);
-돌려받은 noticeList값 출력해보기
[Notice [nno=1, ntitle=첫번째 공지사항입니다., ncontent=환영합니다., nwriter=admin, ncount=0, ndate=2021-10-06, status=Y]]
request.setAttribute("noticeList", noticeList);
request.getRequestDispatcher("/WEB-INF/views/notice/noticeListView.jsp").forward(request, response);
-noticeList 위임해서 noticeListView에 보여주기

 

11. NoticeListView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>	
	
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공지사항</title>
<style>
.outer {
	width: 800px;
	margin: auto;
}

.wrap {
	width: 780px;
	margin: 100px auto;
}

ul, li {
	margin: 0;
	padding: 0;
}

.notice_title {
	border-bottom: 1px solid #282A35;
}

.notice_list {
	margin: 20px 30px;
	min-height: 540px;
}

.notice_list>ul {
	border-bottom: 1px solid #f3f5f7;
	height: 50px;
	line-height: 50px;
	display: flex;
	justify-content: space-around;
	list-style: none;
}

.notice_list>ul.last {
	border: 0;
}

.notice_list>ul>li {
	text-align: center;
}

.notice_list .no {
	width: 100px;
}

.notice_list .title {
	width: 520px;
	text-align: left;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.notice_list .date {
	width: 100px;
}

.onmouseover {
	background: #f3f5f7;
	cursor: pointer;
}

.search_area {
	text-align: center;
	padding: 30px;
}

.search_area select {
	width: 150px;
	height: 30px;
	border: 0px;
}

.input_area {
	border: solid 1px #dadada;
	padding: 10px 10px 14px 10px;
	margin-right: 20px;
	background: white;
}

.input_area input {
	width: 250px;
	height: 30px;
	border: 0px;
}

.input_area input:focus, .search_area select:focus {
	outline: none;
}

.search_area button {
	width: 100px;
	height: 35px;
	border: 0px;
	color: white;
	background: #282A35;
	margin: 5px;
	cursor : pointer;
}
</style>
</head>
<body>
	<jsp:include page="/WEB-INF/views/common/menubar.jsp" />
	<div class="outer">
		<div class="wrap">
			<div class="notice_area">
				<div class="notice_title">
					<h1>공지사항</h1>
				</div>
				
				<!-- 출력 영역 -->
				<div class="notice_list">
				<c:forEach var="notice" items="${ noticeList }">
					<ul class="notice_ul">
						<li class="no">${ notice.nno }</li>
						<li class="title">${ notice.ntitle }</li>
						<li class="date">${ notice.ndate }</li>
					</ul>
				</c:forEach>
				
				
				
				
				
				
				</div>
			</div>
			<div class="search_area">
				<form method="get">
					<select id="searchCondition" name="searchCondition">
						<option value="title">제목</option>
						<option value="content">내용</option>
					</select> <span class="input_area"> <input type="search"
						name="searchValue">
					</span>
					<button type="submit">검색하기</button>
				</form>
			</div>
		</div>
	</div>
</body>
</html>
<div class="notice_list">
<c:forEach var="notice" items="${ noticeList }">
<ul class="notice_ul">
<li class="no">${ notice.nno }</li>
<li class="title">${ notice.ntitle }</li>
<li class="date">${ notice.ndate }</li>
</ul>
</c:forEach>
-noticeList로 받아온 정보값 출력하기

댓글수0