当大家了解了如何编写一个简单的Spring MVC程序后,大家心中应该会有一些好奇:这背后到底发生了什么?
Spring MVC是怎么把这些功能串联起来的?我们只是写了一个控制器而已,HTTP请求是怎么转换为控制器方法的调用的?结果又是怎么变成JSON的…..啊这小伙伴们是不是已经混乱了!?
接下来让我们看看这背后究竟发生了什么。
现代Java Web项目在处理HTTP请求时基本都遵循一样的规范,即Java Servlet规范(JSR 340)。其处理流程都是Servlet容器(例如Tomcat或Jetty)收到一个请求,接着找到合适的Servlet进行处理,随后返回响应。
在SpringMVC中,这个处理请求的Servlet就是前面提到过的DispatcherServlet。
根据配置,Servlet容器会将指定的请求都交由它来处理,在收到请求后,DispatcherServlet会在Spring容器中找到合适的处理器(大部分情况下是控制器,即带有@Controller注解的类)来处理请求,处理结果经过视图模版后得到呈现(render)的响应内容,最后再返回给用户,具体流程如下图所示:
Servlet继承图
既然DispatcherServlet是一个Servlet的实现,那就会遵循其生命过程,例如会在创建后进行初始化。
HttpServletBean.init()方法调用了子类的方法FrameworkServlet.initServletBean(),其中做了Web应用上下文的初始化,用的就是initWebApplicationContext()。
在初始化Web应用上下文或者是上下文更新时,都会调用DispatcherServlet.onRefresh(),而这个方法就一句话,直接调用initStrategies(),就是在初始化Spring MVC的很多特殊类型的Bean
Spring MVC中的特殊Bean类型
Bean类型
说明
MultipartResolver
用来解析Multipart请求的解析器,通常是上传文件的请求,MultipartResolver这层抽象的背后会有多种实现,例如基于Commons FileUpload
LocaleResolver
和语言环境有关的解析器,通常用于国际化相关的场景中,包含时区、语言等多种信息
ThemeResolver
主题(Theme)解析器,选择应用程序的外观界面,主题通常是一组静态资源
HandlerMapping
用于将请求映射到处理器上,过程中还包括各种前置与后置处理,两个主要的实现类是RequestMappingHandlerMapping和SimpleUrlHandlerMapping
Handler Adapter
用于触发执行处理器,通过这层抽象,DispatcherServler可以不用关心具体如何执行调用
HandlerExceptionResolver
异常处理解析器
ViewResolver
用于将字符串形式的视图名称转化为具体的View,RequestToViewNameTranslator会根据请求信息转换对应的视图名称
FlashMapManager
用于存取在请求暂存的输入与输出信息,通常会用在重定向时
DispatcherServlet在收到请求后,会交由doService()方法来进行处理,其中包含了两个主要的步骤:
在这里说一下,DispatcherServlet用到的设计模式是委派模式
委派模式:干活算你的(普通员工),功劳算我的(一些项目经理,他们不干活!)
例如:老板(Boss)给项目经理(Leader)下达任务,项目经理会根据实际情况给每个员工派发任务,待员工把任务完成后,再由项目经理向老板汇报结果
下表是doService()方法中设置到HttpServletRequest里的几个属性:
属性名
说明
WEB_APPLICATION_CONTEXT_ATTRIBUTE
WebApplicationContext,Web的应用上下文
LOCALE_RESOLVER_ATTRIBUTE
处理请求时可能会需要用到的LocaleResolver,如果没有国际化需求,可以忽略它
THEME_RESOLVER_ATTRIBUTE
用来决定使用哪个显示主题的ThemeResolver,如果没有这个需求,也可以忽略它
THEME_SOURCE_ATTRIBUTE
用来获取主题的ThemeSource,默认是当前的WebApplicationContext
INPUT_FLASH_MAP_ATTRIBUTE
上个请求传递过来暂存到FlashMapManager里的FlashMap
OUTPUT_FLASH_MAP_ATTRIBUTE
用来向后传递的FlashMap中的暂存信息
FLASH_MAP_MANAGER_ATTRIBUTE
如果当前存在FlashMapManager,则将它设置到请求里
doDispatch()方法的大致处理逻辑如下图,DispatcherServlet会尝试根据请求来找到合适的处理器,再通过HandlerAdapter来执行处理器的逻辑,经过前置处理、处理器处理和后置处理等多个步骤,最终返回一ModelAndView。
Request MappingHandlerAdapter是专门用来调用@RequestMapping注解标记的处理器的。在处理结果的那一步,如果有异常就处理异常,例如交给专门的HandlerExceptionResolver来处理;如果没有异常就看ModelAndView,不为空则呈现具体的视图,不存在也不用担心,因为请求可能已经处理完成了。
在调用处理器逻辑处理的过程中,针对方法的返回值,会调用HandlerMethodReturnValueHandler进行处理——根据不同的情况,会有不同实现来做处理。
例如,加了@ResponseBody的方法,返回值就直接被RequestResponseBodyMethodProcessor处理掉了,选择合适的HttpMessageConverter将对象直接序列化为相映的内容;而返回字符串作为视图名的情况,则是由ViewNameMethodReturnValueHandler来处理的。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章