Front-Controller
mvc1편에서 배운 Front-Controller v5는, map에 uri를 등록하고, 찾아서 쓰도록 설계 되어 있다.
...
/* handler(Controller)가 매핑된 Map */
private final Map<String, Controller> handlerMappingMap = new HashMap<>();
...
/**
* 이 클래스가 생성되면서 handler(Controller)가 매핑된 Map, handlerAdapter가 들어있는 List가 초기화 됩니다.
*/
public FrontControllerServlet() {
initHandlerMappingMap();
}
...
private void initHandlerMappingMap() {
handlerMappingMap.put("/site", new IndexController());
handlerMappingMap.put("/site/join", new JoinController());
handlerMappingMap.put("/site/login", new LoginController());
handlerMappingMap.put("/site/book/rent", new RentController());
handlerMappingMap.put("/site/book/unrent", new UnRentController());
handlerMappingMap.put("/site/admin", new AdminPageController());
handlerMappingMap.put("/site/users/1", new AdminUsersController1());
handlerMappingMap.put("/site/users/2", new AdminUsersController2());
handlerMappingMap.put("/site/users/3", new AdminUsersController3());
...
}
...
/* 핸들러 획득 */
Controller handler = getHandler(request);
...
private Controller getHandler(HttpServletRequest request) {
String requestURI = request.getRequestURI();
return handlerMappingMap.get(requestURI);
}
단순히 로그인, 회원가입같은 구조는 괜찮지만, REST API 설계를 하기에는 매우 부적합하다. 리소스 위치마다 모두 handlerMappingMap에 등록해줄 수 없기 때문이다.
...
handlerMappingMap.put("/site/users/*", new AdminUsersController());
...
이런 식으로 등록할 수 있다면 참 좋은데, getHandler에서 URI자체를 가져오기 때문에 쉽지 않았다.
해결 방법
해결 방법은 의외로 간단했다. getHandler 메서드에서 핸들러를 찾기에 실패했을 경우 한 번 조건문으로 걸러서 추가해주면 된다. startWith 메서드를 활용했다.
이 방법으로 추가로, /book/rent, /book/unRent까지 개선이 가능할 것 같다.
private void initHandlerMappingMap() {
...
handlerMappingMap.put("/site/users/*", new AdminUsersController());
}
private Controller getHandler(HttpServletRequest request) {
String requestURI = request.getRequestURI();
Controller handler = handlerMappingMap.get(requestURI);
if (handler == null) {
//users 컨트롤러
if (request.getRequestURI().startsWith("/site/users/")) {
handler = handlerMappingMap.get("/site/users/*");
}
}
return handler;
}