[Spring MVC] #2 프레임워크 만들기 (2) View 분리

Jaeyoo (유재형)·2022년 2월 2일
1

SpringMVC

목록 보기
3/12
post-thumbnail
post-custom-banner

이전에 프론트 컨트롤러 패턴을 도입한 구조에서 컨트롤러 마다 뷰로 이동하는 부분에 코드 중복이 있었다.
별도로 뷰를 처리하는 객체를 만들어 코드 중복을 없애보자


View 분리


View 처리 객체 추가

MyView

public class MyView {

    private String viewPath;

    public MyView(String viewPath){
        this.viewPath = viewPath;
    }

    public void render(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request, response);
    }
}
  • viewPath로 이동하는 render함수

controllerV2

public interface ControllerV2 {

    MyView process(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException;
}
  • 이전과 동일하게 인터페이스로 구현
  • MyView 객체를 리턴

회원 등록 컨트롤러

public class MemberFormControllerV2 implements ControllerV2 {

    @Override
    public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        return new MyView("/WEB-INF/views/new-form.jsp");
    }
}
  • viewPath로 객체를 생성후 반환한다.
  • 그 전과 비교해 dispatcher를 forward 하는 부분이 없어서 깔끔하다.

회원 저장 컨트롤러

public class MemberSaveControllerV2 implements ControllerV2 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        int age = Integer.parseInt(request.getParameter("age"));

        Member member = new Member(username, age);
        memberRepository.save(member);
        //Model에 데이터를 보관한다.
        request.setAttribute("member", member);

        return new MyView("/WEB-INF/views/save-result.jsp");
    }
}

회원 목록 컨트롤러

public class MemberListControllerV2 implements ControllerV2 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @Override
    public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Member> members = memberRepository.findAll();
        request.setAttribute("members", members);
        return new MyView("/WEB-INF/views/members.jsp");
    }
}

프론트 컨트롤러 V2

@WebServlet(name = "frontControllerServletV2", urlPatterns = "/front-controller/v2/*")
public class FrontControllerServletV2 extends HttpServlet {

    private Map<String, ControllerV2> controllerMap = new HashMap<>();

    public FrontControllerServletV2() {
        controllerMap.put("/front-controller/v2/members/new-form", new MemberFormControllerV2());
        controllerMap.put("/front-controller/v2/members/save", new MemberSaveControllerV2());
        controllerMap.put("/front-controller/v2/members", new MemberListControllerV2());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String requestURI = request.getRequestURI();

        ControllerV2 controller = controllerMap.get(requestURI);
        if (controller == null){
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        MyView view = controller.process(request, response);
        view.render(request, response);
    }
}
  • 매핑정보 저장하는건 이전과 동일
  • Myview 객체의 render()를 호출하면 일괄처리할수있다.
  • 각각의 컨트롤러는 MyView 객체를 생성해서 반환하면 된다.

더 개선해야될 부분

  • 아직 모델 부분이 부족하다.
  • 프론트 컨트롤러를 사용하면 각각의 컨트롤러에 request, response를 제거할수있다. (서블릿 종속성 제거)
profile
기록과 반복
post-custom-banner

0개의 댓글