好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

java spring mvc处理器映射器介绍

前言:

本文源码基于 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处理器映射器介绍的详细内容...

  阅读:16次