1
|
package org.springframework.web.servlet.handler;
|
2
|
|
3
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
4
|
import org.springframework.util.ClassUtils;
|
5
|
import org.springframework.web.cors.CorsUtils;
|
6
|
import org.springframework.web.method.HandlerMethod;
|
7
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
8
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
9
|
|
10
|
import javax.servlet.http.HttpServletRequest;
|
11
|
import java.lang.reflect.Field;
|
12
|
import java.lang.reflect.Method;
|
13
|
import java.util.*;
|
14
|
import java.util.concurrent.CopyOnWriteArrayList;
|
15
|
|
16
|
/**
|
17
|
* 覆盖RequestMappingHandlerMapping的实现,优化性能
|
18
|
*
|
19
|
* @author yezq
|
20
|
*/
|
21
|
public class KmssRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
|
22
|
/**
|
23
|
* 构造实例
|
24
|
*/
|
25
|
public static RequestMappingHandlerMapping build() {
|
26
|
return new KmssRequestMappingHandlerMapping();
|
27
|
}
|
28
|
|
29
|
private KmssMappingRegistry mappingRegistry;
|
30
|
|
31
|
private List<RequestMappingInfo> patternsMappings = new CopyOnWriteArrayList<>();
|
32
|
|
33
|
private KmssRequestMappingHandlerMapping() {
|
34
|
// 重写mappingRegistry属性
|
35
|
mappingRegistry = new KmssMappingRegistry();
|
36
|
try {
|
37
|
Field field = AbstractHandlerMethodMapping.class.getDeclaredField("mappingRegistry");
|
38
|
field.setAccessible(true);
|
39
|
field.set(this, mappingRegistry);
|
40
|
} catch (Exception e) {
|
41
|
ExceptionUtils.wrapAndThrow(e);
|
42
|
}
|
43
|
}
|
44
|
|
45
|
/**
|
46
|
* 覆盖MappingRegistry,记录带通配符的路径
|
47
|
*/
|
48
|
private class KmssMappingRegistry extends AbstractHandlerMethodMapping<RequestMappingInfo>.MappingRegistry {
|
49
|
@Override
|
50
|
public void register(RequestMappingInfo mapping, Object handler, Method method) {
|
51
|
super.register(mapping, handler, method);
|
52
|
Set<String> paths = getMappingPathPatterns(mapping);
|
53
|
if (paths.isEmpty()) {
|
54
|
patternsMappings.add(mapping);
|
55
|
}else {
|
56
|
for (String path : paths) {
|
57
|
if (getPathMatcher().isPattern(path)) {
|
58
|
patternsMappings.add(mapping);
|
59
|
return;
|
60
|
}
|
61
|
}
|
62
|
}
|
63
|
}
|
64
|
|
65
|
@Override
|
66
|
public void unregister(RequestMappingInfo mapping) {
|
67
|
super.unregister(mapping);
|
68
|
patternsMappings.remove(mapping);
|
69
|
}
|
70
|
}
|
71
|
|
72
|
// ========== 以下代码主框架抄袭父类,修改地方见注释 ==========
|
73
|
@Override
|
74
|
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
|
75
|
List<Match> matches = new ArrayList<>();
|
76
|
List<RequestMappingInfo> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
|
77
|
if (directPathMatches != null) {
|
78
|
addMatchingMappings(directPathMatches, matches, request);
|
79
|
}
|
80
|
if (matches.isEmpty()) {
|
81
|
//原文:addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
|
82
|
//原文的遍历太多,实际上只需要遍历带通配符的mapping就好
|
83
|
addMatchingMappings(this.patternsMappings, matches, request);
|
84
|
}
|
85
|
|
86
|
if (!matches.isEmpty()) {
|
87
|
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
|
88
|
matches.sort(comparator);
|
89
|
Match bestMatch = matches.get(0);
|
90
|
if (matches.size() > 1) {
|
91
|
if (logger.isTraceEnabled()) {
|
92
|
logger.trace(matches.size() + " matching mappings: " + matches);
|
93
|
}
|
94
|
if (CorsUtils.isPreFlightRequest(request)) {
|
95
|
return PREFLIGHT_AMBIGUOUS_MATCH;
|
96
|
}
|
97
|
Match secondBestMatch = matches.get(1);
|
98
|
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
|
99
|
Method m1 = bestMatch.handlerMethod.getMethod();
|
100
|
Method m2 = secondBestMatch.handlerMethod.getMethod();
|
101
|
String uri = request.getRequestURI();
|
102
|
throw new IllegalStateException(
|
103
|
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
|
104
|
}
|
105
|
}
|
106
|
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
|
107
|
handleMatch(bestMatch.mapping, lookupPath, request);
|
108
|
return bestMatch.handlerMethod;
|
109
|
} else {
|
110
|
//原文:return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
|
111
|
//原文很奇怪,明明找不到,handleNoMatch又遍历了一次,还是找不到
|
112
|
return null;
|
113
|
}
|
114
|
}
|
115
|
|
116
|
// ========== 以下代码纯搬运 ==========
|
117
|
private static final HandlerMethod PREFLIGHT_AMBIGUOUS_MATCH = new HandlerMethod(new EmptyHandler(),
|
118
|
ClassUtils.getMethod(EmptyHandler.class, "handle"));
|
119
|
|
120
|
private void addMatchingMappings(Collection<RequestMappingInfo> mappings, List<Match> matches,
|
121
|
HttpServletRequest request) {
|
122
|
for (RequestMappingInfo mapping : mappings) {
|
123
|
RequestMappingInfo match = getMatchingMapping(mapping, request);
|
124
|
if (match != null) {
|
125
|
matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
|
126
|
}
|
127
|
}
|
128
|
}
|
129
|
|
130
|
private class MatchComparator implements Comparator<Match> {
|
131
|
private final Comparator<RequestMappingInfo> comparator;
|
132
|
|
133
|
public MatchComparator(Comparator<RequestMappingInfo> comparator) {
|
134
|
this.comparator = comparator;
|
135
|
}
|
136
|
|
137
|
@Override
|
138
|
public int compare(Match match1, Match match2) {
|
139
|
return this.comparator.compare(match1.mapping, match2.mapping);
|
140
|
}
|
141
|
}
|
142
|
|
143
|
private class Match {
|
144
|
private final RequestMappingInfo mapping;
|
145
|
|
146
|
private final HandlerMethod handlerMethod;
|
147
|
|
148
|
public Match(RequestMappingInfo mapping, HandlerMethod handlerMethod) {
|
149
|
this.mapping = mapping;
|
150
|
this.handlerMethod = handlerMethod;
|
151
|
}
|
152
|
|
153
|
@Override
|
154
|
public String toString() {
|
155
|
return this.mapping.toString();
|
156
|
}
|
157
|
}
|
158
|
|
159
|
private static class EmptyHandler {
|
160
|
@SuppressWarnings("unused")
|
161
|
public void handle() {
|
162
|
throw new UnsupportedOperationException("Not implemented");
|
163
|
}
|
164
|
}
|
165
|
}
|