본문 바로가기
JSP

[게시판 Ver.2] 내가 쓴 글 목록 보기

by amoomar 2022. 3. 16.
반응형

 

해당 포스팅 역시 이전 포스팅의 내용에 살을 붙이는 방식으로 진행되었기에 함께 확인해야 할 필요가 있다. 목차는 다음과 같다.

1. Model
   1) SQL문의 추가
   2) 비즈니스 메서드의 수정

2. View

3. Controller
   1) LoginAction
   2) dispatcher

4. 총정리

로직을 추가하여 로그인 후 본인의 이름을 클릭했을때, 내가 작성한 게시글들을 확인할 수 있는 코드로 변경할 예정이다.

 


 

 

1. Model

 

1) SQL문의 추가

실질적인 로직을 추가하기 위해서는 DB데이터를 필요로 하기 때문에 sql문을 우선으로 추가한다.

 

검색으로 진행되며, 반환되는 데이터가 2개 이상일 수 있기 때문에 selectAll로직을 사용하게 되고, 기존의 sql문에서 where절을 활용하여 검색기능을 사용할 수 있게 된다.

 

이때 아래의 sql문은 mySQL기준이며, oracle의 경우 limit을 대체하여 rownum을 사용하며 문장이 약간 상이하기에 rownum을 활용하기 위한 sql문을 먼저 파악해야할 필요가 있다.

//기존 selectAll_SQL
static final String selectAll_board="select * from board order by bid desc limit 0,?"; // 페이징처리 pagination

//내가 쓴 글 확인하려고!
static final String selectAll_board2="select * from board where mid=? order by bid desc limit 0,?";

 


 

2) 비즈니스 메서드의 수정

추가한 sql문을 활용하여 메서드를 하나 더 추가할 수도 있겠지만, 기존의 selectAll메서드를 수정하여 vo가 들어갔을때는 검색, 들어가지 않았을때는 전체 목록 출력될 수 있도록 구현할수도 있다.

// 전체 글+댓글 출력 ☆
	public ArrayList<BoardSet> selectAll(BoardVO vo, int cnt){
		ArrayList<BoardSet> datas=new ArrayList<BoardSet>();
		conn=JDBCUtil.connect();
		try {
			//그게 아니라면 더 하던거 해(특정인 검색을 안했다면!)
			// ★ 이때 왼쪽부터 읽기 때문에 equals가 먼저 온다면 "야! 이거 null인데 어떻게 equals해!"
			//하면서 Exception뜬다! 그러니까 무조건 null부터 써야함!!! ★
			if(vo.getMid()==null || vo.getMid().equals("")) {
				System.out.println("dao로그 : 전체목록출력");
				pstmt=conn.prepareStatement(selectAll_board);
				pstmt.setInt(1, cnt);
			}else {//특정인 게시글 보기였다면,
				System.out.println("dao로그 : 내가 쓴 글 목록 보기");
				pstmt=conn.prepareStatement(selectAll_board2);
				pstmt.setString(1, vo.getMid());
                pstmt.setInt(2, cnt);
			}

			//이 아래로는 동일합니다
			ResultSet rs=pstmt.executeQuery();
			while(rs.next()) {
				BoardSet bs=new BoardSet();
				
				BoardVO boardVO=new BoardVO();
				boardVO.setBdate(rs.getString("bdate"));
				boardVO.setBid(rs.getInt("bid"));
				boardVO.setContent(rs.getString("content"));
				boardVO.setFavcnt(rs.getInt("favcnt"));
				boardVO.setMid(rs.getString("mid"));
				boardVO.setRpcnt(rs.getInt("rpcnt"));
				bs.setBoardVO(boardVO);
				
				ArrayList<ReplyVO> replyList=new ArrayList<ReplyVO>();
				pstmt=conn.prepareStatement(selectAll_reply);
				pstmt.setInt(1, rs.getInt("bid"));
				ResultSet rs2=pstmt.executeQuery();
				while(rs2.next()) {
					ReplyVO replyVO=new ReplyVO();
					replyVO.setBid(rs2.getInt("bid"));
					replyVO.setMid(rs2.getString("mid"));
					replyVO.setMsg(rs2.getString("msg"));
					replyVO.setRdate(rs2.getString("rdate"));
					replyVO.setRid(rs2.getInt("rid"));
					replyList.add(replyVO);
				}
				rs2.close();
				bs.setReplyList(replyList);
				
				datas.add(bs);
			}
			rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		JDBCUtil.disconnect(pstmt, conn);
		return datas;
	}

 

주석으로도 확인이 가능하지만, vo.get이 비어있는지를 확인할때 Exception의 발생을 유의하여 null인지를 먼저 확인 후 equalse("")로 공백인지를 체크하는 순서로 해야만 한다.

 


 

2. View

아래는 커스텀태그 파일의 첨부이다. <a>태그를 클릭하게 되면 현재 로그인되어있는 mid를 기준으로 하여 본인이 작성한 게시글목록을 메인 화면으로 확인할 수 있게 될 것이다.

<%@ tag language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:choose>
	<c:when test="${member!=null}">
		<form action="logout.do" method="post">
		<a href="main.do?mid=${member}">${memberName}님 환영합니다!</a>
		<input type="submit" value="로그아웃">
		</form>
	</c:when>
	<c:otherwise>
		<form action="login.do" method="post">
		 아이디: <input type="text" name="mid">
		 비밀번호:<input type="password" name="mpw">
		 <input type="submit" value="로그인">
		 <a href="signup.jsp">회원가입</a>
		</form>
	</c:otherwise>
</c:choose>

 


 

3. Controller

 

1) MainAction

package controller.action;

import java.util.ArrayList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import model.dao.BoardDAO;
import model.vo.BoardSet;
import model.vo.BoardVO;

public class MainAction implements Action{

	@Override
	public ActionForward execute(HttpServletRequest req, HttpServletResponse res) throws Exception {
		ActionForward forward=new ActionForward();

		BoardDAO dao=new BoardDAO();
		BoardVO vo=new BoardVO();
		// 세션으로 부른애 말고! 파라미터로 불러오는애로 넣자!
		// 세션으로 넣으면 한 번 로그인하면 null이 없는데? 계속 선택보기 될텐데??
		vo.setMid(req.getParameter("mid"));
		ArrayList<BoardSet> datas=dao.selectAll(vo, 3);
		req.setAttribute("datas", datas);
		
		//datas가지고 메인으로 곧장 가
		forward.setPath("main.jsp");
		forward.setRedirect(false);
		
		return forward;
	}

}

 

해당 페이지에서 mid값이 넘어왔다면 set을 해주게 되어, mid가 전달되면 검색보기, 아니라면 전체보기가 진행되도록 수정하였다.

 

이 상태에서 바로 실행하게 되면 main페이지에서 로그인을 하게 되었을때 a태그를 클릭하지 않았음에도 게시글 목록이 아닌 내가 쓴 글 목록을 조회할 수 밖에 없게 된다. 아래에서 그 이유와 해결방법을 확인할 수 있다.

 


 

2) dispatcher

 

주석을 통해 대략적으로 이해가 가능하다.

package controller.common;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
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 controller.action.ActionForward;
import controller.action.DeleteBoardAction;
import controller.action.DeleteReplyAction;
import controller.action.FavAction;
import controller.action.InsertBoardAction;
import controller.action.InsertReplyAction;
import controller.action.LoginAction;
import controller.action.LogoutAction;
import controller.action.MainAction;
import controller.action.SignupAction;

/**
 * Servlet implementation class FrontController
 */
@WebServlet("*.do")
public class FrontController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public FrontController() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		actionDo(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		actionDo(request, response);
	}
	private void actionDo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		String uri=request.getRequestURI();
		String cp=request.getContextPath();
		String command=uri.substring(cp.length());

		ActionForward forward=null;
		if(command.equals("/main.do")) {

			System.out.println("FC:메인으로 이동");
			try {
				forward=new MainAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/login.do")) {

			System.out.println("FC:로그인 시도");
			try {
				forward=new LoginAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/logout.do")) {

			System.out.println("FC:로그아웃 시도");
			try {
				forward=new LogoutAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/signup.do")) {

			System.out.println("FC:회원가입 요청");
			try {
				forward=new SignupAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}else if(command.equals("/fav.do")) {

			System.out.println("FC:좋아요 요청");
			try {
				forward=new FavAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}else if(command.equals("/insertReply.do")) {

			System.out.println("FC:댓글작성 요청");
			try {
				forward=new InsertReplyAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}else if(command.equals("/insertBoard.do")) {

			System.out.println("FC:게시글작성 요청");
			try {
				forward=new InsertBoardAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}else if(command.equals("/deleteReply.do")) {

			System.out.println("FC:댓글 삭제 요청");
			try {
				forward=new DeleteReplyAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}else if(command.equals("/deleteBoard.do")) {

			System.out.println("FC:게시글삭제 요청");
			try {
				forward=new DeleteBoardAction().execute(request, response);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}else {
			System.out.println("잘못된 요청");
		}

		//성공 했을때만 디스패처 실행
		if(forward!=null) {
			
			//forward.getRedirect()원래 이건데 boolean이라 get아니고 is임
			
			//response.sendRedirect방식으로 가라고 그랬나?
			if(forward.isRedirect()) {//true
				response.sendRedirect(forward.getPath());
				//디스패처 하라고 안했으니까 이제 requset랑 response 새로 가져가겠지^^
			}else {//false
				RequestDispatcher dispatcher=request.getRequestDispatcher(forward.getPath());//이 경로로
				dispatcher.forward(request, response);//request, response 내용 갖고가! 	
			}
		} // forward가 null이 아니면 페이지가 이동해버려서 else처리 해주지 않아도 정상작동 된다.
		
		//이전에는 forward가 null일때 에러페이지로 갈 수 있도록 new처리 해주었지만
		// 지금은 <script>처리
		PrintWriter out=response.getWriter();
		out.println("<script>alert('요청처리 실패');history.go(-1);</script>");
		
	}
}

 

 


 

4. 총정리

 

1) 본인의 이해

 

[1번 개념: request의 스코프]
response.sendRedirect = request, response를 초기화해서 비어있는 새걸로 가져감
forward방식 = request, response의 내용을 그대로 전달해서 가져감

[2번 개념: RequestDispatcher클래스]
RequestDispatcher의 객체인 dispatcher는 처리 결과를 올바른 결과페이지로 보내는 역할을 수행한다.
* forward방식(메서드)과 ActionForward의 객체인 forward를다르게 보아야한다 *

(ex는 아래와 같다)
RequestDispatcher dispatcher=request.getRequestDispatcher(forward.getPath()); -> 이 경로로(ActionForward의 객체 사용)
dispatcher.forward(request, response); -> request, response 갖고가!(forward방식의 사용) 

 

 

일단 view에서 mid와 mpw를 입력하게 되면 request를 통해 controller로 전달됨
이 request를 전달해서 session에 setAttribute하게 되고,
이때 정상적으로 로그인이 됐다면 sendRedirect방식이든 아니든 상관 없이 dispatcher가 냅다 forward하기 때문에 request에 mid가 존재하게 됨
이를 방지하기 위해서 sendRedirect방식이라면 response.sendRedirect(새로요청)해주고, 아니라면 그냥 dispatcher.forward(유지)한다.

 


 

2) 순차적 이해

 

1.필수개념
forward방식                  vs sendRedirect방식
로그인정보 남아있다          새로운 요청이므로 정보x

2. 순서
[login.tag]에서 폼으로 파라미터 전달   -> mid:timo    mpw: 1234
(login.do로 보내주세요)


[FrontController]
command가 [login.do]네요?
loginAction에서 처리해주세요


[loginAction]
request.getParameter로 mid, mpw 정보를 받아와서 sql구문 동작시킵니다.
sql이 정상적으로 작동했다면
session에 member: mvo.getMid(), memberName:mvo.getMname(); 저장하고
forward에 forward.setPath("main.do")       forward.setRedirect(true) 저장

중요
★forward.setRedirect(true) -> 새 요청을 해서 정보를 초기화할래요!(<->forward)



[FrontController]
그러나, 아무리 setRedirect(true)로 설정해도 기존 FrontController에서는 forward(정보 유지) 기능밖에 못했답니다.
이 문제를 해결하기 위해서 response.sendRedirect(어디로 갈지)를 추가해줍니다!
if(forward.isRedirect()){
  response.sendRedirect(forward.getPath());
}
else{
  requestDispatcher dispatcher=request.getRequestDispatcher(forward.getPath());
  dispatcher.forward(request, response);

}

 


 

반응형