1. 程式人生 > >SpringMVC-HandlerMapping

SpringMVC-HandlerMapping

lin ktr lmap == pty pen throwable getclass rep

網上介紹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();
        }
    }

SpringMVC-HandlerMapping