1:多个映射器和适配器可以并存,前端控制器判断url能让哪些映射器映射以及handler被哪个适配器适配(supports),就让正确的映射器处理和适配器执行。
映射器的作用:把url和handle对应起来
适配器的作用:判断handler是什么类型的,从而执行handler,如果没有适配器DispatcherServlet是不知道执行handler的哪个方法的,所有的适配器都实现了HandlerAdapter接口。
例如:org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
要求编写的Handler实现 Controller接口。这样的handler才能被SimpleControllerHandlerAdapter这个适配器执行。如果判断适配器能否执行此handler呢?就是通过每个适配器的supports方法,看此handler是否是自己能够执行的类型。
public boolean supports(Object handler) {
return handler instanceof HttpRequestHandler;
}
注解映射器和适配器的用法
<!--注解映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!-- 使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置
mvc:annotation-driven默认加载很多的参数绑定方法,
比如json转换解析器就默认加载了,如果使用mvc:annotation-driven不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter
实际开发时使用mvc:annotation-driven
-->
<mvc:annotation-driven></mvc:annotation-driven>
如果不配置springmvc的映射器和适配器也可以使用,因为springmvc会加载默认的配置文件DispatcherServlet.properties,此文件中含有默认的多个映射器和适配器。
映射器的原理解析
每个映射器都维护了一个Map<String, Object> handlerMap对象String就是url,Object就是对应的handler对象。
Map<String, Object> handlerMap = new LinkedHashMap();
Object handler = this.handlerMap.get(urlPath);
Springmvc的执行流程
首先执行DispatcherServlet的Service方法–》doService–》doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//这里面遍历了所有的映射器找到目标handler和拦截器等信息,然后封装成HandlerExecutionChain对象返回
mappedHandler = this.getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
//遍历所有的适配器,获取handler对应的适配器对象,用于后面执行handler
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (this.logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
this.logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
//遍历匹配此url的所有HandlerInterceptor拦截器,遍历所有拦截器的前置方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
try {
//适配器执行目标handler返回ModelAndView 对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
//如果视图没有再次设置
this.applyDefaultViewName(request, mv);
//遍历匹配此url的所有HandlerInterceptor拦截器,遍历所有拦截器的后置方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var28) {
dispatchException = var28;
}
//通过视图解析器获取视图并渲染。
this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception var29) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var29);
} catch (Error var30) {
this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var30);
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
} else {
if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
}
HandlerExecutionChain源码
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
private final Object handler;
private HandlerInterceptor[] interceptors;
private List<HandlerInterceptor> interceptorList;
private int interceptorIndex;
public HandlerExecutionChain(Object handler) {
this(handler, (HandlerInterceptor[])null);
}
public HandlerExecutionChain(Object handler, HandlerInterceptor[] interceptors) {
this.interceptorIndex = -1;
if (handler instanceof HandlerExecutionChain) {
HandlerExecutionChain originalChain = (HandlerExecutionChain)handler;
this.handler = originalChain.getHandler();
this.interceptorList = new ArrayList();
CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
} else {
this.handler = handler;
this.interceptors = interceptors;
}
}
public Object getHandler() {
return this.handler;
}
public void addInterceptor(HandlerInterceptor interceptor) {
this.initInterceptorList();
this.interceptorList.add(interceptor);
}
public void addInterceptors(HandlerInterceptor[] interceptors) {
if (interceptors != null) {
this.initInterceptorList();
this.interceptorList.addAll(Arrays.asList(interceptors));
}
}
private void initInterceptorList() {
if (this.interceptorList == null) {
this.interceptorList = new ArrayList();
}
if (this.interceptors != null) {
this.interceptorList.addAll(Arrays.asList(this.interceptors));
this.interceptors = null;
}
}
public HandlerInterceptor[] getInterceptors() {
if (this.interceptors == null && this.interceptorList != null) {
this.interceptors = (HandlerInterceptor[])this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
}
return this.interceptors;
}
//进入 Handler方法之前执行
//用于身份认证、身份授权
//比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (this.getInterceptors() != null) {
//注意此时的i是从0开始的
for(int i = 0; i < this.getInterceptors().length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = this.getInterceptors()[i];
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
//进入Handler方法之后,返回modelAndView之前执行
//应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
if (this.getInterceptors() != null) {
//此处的i是从数组最后一位开始的
for(int i = this.getInterceptors().length - 1; i >= 0; --i) {
HandlerInterceptor interceptor = this.getInterceptors()[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
//执行Handler完成执行此方法
//应用场景:统一异常处理,统一日志处理
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
if (this.getInterceptors() != null) {
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = this.getInterceptors()[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var7) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var7);
}
}
}
}
void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
if (this.getInterceptors() != null) {
for(int i = this.getInterceptors().length - 1; i >= 0; --i) {
if (this.interceptors[i] instanceof AsyncHandlerInterceptor) {
try {
AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor)this.interceptors[i];
asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
} catch (Throwable var5) {
logger.error("Interceptor [" + this.interceptors[i] + "] failed in afterConcurrentHandlingStarted", var5);
}
}
}
}
}
public String toString() {
if (this.handler == null) {
return "HandlerExecutionChain with no handler";
} else {
StringBuilder sb = new StringBuilder();
sb.append("HandlerExecutionChain with handler [").append(this.handler).append("]");
if (!CollectionUtils.isEmpty(this.interceptorList)) {
sb.append(" and ").append(this.interceptorList.size()).append(" interceptor");
if (this.interceptorList.size() > 1) {
sb.append("s");
}
}
return sb.toString();
}
}
}
一个请求首先要经过Filter链的过滤,然后如果使用springmvc作为前端控制器还要经过springmvc的拦截器(interceptor)的拦截,最后目标对象如果符合AOP的切入点,生成代理对象,那么还要经过AOP的过滤。