해당 포스팅 역시 이전 포스팅의 내용에 살을 붙이는 방식으로 진행되었기에 함께 확인해야 할 필요가 있다. 목차는 다음과 같다.
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);
}
'JSP' 카테고리의 다른 글
[JSTL] 현재 날짜 구하기 (0) | 2022.09.27 |
---|---|
[게시판 Ver.2] 페이징처리 & 추가 수정 (1) | 2022.03.17 |
[게시판 Ver.2] 커스텀태그_응용 (0) | 2022.03.15 |
[게시판 Ver.2] 게시글과 댓글의 화면 출력 (0) | 2022.03.14 |
[JDBC] MVC나누기 3_게시판+FC,필터,리스너 (0) | 2022.03.11 |