前言:
本文源码基于 spring-framework-5.3.10 。 mvc 是 spring 源码中的一个子模块!
一、RequestMappingHandlerMapping解析映射简单介绍
@RequestMapping通过 RequestMappingHandlerMapping 进行解析! HandlerMapping是一个根据URL映射到Handler的方法。 RequestMappingHandlerMapping 是HandlerMapping的一个子类! RequestMappingHandlerMapping他的父类有InitializingBean,所有在spring启动实例化的时候会调用afterPropertiesSet()方法。解析逻辑就在这里。 RequestMappingHandlerMapping 有俩个过程:解析、映射
二、@RequestMapping解析源码流程
容器加载,调用 RequestMappingHandlerMapping 的 afterPropertiesSet ()。 调用父类的 afterPropertiesSet() 方法。 调用initHandlerMethods()方法。 循环每一个Bean,看方法上有@RequestMapping或者@Controller的Bean。 解析 HandlerMethods ,进行封装RequestMappingInfo。 将封装好的 RequestMappingInfo 存起来:key为路径,值为mapping(RequestMappingInfo)
三、@RequestMapping映射源码流程
请求进来,调用 getHandler 方法。 获取当前请求对应的 HandlerMethod 。 通过 UrlPathHelper 对象,用于来解析从们的request中解析出请求映射路径。 更具路径去 pathLookup 中找。 上面没找到,从所有的里面找有通配符的。 找到多个进行排序,优先级:? > * > {} >** 。 不为空拿到第一个返回。 如果为空获取默认的。默认还是空的,直接返回null。 封装拦截器,返回。
四、@RequestMapping解析源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
/** * 解析的开始位置。 * 由于实现了InitializingBean,初始化Bean的时候调用这个方法。 * 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet() */ public void afterPropertiesSet() {
this .config = new RequestMappingInfo.BuilderConfiguration(); this .config.setTrailingSlashMatch(useTrailingSlashMatch()); // 尾部斜杠 this .config.setContentNegotiationManager(getContentNegotiationManager());
if (getPatternParser() != null ) { this .config.setPatternParser(getPatternParser()); Assert.isTrue(! this .useSuffixPatternMatch && ! this .useRegisteredSuffixPatternMatch, "Suffix pattern matching not supported with PathPatternParser." ); } else { this .config.setSuffixPatternMatch(useSuffixPatternMatch()); this .config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch()); this .config.setPathMatcher(getPathMatcher()); }
// 调用父类的afterPropertiesSet方法 super .afterPropertiesSet(); }
/** * 父类的afterPropertiesSet方法。 * 源码位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet() */ public void afterPropertiesSet() { initHandlerMethods(); }
/** * 解析@RequestMapping方法 * 源码位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods() */ protected void initHandlerMethods() { // 获得所有候选beanName—— 当前容器所有的beanName for (String beanName : getCandidateBeanNames()) { // BeanName不是scopedTarget.开头的 if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { // *处理候选bean——即解析@RequestMapping和映射路径 processCandidateBean(beanName); } } // 解析完所有@RequestMapping的时候调用 handlerMethodsInitialized(getHandlerMethods()); }
/** * 处理候选bean——即解析@RequestMapping和映射路径 * 源码位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.processCandidateBean(String) */ protected void processCandidateBean(String beanName) { Class<?> beanType = null ; try { // 得到当前BeanName得到这个Bean的类型 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); } } // 这一步判断是关键:是否有Controller 或 RequestMapping注解 if (beanType != null && isHandler(beanType)) { // 解析HandlerMethods detectHandlerMethods(beanName); } }
/** * 解析HandlerMethods * 源码位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(Object) */ protected void detectHandlerMethods(Object handler) { Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null ) { Class<?> userType = ClassUtils.getUserClass(handlerType); // 循环所有方法 Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> { try { // 根据Method得到Mapping映射 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)); } else if (mappingsLogger.isDebugEnabled()) { mappingsLogger.debug(formatMappings(userType, methods)); } // 遍历每一个方法,这里是所有Bean的所有方法 methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); // pathLookup放入:key为路径,值为mapping(RequestMappingInfo) registerHandlerMethod(handler, invocableMethod, mapping); }); } }
/** * 根据Method得到Mapping映射 * 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.getMappingForMethod(Method, Class<?>) */ protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) { // 如果方法上面有@RequestMapping:解析出RequestMappingInfo // RequestMappingInfo 是用来在请求的时候做匹对的 RequestMappingInfo info = createRequestMappingInfo(method); if (info != null ) { // 如果方法上面有@RequestMapping,看看类上面是不是有@RequestMapping RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); // 类上面也有@RequestMapping 那就合并 // 比如 类:/user 方法:/info 合并为 /user/info if (typeInfo != null ) { info = typeInfo测试数据bine(info); }
// 合并前缀 5.1新增 默认null // 可通过 WebMvcConfigurer#configurePathMatch 进行定制 String prefix = getPathPrefix(handlerType); if (prefix != null ) { info = RequestMappingInfo.paths(prefix).options( this .config).build()测试数据bine(info); } } return info; }
/** * 创建请求映射信息的外部逻辑 * 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.createRequestMappingInfo(AnnotatedElement) */ private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) { // 获取RequestMapping注解信息 RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping. class ); // 获取请求调解:[可扩展], 如果有:该条件会在请求时匹对 RequestCondition<?> condition = (element instanceof Class ? getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element)); // 如果有RequestMapping注解,封装成RequestMappingInfo return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null ); }
/** * 创建请求映射信息的内部逻辑 * 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.createRequestMappingInfo(RequestMapping, RequestCondition<?>) */ protected RequestMappingInfo createRequestMappingInfo( RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) { // 将@RequestMapping注解属性的值构建成一个 RequestMappingInfo RequestMappingInfo.Builder builder = RequestMappingInfo //构建路径 .paths(resolveEmbeddedValuesInPatterns(requestMapping.path())) //构建方法(get还是post等) .methods(requestMapping.method()) //参数 对应http request parameter .params(requestMapping.params()) //头部 .headers(requestMapping.headers()) //request的提交内容类型content type,如application/json, text/html .consumes(requestMapping.consumes()) //指定返回的内容类型的content type,仅当request请求头中的(Accept)类型中包含该指定类型才返回 .produces(requestMapping.produces()) .mappingName(requestMapping.name()); if (customCondition != null ) { builder.customCondition(customCondition); } // 构造RequestMappingInfo:将上面的属性构建成一个个的RequestCondition对象方便在请求的时候组合匹对 return builder.options( this .config).build(); }
/** * 得到所有的方法 * 源码位置:org.springframework.core.MethodIntrospector.selectMethods(Class<?>, MetadataLookup<T>) */ public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) { final Map<Method, T> methodMap = new LinkedHashMap<>(); Set<Class<?>> handlerTypes = new LinkedHashSet<>(); Class<?> specificHandlerType = null ; //获取原始的class对象 if (!Proxy.isProxyClass(targetType)) { specificHandlerType = ClassUtils.getUserClass(targetType); handlerTypes.add(specificHandlerType); } //获取class的接口 handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType)); //循环我们的class集合 for (Class<?> currentHandlerType : handlerTypes) { final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);
ReflectionUtils.doWithMethods(currentHandlerType, method -> { //获取具体的方法对象 Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass); /**回调 即解析@RequestMapping 返回RequestMappingInfo * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#getMappingForMethod(java.lang.reflect.Method, java.lang.Class)*/ T result = metadataLookup.inspect(specificMethod); if (result != null ) { // 看看有没有桥接方法:泛型实现类jvm会自动生成桥接类 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null ) { //把方法对象作为key,RequestMappingInfo对象作为value保存到map中 methodMap.put(specificMethod, result); } } }, ReflectionUtils.USER_DECLARED_METHODS); }
return methodMap; } |
五、@RequestMapping映射源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
/** * 获取@RequestMapping映射 * 源码位置:org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(HttpServletRequest) */ public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 获取当前请求对应的HandlerMethod Object handler = getHandlerInternal(request);
// 获取默认的handler if (handler == null ) { handler = getDefaultHandler(); }
// 还是没有handler的时候返回null,404了 if (handler == null ) { return null ; } // Bean name or resolved handler? // String类型?获取Bean if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); }
// Ensure presence of cached lookupPath for interceptors and others if (!ServletRequestPathUtils.hasCachedPath(request)) { initLookupPath(request); }
// 获取拦截器相关的调用链 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) { logger.trace( "Mapped to " + handler); } else if (logger.isDebugEnabled() && !DispatcherType.ASYNC.equals(request.getDispatcherType())) { logger.debug( "Mapped to " + executionChain.getHandler()); }
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) { CorsConfiguration config = getCorsConfiguration(handler, request); if (getCorsConfigurationSource() != null ) { CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request); config = (globalConfig != null ? globalConfig测试数据bine(config) : config); } if (config != null ) { config.validateAllowCredentials(); } executionChain = getCorsHandlerExecutionChain(request, executionChain, config); }
return executionChain; }
/** * 获取当前请求对应的HandlerMethod * 源码位置:org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(HttpServletRequest) */ protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); try { // 直接调用父类的getHandlerInternal方法 return super .getHandlerInternal(request); } finally { ProducesRequestCondition.clearMediaTypesAttribute(request); } } /** * 获取当前请求对应的HandlerMethod---父类的 * 源码位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(HttpServletRequest) */ protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { // 通过UrlPathHelper对象,用于来解析从们的request中解析出请求映射路径 String lookupPath = initLookupPath(request); this .mappingRegistry.acquireReadLock(); try { // 通过lookupPath解析最终的handler——HandlerMethod对象 HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null ); } finally { this .mappingRegistry.releaseReadLock(); } }
/** * 通过lookupPath解析最终的handler * 源码位置:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(String, HttpServletRequest) */ protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<>(); // 根据uri从mappingRegistry.pathLookup获取 RequestMappingInfo // pathLookup<path,RequestMappingInfo>会在初始化阶段解析好 List<T> directPathMatches = this .mappingRegistry.getMappingsByDirectPath(lookupPath); if (directPathMatches != null ) { // 如果根据path能直接匹配的RequestMappingInfo 则用该mapping进行匹配其他条件(method、header等) addMatchingMappings(directPathMatches, matches, request); } if (matches.isEmpty()) { // 如果无path匹配,用所有的RequestMappingInfo 通过AntPathMatcher匹配 addMatchingMappings( this .mappingRegistry.getRegistrations().keySet(), matches, request); } if (!matches.isEmpty()) { // 选择第一个为最匹配的 Match bestMatch = matches.get( 0 ); /** * 如果匹配到多个 @RequestMapping(value="/mappin?") @RequestMapping(value="/mappin*") @RequestMapping(value="/{xxxx}") @RequestMapping(value="/**") */ if (matches.size() > 1 ) { //创建MatchComparator的匹配器对象 Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
/** 根据精准度排序 大概是这样的: ? > * > {} >** 具体可以去看: * @see org.springframework.util.AntPathMatcher.AntPatternComparator#compare(java.lang.String, java.lang.String)*/ matches.sort(comparator);
// 排完序后拿到优先级最高的 bestMatch = matches.get( 0 ); if (logger.isTraceEnabled()) { logger.trace(matches.size() + " matching mappings: " + matches); } // 是否配置CORS并且匹配 if (CorsUtils.isPreFlightRequest(request)) { for (Match match : matches) { if (match.hasCorsConfig()) { return PREFLIGHT_AMBIGUOUS_MATCH; } } } else { //获取第二最匹配的 Match secondBestMatch = matches.get( 1 ); //若第一个和第二个是一样的 抛出异常 if (comparator测试数据pare(bestMatch, secondBestMatch) == 0 ) { Method m1 = bestMatch.getHandlerMethod().getMethod(); Method m2 = secondBestMatch.getHandlerMethod().getMethod(); String uri = request.getRequestURI(); throw new IllegalStateException( "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}" ); } } } //把最匹配的设置到request中 request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod()); handleMatch(bestMatch.mapping, lookupPath, request); //返回最匹配的 return bestMatch.getHandlerMethod(); } else { // return null return handleNoMatch( this .mappingRegistry.getRegistrations().keySet(), lookupPath, request); } } |
到此这篇关于java spring mvc处理器映射器介绍的文章就介绍到这了,更多相关spring mvc处理器映射器内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
原文链接:https://HdhCmsTestcnblogs测试数据/zfcq/p/16069331.html
查看更多关于java spring mvc处理器映射器介绍的详细内容...