이전 게시글은 여기 >>
Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(9) - Lucy 라이브러리를 이용한 XSS(크로스사이트 스크립팅) 방어하기
블로그의 글을 잘 생각해보자.
글 제목과 글쓴이, 글 내용, 그리고 수정, 삭제, 뒤로가기 버튼 등이 있다.
먼저 글 제목과 글 내용을 가져와보자.
그러기 위해서 우리가 model을 만들어놨지 않은가..!
model에 값을 넣어서 게시글에 뿌리면 된다. 또 그러려면 먼저 액션과 repository를 통해 데이터를 가져와야한다. 상세보기를 누를 때 액션을 발생시키자.
- BoardControll.java 의 router 클래스
public Action router(String cmd) {
if(cmd.equals("home")) {
// 회원가입 페이지로 이동
return new BoardHomeAction(); //Board의 목록
}else if(cmd.equals("write")) {
// 글쓰기 페이지로 이동
return new BoardWriteAction();
}else if(cmd.equals("writeProc")) {
// 글쓰기 정보 넘기기
return new BoardWriteProcAction();
}else if(cmd.equals("detail")) {
//상세보기
return new BoardDetailAction();
액션을 통해 수행할 클래스는 다음과 같다
- BoardDetailAction.java
package com.cos.blog.action.board;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.cos.blog.action.Action;
import com.cos.blog.dto.DetailResponseDto;
import com.cos.blog.model.Board;
import com.cos.blog.repository.BoardRepository;
import com.cos.blog.util.Script;
import com.cos.blog.util.YoutubeParser;
public class BoardDetailAction implements Action{
private String result=null;
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie viewCookie=null;
Cookie[] cookies=request.getCookies();
System.out.println("cookie : "+cookies);
//0. 유효성 검사
if(
request.getParameter("id")==null||
request.getParameter("id").equals("")
) {
Script.back("잘못된 접근입니다.", response);
return;
}
//1. 페이지에서 게시판의 id 값을 가지고 옴
int id=Integer.parseInt(request.getParameter("id"));
BoardRepository boardRepository=BoardRepository.getInstance();
//2. id값을 이용해 DB에서 게시판 글을 가져옴
DetailResponseDto dto = boardRepository.findById(id);
//3. RequestDispatch를 이용해 받아온 데이터를 세션에 담아 페이지로 이동
if(dto!=null) {
request.setAttribute("dto", dto);
//request를 유지하기 때문에 데이터를 담고 이동할때 사용
RequestDispatcher dis=request.getRequestDispatcher("board/detail.jsp");
dis.forward(request, response);
}else {
Script.back("잘못된 접근입니다.", response);
}
}
}
데이터를 DB에서 가져와서 게시글의 값을 가져올 것이다.
그런데 여기서 문제가 하나 생긴다. 유저의 이름을 함께 띄우려고 할 때, board 테이블에서 유저의 이름이 없다는 것이다. 이 때, 두 테이블을 조인하는 것 까진 괜찮다. 그러나 이것을 채워줄 모델링이 없다는 것이 문제다.
이를 합쳐주는 것이 DTO (data transfer object)이다.
이를 제네릭으로 만들어주자.
- DetailResponseDto.java
package com.cos.blog.dto;
import com.cos.blog.model.Board;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DetailResponseDto {
private Board board;
private String username;
}
이 제네릭에 값을 넣어줄 것이다.
이제 쿼리문을 작성해보자.
- BoardReposity.java 중 아이디를 이용해 상세문을 찾는 메서드
public DetailResponseDto findById(int id) {
StringBuilder sb=new StringBuilder();
sb.append("select b.id,b.userid,b.title,b.content,b.readCount,b.createdate,u.username ");
sb.append("from board b inner join users u ");
sb.append("on b.userid=u.id ");
sb.append("where b.id=?");
final String SQL=sb.toString();
DetailResponseDto dto=null;
try {
conn=DBConn.getConnection();
pstmt = conn.prepareStatement(SQL);
//물음표 완성하기
pstmt.setInt(1, id);
rs=pstmt.executeQuery();
//if -> rs
if(rs.next()) {
dto=new DetailResponseDto();
Board board=Board.builder()
.id(rs.getInt(1))
.userId(rs.getInt(2))
.title(rs.getString(3))
.content(rs.getString(4))
.readCount(rs.getInt(5))
.createDate(rs.getTimestamp(6))
.build();
dto.setBoard(board);
dto.setUsername(rs.getString(7));
}
return dto;
} catch (Exception e) {
e.printStackTrace();
System.out.println(TAG+"findById : "+e.getMessage());
}finally {
DBConn.close(conn, pstmt);
}
return null;
}
여기서 도출되는 값을 가지고 getRequestDispatchet으로 값을 유지하면서 이동한다.
이 이동한 값을 화면에 출력해보자.
- detail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="../include/nav.jsp"%>
<div class="container">
<!-- <button class="btn btn-secondary" href="javascript:history.back();">뒤로가기</button> -->
<button class="btn btn-primary" onclick="history.back()">뒤로가기</button>
<a href="/blog/board?cmd=update&id=${dto.board.id }" class="btn btn-primary">수정</a>
<button class="btn btn-danger">삭제</button>
<br/><br/>
<h6>작성자 : <i>${dto.username }</i></h6>
<br/>
<h3><b>${dto.board.title }</b></h3>
<div class="form-group">
<div class="container p-3 my-3 border">${dto.board.content }</div>
</div>
</div>
<%@ include file="../include/footer.jsp"%>
값은 제네릭을 담아올때 지정했던 이름 dto. 내부의 board 객체 속 제목과 내용을 el문으로 가져온다.
${dto. borad. content} , ${dto. borad. title}
작성자는 딱히 board 내부의 객체가 아니므로,
${dto. username}
현지 완성된 정도는 다음과 같다.