본문 바로가기
JSP

Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(10) - DTO(Data Transfer Object)를 이용한 블로그 상세보기 만들기

by 김마리님 2020. 6. 10.

이전 게시글은 여기 >>

Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(9) - Lucy 라이브러리를 이용한 XSS(크로스사이트 스크립팅) 방어하기

 

Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(9) - Lucy 라이브러리를 이용한 XSS(크로스사이트 �

이전 게시글은 여기 << Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(8) - 부트스트랩과 섬머노트를 이용한 글쓰기 페이지 만들기 Servlet 과 JSP를 이용한(모델2 형식) 블로그 만들기(8) - 부트스��

itstudy-mary.tistory.com

 

 

블로그의 글을 잘 생각해보자.

글 제목과 글쓴이, 글 내용, 그리고 수정, 삭제, 뒤로가기 버튼 등이 있다.

먼저 글 제목과 글 내용을 가져와보자.

그러기 위해서 우리가 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}

 

 

현지 완성된 정도는 다음과 같다.

 

 

 

반응형