Spring MVC是基于组件式的Web框架,一个不同的功能点都由一个不同的组件负责,这样做的好处之一就是:各个组件分工明确、相互配合完成请求的处理和响应工作。
Spring MVC使用分派控制器模式,DispatcherServlet
提供了用于请求处理和分发的整体逻辑,而实际上的请求处理的工作是由各个可配置的组件来完成的。该模型非常灵活,并支持多种工作流程。
DispatcherServlet
也被称作前端控制器。简单的说,用户请求到达DispatcherServlet
,然后由它调用其它组件处理用户的请求,DispatcherServlet
是整个请求处理的流程控制中心,DispatcherServlet
的存在降低了组件之间的耦合性。
即处理器,它对应着MVC中的C也就是Controller,在Spring MVC框架中,它的实现有很多种,比如:
HttpServlet
类等方法,这是最传统的方式,在使用框架之后,此方式几乎不再使用了。HttpRequestHandler
接口或者继承HttpRequestHandler的实现类。@RequestMapping
注解以及使用@RequestMapping
作为元注解的注解(比如@GetMapping
、@PostMapping
、@PutMapping
、@DeleteMapping
、@PatchMapping
等)的方法。Handler中就包含我们的业务代码逻辑!
处理器映射器,用于查找能够处理请求的Handler,将请求映射为HandlerExecutionChain
对象(包含一个Handler处理器对象、多个 HandlerInterceptor
拦截器)对象。
Spring默认将加载BeanNameUrlHandlerMapping
、RequestMappingHandlerMapping
。
beanName方式。BeanNameUrlHandlerMapping
,利用Controller的beanname来作为URL映射查找对应的Handler。
BeanNameUrlHandlerMapping
只会查找采用实现了Controller接口或者继承Controller的实现类,以及实现了HttpRequestHandler
接口或者继承HttpRequestHandler
的实现类这两种方式实现的Handler。
@org.springframework.stereotype.Controller("/beanNameUrl")
public class BeanNameUrlController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
//跳转到哪个页面 mvc会走视图解析器
mv.setViewName("index.jsp");
return mv;
}
}
注解方式。RequestMappingHandlerMapping
是最常用的一个HandlerMapping
,因为它支持查找通过@RequestMapping
注解或者@RequestMapping
作为元注解的方式实现的Handler。
RequestMappingHandlerMapping
在构建HandlerExecutionChain
对象时,会在内部将对象内的handler属性的类型设置成HandlerMethod
类型。
处理器适配器,帮助 DispatcherServlet
调用请求映射到的Handler,但是不管Handler实际如何调用。将会返回一个ModelAndView
对象,其中model是一个Map结构,存放了我们返回的所有数据,view是逻辑视图名,即ViewName。如果不需要渲染视图,则可能返回null,比如application/json
请求。
通常一种类型的Handler需要一种对应的的HandlerAdapter
。
RequestMappingHandlerAdapter
主要是适配注解处理器,注解处理器就是我们经常使用@RequestMapping
注解及其作为元注解的方法处理器。HttpRequestHandlerAdapter
主要是适配静态资源处理器,静态资源处理器就是实现了HttpRequestHandler
接口或HttpRequestHandler
接口子类的类处理器,这一类处理器的作用是处理通过Spring MVC来访问的静态资源的请求。SimpleControllerHandlerAdapter
是Controller处理适配器,适配实现了Controller接口或Controller接口子类的处理器。SimpleServletHandlerAdapter
是Servlet处理适配器,适配实现了Servlet接口或Servlet的子类的处理器,我们不仅可以在web.xml
里面配置Servlet,其实也可以用SpringMVC来配置Servlet,不过这个适配器很少用到,而且Spring MVC默认的适配器没有它。异常解析器,如果在前面执行handler的过程中抛出了某个异常,将会走异常解析器的方法!在异常解析器中可以将此错误映射到其他handler、HTML 错误视图(错误页面)或统一抛出自己的异常。
自定义的异常解析器必须实现HandlerExceptionResolver
接口,并实现resolveException
方法,然后将该异常解析器配置到容器中!
public interface HandlerExceptionResolver {
/**
* 尝试解决在处理程序执行期间抛出的给定异常,返回表示特定错误的ModelAndView视图(比如一个统一的异常页面)
*
* 返回的ModelAndView可能是一个空的兑现(ModelAndView.isEmpty()返回true)
* 表示异常已成功解决,但不会呈现任何视图,例如通过设置状态代码。
*
* @param request 当前 HTTP 请求
* @param response 当前 HTTP 响应
* @param handler 执行的handler
* @param ex 在handler执行期间抛出的异常
* @return 相应的要转发到的ModelAndView,或null
*/
@Nullable
ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
}
视图解析器,ViewResolver
根据handler执行之后返回的ModelAndView
中的String类型的逻辑视图名解析成物理视图名,即具体的资源URL地址,再生成对应的View视图对象,具体的视图渲染和数据填充的工作由View视图自己完成,实际上View中也仅仅是进行了数据准备工作,最终仍然是通过调用对应的视图的API来进行视图渲染和数据填充的,而这些方法都是各种视图模版或者技术规范自身的API,并非是View实现的。
ViewResolver
接口只有一个resolveViewName
方法,用于根据给定的逻辑视图名viewName和区域(用于国际化)locale查找对应的物理视图URL位置,并将其解析为一个View视图对象!
public interface ViewResolver {
/**
* 按给定的viewName解析为View视图。
*
*
* @param viewName 要解析的视图的名称
* @param locale 解析视图的区域设置,用于支持国际化
* @return View 对象,如果找不到对应的视图,那么返回null
* @throws Exception 如果视图无法解析(通常在创建实际View视图对象时出现问题)
*/
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
Spring为我们提供了非常多的视图解析器的默认实现,例如:
BeanNameViewResolver
:在当前应用程序上下文中将逻辑视图名称解析为 bean名称,随后查找对应的名称的bean实例并返回。也就是说对应名称的bean应该是一个View
视图对象。FreeMarkerViewResolver
:将逻辑视图名称解析为FreeMarkerView
对象,说白了就是对FreeMarker
模版的支持!InternalResourceViewResolver
:使用的最广泛的一个视图解析器。将逻辑视图名称解析为InternalResourceView
对象,而InternalResourceView
则会将返回的Model模型的属性都存放到对应的request属性中,然后通过RequestDispatcher
在服务器端把请求forword到目标URL。我们知道/WEB-INF/
下面的内容是不能直接通过请求的方式请求到的,为了安全性考虑,我们通常会把jsp等资源文件放在WEB-INF
目录下,而InternalResourceViewResolver
的自动转发机制就能即安全又方便的访问这些资源了。默认的ViewResolver
就是InternalResourceViewResolver
,指定的ViewResolver
同样支持Order排序!
视图,Spring MVC框架提供了很多类型的View视图支持,包括:JstlView
、FreemarkerView
、PdfView
等,我们最常用的视图就是jsp,它对应着InternalResourceView
。
View
对象中保存了经过逻辑视图名解析出来的物理视图资源URL路径,通过View.render
方法可将返回的model数据(需要展示的数据)填充(渲染)到对应的物理视图中的对应位置,并将最终渲染完毕的页面通过response响应给客户端(比如返回拼接的HTML文本)。
public interface View {
/**
* @return Content-Type 字符串,可能包含charset
*/
@Nullable
default String getContentType() {
return null;
}
/**
* 根据给定的model数据渲染当前的view
*
* @param model 一个Map,名称作为key,值作为value
* @param request 当前请求
* @param response 响应对象
*/
void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception;
}
区域解析器,用户的区域也称为Locale,Locale信息是可以由前端直接获取的,可以根据不同的用户区域展示不同的视图,比如为不同区域的用户可以设置不同的语言和时区,也就是提供国际化视图支持。
主题解析器,主题就是系统的整体样式或风格,可通过Spring MVC框架提供的主题(theme)设置应用不同的整体样式风格,提高用户体验。Spring MVC的主题就是一些静态资源的集合,即包括样式及图片,用来控制应用的视觉风格。主题也支持国际化,同一个主题不同区域也可以显示不同的风格。
多部件解析器,用于处理上传请求,文件上传时就可以使用MultipartResolver来解析上传请求中的文件数据,方便快捷的实现文件上传!
存储并检索FlashMap,这些FlashMap可用于将属性从一个请求传递到另一个请求,通常是用在重定向中。也就是说FlashMap主要用在redirect中传递参数,而FlashMapManager则用于管理这些FlashMap。
查看Spring MVC 注解使用全解