网上介绍HandlerMapping的文章很多,今天我用自己的理解和语言来介绍下HandlerMapping
一. HandlerMapping的作用和背景:
SpringMVC的M、V、C就不说了,HandlerMapping就是用来存放用户Request(具体可以理解为一个请求URL)和处理具体请求的Handler中的method关系的地方,例如:将/query?id=XXX的请求交给XXXService.queryById(int id)这个方法来处理。
二. HandlerMapping的构成:
在Spring源码中,HandlerMapping含有HandlerExcutionChain对象,HandlerExcutionChain是由Handler和拦截器组成。有兴趣可以看下源代码,这里我仍然用自己的理解和语言来描述。
HandlerExcutionChain你可以理解为一个对象,它是由Object(实际上就是Controller)、URL Pattern(URL的封装)和Method组成(具体对应的就是HandlerExcutionChain中的handler、interceptors),或者你可以这么理解,List<HandlerMapping>=List<new MyHandlerMapping(handler,method,url)>。
其中handler就是Controller,是SpringMVC中所有的Controller(例如:加上@Controller的类),可以循环context中所有BeanName对应的Bean,判断Bean对象是否有@Controller标签来实现。
method就是Controller中具体执行请求的方法,通过循环Bean中的所有method。
url就是把Controller和method的@RequestMapping拼起来。
// HandlerMapping源码 public interface HandlerMapping { String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping"; String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern"; String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping"; String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables"; String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables"; String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes"; HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception; } // HandlerExcutionChain源码 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().add(interceptor); } public void addInterceptors(HandlerInterceptor... interceptors) { if (!ObjectUtils.isEmpty(interceptors)) { CollectionUtils.mergeArrayIntoCollection(interceptors, this.initInterceptorList()); } } private List<HandlerInterceptor> initInterceptorList() { if (this.interceptorList == null) { this.interceptorList = new ArrayList(); if (this.interceptors != null) { CollectionUtils.mergeArrayIntoCollection(this.interceptors, this.interceptorList); } } this.interceptors = null; return this.interceptorList; } public HandlerInterceptor[] getInterceptors() { if (this.interceptors == null && this.interceptorList != null) { this.interceptors = (HandlerInterceptor[])this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]); } return this.interceptors; } boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(request, response, this.handler)) { this.triggerAfterCompletion(request, response, (Exception)null); return false; } } } return true; } void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = interceptors.length - 1; i >= 0; --i) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(request, response, this.handler, mv); } } } void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = this.interceptorIndex; i >= 0; --i) { HandlerInterceptor interceptor = interceptors[i]; try { interceptor.afterCompletion(request, response, this.handler, ex); } catch (Throwable var8) { logger.error("HandlerInterceptor.afterCompletion threw exception", var8); } } } } void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = interceptors.length - 1; i >= 0; --i) { if (interceptors[i] instanceof AsyncHandlerInterceptor) { try { AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor)interceptors[i]; asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler); } catch (Throwable var6) { logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", var6); } } } } } public String toString() { Object handler = this.getHandler(); if (handler == null) { return "HandlerExecutionChain with no handler"; } else { StringBuilder sb = new StringBuilder(); sb.append("HandlerExecutionChain with handler [").append(handler).append("]"); HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { sb.append(" and ").append(interceptors.length).append(" interceptor"); if (interceptors.length > 1) { sb.append("s"); } } return sb.toString(); } } }
按照自己理解写的intiHandlerMapping()方法:
private void initHandlerMappings(ApplicationContext context) { //首先从容器中取到所有的实例 String[] beanNames = context.getBeanDefinitionNames(); try { for (String beanName : beanNames) { Object controller = context.getBean(beanName); Class<?> clazz = controller.getClass(); //但是不是所有的牛奶都叫特仑苏,只有带有@Controller的才处理 if (!clazz.isAnnotationPresent(Controller.class)) { continue; } String baseUrl = ""; if (clazz.isAnnotationPresent(RequestMapping.class)) { RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class); baseUrl = requestMapping.value(); } //扫描所有的public方法 Method[] methods = clazz.getMethods(); for (Method method : methods) { if (!method.isAnnotationPresent(RequestMapping.class)) { continue; } RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); String regex = ("/" + baseUrl + requestMapping.value().replaceAll("\\*", ".*")).replaceAll("/+", "/"); Pattern pattern = Pattern.compile(regex); this.handlerMappings.add(new HandlerMapping(pattern, controller, method)); System.out.println("Mapping: " + regex + " , " + method); } } } catch (Exception e) { e.printStackTrace(); } }