SpringMVC 프로세스 분석

8938 단어 springMVC

SpringMVC 프로세스


서버 시작 단계(DispatcherServlet 초기화 단계)

  • 이 시작된 후 ContextLoaderListener은 우선 초기화 방법 contextInitialized(ServletContextEvent event)에서 initWebApplicationContext(event.getServletContext())을 호출하여 WebApplicationContext을 만듭니다.ServletContext의 속성으로 서브렛 환경에 설정합니다.이 상하문 대상은 상하문 대상이다.ContextLoader#initWebApplicationContext(ServletContext servletContext)
    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
    
  • DispatcherServlet 초기화 과정에서 WebApplicationContext 대상을 만들고 ContextLoaderListener이 만든 상하문 대상을 부모 상하문으로 합니다.ServletContext의 속성으로도 사용됩니다.Framework Servlet#initWebApplicationContext()
    String attrName = getServletContextAttributeName();    
    getServletContext().setAttribute(attrName, wac);
    
    은 컨텍스트 객체를 작성한 후 onRefresh을 호출하여 일련의 초기화 작업을 수행합니다.Dispatcher Servlet #initStrategies (Application Context context)
    initMultipartResolver(context); 
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
    
    이 몇 가지 init 방법의 실현 사고방식은 기본적으로 같다. 먼저 Bean 용기에서 지나간 특정한 유형의 클래스의 실례이다.찾을 수 없으면 기본 설정을 사용합니다.DispatcherServlet.properties의 구성입니다.DispatcherServlet#initHandlerAdapters(ApplicationContext context)
    private void initHandlerAdapters(ApplicationContext context) {
        this.handlerAdapters = null;
    
        if (this.detectAllHandlerAdapters) {
            // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
            Map<String, HandlerAdapter> matchingBeans =
                    BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());
                // We keep HandlerAdapters in sorted order.
                //  getHandlerAdapter 
                OrderComparator.sort(this.handlerAdapters);
            }
        }
        else {
            try {
                HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
                this.handlerAdapters = Collections.singletonList(ha);
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Ignore, we'll add a default HandlerAdapter later.
            }
        }
    
        // Ensure we have at least some HandlerAdapters, by registering
        // default HandlerAdapters if no other adapters are found.
        if (this.handlerAdapters == null) {
            this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
            if (logger.isDebugEnabled()) {
                logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
            }
        }
    }
    

  • 일련의 init 방법을 거친 후 DispatcherServlet을 정식으로 초기화하여 완성하였다.

    요청 - 응답 단계

  • 요청 DispatcherServlet은 표준 Servlet입니다.GET 요청을 보내면 DispatcherServletdoGet(HttpServletRequest request, HttpServletResponse response)이 처리됩니다.Framework Servlet #doGet(Http Servlet Request request, Http Servlet Response response)
    processRequest(request, response);
    
    processRequest 단계에서 doService을 주로 호출하고 그 다음에 doDispatch을 호출합니다.
  • 처리 요청은 doDispatch에서 주로 몇 가지 작업이 있습니다.1) 먼저 getHandler을 호출하여 HandlerMapping 대상을 먼저 얻은 다음에 getHandler 방법으로 HandlerExecutionChain 대상을 되돌려줍니다.구체적으로 HandlerMapping 구현 클래스를 보십시오. 예를 들어 RequestMappingHandlerMapping Dispatcher Servlet #getHandler(Http Servlet Request request)
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }
    
    RequestMethodHandlerMapping을 예로 들 수 있습니다. 이 대상에는 HandlerMethod의 실례와 이 요청을 처리하는 차단기가 포함되어 있습니다.2) getHandlerAdapter을 호출하여 첫 번째 supports(handler)trueHandlerAdapter을 얻는다.Dispatcher Servlet #getHandler Adapter(Object handler)
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        for (HandlerAdapter ha : this.handlerAdapters) {
            if (logger.isTraceEnabled()) {
                logger.trace("Testing handler adapter [" + ha + "]");
            }
            if (ha.supports(handler)) {
                return ha;
            }
        }
        throw new ServletException("No adapter for handler [" + handler +
                "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }
    
    3)를 호출한 다음 HandlerExecutionChain#applyPreHandle(...)을 호출하여 차단기를 적용하고 preHandle 방법을 하나씩 호출합니다.Handler Execution Chain #apply Pre Handle(Http Servlet Request request, Http Servlet Response response)
    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (getInterceptors() != null) {
            for (int i = 0; i < getInterceptors().length; i++) {
                HandlerInterceptor interceptor = getInterceptors()[i];
                if (!interceptor.preHandle(request, response, this.handler)) {
                    triggerAfterCompletion(request, response, null);
                    return false;
                }
                this.interceptorIndex = i;
            }
        }
        return true;
    }   
    
    4)에 이어 HandlerAdapter.handle(...)을 호출하여 ModelAndView 대상을 받았습니다. 그 안에 데이터 대상과 구체적인View 대상이 봉인되어 있습니다.구체적인 실현은 HandlerAdapter 실현류를 살펴야 한다.예: RequestMappingHandlerAdapter.5) 그리고 HandlerExecutionChain#applyPostHandle(...)을 호출하여 차단기를 다시 적용하고 postHandle 방법을 호출한다.HandlerExecutionChain #applyPreHandleapplyPostHandle(HttpServletRequest request, HttpServletResponse response, Model AndView mv)
    void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
        if (getInterceptors() == null) {
            return;
        }
        for (int i = getInterceptors().length - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = getInterceptors()[i];
            interceptor.postHandle(request, response, this.handler, mv);
        }
    }
    
    6) 마지막 processDispatchResult 처리 결과는 클라이언트에게 상응하는 것입니다.processDispatchResult에서 render 방법인 Dispatcher Servlet #process Dispatch Result(Http Servlet Request request, Http Servlet Response response, Handler Execution Chain mapped Handler, Model AndView mv, Exception exception)
    render(mv, request, response);
    
    이 마지막으로 HandlerExecutionChain#triggerAfterCompletion(...), 차단기를 호출하는 afterCompletion 방법을 먼저 호출했습니다.차단기 처리 프로세스는 여기서 끝납니다.reader방법을 분석해 보겠습니다.먼저 resolveViewName을 호출하고 그 안에서 모든 ViewResolver의 실례를 훑어보고 resolveViewName의 방법을 호출하여 첫 번째가 비어 있지 않은 View의 실례를 되돌려줍니다.DispatcherServlet#resolveViewName(StringviewName, Map model, Localelocale, HttpServletRequest request)
    protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
            HttpServletRequest request) throws Exception {
    
        for (ViewResolver viewResolver : this.viewResolvers) {
            View view = viewResolver.resolveViewName(viewName, locale);
            if (view != null) {
                return view;
            }
        }
        return null;
    }
    
    ViewResolver#resolveViewName은 구체적으로 InternalResourceViewResolver을 참고하여 실현할 수 있다.마지막으로 Viewrender 방법을 호출합니다.render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) 방법의 구체적인 실현은 View 실현류 JstlView을 참고할 수 있다.JstlView에서 주로 renderMergedOutputModel을 호출한다. 먼저 모델 대상 데이터를 request에 설치한 다음에 RequestDispatcher을 얻어 마지막으로 forward 방법으로 클라이언트에게 응답한다.

  • 이로써 요청 - 응답 프로세스가 종료됩니다.

    참고 자료


    SpringMVC 원본 분석 Spring MVC 강좌, 빠른 입문, 심층 분석 및 SpringMVC 학습

    좋은 웹페이지 즐겨찾기