Servlet-JSP MVC04 (2) - handlerMapping and viewResolver
- (1)번에서 만들었던 frontcontroller를 더 수정해보자.
- frontcontroller의 역할을 다시한번 상기하자면,
> 요청받기, 공통부분처리, pojo 메서드호출, view연결이다.
- 이러한 역할들 중에 pojo를 호출하는 분기문을 handlerMapping을 적용하여 더 깔끔하게 정리해보도록하자.
- 또한 viewresolver를 적용해보자.
1. HandlerMapping
-사용자 요청과 이를 처리할 pojo를 맵핑시켜주는 역할을 담당한다.
-이전에 분기문으로 사용자 요청을 확인하고, 이에 따라 적절한 pojo를 연결하는 작업을 frontcontroller내에서 했는데
이를 따로 떼어두는 것이다.
public class HandlerMapping{
private HashMap<String,Controller> mappings = new HashMap<>();
public HandlerMapping(){
mappings.put("/memberList.do",new MemberListController());
//...추가
}
public getController(String key){
return mappings.get(key);
}
}
- 생성자에 각 요청에 대한 url정보와 이를 처리할 pojo를 hashMap으로 연결한다.
- 컨트롤러 반환 메서드를 호출하면, key값에 맞는 controller를 return한다.
//FrontContrller
String url = request.getRequestURI();
String context = request.getContextPath();
//요청정보확인
String command = url.substring(context.length());
String nextPage =null;
Controller cr = null;
HandlerMapping mp = new HandlerMapping();//생성되면서, hashmap에 mapping정보 초기화
cr = mp.getController(command); // 요청정보를 전달받아 이에 맞는 pojo return
nextPage = cr.requestHandler(request,response); //pojo메서드 호출한 뒤 nextPage return받음
HandlerMapping을 통해 FrontController의 분기문을 위와 같이 간결하게 처리할 수 있다.
2. ViewResolver
- 지금까지는 pojo에 다음 처리할 view의 path를 직접 적어두었다.
- 처리할 view의 이름은 자주 변하지 않지만, 폴더구조는 자주 변할 수 있다. 폴더 구조가 변하면 모든 pojo에 가서 다시 적어줘야하는데 매우 비효율적이다.
- 이러한 일을 간단하게 처리할 수 있도록 pojo는 view의 이름만 return하고, 나머지 폴더구조는
한 곳에서만 관리하여, 폴더 구조가 변하면 한 곳만 수정하면 좋을 것이다.
- 이러한 역할을 해주는 것이 ViewResolver이다.
* viewresolver를 설정하기 전에 jsp파일을 모아둔 폴더는 WEB-INF로 옮겨두자
이는 클라이언트가 컨트롤러 요청 외 직접 jsp파일로 접근하지 못하게 하기 위해서이다.
forward로 서버 내부 페이지 전환시에는 WEB-INF폴더에 접근할 수 있다.
public class ViewResolver{
private static String prefix="/WEB-INF/member/";
private static String postfix=".jsp";
public static String getPath(String viewname){
return prefix+viewname+postfix;
}
}
접두사와 접미사를 붙여서 view이름을 return해주는 클래스를 만들었다.
이제 frontController내부에서 다음과 같이 처리할 수 있다.
// ... pojo로 메서드를 호출하고 nextPage를 return 받은 상황
if(nextPage !=null){
if(nextPage.contain("redirect:"){
response.sendRedirect(nextPage.split(":")[1]);
}else{
RequestDispatcher rd = request.getRequestDispatcher(ViewResolver.getPath(nextPage));
re.forward(request,response);
}
}
3. 추가 ContextPath가 변경시에도 동일하게 작동하도록 하기
- ContextPath가 변경되면 ContextPath를 포함해서 지정해두었던 모든 view와 Controller를 수정해줘야할 것이다
(redirect, form태그에 action들)
- ContextPath가 변경되어도 이를 자동반영하도록 수정해보자.
- frontController에서 request.getContextPath();얻은 것 처럼 하면 된다.
//contextPath가 필요한 pojo 상단에 추가
//요청정보에따라 contextPath를 읽는다.
String ctx = request.getContextPath();
//..처리
// return할 nextPage에 기존 ContextPath였던 부분을 변수로 ctx로 고쳐준다.
nextPage = "redirect:"+ctx+"/memberList.do";
//jsp
<c:set var="ctx" value="${pageContext.request.contextPath}"
//pageContext를 통해 request객체에 접근하여 contextPath를 읽어온다
EL을 통해 다음과 같이 읽어온 contextPath의 값을 경로에 집어넣는다.
<form action="${ctx}/memberUpdate.do" method="post">
위와 같이 request객체를 통해 contextPath를 읽어오고 이를 변수에 담은 뒤에 필요한 부분에 대입하면된다.
*contextPath나 폴더구조(뷰이름제외)등은 자주 변할 수 있으니 직접 적는 것은 피하고, 뷰리졸버나 변수를 통해 대입하자
참고자료:
나프1탄(인프런) -박매일
https://www.inflearn.com/course/%EB%82%98%ED%94%84-mvc-1
[NarP Series] MVC 프레임워크는 내 손에 [나프1탄] - 인프런 | 강의
본 과정은 WEB MVC 프레임워크가 무엇이고 WEB MVC 프레임워크가 어떻게 변형이 되면서 Spring WEB MVC 프레임워크로 넘어가는지 TPC(생각하고-표현하고-코딩하고) 기법을 통해 단계적으로 학습하고 이
www.inflearn.com
https://devmoony.tistory.com/102
[Spring MVC] Dispatcher Servlet 이란? -(FrontController패턴 포함)
Dispatcher Servlet 이란? Dispatcher Servlet에서 dispatch는 "보내다" 라는 사전적 의미를 가지고 있습니다. 본격적으로 Dispatcher Servlet에 대해 설명하기 앞서 FrontController 패턴의 개념을 살펴보고 가겠습니다
devmoony.tistory.com