springMVC源码简读——2.2 HandlerMapping的解析器(下)

    xiaoxiao2021-04-15  241

    下主要介绍的是基于方法的接口实现类,以及对应的拦截器

    实现类-基于 Method 进行匹配

    AbstractHandlerMethodMapping

    继承 AbstractHandlerMapping 抽象类,以 Method 作为 Handler 的 HandlerMapping 抽象类,提供 Mapping 的初始化、注册等通用的骨架方法

    构造方法

    // AbstractHandlerMethodMapping.java /** * Mapping 命名策略 */ @Nullable private HandlerMethodMappingNamingStrategy<T> namingStrategy; /** * Mapping 注册表 */ private final MappingRegistry mappingRegistry = new MappingRegistry(); MappingRegistry @FunctionalInterface public interface HandlerMethodMappingNamingStrategy<T> { /** * Determine the name for the given HandlerMethod and mapping. * @param handlerMethod the handler method * @param mapping the mapping * @return the name * 根据映射和处理方法,获得名字 */ String getName(HandlerMethod handlerMethod, T mapping); } RequestMappingInfoHandlerMethodMappingNamingStrategy实现了此接口 public String getName(HandlerMethod handlerMethod, RequestMappingInfo mapping) { // 情况一,请求映射对象名字非空,则使用 mapping 的名字 if (mapping.getName() != null) { return mapping.getName(); } // 情况二,使用类名大写 + "#" + 方法名 StringBuilder sb = new StringBuilder(); // 获得类型的名字 String simpleTypeName = handlerMethod.getBeanType().getSimpleName(); for (int i = 0; i < simpleTypeName.length(); i++) { // 假如大写就添加进来 if (Character.isUpperCase(simpleTypeName.charAt(i))) { sb.append(simpleTypeName.charAt(i)); } } sb.append(SEPARATOR).append(handlerMethod.getMethod().getName()); return sb.toString(); }

    createHandlerMethod

    使用处理器和方法对象创建HandlerMethod 对象

    // AbstractHandlerMethodMapping.java protected HandlerMethod createHandlerMethod(Object handler, Method method) { HandlerMethod handlerMethod; // 如果 handler 类型为 String, 说明对应一个 Bean 对象, // 例如 UserController 使用 @Controller 注解后, // 默认 handler 为它的 beanName ,即 `userController` if (handler instanceof String) { String beanName = (String) handler; handlerMethod = new HandlerMethod(beanName, obtainApplicationContext().getAutowireCapableBeanFactory(), method); } // 如果 handler 类型非 String ,说明是一个已经是一个 handler 对象, // 就无需处理,直接创建 HandlerMethod 对象 else { handlerMethod = new HandlerMethod(handler, method); } return handlerMethod; }

    MappingRegistration

    mapping注册登记

    构造方法
    // AbstractHandlerMethodMapping.java /** * Mapping 对象 */ private final T mapping; /** * HandlerMethod 对象 */ private final HandlerMethod handlerMethod; /** * url数组 */ private final List<String> directUrls; /** * {@link #mapping} 的名字 */ @Nullable private final String mappingName;

    MappingRegistry

    mapping的注册表

    构造方法
    // AbstractHandlerMethodMapping.java /** * mapping注册表 和mapping的映射关系 * key mapping */ private final Map<T, MappingRegistration<T>> registry = new HashMap<>(); /** * 注册表2 * key mapping */ private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>(); /** * 直接 URL 的映射 * KEY:直接 URL * VALUE:Mapping 数组 */ private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>(); /** * Mapping 的名字与 HandlerMethod 的映射 * KEY:Mapping 的名字 * VALUE:HandlerMethod 数组 */ private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
    register

    注册相关内容

    public void register(T mapping, Object handler, Method method) { // 获得写锁 this.readWriteLock.writeLock().lock(); try { // 创建 HandlerMethod 对象 HandlerMethod handlerMethod = createHandlerMethod(handler, method); // 校验当前 mapping 不存在,否则抛出 IllegalStateException 异常 assertUniqueMethodMapping(handlerMethod, mapping); // 添加 mapping + HandlerMethod 到 mappingLookup 中 // 注册mapping和handlerMethod this.mappingLookup.put(mapping, handlerMethod); // 获得 mapping 对应的普通 URL 数组 List<String> directUrls = getDirectUrls(mapping); // 添加到 url + mapping 到 urlLookup 集合中 for (String url : directUrls) { // 注册 url 和 mapping this.urlLookup.add(url, mapping); } // 初始化 nameLookup String name = null; if (getNamingStrategy() != null) { // 获得 Mapping 的名字 name = getNamingStrategy().getName(handlerMethod, mapping); // 添加到 mapping 的名字 + HandlerMethod 到 nameLookup 中 // Mapping 的名字与 HandlerMethod 的映射 addMappingName(name, handlerMethod); } CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null) { // 注册 this.corsLookup.put(handlerMethod, corsConfig); } // 创建 MappingRegistration 对象, // 并 mapping + MappingRegistration 添加到 registry 中 this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name)); } finally { // 释放写锁 this.readWriteLock.writeLock().unlock(); } }

    完成 mapping、HandlerMethod、NamingStrategy关系的注册

    unregister

    取消注册的方法

    // AbstractHandlerMethodMapping.java public void unregister(T mapping) { // 获得锁 this.readWriteLock.writeLock().lock(); try { // 从 registry 中移除 MappingRegistration<T> definition = this.registry.remove(mapping); if (definition == null) { return; } // 从 mappingLookup 中移除 this.mappingLookup.remove(definition.getMapping()); // 从 urlLookup 移除 for (String url : definition.getDirectUrls()) { List<T> list = this.urlLookup.get(url); if (list != null) { list.remove(definition.getMapping()); if (list.isEmpty()) { this.urlLookup.remove(url); } } } // 从 nameLookup 移除 removeMappingName(definition); // 从 corsLookup 中移除 this.corsLookup.remove(definition.getHandlerMethod()); } finally { // 释放锁 this.readWriteLock.writeLock().unlock(); } }

    依次移除

    registrymappingLookupurlLookupnameLookupcorsLookup

    afterPropertiesSet

    真正进行初始化的代码

    // AbstractHandlerMethodMapping.java // 真正的初始化在initHandlerMethods protected void initHandlerMethods() { // 遍历 Bean ,逐个处理 for (String beanName : getCandidateBeanNames()) { // 主要bean名字不是以scopedTarget开头 if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { // 处理 Bean processCandidateBean(beanName); } } // 初始化处理器的方法们。目前是空方法,暂无具体的实现 handlerMethodsInitialized(getHandlerMethods()); }
    processCandidateBean

    对扫描过来的bean进行进一步处理,

    // AbstractHandlerMethodMapping.java protected void processCandidateBean(String beanName) { // 获得 Bean 对应的类型 Class<?> beanType = null; try { beanType = obtainApplicationContext().getType(beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - let's ignore it. if (logger.isTraceEnabled()) { logger.trace("Could not resolve type for bean '" + beanName + "'", ex); } } // 判断 Bean 是否为处理器,如果是,则扫描处理器方法 if (beanType != null && isHandler(beanType)) { detectHandlerMethods(beanName); } }

    detectHandlerMethods

    假如扫描的出的bean为处理器,则进行进一步处理

    // AbstractHandlerMethodMapping.java protected void detectHandlerMethods(Object handler) { // 获得处理器 Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { // 获得真实的类,因为handlerType 可能是代理类 Class<?> userType = ClassUtils.getUserClass(handlerType); // 获得匹配的方法的集合 Map<Method, T> methods = MethodIntrospector.selectMethods(userType, // 抽象方法,子类实现,根据方法和 (MethodIntrospector.MetadataLookup<T>) method -> { try { return getMappingForMethod(method, userType); } catch (Throwable ex) { throw new IllegalStateException("Invalid mapping on handler class [" + userType.getName() + "]: " + method, ex); } }); if (logger.isTraceEnabled()) { logger.trace(formatMappings(userType, methods)); } // 遍历方法,逐个注册 HandlerMethod methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); registerHandlerMethod(handler, invocableMethod, mapping); }); } }

    getHandlerInternal

    获得请求对应的HanderMethod对象

    // AbstractHandlerMethodMapping.java protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { // 获得请求的路径 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); // 获得写锁 this.mappingRegistry.acquireReadLock(); try { // 获得 HandlerMethod 对象 HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } }
    lookupHandlerMethod

    如果通过路径和请求获得HandlerMethod 对象,核心逻辑之一,根据路径和请求获得处理器方法对象

    // AbstractHandlerMethodMapping.java protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { // Match 数组,存储匹配上当前请求的结果 List<Match> matches = new ArrayList<>(); // 优先,基于直接 URL 的 Mapping 们,进行匹配 List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { addMatchingMappings(directPathMatches, matches, request); } // 其次,扫描注册表的 Mapping 们,进行匹配 if (matches.isEmpty()) { // No choice but to go through all mappings... addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); } // 如果匹配到,则获取最佳匹配的 Match 对象的 handlerMethod 属性 if (!matches.isEmpty()) { // 创建 MatchComparator 对象,排序 matches 结果 Comparator<Match> comparator = new MatchComparator(getMappingComparator(request)); matches.sort(comparator); // 获得首个 Match 对象 Match bestMatch = matches.get(0); // 处理存在多个 Match 对象的情况!! if (matches.size() > 1) { if (logger.isTraceEnabled()) { logger.trace(matches.size() + " matching mappings: " + matches); } if (CorsUtils.isPreFlightRequest(request)) { return PREFLIGHT_AMBIGUOUS_MATCH; } // 比较 bestMatch 和 secondBestMatch ,如果相等,说明有问题,抛出 IllegalStateException 异常 // 因为,两个优先级一样高,说明无法判断谁更优先 Match secondBestMatch = matches.get(1); if (comparator.compare(bestMatch, secondBestMatch) == 0) { Method m1 = bestMatch.handlerMethod.getMethod(); Method m2 = secondBestMatch.handlerMethod.getMethod(); String uri = request.getRequestURI(); throw new IllegalStateException( "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}"); } } request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); // 处理首个 Match 对象 handleMatch(bestMatch.mapping, lookupPath, request); // 返回首个 Match 对象的 handlerMethod 属性 return bestMatch.handlerMethod; } // 如果匹配不到,则处理不匹配的情况 else { return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }

    RequestMappingInfoHandlerMapping

    继承 AbstractHandlerMethodMapping 抽象类,其中泛型被设置为RequestMappingInfo,则mapping其实就是RequestMappingInfo

    RequestMappingInfo

    实现 RequestCondition 接口,请求匹配信息

    构造方法

    一堆的属性

    // RequestMappingInfo.java /** * 名字 */ @Nullable private final String name; /** * 请求路径的条件 */ private final PatternsRequestCondition patternsCondition; /** * 请求方法的条件 */ private final RequestMethodsRequestCondition methodsCondition; /** * 参数的条件 */ private final ParamsRequestCondition paramsCondition; /** * 请求头的条件 */ private final HeadersRequestCondition headersCondition; /** * 可消费的 Content-Type 的条件 */ private final ConsumesRequestCondition consumesCondition; /** * 可生产的 Content-Type 的条件 */ private final ProducesRequestCondition producesCondition; /** * 自定义的条件 */ private final RequestConditionHolder customConditionHolder;
    getMatchingCondition

    从当前 RequestMappingInfo 获得匹配的条件。如果匹配,则基于其匹配的条件,创建新的 RequestMappingInfo 对象。如果不匹配,则返回 null

    // RequestMappingInfo.java public RequestMappingInfo getMatchingCondition(HttpServletRequest request) { RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request); if (methods == null) { return null; } ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request); if (params == null) { return null; } HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request); if (headers == null) { return null; } ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request); if (consumes == null) { return null; } ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request); if (produces == null) { return null; } PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request); if (patterns == null) { return null; } RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request); if (custom == null) { return null; } // 创建匹配的 RequestMappingInfo 对象。 return new RequestMappingInfo(this.name, patterns, methods, params, headers, consumes, produces, custom.getCondition()); }

    getMatchingMapping

    获得请求对应的 RequestMappingInfo 对象

    // RequestMappingInfoHandlerMapping.java // 底层逻辑使用的是 RequestMappingInfo的getMatchingCondition info.getMatchingCondition(request)

    getMappingPathPatterns

    获得 Mapping 对应的请求路径集合

    // RequestMappingInfoHandlerMapping.java // 底层逻辑是获得RequestMappingInfo的 private final PatternsRequestCondition patternsCondition;

    handleMatch

    覆写父类的方法,设置更多的属性给request

    // RequestMappingInfoHandlerMapping.java protected void handleMatch(RequestMappingInfo info, String lookupPath, HttpServletRequest request) { super.handleMatch(info, lookupPath, request); // 获得 bestPattern 和 uriVariables // 最佳路径 String bestPattern; // 路径上的变量集合 Map<String, String> uriVariables; Set<String> patterns = info.getPatternsCondition().getPatterns(); if (patterns.isEmpty()) { bestPattern = lookupPath; uriVariables = Collections.emptyMap(); } else { bestPattern = patterns.iterator().next(); uriVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath); } request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern); // 设置 MATRIX_VARIABLES_ATTRIBUTE 属性,到请求中 if (isMatrixVariableContentAvailable()) { Map<String, MultiValueMap<String, String>> matrixVars = extractMatrixVariables(request, uriVariables); request.setAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, matrixVars); } // 设置 URI_TEMPLATE_VARIABLES_ATTRIBUTE 属性,到请求中 Map<String, String> decodedUriVariables = getUrlPathHelper().decodePathVariables(request, uriVariables); request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, decodedUriVariables); // 设置 PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE 属性,到请求中 if (!info.getProducesCondition().getProducibleMediaTypes().isEmpty()) { Set<MediaType> mediaTypes = info.getProducesCondition().getProducibleMediaTypes(); request.setAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, mediaTypes); } }

    handleNoMatch

    覆写父类方法,处理无匹配 Mapping 的情况

    // RequestMappingInfoHandlerMapping.java protected HandlerMethod handleNoMatch( Set<RequestMappingInfo> infos, String lookupPath, HttpServletRequest request) throws ServletException { // 创建 PartialMatchHelper 对象,解析可能的错误 PartialMatchHelper helper = new PartialMatchHelper(infos, request); if (helper.isEmpty()) { return null; } // 方法错误 if (helper.hasMethodsMismatch()) { Set<String> methods = helper.getAllowedMethods(); if (HttpMethod.OPTIONS.matches(request.getMethod())) { HttpOptionsHandler handler = new HttpOptionsHandler(methods); return new HandlerMethod(handler, HTTP_OPTIONS_HANDLE_METHOD); } throw new HttpRequestMethodNotSupportedException(request.getMethod(), methods); } // 可消费的 Content-Type 错误 if (helper.hasConsumesMismatch()) { Set<MediaType> mediaTypes = helper.getConsumableMediaTypes(); MediaType contentType = null; if (StringUtils.hasLength(request.getContentType())) { try { contentType = MediaType.parseMediaType(request.getContentType()); } catch (InvalidMediaTypeException ex) { throw new HttpMediaTypeNotSupportedException(ex.getMessage()); } } throw new HttpMediaTypeNotSupportedException(contentType, new ArrayList<>(mediaTypes)); } // 可生产的 Content-Type 错误 if (helper.hasProducesMismatch()) { Set<MediaType> mediaTypes = helper.getProducibleMediaTypes(); throw new HttpMediaTypeNotAcceptableException(new ArrayList<>(mediaTypes)); } // 参数错误 if (helper.hasParamsMismatch()) { List<String[]> conditions = helper.getParamConditions(); throw new UnsatisfiedServletRequestParameterException(conditions, request.getParameterMap()); } return null; }

    RequestMappingHandlerMapping

    基于 @RequestMapping 注解来构建 RequestMappingInfo 对象 设置各种错误信息

    构造方法

    // RequestMappingHandlerMapping.java /** * 使用后缀模式匹配 */ private boolean useSuffixPatternMatch = true; /** * 使用后缀模式匹配注册 */ private boolean useRegisteredSuffixPatternMatch = false; /** * 使用 / 匹配 */ private boolean useTrailingSlashMatch = true; /** * 路径匹配 */ private Map<String, Predicate<Class<?>>> pathPrefixes = new LinkedHashMap<>(); /** * RequestMappingInfo 构造器 */ private RequestMappingInfo.BuilderConfiguration config = new RequestMappingInfo.BuilderConfiguration();

    afterPropertiesSet

    为 RequestMappingInfo.BuilderConfiguration 设置参数

    // RequestMappingHandlerMapping.java public void afterPropertiesSet() { this.config = new RequestMappingInfo.BuilderConfiguration(); this.config.setUrlPathHelper(getUrlPathHelper()); this.config.setPathMatcher(getPathMatcher()); this.config.setSuffixPatternMatch(this.useSuffixPatternMatch); this.config.setTrailingSlashMatch(this.useTrailingSlashMatch); this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch); this.config.setContentNegotiationManager(getContentNegotiationManager()); super.afterPropertiesSet(); }

    isHandler

    判断是否为处理器,这里可以看到对于spring来说,Controller和RequestMapping会被认为是处理器,那么我们上面所说的处理器的方法就是,controller内的方法

    // RequestMappingHandlerMapping.java return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));

    getMappingForMethod

    获得方法上的 RequestMappingInfo 对象,其实就是获得RequestMapping的参数

    // RequestMappingHandlerMapping.java protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) { // 基于方法上的 @RequestMapping 注解,创建 RequestMappingInfo 对象 RequestMappingInfo info = createRequestMappingInfo(method); if (info != null) { // 基于类上的 @RequestMapping 注解,合并进去 RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); if (typeInfo != null) { info = typeInfo.combine(info); } // 如果有前缀,则设置到 info 中 String prefix = getPathPrefix(handlerType); if (prefix != null) { info = RequestMappingInfo.paths(prefix).build().combine(info); } } return info; }

    match

    执行匹配

    // RequestMappingHandlerMapping.java public RequestMatchResult match(HttpServletRequest request, String pattern) { // 创建 RequestMappingInfo 对象 RequestMappingInfo info = RequestMappingInfo.paths(pattern).options(this.config).build(); // 获得匹配的 新的 RequestMappingInfo 对象 RequestMappingInfo matchingInfo = info.getMatchingCondition(request); // 如果不匹配,则返回 nul if (matchingInfo == null) { return null; } // 从新的RequestMappingInfo 获得对应的请求路径的集合 Set<String> patterns = matchingInfo.getPatternsCondition().getPatterns(); // 获得请求的路径 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); // 创建 RequestMatchResult 结果,请求匹配的结果 return new RequestMatchResult(patterns.iterator().next(), lookupPath, getPathMatcher()); }

    拦截器

    概述

    在AbstractHandlerMapping.java中初始化的是有这一一段代码

    protected void initApplicationContext() throws BeansException { // 空方法。交给子类实现,用于注册自定义的拦截器到 interceptors 中。目前暂无子类实现。 extendInterceptors(this.interceptors); // 扫描已注册的 MappedInterceptor 的 Bean 们,添加到 mappedInterceptors 中 detectMappedInterceptors(this.adaptedInterceptors); // 将 interceptors 初始化成 HandlerInterceptor 类型,添加到 mappedInterceptors 中 initInterceptors(); }

    作为HandlerMapping后续实现类的基类,初始化的时候都会初始一系列处理器的拦截器进去

    顶级接口

    public interface HandlerInterceptor { /** * 拦截处理器,在 {@link HandlerAdapter#handle(HttpServletRequest, HttpServletResponse, Object)} 执行之前 */ default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } /** * 拦截处理器,在 {@link HandlerAdapter#handle(HttpServletRequest, HttpServletResponse, Object)} 执行成功之后 */ default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } /** * 拦截处理器,在 {@link HandlerAdapter} 执行完之后,无论成功还是失败 * 并且,只有 {@link #preHandle(HttpServletRequest, HttpServletResponse, Object)} 执行成功之后,才会被执行 */ default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } }

    类图

    处理器执行链

    HandlerExecutionChain

    构造方法

    主要包含了当前了处理器,和处理器内的拦截器

    // HandlerExecutionChain.java // 处理器 private final Object handler; // 拦截器数组 @Nullable private HandlerInterceptor[] interceptors;

    addInterceptor & getInterceptors

    添加拦截器到拦截器列表中 & 获得拦截器列表 简单的集合数据添加,没啥好说的

    public void addInterceptor(HandlerInterceptor interceptor) { initInterceptorList().add(interceptor); } public void addInterceptors(HandlerInterceptor... interceptors) { if (!ObjectUtils.isEmpty(interceptors)) { CollectionUtils.mergeArrayIntoCollection(interceptors, initInterceptorList()); } }

    applyPreHandle

    应用拦截器的前置处理

    // HandlerExecutionChain.java boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { // 获得拦截器数组 HandlerInterceptor[] interceptors = getInterceptors(); // 首先有拦截器才需要拦截,没有就不需要了 if (!ObjectUtils.isEmpty(interceptors)) { // 遍历拦截器数组 for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; // 前置处理 if (!interceptor.preHandle(request, response, this.handler)) { // 触发已完成处理,进入此循环证明之前的拦截器返回false中断了或者处理失败 triggerAfterCompletion(request, response, null); // 返回 false ,前置处理失败 return false; } // 标记 interceptorIndex 位置 this.interceptorIndex = i; } } // 返回 true ,前置处理成功 return true; }

    preHandle具体逻辑就是根据不同拦截器来实现不同内容了。

    triggerAfterCompletion

    拦截器的完成处理

    // HandlerExecutionChain.java void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception { // 获得拦截器数组 HandlerInterceptor[] interceptors = 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 ex2) { // 注意,如果执行失败,仅仅会打印错误日志,不会结束循环 logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); } } } }

    注意因为之前interceptorIndex在循环中不断被重新设置,所以这里是将之前执行过的拦截器执行afterCompletion操作(不包括当前这个拦截器)

    applyPostHandle

    应用拦截器的后置处理

    // HandlerExecutionChain.java void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { // 获得拦截器数组 HandlerInterceptor[] interceptors = 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); } } }

    后置处理就没有中断了

    实现类

    xml配置

    <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/interceptor/**" /> <mvc:exclude-mapping path="/interceptor/b/*" /> <bean class="com.elim.learn.spring.mvc.interceptor.MyInterceptor" /> </mvc:interceptor> </mvc:interceptors>

    springboot配置

    @EnableWebMvc @Configuration public class MVCConfiguration extends WebMvcConfigurerAdapter { @Autowired private YouInterceptor interceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(interceptor); } } @Component public class YouInterceptor extends HandlerInterceptorAdapter { // ... 省略无关代码 }

    HandlerInterceptorAdapter是AsyncHandlerInterceptor的抽象继承于HandlerInterceptor

    public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor { /** * This implementation always returns {@code true}. */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } /** * This implementation is empty. */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } /** * This implementation is empty. */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } /** * This implementation is empty. */ @Override public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { } }

    全部空实现

    总结

    HandlerMapping我们在他们判断handler的方法中可以知道,对于springMVC,我们常用的Controller和RequestMapping会被认为是处理器,然后根据路径或者根据方法获得controller中的方法然后执行其方法。 有一点要注意根据路径(URL匹配)AbstractUrlHandlerMapping 并不是我们用的RequestMapping。他是使用很老的xml配置

    <bean class="org.springframework.web.servlet.handler. SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/hello.form“>helloController</prop> </props> </property> </bean>

    这种配置来进行匹配,现在几乎已经不用了都是通过注解RequestMapping来进行匹配。也就是AbstractHandlerMethodMapping里面的。


    最新回复(0)