1. board에서 쓴 글 확인하는 조회
* boardController
else if( command.equals("/board/board_list.board")) { //목록화면
//조회 메서드 - list를 화면으로 가지고 나가야 합니다.
ArrayList<BoardVO> list= service.getList(request, request);
request.setAttribute("list", list);
request.getRequestDispatcher("board_list.jsp").forward(request, response);
* boardservice
ArrayList<BoardVO> getList(HttpServletRequest request, HttpServletResponse response); //조회
* boardServiceImpl
@Override
public ArrayList<BoardVO> getList(HttpServletRequest request, HttpServletResponse response) {
//DAO 생성
BoardDAO dao = BoardDAO.getInstance();
//getlist를 arraylist의 list로 반환
ArrayList<BoardVO> list = dao.getList();
return list;
}
* boardDAO
//조회 메서드
public ArrayList<BoardVO> getList() {
ArrayList<BoardVO> list = new ArrayList<>();
//번호 기준으로 거꾸로 뒤집어야 최신글이 제일 위로 올라옴
String sql = "select * from board order by bno desc";
try {
conn = DriverManager.getConnection(URL, UID, UPW);
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
//rs결과를 list에 담는다.
while(rs.next()) {
BoardVO vo = new BoardVO();
vo.setBno( rs.getInt("bno"));
vo.setTitle( rs.getString("title") );
vo.setWriter( rs.getString("writer") );
vo.setContent( rs.getString("content") );
vo.setContent( rs.getString("regdate") );
vo.setHit( rs.getInt("hit")) ;
//list에 한줄씩 담아줌
list.add(vo);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(conn, pstmt, rs);
}
return list;
}
* board_list.jsp
- 저 list가 DAO에 있는 list
<thead>
<tr>
<th>순서</th>
<th>글 번호</th>
<th>작성자</th>
<th>제목</th>
<th>날짜</th>
<th>조회수</th>
</tr>
</thead>
<tbody>
<c:forEach var = "vo" items = "${list }" varStatus = "num">
<tr>
<td>${num.count }</td>
<td>${vo.bno }</td>
<td>${vo.writer }</td>
<td>${vo.title }</td>
<td>${vo.regdate }</td>
<td>${vo.hit }</td>
</tr>
</c:forEach>
</tbody>
* 날짜(board_list.jsp)
- UI를 생각 했을 때 이렇게 나오면 안됨
- 지금 데이터 타입은 date, formatdate로 바꿔줄 것
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
- 위에 이거 추가해주고 밑에 이렇게 추가해줄 것
<td><fmt:formatDate value="${vo.regdate }" pattern = "yyyy-MM-dd HH시mm분ss초"/></td>
2. 제목을 누르면 상세보기로 넘어감
board_list.jsp
<a>태그로 감싸면 눌렀을 때 넘어갈 수 있음. 그리고 뒤에 .board니까 컨트롤러로 태움
<td><a href = "board_content.board">${vo.title }</a></td>
get 방식은 반드시 폼태그가 필요한 것은 아니며,
주소를 통해서 강제로 파라미터 값을 전달할 수 있습니다.
?변수명=값
여러 값이라면 &조건으로 연결
ex. <a href="req_get04.jsp?name=홍길동&age=20">get 방식 queryString 이용하기</a>
<a href="board_content.board?bno=${vo.bno }">${vo.title }</a>
* boardService
//반환이 BoardVO=1행에 대한 데이터니까
BoardVO getContent(HttpServletRequest request, HttpServletResponse response);
* boardDAO
public BoardVO getContent(String bno) {
BoardVO vo = null;
String sql = "select * from board where bno = ?";
try {
conn = DriverManager.getConnection(URL, UID, UPW);
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, bno);
//select니까 query
rs = pstmt.executeQuery();
if(rs.next()) {
vo = new BoardVO();
vo.setBno( rs.getInt("bno"));
vo.setTitle( rs.getString("title") );
vo.setWriter( rs.getString("writer") );
vo.setContent( rs.getString("content") );
vo.setRegdate( rs.getTimestamp("regdate") );
vo.setHit( rs.getInt("hit")) ;
}
} catch (Exception e) {
e.printStackTrace();
}
return vo;
}
* boardServiceImpl
@Override
public BoardVO getContent(HttpServletRequest request, HttpServletResponse response) {
//a태그로 넘어오는 parameter
String bno = request.getParameter("bno");
BoardDAO dao = BoardDAO.getInstance();
BoardVO vo = dao.getContent(bno);
return vo;
}
* boardController
else if( command.equals("/board/board_content.board")) { //상세 내용 화면
//content 화면에서는 조회한 글에 대한 정보를 조회해야 합니다. 5번 글 눌렀으면 5번 글 나와야함
//반환값이 있으니까 vo에 받아줌
//조회한 글에 대한 정보 조회
BoardVO vo= service.getContent(request, response);
request.setAttribute("vo", vo);
request.getRequestDispatcher("board_content.jsp").forward(request, response);
* board_content.jsp
<tr>
<td width="20%">글번호</td>
<td width="30%">${vo.bno }</td>
<td width="20%">조회수</td>
<td width="30%">${vo.hit }</td>
</tr>
<tr>
<td>작성자</td>
<td>${vo.writer }</td>
<td>작성일</td>
<td >${vo.regdate }</td>
</tr>
<tr>
<td width="20%">글제목</td>
<td colspan="3">${vo.title }</td>
</tr>
<tr>
<td width="20%">글내용</td>
<td colspan="3" height="120px">${vo.content }</td>
</tr>
3.
목록, 수정, 삭제 기능 넣기
* board_content.jsp
- 목록은 list로 가게끔 href에 'board_list.board'로 보냄
- 수정 기능
<tr>
<td colspan="4" align="center">
<input type="button" value="목록" onclick = "location.href='board_list.board' ">
<input type="button" value="수정" onclick = "location.href='board_modify.board?bno=${vo.bno}' ">
<input type="button" value="삭제" onclick = "location.href='???' ">
</td>
</tr>
* boardcontroller
else if( command.equals("/board/board_modify.board")) { //수정 화면
//조회한 글에 대한 정보 조회 재활용
BoardVO vo= service.getContent(request, response);
request.setAttribute("vo", vo);
request.getRequestDispatcher("board_modify.jsp").forward(request, response);
* board_modify.jsp
<%--
화면에 보일 필요는 없는데, 데이터를 보내야 하는 경우 hidden 태그를 사용합니다.
--%>
<tr>
<td>글 번호</td>
<td>${vo.bno }
<input type = "hidden" name = "bno" value = "${vo.bno }">
</td>
</tr>
<tr>
<td>작성자</td>
<td><input type="text" name="writer" value="${vo.writer }" readonly></td>
</tr>
<tr>
<td>글 제목</td>
<td>
<input type="text" name="title" value="${vo.title }">
</td>
</tr>
<tr>
<td>글 내용</td>
<td>
<textarea rows="10" style="width: 95%;" name="content">
${vo.content }
</textarea>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="수정 하기" onclick="">
<input type="button" value="목록" onclick = "location.href='board_list.board'">
</td>
</tr>
* boardservice
void update(HttpServletRequest request, HttpServletResponse response); //정보수정
* boardserviceImpl
@Override
public void update(HttpServletRequest request, HttpServletResponse response) {
//화면에서 넘어오는 값
String bno = request.getParameter("bno");
String writer = request.getParameter("writer");
String title = request.getParameter("title");
String content = request.getParameter("content");
}
* boardDAO
public void update(String bno, String title, String content) {
String str = "update board set title = ?, content = ? where bno = ? ";
try {
conn = DriverManager.getConnection(URL, UID, UPW);
pstmt = conn.prepareStatement(str);
pstmt.setString(1, title);
pstmt.setString(2, content);
pstmt.setString(3, bno);
pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(conn, pstmt, rs);
}
}
* boardserviceImpl에서 DAO 추가
@Override
public void update(HttpServletRequest request, HttpServletResponse response) {
//화면에서 넘어오는 값
String bno = request.getParameter("bno");
//String writer = request.getParameter("writer");
String title = request.getParameter("title");
String content = request.getParameter("content");
//DAO
BoardDAO dao = BoardDAO.getInstance();
dao.update(bno, title, content);
}
* boardcontroller
else if ( command.equals("/board/updateForm.board")) {
//service와 연결
service.update(request, response);
//업데이트가 된 이후에 목록화면으로 보냄
//이미 만들어져있는 list 화면으로 나가기 때문에 redirect 이용해야 함
//1st.
//response.sendRedirect("board_list.board");
//2nd
//화면에서 넘어오는 키값을 getParameter로 bno값 받아야 함
response.sendRedirect("board_content.board?bno=" + request.getParameter("bno"));
}
- 삭제
- 삭제는 원래 get방식으로 만들면 안됨.
* boardcontent
<tr>
<td colspan="4" align="center">
<input type="button" value="목록" onclick = "location.href='board_list.board' ">
<input type="button" value="수정" onclick = "location.href='board_modify.board?bno=${vo.bno}' ">
<input type="button" value="삭제" onclick = "location.href='board_delete.board?bno=${vo.bno}' ">
</td>
</tr>
* boardcontroller
else if ( command.equals("/board/board_delete.board")) {
}
* boardservice
int delete(HttpServletRequest request, HttpServletResponse response); //글 삭제
* boardserviceImpl에서 오버라이드
@Override
public int delete(HttpServletRequest request, HttpServletResponse response) {
String bno = request.getParameter("bno");
return 0;
}
* boardcontroller
else if ( command.equals("/board/board_delete.board")) {
service.delete(request, response);
}
* boardDAO
public int delete(String bno) {
int result = 0;
String sql = "delete from board where bno = ?";
try {
conn = DriverManager.getConnection(URL, UID, UPW);
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, bno);
result = pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(conn, pstmt, rs);
}
return result;
}
* boardserviceImpl
@Override
public int delete(HttpServletRequest request, HttpServletResponse response) {
String bno = request.getParameter("bno");
//DAO
BoardDAO dao = BoardDAO.getInstance();
int result = dao.delete(bno);
return result;
}
* boardcontroller
else if ( command.equals("/board/board_delete.board")) {
int result = service.delete(request, response);
String msg = "";
if(result == 1) { //삭제 성공
msg = "삭제 성공";
} else { //삭제 실패
msg = "삭제 실패";
}
response.setContentType("text/html; charset = utf-8");
PrintWriter out = response.getWriter();
out.println("<script>");
out.println("alert('"+ msg+"');");
out.println("location.href='board_list.board'; ");
out.println("</script>");
}
4. 조회수 기능(중복 방지를 위해 쿠키를 써야함)
- update board set hit = hit + 1 where bno = 3;
5. filter
* boardController
- 세션의 인증 방법을 사용해서 로그인을 해야 글을 쓸 수 있도록 해줌
- 세션이 필요한 곳과 필요 없는 곳을 나누어 생각할 것(등록, 수정..)
- 밑에 방법처럼 세션을 사용하면 하나씩 다 해줘야하기 때문에 복잡함
- 이걸 편하게 하기 위해서 filter 사용함
//세션
HttpSession session = request.getSession();
if( command.equals("/board/board_write.board")) { //등록 화면
if(session.getAttribute("user_id") == null) {
response.sendRedirect("../user/user_login.user");
return;
}
- 필터란? FrontController(서블릿) 으로 들어가기전 요청을 가로채 검사하는 역할
필터의 생성방법
1) 필터 클래스는 일반 자바 파일로 생성합니다.
2) Filter 인터페이스를 상속 받습니다
3) 일반적으로 doFilter메서드를 오버라이딩 합니다
4) 사용 후 doFilter(request, response); 메서드를 반드시 사용한다
- 방법 2개 중 하나를 선택함
* 어노테이션 방법
- 따라서 webfilter에는 검사할 경로만 넣어줄 것
(중괄호 하면 배열처럼 여러개를 넣을 수 있음)
package com.example.util.filter;
import java.io.IOException;
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.HttpFilter;
//필터를 실행할 요청 경로
@WebFilter({"/board/board_write.board",
"/board/board_modify.board",
"/board/registForm.board",
"/board/updateForm.board",
"/board/board_delete.board"
})
public class AuthFilter implements Filter {
//실제 필터가 해야할 일(오버라이딩 되어있음)
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("필터 실행됨");
//필터가 여러개라면 다음 필터로 연결함(꼭 써줘야함), 필터가 없으면 원래 요청이 들어오는 컨트롤러로 붙여줌
chain.doFilter(request, response);
}
}
* xml 방법
<!-- 필터 등록하는 방법과 필터체이닝 -->
<filter>
<filter-name>A</filter-name>
<filter-class>com.example.util.filter.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>A</filter-name>
<url-pattern>/board/board_write.board</url-pattern>
</filter-mapping>
</web-app>
- filter2 만들기
package com.example.util.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class AuthFilter2 implements Filter{
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("필터 2 실행됨");
chain.doFilter(request, response);
}
}
<filter>
<filter-name>A</filter-name>
<filter-class>com.example.util.filter.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>A</filter-name>
<url-pattern>/board/board_write.board</url-pattern>
</filter-mapping>
<filter>
<filter-name>B</filter-name>
<filter-class>com.example.util.filter.AuthFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>B</filter-name>
<url-pattern>/board/board_write.board</url-pattern>
</filter-mapping>
* authfilter
package com.example.util.filter;
import java.io.IOException;
import java.io.PrintWriter;
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.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
//필터를 실행할 요청 경로
@WebFilter({"/board/board_write.board",
"/board/board_modify.board",
"/board/registForm.board",
"/board/updateForm.board",
"/board/board_delete.board"
})
public class AuthFilter implements Filter {
//실제 필터가 해야할 일(오버라이딩 되어있음)
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//권한검사
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
//req에서 세션을 얻는다.
HttpSession session = req.getSession();
String user_id = (String)session.getAttribute("user_id");
//user_id == null이라면 권한이 없다는 의미
if(user_id == null) {
String path = req.getContextPath(); //컨택스트 패스
res.setContentType("text/html; charset = utf-8");
PrintWriter out = res.getWriter();
out.println("<script>");
out.println("alert('권한이 필요한 기능입니다.');");
//절대 경로 넣어줄 것(절대 경로여야지 안전함)
out.println("location.href=' "+ path + "/user/user_login.user" + "';");
out.println("</script>");
return; //함수를 종료하면 컨트롤러로 연결 되지 않음
}
System.out.println("필터 실행됨");
//필터가 여러개라면 다음 필터로 연결함(꼭 써줘야함), 필터가 없으면 원래 요청이 들어오는 컨트롤러로 붙여줌
chain.doFilter(request, response);
}
}
6. 작성자 id 고정
* board_wirte.jsp 수정
<tr>
<td>작성자</td>
<td>
<input type="text" name="writer" value="${sessionScope.user_id }" size="10" readonly required>
</td>
</tr>
7. 로그인 된 사람만 글의 수정과 삭제 버튼을 볼 수 있도록 만들어줌
* board_content(c:if로 감싸줌)
<td colspan="4" align="center">
<input type="button" value="목록" onclick = "location.href='board_list.board' ">
<c:if test = "${sessionScope.user_id != null }">
<input type="button" value="수정" onclick = "location.href='board_modify.board?bno=${vo.bno}' ">
<input type="button" value="삭제" onclick = "location.href='board_delete.board?bno=${vo.bno}' ">
</c:if>
</td>
8. 작성자가 다르면 수정, 삭제가 안되는 기능 추가
* AuthFilter2
package com.example.util.filter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
//수정, 업데이트, 삭제(경로)
@WebFilter({"/board/board_modify.board",
"/board/updateForm.board",
"/board/board_delete.board"
}) //경로
public class AuthFilter2 implements Filter{
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
/*
* 세션의 user_id와 request로 넘어오는 작성자가 다르면 수정이 불가함.
*
* 1. 각 요청 경로에서 writer가 파라미터로 반드시 전달되도록 처리.
*
*
*/
request.setCharacterEncoding("utf-8");
//권한검사
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
//각 요청에 넘어오는 writer 파라미터
String writer = request.getParameter("writer");
//세션에 저장된 user_id
HttpSession session = req.getSession();
String user_id = (String)session.getAttribute("user_id");
// System.out.println("작성자" + writer);
// System.out.println("세션ID" + user_id);
//null이거나 다른 경우(내가 쓴 글이 아닐 때)에도 실패
//세션이 없거나 or 작성자와 세션이 다른 경우
if(user_id == null || !writer.equals(user_id) ) {
String path = req.getContextPath(); //컨택스트 패스
res.setContentType("text/html; charset = utf-8");
PrintWriter out = res.getWriter();
out.println("<script>");
out.println("alert('권한이 필요한 기능입니다');");
out.println("location.href='" + path + "/board/board_list.board" + "';");
out.println("</script>");
return;
}
chain.doFilter(request, response);
}
}
* boardContent
<tr>
<td colspan="4" align="center">
<input type="button" value="목록" onclick = "location.href='board_list.board' ">
<c:if test = "${sessionScope.user_id != null }">
<input type="button" value="수정" onclick = "location.href='board_modify.board?bno=${vo.bno}&writer=${vo.writer }' ">
<input type="button" value="삭제" onclick = "location.href='board_delete.board?bno=${vo.bno}&writer=${vo.wirter }' ">
</c:if>
</td>
</tr>