SpringMVC-HandlerMapping和HandlerAdapter

网上介绍HandlerMapping和HandlerAdapter的文章很多,今天我用自己的理解和语言来介绍下HandlerMapping和HandlerAdapter

一. HandlerMapping和HandlerAdapter的作用和背景:

SpringMVC的M、V、C就不说了,HandlerMapping就是用来存放用户Request(具体可以理解为一个请求URL)和处理具体请求的Handler中的method关系的地方,例如:将/query?id=XXX的请求交给XXXService.queryById(int id)这个方法来处理。

真正调用一个方法,首先必须找到方法定义,然后传入实参。HandlerMapping是用来映射URL和method的关系的话,HandlerAdapter是用来负责传递方法的实参。

二. HandlerMapping和HandlerAdapter的构成:

在Spring源码中,HandlerMapping含有HandlerExcutionChain对象,HandlerExcutionChain是由Handler和拦截器组成。有兴趣可以看下源代码,这里我仍然用自己的理解和语言来描述。

HandlerExcutionChain你可以理解为一个对象,它是由Object(实际上就是Controller)、URL Pattern(URL的封装)和Method组成(具体对应的就是HandlerExcutionChain中的handler、interceptors),或者你可以这么理解HandlerMapping就是List<MyHandlerMapping(handler,method,url)>,URL请求交给Controller的method()来处理。

其中handler就是SpringMVC中所有的Controller(例如:加上@Controller的类),可以循环context中所有BeanName对应的Bean,判断Bean对象是否有@Controller标签来实现。method就是Controller中具体执行请求的方法,通过循环Bean中的所有method,判断是否有@RequestMapping的value和请求的url是否匹配。url就是把Controller和method的@RequestMapping拼起来。

HandlerAdapter是用来存放调用Controller的method时传入的形参类型,在SpringMVC中参数都是在请求URL上带入的。我们可以把HandlerAdapter理解为一个Map<HandlerMapping,paramMapping<position index,param type>>,其中HandlerMapping是用来保存请求的URL和Controller的method之间的关系,paramMapping用来保存该HandlerMapping.method的形参类型(paramMapping的key是position index,value是param type)

// 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();
        }
    }
原文地址:https://www.cnblogs.com/panning/p/9744708.html