目录
HandlerExceptionResolver:处理器异常解析器
HttpMessageConverter:http报文转换器
②:根据请求获取 HandlerExecutionChain 对象
⑤:调用 handler 实际处理请求,获取 ModelAndView 对象
SpringMVC的三大组件
DispatcherServlet:前端控制器
这是大家是最熟悉的,是一个 servlet,是 springmvc 处理请求的入口,不需要咱们开发,由框架提供。
作用:统一处理请求和响应,整个流程控制的中心,由它来调用其他组件处理用户的请求。
HandlerMapping:处理器映射器
作用:根据请求的信息(如 url、method、header 等)查找请求处理器,即找到自定义的 controller 中处理请求的方法。
HandlerMapping 接口源码如下,getHandler:根据请求查找请求处理器,会返回一个 HandlerExecutionChain 对象。
public interface HandlerMapping {
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
常见的实现类:
-
RequestMappingHandlerMapping:请求映射处理器映射,用来处理@RequestMapping 定义的处理器的
HandlerExecutionChain:处理器执行链
HandlerMapping#getHandler 方法会根据请求得到一个 HandlerExecutionChain 对象。
HandlerExecutionChain 源码如下,主要包含了 3 个信息
-
handler:请求处理器,通常就是我们自定义的 controller 对象及方法
-
interceptorList:拦截器,当前请求匹配到的拦截器列表
-
interceptorIndex:拦截器索引,用来记录执行到第几个拦截器了
public class HandlerExecutionChain {
private final Object handler;
private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
private int interceptorIndex = -1;
}
Handler:处理器
通常需要我们自己开发,一般指我们自定义的 controller,在 DispatcherServlet 的控制下 handler 对具体的请求进行处理。
HandlerAdapter:处理器适配器
他负责对 handler 的方法进行调用,由于 handler 的类型可能有很多种,每种 handler 的调用过程可能不一样,此时就需要用到适配器 HandlerAdapte,适配器对外暴露了统一的调用方式(见其 handle 方法),内部将 handler 的调用过程屏蔽了,HandlerAdapter 接口源码如下,主要有 2 个方法需要注意:
-
supports:当前 HandlerAdapter 是否支持 handler,其内部主要就是判 HandlerAdapter 是否能够处理 handler 的调用
-
handle:其内部负责调用 handler 的来处理用户的请求,返回返回一个 ModelAndView 对象
public interface HandlerAdapter {
boolean supports(Object handler);
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
常见的实现类:
-
RequestMappingHandlerAdapter:其内部用来调用@RequestMapping 标注的方法
ModelAndView:模型和视图
这个对象中主要用来存放视图的名称和共享给客户端的数据。
public class ModelAndView {
/*视图*/
@Nullable
private Object view;
/*模型,用来存放共享给客户端的数据*/
@Nullable
private ModelMap model;
}
ViewResolver:视图解析器
这个是框架提供的,不需要咱们自己开发,它负责视图解析,根据视图的名称得到对应的视图对象(View)。
ViewResolver 接口源码
public interface ViewResolver {
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
这个接口有很多实现类,比如 jsp 的、freemarker、thymeleaf 的等,他们都有各自对应的 ViewResolver。
而比较常的实现类是InternalResourceViewResolver,这个大家应该比较熟悉吧,目前为止我们前面的文章用到的都是这个视图解析器,用来处理 jsp 格式的视图页面,带大家再回顾一下这个类的配置,如下
<!-- 添加视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
InternalResourceViewResolver 比较重要,这里说下这个类的 resolveViewName 方法获取视图的过程,大家也可以去阅读InternalResourceViewResolver#resolveViewName方法获得,大致的过程如下:
step1:判断视图 viewName 是否以redirect:开头,如果是,则返回RedirectView类型的视图对象,RedirectView 是用来重定向的,RedirectView 内部用到的是response.sendRedirect(url)进行页面重定向;否则继续向下 step2
step2:判断 viewName 是否以forward:开头,如果是,则返回InternalResourceView类型的视图对象,InternalResourceView 是用来做跳转的,InternalResourceView 内部用到的是request.getRequestDispatcher(path).forward(request, response)进行页面跳转;否则继续向下 step3
step3:判断当前项目是否存在 jstl 所需的类,如果是,则返回 JstlView 类型的视图,否则返回 InternalResourceView 类型的视图,这两个视图的 render 方法最终会通过request.getRequestDispatcher(path).forward(request, response)进行页面的跳转,跳转的路径是:InternalResourceViewResolver 的前缀 prefix + viewName+InternalResourceViewResolver 的后缀 prefix
View:视图
负责将结果展示给用户,View 接口源码如下,render 方法根据指定的模型数据(model)渲染视图,即 render 方法负责将结果输出给客户端。
public interface View {
void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception;
}
View 接口常见的 2 个实现类
-
RedirectView:负责重定向的,内部通过
response.sendRedirect(url)进行页面重定向 -
InternalResourceViewResolver:负责页面跳转的,内部通过
request.getRequestDispatcher(path).forward(request, response)进行页面的跳转
HandlerExceptionResolver:处理器异常解析器
负责处理异常的,HandlerExceptionResolver 接口有个resolveException方法,用来解析异常,返回异常情况下对应的 ModelAndView 对象
public interface HandlerExceptionResolver {
@Nullable
ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
}
HttpMessageConverter:http报文转换器
将请求报文转换为 Java 对象,或将 Java 对象转换为响应报文,在处理@RequestBody、RequestEntity、@ResponseBody、ResponseEntity 的时候会用到
public interface HttpMessageConverter<T> {
/**
* 是否可以将请求报文读取给方法参数指定的类型
*/
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
/**
* 是否可以将响应的报文转换为方法参数指定的类型输出
*/
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
/**
* 当前转换器支持的类型
*/
List<MediaType> getSupportedMediaTypes();
/**
* 当前转换器支持的类型
*/
default List<MediaType> getSupportedMediaTypes(Class<?> clazz) {
return (canRead(clazz, null) || canWrite(clazz, null) ?
getSupportedMediaTypes() : Collections.emptyList());
}
/**
* 将http报文转换为给定的类型,然后返回
*/
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/**
* 将给定的对象t,转换为http报文输出到客户端
*/
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
处理流程:源码解析
请求到达入口:doDispatch
springmvc 的所有请求,最终都会到达org.springframework.web.servlet.DispatcherServlet#doDispatch这个方法,整个请求的大致处理过程都在这个方法中,咱们从这个方法开始分析
最低0.47元/天 解锁文章
1945

被折叠的 条评论
为什么被折叠?



