M
- DTO > 테이블
- DAO 인자를 DTO
- boolean DTO AL
- 결합도를 낮추기 위함
V
- 사용자 편의성 UI/UX
- 유효성 검사
- 안내
- 웹 접근성 표준 지침
C
- MVC1에서는 controller.jsp에서 action 파라미터를 받아서 if 분기처리하여 코드를 작성한다.
- 문제점
- 1) 하나의 기능을 수정한다 해도, 전체 프로그램이 동작하지 않는다.
- 응집도가 낮아서 문제인 상황이다.
- 기능별로 묶어놔야 하는 상황이다.
- 2).jsp는 V를 의미함
- C는 JAVA 코드를 사용한다.
- .java 페이지를 활용하는 것이 바람직하다.
- 1) 하나의 기능을 수정한다 해도, 전체 프로그램이 동작하지 않는다.
- 대안
- MVC2 사용
- controller.jsp를 controller.java로 변경한다.
- 각각의 if문 내부의 기능들을 클래스화(모듈화, 컴포넌트화)
- 응집도가 높아짐 == 유지보수가 용이해짐
- jsp의 내부객체를 사용해야하기 때문에 .java파일이 아닌 Servlet파일로 생성
- Servlet 파일은 패키지와 클래스명이 같아서는 안된다.
- url mapping에 Servlet이 반응 할 키워드를 적어야한다.
- *do로 지정할 경우, 경로를 지정할 때 .do를 붙여준다.
- ex) /main.do, /join.do
- MVC2 사용
Servlet 작성
- Servlet은 무겁기 때문에 경량화를 위해 Servlet은 단 하나만 생성한다.
- FrontController 패턴을 사용한다.
- 프론트 컨트롤러가 요청에 맞는 컨트롤러를 찾아서 호출하는 패턴이다.
- 모든 컨트롤러의 앞 단에서 서블릿 하나로 클라이언트의 모든 요청을 받는다.
- url mapping을 *.do로 정했기 때문에 @WebServlet("*.do")라는 어노테이션이 붙는다.
package controller;
@WebServlet("*.do")
public class FrontController extends HttpServlet {
- 방식이 GET이던 POST던 공통으로 로직을 불러올 수 있도록 수정한다.
- doAction하나로 통일
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doAction(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doAction(request, response);
}
private void doAction(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
- doAction에 controller 로직 작성
private void doAction(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// controller.jsp 의 코드를 옮겨올예정!
String uri = request.getRequestURI();
String cp = request.getContextPath();
String action = uri.substring(cp.length());
System.out.println(action);
if (action.equals("/main.do")) { // ◀ if(action.equals("main")){
ActionForward forward = new MainAction().execute(request, response);
} else if (action.equals("/join.do")) {
} else if (action.equals("/joinPage.do")) {
} else if (action.equals("/logout.do")) {
} else if (action.equals("/testPage.do")) {
} else if (action.equals("/mypage.do")) {
} else if (action.equals("/loginPage.do")) {
} else if (action.equals("/login.do")) {
} else if (action.equals("/replySelectOne.do")) {
} else if (action.equals("/replyInsert.do")) {
} else if (action.equals("/replyUpdate.do")) {
} else if (action.equals("/replyDelete.do")) {
} else if (action.equals("/changeName.do")) {
} else if (action.equals("/memberDelete.do")) {
} else {
}
}
메서드명을 일괄적으로 강제하기 위한 인터페이스
- FrontController 에서 기능 클래스를 호출할때에 메서드명을 일괄적으로 강제하고싶어서 인터페이스 사용한다.
package controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Action {
void execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
}
- execute기능에서는 경로와 방식(리다이렉트, 포워드) 두 가지를 리턴해줘야하기 때문에 자료형을 만들어줄 필요가 있다.
package controller;
public class ActionForward {
private String path; // 어디로 가야하는지 == 경로
private boolean redirect; // 어떻게 갈지 == 리다이렉트 or 포워드
public ActionForward() {
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public boolean isRedirect() {
return redirect;
}
public void setRedirect(boolean redirect) {
this.redirect = redirect;
}
}
- execute의 자료형을 ActionForward로 지정한다.
package controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Action {
ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
}
기능 클래스 제작
- 메서드명을 통일하기 위해 만든 Action 인터페이스를 implements한다.
public class MainAction implements Action{
- 메서드 오버라이딩한다.
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
- 기능을 기술한다.
public class MainAction implements Action{
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward forward = new ActionForward();
forward.setPath("/main.jsp");
forward.setRedirect(false); // false = pageContext.forward("main.jsp");
// true = sendRedirect
request.setCharacterEncoding("UTF-8");
ReplyDAO rDAO = new ReplyDAO();
ReplyDTO rDTO = new ReplyDTO();
ArrayList<ReplyDTO> rdatas=rDAO.selectAll(rDTO);
request.setAttribute("rdatas", rdatas);
MemberDAO mDAO=new MemberDAO();
MemberDTO mDTO=new MemberDTO();
ArrayList<MemberDTO> mdatas=mDAO.selectAll(mDTO);
request.setAttribute("mdatas", mdatas);
return forward;
}
}
전체 흐름
- 인덱스 페이지에서 main.do 호출
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
response.sendRedirect("main.do");
// controller.jsp?action=main
// .do 가 이미 C 를 호출
// 파라미터를 절약하기위해 main.do 로 호출
%>
- FrontController에서 if문으로 main.do를 찾아 로직 수행
private void doAction(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// controller.jsp 의 코드를 옮겨올예정!
String uri = request.getRequestURI();
String cp = request.getContextPath();
String action = uri.substring(cp.length());
System.out.println(action);
ActionForward forward = null;
if (action.equals("/main.do")) { ←←←←←←
forward = new MainAction().execute(request, response); ←←←←←←
} else if (action.equals("/join.do")) {
forward = new JoinAction().execute(request, response);
- MainAction의 execute 로직을 수행
- 경로와 방식(리다이렉트, 포워드)를 반환한다.
public class MainAction implements Action{
@Override
public ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionForward forward=new ActionForward();
forward.setPath("/main.jsp"); ←←←←←← 이동 경로 지정
forward.setRedirect(false); ←←←←←← 방식 지정
request.setCharacterEncoding("UTF-8");
ReplyDAO rDAO=new ReplyDAO();
ReplyDTO rDTO=new ReplyDTO();
ArrayList<ReplyDTO> rdatas=rDAO.selectAll(rDTO);
request.setAttribute("rdatas", rdatas);
MemberDAO mDAO=new MemberDAO();
MemberDTO mDTO=new MemberDTO();
ArrayList<MemberDTO> mdatas=mDAO.selectAll(mDTO);
request.setAttribute("mdatas", mdatas);
return forward; ←←←←← 값 반환
}
}
- 반환 받은 값으로 포워딩
if (forward.isRedirect()) {
response.sendRedirect(forward.getPath());
} else {
RequestDispatcher dispatcher = request.getRequestDispatcher(forward.getPath());
dispatcher.forward(request, response);
}
}
'개발 패턴 > MVC' 카테고리의 다른 글
[개발패턴] <MVC2> Servlet의 .doGet, .doPost, .doAction은 누가하는가 (1) | 2024.01.11 |
---|---|
[개발패턴] <MVC1> 웹 MVC1 PATTERN NO SPRING (0) | 2024.01.09 |
[개발 패턴] <MVC> 기초 (0) | 2023.12.11 |