핸들러맵핑 이란?
좋은 FrontController 기반의 프레임워크들이
멤버변수로 가지게 하는 것이다.
싱글톤 패턴을 유지하는 역할을 한다.
싱글톤 패턴 이란?
new를 절약하는 패턴중 하나로,
한번 new해서 존재하는 객체가 있다면
해당 객체를 계속 재사용하는 패턴이다.
"new"연산자는 힙 메모리영역을 사용
적게 사용할 수록 좋다.
<HandlerMapper.java>
package controller.common;
import java.util.HashMap;
import java.util.Map;
import controller.board.BoardAction;
import controller.board.MainAction;
import controller.member.LoginAction;
public class HandlerMapper {
private Map<String, Action> mapper; // <커맨드(요청),객체(기능)> 커맨드에 대해서 객체를 반환할 생각이다.
public HandlerMapper() { // 기본생성자
this.mapper = new HashMap<String,Action>(); // map은 추상 클래스 // 멤버변수 초기화
this.mapper.put("/main.do", new MainAction());
this.mapper.put("/board.do", new BoardAction());
this.mapper.put("/login.do", new LoginAction());
}
public Map<String, Action> getMapper() {
return mapper;
}
// public void setMapper(Map<String, Action> mapper) {
// this.mapper = mapper;
// }
public Action getAction(String command) {
return this.mapper.get(command);
}
}
<FrontController.java>
package controller.common;
import java.io.IOException;
import controller.board.BoardAction;
import controller.board.MainAction;
import controller.member.JoinAction;
import controller.member.LoginAction;
import controller.member.LogoutAction;
import controller.page.JoinPageAction;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet("*.do") // 어쩌구 저쩌구 .do로 끝나면 여기로 와~! // 서버 start할 때 바로 알아듣는다. // 어노테이션
// 톰캣(server)이 구동될때, xxx.do로 끝나는 요청에 대하여 FC를 호출하게됨
// 설정이 궁금하면 Web.xml을 까봐야 하는데 그게 어려우니까... // xml과 같이하면 충돌이 일어남
// 어노테이션은 반드시 클래스 위에 붙어있어야 함
// servlet파일 만들면 web.xml이 자동으로 생성
public class FrontController extends HttpServlet {
private static final long serialVersionUID = 1L;
private HandlerMapper mappings;
public FrontController() { // 기본생성자
super();
mappings=new HandlerMapper(); // 기본생성자는 최초 1회만 생성하기 때문에 new를 한번만 사용할 수 있다.
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doAction(request, response); // doAction으로 실행
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doAction(request, response); // doAction으로 실행
}
private void doAction(HttpServletRequest request, HttpServletResponse response) { // get으로 오든 post로 오든 다 얘로 실행해줘 // 요즘은 doAction대신 execute로 명칭
// 요청 정보 == request
// 1. 사용자가 무슨 요청을 했는지 추출 및 확인
String uri=request.getRequestURI(); // 무슨 요청을 했나 uri로 확인
String cp=request.getContextPath(); // /xxx.do 전에 경로 // 요청한 uri중 프로젝트 명(경로)을 제거
String command=uri.substring(cp.length()); // uri에서 cp길이(나머지 경로)만큼 잘라버려~ == action number, menu number
System.out.println("command : "+command);
// 2. 요청을 수행
Action action = mappings.getAction(command);
ActionForward forward=action.execute(request, response);
/*
ActionForward forward=null; // forward 다 new해줘야하니까 스코프 밖에서 null로 설정 // 초기화
if(command.equals("/main.do")) { // 요청값이 .do로 끝난다면
//
// main.jsp에서 보여줘야하는 데이터들이 있나? 확인해봐야함
// 로그인 여부(session에 저장하기 때문에 여기서하는게 아니다!)
BoardDAO boardDAO=new BoardDAO(); // 그동안 jsp에서는 useBean을 통해 4개의 new를 진행했었다.
BoardDTO boardDTO=new BoardDTO(); // servlet에서는 new 2번만 사용한다. == 백단이 가벼워진다, 경제적이다. == 뭐가 사용되었는지 직관적으로 보인다.
ArrayList<BoardDTO> datas=boardDAO.selectAll(boardDTO);
request.setAttribute("datas", datas);
// 게시글 목록만 보여주면됨
pageContext.forward("main.jsp"); // 전달할게 있다 == forward // 내장객체가 없다. 그러므로 pageContext xx
// main.jsp 페이지로 이동
//
MainAction mainAction=new MainAction();
forward=mainAction.execute(request, response);
}
else if(command.equals("/login.do")) {
//
MemberDAO memberDAO=new MemberDAO();
// jsp로 작성할떄는 페이지 지시어로 모든 데이터를 new(객체생성, 메모리할당) 해야하지만
// 서블릿으로 작성할때는 필요한 데이터만 new 하면되서 경제적이고, 가벼워진다
// 어떤 데이터가 사용됬는지 직관적으로 확인가능해서 가독성도 증가한다
MemberDTO memberDTO=new MemberDTO();
memberDTO.setMid(request.getParameter("mid"));
memberDTO.setPassword(request.getParameter("password")); // Model에서 뭐가 필요한지 직관적으로 보이기 시작한다.
memberDTO=memberDAO.selectOne(memberDTO);
if(memberDTO!=null) { // 로그인에 성공했을 때
seeeion.setAttribute("loginInfo", memberDTO.getMid)// session에 로그인 정보를 저장
}
//
LoginAction loginAction=new LoginAction();
forward = loginAction.execute(request, response); // 기존의 요청을 유지해주는 역할을 한다.
}
else if(command.equals("/loginPage.do")) {
JoinPageAction joinPageAction=new JoinPageAction();
forward = joinPageAction.execute(request, response);
}
else if(command.equals("/board.do")) {
BoardAction boardAction=new BoardAction();
forward = boardAction.execute(request, response);
}
else if(command.equals("/join.do")) {
JoinAction joinAction=new JoinAction();
forward = joinAction.execute(request, response);
}
else if(command.equals("/joinPage.do")) {
JoinPageAction joinPageAction=new JoinPageAction();
forward = joinPageAction.execute(request, response);
}
else if(command.equals("/logout.do")) {
// new가 0개
LogoutAction logoutAction=new LogoutAction();
forward = logoutAction.execute(request, response);
}
*/
if(command==null) { // 에러페이지로 이동 // 주소가 없을때 // 이상한애가 들어온다면~
// 등록되지 않은 요청입니다.
try {
response.sendRedirect("error.jsp"); // 바로 에러페이지로 이동
} catch (IOException e) {
e.printStackTrace();
}
}
else { // 주소가 있다면, // 이상한 애가 아니라면
if(forward.isRedirect()) { // true면 리다이렉트 방식
try {
response.sendRedirect(forward.getPath());
} catch (IOException e) {
e.printStackTrace();
}
}
else { // false면 포워드 방식
RequestDispatcher dispatcher=request.getRequestDispatcher(forward.getPath());
try {
dispatcher.forward(request, response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
} // 이렇게 되면 controller.jsp가 필요 없어지게 된다.
// 3. 응답(페이지 이동 중) == 어떤 코드를 뜯어봐도 이런 흐름으로 진행된다.
// 한번에 전달한다.
// 1) 전달할 데이터가 있니? 없니? == 포워드? 리다이렉트?
// 2) 그래서 어디로 갈까? == 경로 // 이렇게 2가지만 알면 다 보내줄 수 있다.
// 현재의 FC코드는 응집도가 낮은 상태...
}
}
2024.08.22
'WEB' 카테고리의 다른 글
| [WEB] 12. 리스너 (0) | 2024.09.03 |
|---|---|
| [WEB] 11. 비동기 처리 (0) | 2024.08.23 |
| [WEB] 09. 스프링 프레임워크의 구조 (0) | 2024.08.20 |
| [WEB] 08. jQuery (0) | 2024.08.19 |
| [WEB] 07. JavaScript, xml (0) | 2024.08.16 |