FrontController Root 디렉토리 탐색 문제

FrontControllerServlet urlPatterns 가 루트 하위 전체로 잡힌 경우

@WebServlet(name = "frontControllerServlet", urlPatterns = "/*")
public class FrontControllerServlet extends HttpServlet {

    private final Map<String, Controller> handlerMappingMap = new HashMap<>();
    private final List<HandlerAdapter> handlerAdapters = new ArrayList<>();

    public FrontControllerServlet() {
        initHandlerMappingMap();
        initHandlerAdapters();
    }

    private void initHandlerMappingMap() {
        handlerMappingMap.put("/", new UserIndexController());
    }

    private void initHandlerAdapters() {
        handlerAdapters.add(new UserControllerAdapter());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Controller handler = getHandler(request);

        System.out.println("handler = " + handler); // 핸들러 확인

        if (handler == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        HandlerAdapter adapter = getHandlerAdapter(handler);
        ModelView mv = adapter.handle(request, response, handler);

        String viewName = mv.getViewName();
        MyView view = viewResolver(viewName);

        view.render(mv.getModel(), request, response);
    }

    private Controller getHandler(HttpServletRequest request) {
        String requestURI = request.getRequestURI(); // URI 확인
        System.out.println("requestURI = " + requestURI);
        return handlerMappingMap.get(requestURI);
    }

    private HandlerAdapter getHandlerAdapter(Controller handler) {
        for (HandlerAdapter adapter : handlerAdapters) {
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
        throw new IllegalArgumentException("handler adapter를 찾을 수 없습니다. hander=" + handler);
    }

    private static MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }

}

이 경우, MyView 클래스의 render 클래스에서 호출하는 dispatcher.forward 메서드까지 잡히는 것 같다.

public class MyView {
    private final String viewPath;

    public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        modelToRequestAttribute(model, request);
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
        dispatcher.forward(request,response);
    }

    private static void modelToRequestAttribute(Map<String, Object> model, HttpServletRequest request) {
        model.forEach((key, value) -> request.setAttribute(key, value));
    }
}
requestURI = /
handler = com.weblibrary.controller.UserIndexController@5bf88c8f
requestURI = /WEB-INF/views/home/index.jsp
handler = null

따라서 콘솔창에 이렇게 두 번 인식되며, 404 응답이 내려진다.

해결 방법

추후 과제로 남겨두고, 현재 단계에서는 사이트 전체를 /site/ 하위로 접근하도록 수정하였다.

@WebServlet(name = "frontControllerServlet", urlPatterns = "/site/*")
public class FrontControllerServlet extends HttpServlet {

    private final Map<String, Controller> handlerMappingMap = new HashMap<>();
    private final List<HandlerAdapter> handlerAdapters = new ArrayList<>();

    public FrontControllerServlet() {
        initHandlerMappingMap();
        initHandlerAdapters();
    }

    private void initHandlerMappingMap() {
        handlerMappingMap.put("/site", new UserIndexController());
    }

    private void initHandlerAdapters() {
        handlerAdapters.add(new UserControllerAdapter());
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Controller handler = getHandler(request);

        System.out.println("handler = " + handler); // 핸들러 확인

        if (handler == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        HandlerAdapter adapter = getHandlerAdapter(handler);
        ModelView mv = adapter.handle(request, response, handler);

        String viewName = mv.getViewName();
        MyView view = viewResolver(viewName);

        view.render(mv.getModel(), request, response);
    }

    private Controller getHandler(HttpServletRequest request) {
        String requestURI = request.getRequestURI(); // URI 확인
        System.out.println("requestURI = " + requestURI);
        return handlerMappingMap.get(requestURI);
    }

    private HandlerAdapter getHandlerAdapter(Controller handler) {
        for (HandlerAdapter adapter : handlerAdapters) {
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
        throw new IllegalArgumentException("handler adapter를 찾을 수 없습니다. hander=" + handler);
    }

    private static MyView viewResolver(String viewName) {
        return new MyView("/WEB-INF/views/" + viewName + ".jsp");
    }

}

댓글

개발자  김철준

백엔드 개발자 김철준의 블로그입니다.

주요 프로젝트