DispatcherServlet

DispatcherServlet(前端控制器)是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。前端控制器既可以使用Filter实现(Struts2采用这种方式),也可以使用Servlet来实现(spring MVC框架)。

 ds

 

DispatcherServlet 作为前置控制器是web服务器的入口,是spring mvc最重要的一个类,通过它的生命周期可以加深对web服务器的理解。

  1)初始化阶段:调用init()方法,Servlet被装载后,Servlet容器创建一个Servlet实例并且调用Servlet的init()方法进行初始化。

     在Servlet的整个生命周期内,init()方法只被调用一次。

  2)响应客户请求阶段:调用service()方法

  3)终止阶段:调用destroy()方法

Servlet初始化阶段:

  在下列时刻Servlet容器装载Servlet:

  1)Servlet容器启动时自动装载某些Servlet,实现它只需要在web.XML文件中的<Servlet></Servlet>之间添加如下代码:  

   <loadon-startup>1</loadon-startup> 

  2)在Servlet容器启动后,客户首次向Servlet发送请求

  3)Servlet类文件被更新后,重新装载Servlet

DispatcherServlet的结构

复习了上述知识后我们来看看DispatcherServlet的结构:

DispatcherServlet继承自抽象类:FrameworkServlet,间接继承了HttpServlet (FrameworkServlet继承自HttpServletBean,而HttpServletBean继承自HttpServlet )

 

Servlet的初始化

 1     protected void initStrategies(ApplicationContext context) {
 2         initMultipartResolver(context); //文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
 3         initLocaleResolver(context);    //本地化解析
 4         initThemeResolver(context);   //主题解析
 5         initHandlerMappings(context);   //通过HandlerMapping,将请求映射到处理器
 6         initHandlerAdapters(context);   //通过HandlerAdapter支持多种类型的处理器
 7         initHandlerExceptionResolvers(context); //如果执行过程中遇到异常将交给HandlerExceptionResolver来解析
 8         initRequestToViewNameTranslator(context); //直接解析请求到视图名
 9         initViewResolvers(context);      //通过ViewResolver解析逻辑视图名到具体视图实现
10         initFlashMapManager(context);   //flash映射管理器
11     }

 

servlet如何处理请求

servlet的service方法处理http请求。

FrameworkServlet.java 定义了servlet的service和destroy方法,如下所示:

 1     protected void service(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3 
 4         String method = request.getMethod();
 5         if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {
 6             processRequest(request, response);
 7         }
 8         else {
 9             super.service(request, response);
10         }
11     }

我们知道http请求类型有七种(外加一个option选项),定义如下:

public enum RequestMethod {

GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE

}
FrameworkServlet的service()处理不同的请求,我们以常见的post来说明:
 1 protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3 
 4         long startTime = System.currentTimeMillis();
 5         Throwable failureCause = null;
 6 
 7         LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
 8         LocaleContext localeContext = buildLocaleContext(request);
 9 
10         RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
11         ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
12 
13         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
14         asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
15 
16         initContextHolders(request, localeContext, requestAttributes);
17 
18         try {
19             doService(request, response);
20         }
21         catch (ServletException ex) {
22             failureCause = ex;
23             throw ex;
24         }
25         catch (IOException ex) {
26             failureCause = ex;
27             throw ex;
28         }
29         catch (Throwable ex) {
30             failureCause = ex;
31             throw new NestedServletException("Request processing failed", ex);
32         }
33 
34         finally {
35             resetContextHolders(request, previousLocaleContext, previousAttributes);
36             if (requestAttributes != null) {
37                 requestAttributes.requestCompleted();
38             }
39 
40             if (logger.isDebugEnabled()) {
41                 if (failureCause != null) {
42                     this.logger.debug("Could not complete request", failureCause);
43                 }
44                 else {
45                     if (asyncManager.isConcurrentHandlingStarted()) {
46                         logger.debug("Leaving response open for concurrent processing");
47                     }
48                     else {
49                         this.logger.debug("Successfully completed request");
50                     }
51                 }
52             }
53 
54             publishRequestHandledEvent(request, startTime, failureCause);
55         }
56     }
FrameworkServlet 抽象定义了处理流程,留待子类来实现该方法,完成具体的请求处理。

protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
            throws Exception;

具体实现如下:
 1 protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
 2         if (logger.isDebugEnabled()) {
 3             String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
 4             logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
 5                     " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
 6         }
 7 
 8         Map<String, Object> attributesSnapshot = null;
 9         if (WebUtils.isIncludeRequest(request)) {
10             attributesSnapshot = new HashMap<String, Object>();
11             Enumeration<?> attrNames = request.getAttributeNames();
12             while (attrNames.hasMoreElements()) {
13                 String attrName = (String) attrNames.nextElement();
14                 if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
15                     attributesSnapshot.put(attrName, request.getAttribute(attrName));
16                 }
17             }
18         }
19 
20         request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
21         request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
22         request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
23         request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
24 
25         FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
26         if (inputFlashMap != null) {
27             request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
28         }
29         request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
30         request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
31 
32         try {
33             doDispatch(request, response);
34         }
35         finally {
36             if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
37                 return;
38             }
39             if (attributesSnapshot != null) {
40                 restoreAttributesAfterInclude(request, attributesSnapshot);
41             }
42         }
43     }
 

重头戏,作为请求分发器的实现:

功能:1. 把请求分发到handler(按照配置顺序获取servlet的映射关系获取handler);2. 根据servlet已安装的  HandlerAdapters 去查询第一个能处理的handler;3. handler激发处理请求

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);

                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }

                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                try {
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                }
                finally {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
                }

                applyDefaultViewName(request, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Error err) {
            triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                return;
            }
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }

 

servlet销毁

1  public void destroy() {
2         getServletContext().log("Destroying Spring FrameworkServlet '" + getServletName() + "'");
3         if (this.webApplicationContext instanceof ConfigurableApplicationContext && !this.webApplicationContextInjected) {
4             ((ConfigurableApplicationContext) this.webApplicationContext).close();
5         }
6     }

 

posted @ 2017-06-18 13:41  流浪漢  阅读(778)  评论(0编辑  收藏  举报