개발 무지렁이

[Servlet] 진입점 컨트롤러(DispatcherServlet)와 인터페이스 Controller 및 ModelAndView 객체 본문

Backend/Servlet & JSP

[Servlet] 진입점 컨트롤러(DispatcherServlet)와 인터페이스 Controller 및 ModelAndView 객체

Gaejirang-e 2023. 4. 26. 21:20

𐂂 MVC(Model View Controller)구조를 사용해야하는 이유
🧩 유지보수 및 재사용성을 높이기 위함이다.

𐁍 진입점 컨트롤러 (DispatcherServlet)
front Controller 역할
하나의 Servlet을 만들어 공유(중앙집중), DispatcherServlet

⚠️ 요청(request)Servlet이 만들어지면, 요청주소가 다 달라져서 관리가 힘들다.

𖠃 하나의 Servlet안에서 역할을 어떻게 분산시킬 것인가
init()
기능별(key)로 매핑될 (구현객체) Controller 정보가 문서화된
actionMapping.properties를 읽어들여 매핑시킨다.
(인터페이스 Controller규격삼아)

service()
쿼리스트링key정보를 담고 이를 getParameter로 가져와
해당 key와 매핑된 Controller의 메서드를 호출해서
작업을 수행할 수 있도록 처리해준다.


📜 DispatcherServlet.java

  @WebServlet(urlPatterns="/front", loadOnStartup=1)
  public class DispatcherServlet extends HttpServlet {
      private static final long serialVersionUID = 1L;

      Map<String, Controller> map = new HashMap<>();
      @Override
      public void init(ServletConfig config) throws ServletException {
          //actionMapping.properties 파일 읽어오기
          ResourceBundle rb = ResourceBundle.getBundle("actionMapping");

          try {
              for(String key : rb.keySet()) {
                  String value = rb.getString(key);
                //reflection
                  Class<?> className = Class.forName(value);
                Controller controller = (Controller)className.getDeclaredConstructor().newInstance();

                map.put(key, controller);
              }
          } catch(Exception e) {
            e.printStackTrace();
        }
      }

    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        String key = request.getParameter("key");
        Controller controller = map.get(key);

        ModelAndView mv = controller.handleRequest(request, response);
        if(mv.isRedirect()) {
            response.sendRedirect(mv.getViewName());
        } else {
            request.getRequestDispatcher(mv.getViewName()).forward(request, response);
        }
    }
  }
🦉 ResourceBundle
텍스트 리소스를 관리해주는 클래스를 말한다.
.properties 파일에 저장된 텍스트 리소스로드하여,
웹 애플리케이션에서 사용할 수 있게 해준다.

🦉 리플렉션(reflection)
실행도중에 동적으로 필요한 객체를 생성하거나,
객체가 가지고 있는 생성자 or 메소드동적으로 호출할 수 있는 개념
(Class: reflection 개념을 적용해 놓은 API(in Java) )

📕 참고 자료 📕
Tistory's Card

🦔 actionMapping.properties

🦉 어떤 key에 어떤 객체매핑되어있는지를 문서화
  #key=value
  insert=web.mvc.controller.InsertController
  select=web.mvc.controller.SelectController
  update=web.mvc.controller.UpdateController
  delete=web.mvc.controller.DeleteController
𖠃 인터페이스 Controller

📜 Controller.java

  public interface Controller {
      ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;
  }
🦉 코드 설명
인터페이스 Controller를 implements할 모든 구현객체에는
정보저장 로직이 들어간다.(🚩경로와 💣이동방식)

📜 InsertController.java

  public class InsertController implements Controller {
      @Override
      public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
          System.out.println("InsertController call...");
          //경로와 이동할 방식을 설정
          ModelAndView mv = ModelAndView("front?key=select", true);
          return mv;
      }
  }

📜 ModelAndView.java

⭐.정보저장 (view의 정보, 🚩경로와 💣이동방식)
  public class ModelAndView {
    private String viewName; //경로
      private boolean isRedirect; //true면 redirect, fals면 forward

      public ModelAndView() { }
      public ModelAndView(String viewName) {
          this.viewName = viewName;
      }
      public ModelAndView(String viewName, boolean isRedirect) {
          this(viewName);    
          this.isRedirect = isRedirect;
      }

      //getter, setter 생략...
  }

📜 index.jsp

  <%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
  <!DOCTYPE html>
  <html>
    <head>
        <meta charset="UTF-8">
        <title>Insert title here</title>
    </head>
    <body>
      <h1>Web MVC</h1>
      <h3>
        <a href="${pageContext.request.contextPath}/front?key=insert">등록하기</a><p>
        <a href="${pageContext.request.contextPath}/front?key=update">수정하기</a><p>
        <a href="${pageContext.request.contextPath}/front?key=delete">삭제하기</a><p>
        <a href="${pageContext.request.contextPath}/front?key=select">조회하기</a><p>
      </h3>
    </body>  
  </html>
Comments