内容简介:本文中我们将会看到,SpringMVC里包含的DispatcherServlet是怎样对Web程序开发产生巨大的影响的。我们作为Web应用程序的开发者,最想从以下这些枯燥乏味的工作中抽身出来,只关注真正的业务逻辑实现。
本文中我们将会看到,SpringMVC里包含的DispatcherServlet是怎样对Web程序开发产生巨大的影响的。
SpringMVC的心脏 - DispatcherSerlvet
我们作为Web应用程序的开发者,最想从以下这些枯燥乏味的工作中抽身出来,只关注真正的业务逻辑实现。
HTTP request HTTP request Model-View-Controller HTTP response
SpringMVC中的 DispatcherServlet
正正就是提供这些服务的。它是
这个核心组件接收所有传输到你应用的 HTTP request
。
并且你会看到,DispatcherServlet具有强悍的可扩展性,例如,它允许你为许多任务引入已存在的或你自定义的插件。
实现 HandlerMapping
接口
- 把一个
HTTP request
交给它真正的处理方法
实现 HandlerAdapter
接口
- 无论是普通的serlvet处理方法,还是特定的 设计模式 例如MVC工作流,又或者仅仅只是一个POJO里面的普通方法,都可以处理
HTTP request
实现 ViewResolver
接口
- 根据名称解析出views模板,并允许你使用XML/XSLT或者任意其他不同的模板引擎技术
实现 MultipartResolver
接口
- 针对文件上传类型的
multipart requests
,DispatcherServlet默认使用Apache Commons file uploading implementation (Apache通用文件上传实现)
。当然你也可以实现你自己的MultipartResolver
。
实现 LocaleResolver
接口
- 实现自己的
LocaleResolver
,通过cookie/session/已接收的HTTP头部和任意其它数据,来解析出用户所期待的语言环境。
对HTTP Request的处理
首先,让我们从Controller层中的方法开始,直到响应回用户浏览器为止,追踪一下普通的 HTTP requests
的处理过程。
DispatcherServlet
拥有非常长的继承层次;然而,从上至下一个一个地理解这些独特的层次是非常值得的:request的处理过程非常得有趣,而且理解 HTTP request
是理解MVC体系结构的关键部分(包括在标准开发期间的本地请求和远程请求)。
GenericServlet
GenericServlet是Servlet规范中的一部分,但它并不直接对接HTTP。它定义的service()方法, 只聚焦于接收进入的requests和产生responses 。
请注意:参数 (没有HTTP) ServletRequest
和 (没有HTTP) ServletResponse
:
public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
这个service()是request在一个服务器中最终会经历的方法,即便是最简单的 GET request
也会走到这里。
HttpServlet
HttpServlet也是Servlet规范中的一部分,顾名思义,它仅聚焦于HTTP。
更细节的是,HttpServlet是一个 abstract
类,它所实现的service()方法,仅仅是将 HTTP requests
进行分类:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { // ... doGet(req, resp); } else if (method.equals(METHOD_HEAD)) { // ... doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); // ... } }
HttpServletBean
再下一层,HttpServletBean是在这长串的继承关系中,第一个Spring相关的类。它从 web.xml或WebApplicationInitializer
中加载 servlet初始化参数
,并注入到bean的properties中。
这个类仅负责初始化工作,它并没有覆盖 HttpServlet
的service()方法,因为它继承了 HttpServlet
中对 HTTP requests
的处理逻辑,即仅分发 doGet/doPost/doHead
等等...
FrameworkServlet
FrameworkServlet将 Servlet功能
与 web application context
集成在一起,实现了 ApplictaionContextAware
接口,不过它也可以自己亲手创建出一个 web application context
。
前文说过,它的父类 - HttpServletBean
,把servlet初始化参数注入到bean的属性中。所以,如果serlvet参数中的 contextClass
拥有参数值,那这个 contextClass
的实例将会被创建,并被认为是一个 application context
。否则会使用默认的 XmlWebApplicationConetext
.
随着XML配置已经逐渐不再流行,SpringBoot就将上述参数默认配置为 AnnotationConfigWebApplicationContext
。
你也可以轻松地改变这个配置,例如,如果想要使用 Groovy-based application context
的话,只需在 web.xml
中配置:
dispatcherServlet org.springframework.web.servlet.DispatcherServlet contextClass org.springframework.web.context.support.GroovyWebApplicationContext
同样的效果也可以通过 Java-based
方式的 WebApplicationInitializer
做到。
DispatcherServlet: 统一处理请求
HttpServlet.service()
实现,可以通过区分 请求行为GET/POST
等,对request进行分发。这在初级的serlvets开发中是非常奏效的。然而,在SpringMVC的抽象模型中,由非常多的参数变量值来决定分发方式,而 GET/POST/PUT
等,只是这众多变量中的一小部分。
于是, FrameworkServlet
的其它主要方法,就是把众多处理逻辑再归类到一个统一的 processRequest()
方法,在 processRequest()
中最终会调用 doService()
方法:
@Override protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } @Override protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } // …
DispatcherServlet: 使Request更健壮
最终,DispatcherServlet中的 doService()
,会向request增加多个有用的属性,例如 web application context, locale resolver, theme resolver, theme source
等多个在之后的处理流程中可以拿来即用的元素:
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
另外, doService()
方法也提供了对输入和输出的 Flash Map
。Flash map基本上是一种将参数从一个请求传递到紧接着的另一个请求的模式。这在重定向期间可能非常有用(例如在重定向之后向用户显示一次性信息消息):
FlashMap inputFlashMap = this.flashMapManager .retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
之后, doService()
方法调用 doDispatch()
对请求进行分发。
DispatcherServlet:分发请求
doDispatch()
方法的主要目标:是为request找到适配的 handler(处理器)
,并将 request/response 参数
放入该处理器。这个处理器基本上可以是任意的对象,Spring并没有抽象出接口来规范这个处理器的实现方式,这同时就意味着,Spring需要找到一个 adapter(适配器)
来与这个 handler
进行通信/对话/衔接。
而为了找到适配的handler,Spring需要遍历容器内已注册的 HandlerMapping实现类
。(有非常多的不同的实现方式可供使用)
SimpleUrlHandlerMapping
可以把URL映射到专门的Controller bean。
/welcome.html=ticketController /show.html=ticketController
RequestMappingHandlerMapping
不过最广泛使用的当然是 RequestMappingHandlerMapping
,它可以将请求映射至具体的 @Controller类中的@RequestMapping方法
。
doDispatch()
方法同时进行了其它的 针对HTTP
的特别任务:
MultipartResovler
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 负载均衡 (一) 工作模式以及工作原理
- 学习,工作,养生利器 --- 番茄工作法的正确打开方式
- 性能大比拼-真实世界工作负载vs实验室综合工作负载
- [JWFD开源工作流]JWFD开源工作流-矩阵引擎设计初步
- 学完Python好找工作吗?为什么有人学完找不到工作?
- 学完Python好找工作吗?为什么有人学完找不到工作?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Elements of Statistical Learning
Trevor Hastie、Robert Tibshirani、Jerome Friedman / Springer / 2009-10-1 / GBP 62.99
During the past decade there has been an explosion in computation and information technology. With it have come vast amounts of data in a variety of fields such as medicine, biology, finance, and mark......一起来看看 《The Elements of Statistical Learning》 这本书的介绍吧!