这里说的组件指的是DispatcherServlet中直接初始化的那9个组件;
HandlerMapping
HandlerMapping的作用是根据request找到相应的处理器Handler和Interceptors;
HandlerMapping接口里面只有一个方法,方法的实现非常灵活,只要使用Request返回HandlerExecutionChain即可;
你可以把HandlerExecutionChain看做是Handler+Interceptors;
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
HandlerMapping需要注册到Spring MVC的容器里面才可以使用,注册也很简单,只需要在配置文件里面配置一个Bean就可以了,Spring MVC会按照类型将它注册到HandlerMapping中;
可能有多个HandlerMapping可以处理同个url,可以用order标注优先级,order越小越先使用;
查找Handler是按顺序遍历所有的HandlerMapping,当找到一个HandlerMapping后立即停止查找并返回;
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping hm : this.handlerMappings) {
......
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler; //立即返回
}
}
}
return null;
}
HandlerAdapter
可以理解为使用Handler的人;它里面共有三个方法,
supports(Object handler)判断是否可以使用某个Handler;
handler方法是用来具体使用Handler干活的;
getLastModified是获取资源的Last-Modified,Last-Modified是资源最后一次修改的时间;
public interface HandlerAdapter {
boolean supports(Object handler); //注意:是Object类型
ModeAndView handle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception;
long getLastModified(HttpServletRequest request,Object handler);
}
之所以要使用HandlerAdapter是因为Spring MVC中并没有对Handler做任何限制,Handler可以以任意合理的方式来实现,可以是个类,也可以是个方法,还可以是别的合理的形式;从supports方法的参数是Object类型就可以看出这一点;
//这是Spring MVC自带的HandlerAdapter
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller); //实现了Controller接口的Handler
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//直接调用handleRequest方法
return ((Controller) handler).handleRequest(request, response);
}
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}
选择使用哪个HandlerAdapter的过程在getHandlerAdapter方法中,它的逻辑是遍历所有的Adapter,然后检查哪个可以处理当前的Handler,找到第一个可以处理Handler的Adapter后就停止查找并将其返回;既然查找,那肯定有个顺序,这顺序也是通过Order属性来设置的;
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter ha : this.handlerAdapters) {
......
if (ha.supports(handler)) {
return ha;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
HandlerAdapter需要注册到Spring MVC的容器里,注册方法和HandlerMapping一样,只要配置一个Bean就可以了;Handler是从HandlerMapping里返回的;
HandlerExceptionResolver
处理异常,根据异常设置ModelAndView,之后再交给render方法进行渲染;render只负责将ModelAndView渲染成页面,具体ModelAndView从哪里来的不重要;
从doDispatcher的分析可以知道,HandlerExceptionResolver只是用于解析对请求做处理的过程中产生的异常,而渲染环节产生的异常不归它管,现在我们知道原因了:它是在render之前工作的,先解析出ModelAndView之后render才去渲染,当然它就不能处理render过程中的异常了;
public interface HandlerExceptionResolver {
//异常--> ModelAndView
@Nullable
ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
}
具体实现上,维护一个异常为key,View为value的Map,解析的时候直接从Map里获取View就可以了,如果在Map里没有相应的异常可以返回默认的View;我们可以在这个View上显示一些关于错误的细节;
ViewResolver
ViewResolver将String类型的视图名和Locale解析为View;
public interface ViewResolver {
//视图名和Locale,不过一般情况下,只需要根据视图名找到对应的视图,然后渲染就行了
//locale,是用来达到,不同地区使用不同的View,一般用不到
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
ViewResolver的使用需要注册到Spring MVC的容器中,默认使用的是org.spring.framework.web.servlet.view.InternalResourceViewResolver;
RequestToViewNameTranslator
ViewResolver是根据ViewName查找View,但有的Handler处理完成之后并没有设置View也没有设置viewName,这时就需要从request中获取viewName,而如何从request中获取ViewName就是RequestToViewNameTranslator要做的事情;
public interface RequestToViewNameTranslator {
String getViewName(HttpServletRequest request) throws Exception;
}
FlashMapManager
FlashMap主要用在redirect中传递参数,而FlashMapManager是用来管理FlashMap的;
public interface FlashMapManager {
//恢复参数,并将恢复过额度和超时的参数从FlashMap中删除
@Nullable
FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);
//将参数保存起来
void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
}
默认实现是SessionFlashMapManager,它是将参数保存到session中;