zenn.skin 무료버전 배포중!
자세히보기

Web/Spring

[Spring Web 6.1] DispatcherServlet 뜯어보기 - view 관련

koosco! 2024. 10. 7. 18:18

doDispatch, doService 코드를 보고 나머지 코드들을 보려니까 마음이 편하다.

render메서드와 resolveViewName, applyDefaultViewName 메서드는 모두 view와 관련한 코드들로 handler로부터 받은 값을 처리해주는 역할을 한다.

Render

render 메서드의 동작은 다음과 같다.

1. Locale 설정

2. View 객체 가져오기

3. ModelAndView의 View 객체 사용

4. 응답 상태 설정 및 렌더링

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    // ModelAndView 객체에서 locale을 가져오고, localeResolver가 null이 아닐 경우 localeResolver로부터 Locale 객체를 가져옴
    Locale locale = this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale();

    response.setLocale(locale); // 가져온 locale을 응답값에 설정
    
    /**
     * view 이름 설정
     */
    String viewName = mv.getViewName();
    View view;
    if (viewName != null) {
        // view 이름이 존재하면 resolveViewName을 통해 View 객체 생성
        view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);
        if (view == null) {
            // view 이름을 가져오지 못하는 경우 예외를 발생
            String var10002 = mv.getViewName();
            throw new ServletException("Could not resolve view with name '" + var10002 + "' in servlet with name '" + this.getServletName() + "'");
        }
    } else {
        view = mv.getView(); // View 이름이 존재하지 않을 경우 ModelAndView 객체의 View 객체를 가져옴
        if (view == null) {
            // View 객체가 존재하지 않을 경우 예외를 발생시킴
            throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a View object in servlet with name '" + this.getServletName() + "'");
        }
    }

    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Rendering view [" + view + "] ");
    }

    try {
        // ModelAndView 객체에 HTTP 응답 상태가 설정되어 있다면 해당 상태를 request에 설정하고 response의 상태를 설정
        if (mv.getStatus() != null) {
            request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, mv.getStatus());
            response.setStatus(mv.getStatus().value());
        }

        // View의 render() 메서드를 호출하여 최종적으로 Model 데이터를 View와 함께 response로 렌더링
        view.render(mv.getModelInternal(), request, response);
    } catch (Exception var8) {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Error rendering view [" + view + "]", var8);
        }

        throw var8;
    }
}

 

ViewResolve

viewResolveName 함수는 viewResolvers를 순회하면서 View 객체를 찾아 반환하는 역할을 한다

@Nullable
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception {
    // viewResolvers가 null이 아닐 경우, ViewResolver 리스트에서 View 객체를 찾음
    if (this.viewResolvers != null) {
        // viewResolvers 리스트를 순회할 Iterator 객체 생성
        Iterator var5 = this.viewResolvers.iterator();

        // 모든 ViewResolver를 순회하며 viewName에 맞는 View 객체를 찾음
        while (var5.hasNext()) {
            // 현재 순회 중인 ViewResolver 객체를 가져옴
            ViewResolver viewResolver = (ViewResolver) var5.next();
            // viewName과 locale을 기준으로 ViewResolver에게 View 객체를 요청
            View view = viewResolver.resolveViewName(viewName, locale);

            // ViewResolver가 유효한 View 객체를 반환한 경우, 해당 View 객체를 반환
            if (view != null) {
                return view;
            }
        }
    }

    // 모든 ViewResolver가 null을 반환한 경우 null을 반환하여 View를 찾지 못했음을 알림
    return null;
}

 

applyDefaultViewName

doDispatch에서 ModelAndView를 받아서 기본 View이름을 적용해주는 메서드

private void applyDefaultViewName(HttpServletRequest request, @Nullable ModelAndView mv) throws Exception {
    // ModelAndView 객체가 null이 아니고, View가 설정되어 있지 않은 경우에만 기본 View 이름을 적용
    if (mv != null && !mv.hasView()) {
        // HttpServletRequest 객체로부터 기본 View 이름을 가져옴
        String defaultViewName = this.getDefaultViewName(request);

        // 기본 View 이름이 존재할 경우, ModelAndView 객체에 View 이름을 설정
        if (defaultViewName != null) {
            mv.setViewName(defaultViewName);
        }
    }
}

'Web/Spring'의 다른글

  • 현재글 [Spring Web 6.1] DispatcherServlet 뜯어보기 - view 관련

관련글