- 这些类分别的作用是啥?为啥要这样设计
#初始化config对象,接着调用父类的afterPropertiesSet方法
public void afterPropertiesSet() {
# RequestMappingInfo用于保存Request mapping information.里面有RequestMapping注释中的各种condition,
#比如:patternsCondition,methodsCondition,paramsCondition等
#RequestMappingInfo.BuilderConfiguration为@RequestMapping中配置项的容器,用于request mapping解析的过程中
this.config = new RequestMappingInfo.BuilderConfiguration();
#URL path matching的帮助类
this.config.setUrlPathHelper(getUrlPathHelper());
#用于path matching,定义匹配string的策略接口
this.config.setPathMatcher(getPathMatcher());
#是否开启 pattern matching中的前缀匹配
this.config.setSuffixPatternMatch(useSuffixPatternMatch());
#是否开启PatternsRequestCondition中的尾随斜杠
this.config.setTrailingSlashMatch(useTrailingSlashMatch());
#是否开启后缀访问,方法上的/hello也会匹配到/hello.json路径
this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
#设置ProducesRequestCondition需要的内容管理器
this.config.setContentNegotiationManager(getContentNegotiationManager());
#调用父类的afterPropertiesSet方法
super.afterPropertiesSet();
}
#接下来会调用org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#afterPropertiesSet的方法
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
#遍历获得到的beanName
for (String beanName : getCandidateBeanNames()) {
#如果beanName没有以SCOPED_TARGET_NAME_PREFIX = "scopedTarget."起始
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
#detectHandlerMethodsInAncestorContexts默认为false,代表不会从springMVC的父容器中获取CandidateBeanNames,否则从上下文对象中获取所有的对象
protected String[] getCandidateBeanNames() {
return (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) :
obtainApplicationContext().getBeanNamesForType(Object.class));
}
#返回上下对象
protected final ApplicationContext obtainApplicationContext() {
ApplicationContext applicationContext = getApplicationContext();
Assert.state(applicationContext != null, "No ApplicationContext");
return applicationContext;
}
#获得当前对象运行在的上下文对象
public final ApplicationContext getApplicationContext() throws IllegalStateException {
if (this.applicationContext == null && isContextRequired()) {
throw new IllegalStateException(
"ApplicationObjectSupport instance [" + this + "] does not run in an ApplicationContext");
}
return this.applicationContext;
}
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
#根据beanName获得在相应的类型
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);
}
}
#如果是handler类型,isHandler为抽象方法,具体实现在org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#isHandler,
#如果该beanType上有@controller或者@RequestMapping注解信息
if (beanType != null && isHandler(beanType)) {
#加载该handler中的所有handlerMethod方法
detectHandlerMethods(beanName);
}
}
#获取使用Controller和RequestMapping注释的类
protected boolean isHandler(Class<?> beanType) {
#AnnotatedElementUtils为操作注解的工具类
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
#
protected void detectHandlerMethods(Object handler) {
#如果handler为string,则根据beanName获取handlerType,否则获取类型
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
#返回cglib代理类的原始类
Class<?> userType = ClassUtils.getUserClass(handlerType);
#返回处理后的requestMappingInfo
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));
}
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
#为抽象方法,具体实现在requestmappinghandlermapping类中
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
#获取类对象
public static Class<?> getUserClass(Class<?> clazz) {
if (clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
Class<?> superclass = clazz.getSuperclass();
if (superclass != null && superclass != Object.class) {
return superclass;
}
}
return clazz;
}
#该类中保存mapping和handlerMethod之间的关系
#又是registry!!!
class MappingRegistry {
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
}
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;
if (!Proxy.isProxyClass(targetType)) {
specificHandlerType = ClassUtils.getUserClass(targetType);
handlerTypes.add(specificHandlerType);
}
handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType));
for (Class<?> currentHandlerType : handlerTypes) {
final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);
ReflectionUtils.doWithMethods(currentHandlerType, method -> {
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
T result = metadataLookup.inspect(specificMethod);
if (result != null) {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
methodMap.put(specificMethod, result);
}
}
}, ReflectionUtils.USER_DECLARED_METHODS);
}
return methodMap;
}
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);
#如果方法的info不为空
if (info != null) {
#获取类信息的typeInfo
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
#合并类,方法上标注的requestMapping和
info = typeInfo.combine(info);
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
#使用build后的RequestMappingInfo对象合并info
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
}
}
return info;
}
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
#获得element中@RequestMapping注解的对象
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
#如果element为class,返回Class的RequestCondition
#如果element为method,返回method的RequestCondition
RequestCondition<?> condition = (element instanceof Class ?
getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
#根据requestMapping和condition创建RequestMappingInfo对象
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
#返回null的RequestCondition
protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
return null;
}
#返回null的RequestCondition
protected RequestCondition<?> getCustomMethodCondition(Method method) {
return null;
}
#接口的
protected RequestMappingInfo createRequestMappingInfo(
RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {
#使用build模式将requestMapping和customCondition的信息封装到RequestMappingInfo里面
RequestMappingInfo.Builder builder = RequestMappingInfo
.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
.methods(requestMapping.method())
.params(requestMapping.params())
.headers(requestMapping.headers())
.consumes(requestMapping.consumes())
.produces(requestMapping.produces())
.mappingName(requestMapping.name());
if (customCondition != null) {
builder.customCondition(customCondition);
}
return builder.options(this.config).build();
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfo#combine
public RequestMappingInfo combine(RequestMappingInfo other) {
#如果当前对象的name和other中的name都不为空,则返回name1#name2,放回不为空的name
String name = combineNames(other);
#如果两者的patterns都不为空,则使用org.springframework.util.AntPathMatcher#combine对两个进行combine,否则放回不为空的patterns
PatternsRequestCondition patterns = this.patternsCondition.combine(other.patternsCondition);
#将两个方法methodConditons中的方法合并为set集合,使用set新疆新的
RequestMethodsRequestCondition methods = this.methodsCondition.combine(other.methodsCondition);
#将两个paramsRequest中的expression进行合并为set,使用set新建ParamsRequestCondition
ParamsRequestCondition params = this.paramsCondition.combine(other.paramsCondition);
#逻辑同上
HeadersRequestCondition headers = this.headersCondition.combine(other.headersCondition);
#如果other中consumesCondition的expressions不为空,
#返回给other对象的consumesCondition,否则放回this对象的consumesCondition
#如果method mapping中的的consumer存在,返回给方法的配置,否则返回给类上的配置
ConsumesRequestCondition consumes = this.consumesCondition.combine(other.consumesCondition);
#produces同上,以方法的为主
ProducesRequestCondition produces = this.producesCondition.combine(other.producesCondition);
#合并holder中的condition
RequestConditionHolder custom = this.customConditionHolder.combine(other.customConditionHolder);
#使用合并后的结果新建RequestMappingInfo
return new RequestMappingInfo(name, patterns,
methods, params, headers, consumes, produces, custom.getCondition());
}
public PatternsRequestCondition combine(PatternsRequestCondition other) {
Set<String> result = new LinkedHashSet<>();
if (!this.patterns.isEmpty() && !other.patterns.isEmpty()) {
#如果方法和class上的path都不为空,使用笛卡尔积形式,
#利用pathMatcher对其进行combine后放入set中
for (String pattern1 : this.patterns) {
for (String pattern2 : other.patterns) {
result.add(this.pathMatcher.combine(pattern1, pattern2));
}
}
}
#否则,如果当前的path不为空,放回当前path
else if (!this.patterns.isEmpty()) {
result.addAll(this.patterns);
}
#other不为空,返回other的path
else if (!other.patterns.isEmpty()) {
result.addAll(other.patterns);
}
#两者都为空,返回空串
else {
result.add("");
}
#将当前PatternsRequestCondition中的信息和合并后的结果result重新生成新的PatternsRequestCondition对象
return new PatternsRequestCondition(result, this);
}
private PatternsRequestCondition(Set<String> patterns, PatternsRequestCondition other) {
this.patterns = patterns;
this.pathHelper = other.pathHelper;
this.pathMatcher = other.pathMatcher;
this.useSuffixPatternMatch = other.useSuffixPatternMatch;
this.useTrailingSlashMatch = other.useTrailingSlashMatch;
this.fileExtensions.addAll(other.fileExtensions);
}
#org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition#combine
public RequestMethodsRequestCondition combine(RequestMethodsRequestCondition other) {
Set<RequestMethod> set = new LinkedHashSet<>(this.methods);
#合并两个methods
set.addAll(other.methods);
return new RequestMethodsRequestCondition(set);
}
#org.springframework.web.servlet.mvc.condition.ParamsRequestCondition#combine
public ParamsRequestCondition combine(ParamsRequestCondition other) {
Set<ParamExpression> set = new LinkedHashSet<>(this.expressions);
#合并expressions
set.addAll(other.expressions);
return new ParamsRequestCondition(set);
}
#org.springframework.web.servlet.mvc.condition.HeadersRequestCondition#combine
public HeadersRequestCondition combine(HeadersRequestCondition other) {
Set<HeaderExpression> set = new LinkedHashSet<>(this.expressions);
#合并header中的信息,
set.addAll(other.expressions);
return new HeadersRequestCondition(set);
}
#org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition#combine
public ConsumesRequestCondition combine(ConsumesRequestCondition other) {
return (!other.expressions.isEmpty() ? other : this);
}
#org.springframework.web.servlet.mvc.condition.ProducesRequestCondition#combine
public ProducesRequestCondition combine(ProducesRequestCondition other) {
return (!other.expressions.isEmpty() ? other : this);
}
public RequestConditionHolder combine(RequestConditionHolder other) {
#两者都为空,返回空,两者中任意一个不为空,返回不为空的那个
if (this.condition == null && other.condition == null) {
return this;
}
else if (this.condition == null) {
return other;
}
else if (other.condition == null) {
return this;
}
else {
#判断两者类型是否相等
assertEqualConditionTypes(this.condition, other.condition);
#两者都不为空,进行合并
RequestCondition<?> combined = (RequestCondition<?>) this.condition.combine(other.condition);
#使用组合后的结果,新建RequestConditionHolder对象
return new RequestConditionHolder(combined);
}
}
#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#getPathPrefix
String getPathPrefix(Class<?> handlerType) {
#遍历所有的pathPrefixes集合
for (Map.Entry<String, Predicate<Class<?>>> entry : this.pathPrefixes.entrySet()) {
#如果当前的controller类型符合predict
if (entry.getValue().test(handlerType)) {
String prefix = entry.getKey();
#embeddedValueResolver为org.springframework.util.StringValueResolver
if (this.embeddedValueResolver != null) {
#使用该resolver解析prefix
prefix = this.embeddedValueResolver.resolveStringValue(prefix);
}
return prefix;
}
}
return null;
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfo#paths
public static Builder paths(String... paths) {
#将path封装到DefaultBuilder里面
return new DefaultBuilder(paths);
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfo.DefaultBuilder#options返回默认的build对象
public Builder options(BuilderConfiguration options) {
this.options = options;
return this;
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfo.DefaultBuilder#build,
#使用build模式创建RequestMappingInfo
public RequestMappingInfo build() {
#ContentNegotiationManager为确定request中的media type的核心类
ContentNegotiationManager manager = this.options.getContentNegotiationManager();
#根据当前RequestMappingInfo中的封装好的对象,创建PatternsRequestCondition对象
PatternsRequestCondition patternsCondition = new PatternsRequestCondition(
this.paths, this.options.getUrlPathHelper(), this.options.getPathMatcher(),
this.options.useSuffixPatternMatch(), this.options.useTrailingSlashMatch(),
this.options.getFileExtensions());
#使用处理后的参数重新创建RequestMappingInfo对象
#RequestMappingInfo保存所有的requestmapping信息,
#在requestmappingInfo中使用RequestCondition接口不同实现类
return new RequestMappingInfo(this.mappingName, patternsCondition,
new RequestMethodsRequestCondition(this.methods),
new ParamsRequestCondition(this.params),
new HeadersRequestCondition(this.headers),
new ConsumesRequestCondition(this.consumes, this.headers),
new ProducesRequestCondition(this.produces, this.headers, manager),
this.customCondition);
}
public static Method selectInvocableMethod(Method method, @Nullable Class<?> targetType) {
if (targetType == null) {
return method;
}
Method methodToUse = MethodIntrospector.selectInvocableMethod(method, targetType);
#得到的方法是私有的,对象,并且是springproxy类的子类
if (Modifier.isPrivate(methodToUse.getModifiers()) && !Modifier.isStatic(methodToUse.getModifiers()) &&
SpringProxy.class.isAssignableFrom(targetType)) {
throw new IllegalStateException(String.format(
"Need to invoke method '%s' found on proxy for target class '%s' but cannot " +
"be delegated to target bean. Switch its visibility to package or protected.",
method.getName(), method.getDeclaringClass().getSimpleName()));
}
return methodToUse;
}
#得到该方法声明的信息
public static Method selectInvocableMethod(Method method, Class<?> targetType) {
#如果声明该方法的类是targetType的父类,接口类,返回该方法
if (method.getDeclaringClass().isAssignableFrom(targetType)) {
return method;
}
try {
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
#遍历该类的所有接口,根据方法名和参数类型从这些接口查询声明该方法的接口
for (Class<?> ifc : targetType.getInterfaces()) {
try {
return ifc.getMethod(methodName, parameterTypes);
}
catch (NoSuchMethodException ex) {
// Alright, not on this interface then...
}
}
// A final desperate attempt on the proxy class itself...
return targetType.getMethod(methodName, parameterTypes);
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException(String.format(
"Need to invoke method '%s' declared on target class '%s', " +
"but not found in any interface(s) of the exposed proxy type. " +
"Either pull the method up to an interface or switch to CGLIB " +
"proxies by enforcing proxy-target-class mode in your configuration.",
method.getName(), method.getDeclaringClass().getSimpleName()));
}
}
#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#registerHandlerMethod
@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
#调用父类的方法
super.registerHandlerMethod(handler, method, mapping);
updateConsumesCondition(mapping, method);
}
#org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#registerHandlerMethod
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
#通过mappingRegistry将获取到的mapping,handler和method
#this代表RequestMappingHandlerMapping,mapping代表RequestMappingInfo,method代表反射调用的方法
this.mappingRegistry.register(mapping, handler, method);
}
#org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#register
public void register(T mapping, Object handler, Method method) {
// Assert that the handler method is not a suspending one.
#检测是否是KotlinType
if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
Class<?>[] parameterTypes = method.getParameterTypes();
if ((parameterTypes.length > 0) && "kotlin.coroutines.Continuation".equals(parameterTypes[parameterTypes.length - 1].getName())) {
throw new IllegalStateException("Unsupported suspending handler method detected: " + method);
}
}
#读写锁中的写锁进行锁定,mappingRegistry需要支持并发方法,所以要进行上锁
this.readWriteLock.writeLock().lock();
try {
#创建handlerMethod
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
#验证唯一性,一个requestMapingInfo对应一个handlerMethod,如果存在则抛出异常
validateMethodMapping(handlerMethod, mapping);
#this代表RequestMappingHandlerMapping.MappingRegistry,map中保存requestMappingINfo和methodHandler之间的关系
this.mappingLookup.put(mapping, handlerMethod);
#通过mapping中的PatternsRequestCondition的pattern查询满足的url
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
# 用于保存url和对应的requestMappingInfo之间的关系
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
#使用hanlder中的大写字母#方法名称拼接而成
name = getNamingStrategy().getName(handlerMethod, mapping);
#保存name和handlermethod之间的关系
addMappingName(name, handlerMethod);
}
#返回空的corsConfiguration
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
#如果不为空,建立该方法和corsconfig之间的关系,保存到corsLookup中
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
#registry中保存了mapping和MappingRegistration之间的关系,MappingRegistration保存了所有的映射结果信息
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
#释放读锁
this.readWriteLock.writeLock().unlock();
}
}
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
#如果handler是名称
if (handler instanceof String) {
#通过名称创建HandlerMethod
return new HandlerMethod((String) handler,
obtainApplicationContext().getAutowireCapableBeanFactory(), method);
}
#通过handler和method创建handlerMethod()名副其实)
return new HandlerMethod(handler, method);
}
public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) {
Assert.hasText(beanName, "Bean name is required");
Assert.notNull(beanFactory, "BeanFactory is required");
Assert.notNull(method, "Method is required");
this.bean = beanName;
this.beanFactory = beanFactory;
#通过传入的handler名称获得handler类型
Class<?> beanType = beanFactory.getType(beanName);
if (beanType == null) {
throw new IllegalStateException("Cannot resolve bean type for bean with name '" + beanName + "'");
}
#用于在cglib的情况下获得代理的类
this.beanType = ClassUtils.getUserClass(beanType);
this.method = method;
#获得桥接方法
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
#初始化bridgedMethod 中的参数对象
this.parameters = initMethodParameters();
evaluateResponseStatus();
#descriptionw为类名#方法名
this.description = initDescription(this.beanType, this.method);
}
private MethodParameter[] initMethodParameters() {
#获得桥接方法的参数的个数
int count = this.bridgedMethod.getParameterCount();
#创建长度为count的数组
MethodParameter[] result = new MethodParameter[count];
for (int i = 0; i < count; i++) {
result[i] = new HandlerMethodParameter(i);
}
return result;
}
#创建bridgedMethod的第index个参数的HandlerMethodParameter
public HandlerMethodParameter(int index) {
super(HandlerMethod.this.bridgedMethod, index);
}
private void evaluateResponseStatus() {
#得到该方法的@ResponseStatus欣姐
ResponseStatus annotation = getMethodAnnotation(ResponseStatus.class);
#如果该方法上没有该注解
if (annotation == null) {
annotation = AnnotatedElementUtils.findMergedAnnotation(getBeanType(), ResponseStatus.class);
}
#获得注解信息
if (annotation != null) {
#将注解中的信息保存到handlerMethod中的responseStatus,responseStatusReason 变量中
this.responseStatus = annotation.code();
this.responseStatusReason = annotation.reason();
}
}
#发现该method对象中的某个注解类型的注解
public <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {
return AnnotatedElementUtils.findMergedAnnotation(this.method, annotationType);
}
#org.springframework.core.annotation.AnnotatedElementUtils#findMergedAnnotation
public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
// Shortcut: directly present on the element, with no merging needed?
#AnnotationFilter PLAIN = packages("java.lang", "org.springframework.lang")
#判断annotationType是否符合该AnnotationFilter或者是java自带的,
if (AnnotationFilter.PLAIN.matches(annotationType) ||
AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
#获得该元素声明类型为annotationType的注解信息
return element.getDeclaredAnnotation(annotationType);
}
// Exhaustive retrieval of merged annotations...
return findAnnotations(element)
.get(annotationType, null, MergedAnnotationSelectors.firstDirectlyDeclared())
.synthesize(MergedAnnotation::isPresent).orElse(null);
}
#org.springframework.core.annotation.AnnotationsScanner#hasPlainJavaAnnotationsOnly(java.lang.Object)
static boolean hasPlainJavaAnnotationsOnly(@Nullable Object annotatedElement) {
#如果annotatedElement 为class对象
if (annotatedElement instanceof Class) {
#该注解是否是order类型或者是java自带的
return hasPlainJavaAnnotationsOnly((Class<?>) annotatedElement);
}
#该注解元素是field,方法或者构造函数的实例
else if (annotatedElement instanceof Member) {
#判断其生命类是否是order类型或者java自带的
return hasPlainJavaAnnotationsOnly(((Member) annotatedElement).getDeclaringClass());
}
else {
return false;
}
}
#判断该type是否是java包下,或者是order类型
static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
return (type.getName().startsWith("java.") || type == Ordered.class);
}
#进行注解合并
private static MergedAnnotations findAnnotations(AnnotatedElement element) {
return MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY, RepeatableContainers.none());
}
#org.springframework.core.annotation.AnnotatedElementUtils#findMergedAnnotation
#根据annotationType,predicate和selector获得合并后的注解
@Override
public <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
@Nullable MergedAnnotationSelector<A> selector) {
MergedAnnotation<A> result = find(annotationType, predicate, selector);
return (result != null ? result : MergedAnnotation.missing());
}
private static String initDescription(Class<?> beanType, Method method) {
StringJoiner joiner = new StringJoiner(", ", "(", ")");
for (Class<?> paramType : method.getParameterTypes()) {
joiner.add(paramType.getSimpleName());
}
#通过beanType名和方法名获的描述信息
return beanType.getName() + "#" + method.getName() + joiner.toString();
}
private void validateMethodMapping(HandlerMethod handlerMethod, T mapping) {
// Assert that the supplied mapping is unique.
#Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
#通过mapping查询相应的handlerMethod
#为啥mapping不是string?
#检测mapping的handlerMethod是否存在
HandlerMethod existingHandlerMethod = this.mappingLookup.get(mapping);
#如果从map中取到的handlerMethod和即将需要和mapping建立关系的handlerMapping不相等,抛出Ambiguous mapping异常
if (existingHandlerMethod != null && !existingHandlerMethod.equals(handlerMethod)) {
throw new IllegalStateException(
"Ambiguous mapping. Cannot map '" + handlerMethod.getBean() + "' method \n" +
handlerMethod + "\nto " + mapping + ": There is already '" +
existingHandlerMethod.getBean() + "' bean method\n" + existingHandlerMethod + " mapped.");
}
}
private List<String> getDirectUrls(T mapping) {
List<String> urls = new ArrayList<>(1);
#getMappingPathPatterns为抽象方法,具体实现在RequestMappingInfoHandlerMapping
for (String path : getMappingPathPatterns(mapping)) {
if (!getPathMatcher().isPattern(path)) {
#如果从mapping中获得的path不匹配AbstractHandlerMapping中定义的pathMatcher,则将该path添加到urls集合
urls.add(path);
}
}
return urls;
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#getMappingPathPatterns
protected Set<String> getMappingPathPatterns(RequestMappingInfo info) {
#获得该info中的path集合
return info.getPatternsCondition().getPatterns();
}
#org.springframework.web.servlet.handler.AbstractHandlerMapping#getPathMatcher
public PathMatcher getPathMatcher() {
#返回给antpathmatcher
return this.pathMatcher;
}
#返回配置的命名策略
public HandlerMethodMappingNamingStrategy<T> getNamingStrategy() {
return this.namingStrategy;
}
#命名策略
@Override
public String getName(HandlerMethod handlerMethod, RequestMappingInfo mapping) {
#如果mapping中的name存在,是用该name
if (mapping.getName() != null) {
return mapping.getName();
}
StringBuilder sb = new StringBuilder();
#得到handler的类名(不包含包名)
String simpleTypeName = handlerMethod.getBeanType().getSimpleName();
for (int i = 0; i < simpleTypeName.length(); i++) {
#挑选出类名中的大写字母
if (Character.isUpperCase(simpleTypeName.charAt(i))) {
sb.append(simpleTypeName.charAt(i));
}
}
#public static final String SEPARATOR = "#"
#和方法名进行拼接
sb.append(SEPARATOR).append(handlerMethod.getMethod().getName());
return sb.toString();
}
private void addMappingName(String name, HandlerMethod handlerMethod) {
#根据该name查询所有的handlerMethod
List<HandlerMethod> oldList = this.nameLookup.get(name);
if (oldList == null) {
#为空返回空集合
oldList = Collections.emptyList();
}
#遍历根据name得到的list,如果遍历到的current和handlerMethod相等,返回
for (HandlerMethod current : oldList) {
if (handlerMethod.equals(current)) {
return;
}
}
#新建空的list
List<HandlerMethod> newList = new ArrayList<>(oldList.size() + 1);
#将所有的oldlist放到新建的list
newList.addAll(oldList);
#将handlerMethod加入到newlist
newList.add(handlerMethod);
#缓存到map中
this.nameLookup.put(name, newList);
}
#返回为空
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, T mapping) {
return null;
}
public MappingRegistration(T mapping, HandlerMethod handlerMethod,
@Nullable List<String> directUrls, @Nullable String mappingName) {
#将mapping和handlerMethod,directUrls和mappingName关联到MappingRegistration
Assert.notNull(mapping, "Mapping must not be null");
Assert.notNull(handlerMethod, "HandlerMethod must not be null");
this.mapping = mapping;
this.handlerMethod = handlerMethod;
this.directUrls = (directUrls != null ? directUrls : Collections.emptyList());
this.mappingName = mappingName;
}
private void updateConsumesCondition(RequestMappingInfo info, Method method) {
#返回info中的ConsumesCondition对象
ConsumesRequestCondition condition = info.getConsumesCondition();
if (!condition.isEmpty()) {
#在condition不为空的情况下,遍历method的参数
for (Parameter parameter : method.getParameters()) {
#从parameter中的所有注解和元注解创建MergedAnnotation实例
#得到@RequestBody注解或者元注解
MergedAnnotation<RequestBody> annot = MergedAnnotations.from(parameter).get(RequestBody.class);
#如果参数中被@RequestBody修饰
if (annot.isPresent()) {
#设置注解中的require参数设置是否需要body
condition.setBodyRequired(annot.getBoolean("required"));
break;
}
}
}
}
#org.springframework.core.annotation.MergedAnnotations#from(java.lang.reflect.AnnotatedElement)
static MergedAnnotations from(AnnotatedElement element) {
return from(element, SearchStrategy.DIRECT);
}
static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy) {
return from(element, searchStrategy, RepeatableContainers.standardRepeatables());
}
public static RepeatableContainers standardRepeatables() {
return StandardRepeatableContainers.INSTANCE;
}
#org.springframework.core.annotation.TypeMappedAnnotations#from(java.lang.reflect.AnnotatedElement, org.springframework.core.annotation.MergedAnnotations.SearchStrategy, org.springframework.core.annotation.RepeatableContainers, org.springframework.core.annotation.AnnotationFilter)
static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy,
RepeatableContainers repeatableContainers) {
return TypeMappedAnnotations.from(element, searchStrategy, repeatableContainers, AnnotationFilter.PLAIN);
}
static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy,
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
#ruguo meiyou dedao xvyao jinyibu chulide
if (AnnotationsScanner.isKnownEmpty(element, searchStrategy)) {
return NONE;
}
return new TypeMappedAnnotations(element, searchStrategy, repeatableContainers, annotationFilter);
}
#根据搜索策略判断source是否存在进一步处理的注解
static boolean isKnownEmpty(AnnotatedElement source, SearchStrategy searchStrategy) {
#如果只有java注解的
if (hasPlainJavaAnnotationsOnly(source)) {
return true;
}
#如果搜索策略为DIRECT 或者没有继承结构
if (searchStrategy == SearchStrategy.DIRECT || isWithoutHierarchy(source, searchStrategy)) {
#如果该方法为桥接方法,返回false
if (source instanceof Method && ((Method) source).isBridge()) {
return false;
}
return getDeclaredAnnotations(source, false).length == 0;
}
return false;
}
#在该SearchStrategy下的AnnotatedElement 没有
private static boolean isWithoutHierarchy(AnnotatedElement source, SearchStrategy searchStrategy) {
#为object返回true
if (source == Object.class) {
return true;
}
#为class对象
if (source instanceof Class) {
Class<?> sourceClass = (Class<?>) source;
#既没有父类,也没有接口,返回true
boolean noSuperTypes = (sourceClass.getSuperclass() == Object.class &&
sourceClass.getInterfaces().length == 0);
return (searchStrategy == SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES ? noSuperTypes &&
sourceClass.getEnclosingClass() == null : noSuperTypes);
}
if (source instanceof Method) {
Method sourceMethod = (Method) source;
#判断source是否是私有,该方法的声明类是否没有继承结构
return (Modifier.isPrivate(sourceMethod.getModifiers()) ||
isWithoutHierarchy(sourceMethod.getDeclaringClass(), searchStrategy));
}
return true;
}
#org.springframework.core.annotation.AnnotationsScanner#getDeclaredAnnotations(java.lang.reflect.AnnotatedElement, boolean)
static Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defensive) {
boolean cached = false;
###private static final Map<AnnotatedElement, Annotation[]> declaredAnnotationCache =
new ConcurrentReferenceHashMap<>(256);
#从cache中取到source的注解
Annotation[] annotations = declaredAnnotationCache.get(source);
#从cache中取到值,
if (annotations != null) {
cached = true;
}
else {
#从source中获得声明的注解
annotations = source.getDeclaredAnnotations();
if (annotations.length != 0) {
boolean allIgnored = true;
for (int i = 0; i < annotations.length; i++) {
Annotation annotation = annotations[i];
#如果该注解可以忽略,或者该注解非法,
if (isIgnorable(annotation.annotationType()) ||
!AttributeMethods.forAnnotationType(annotation.annotationType()).isValid(annotation)) {
annotations[i] = null;
}
else {
#存在不和忽略的和合法的注解,将allIgnored 置为false
allIgnored = false;
}
}
#返回可以进一步处理的注解
annotations = (allIgnored ? NO_ANNOTATIONS : annotations);
if (source instanceof Class || source instanceof Member) {
#保存source和注解之间的关系到map中
declaredAnnotationCache.put(source, annotations);
cached = true;
}
}
}
#如果不保护,注解长度为0,不缓存,直接返回注解
if (!defensive || annotations.length == 0 || !cached) {
return annotations;
}
#clone该注解
return annotations.clone();
}
#如果是java的注解,可以忽略
private static boolean isIgnorable(Class<?> annotationType) {
return AnnotationFilter.PLAIN.matches(annotationType);
}
boolean isValid(Annotation annotation) {
assertAnnotation(annotation);
for (int i = 0; i < size(); i++) {
if (canThrowTypeNotPresentException(i)) {
try {
#通过反射调用,没有抛出异常则合法
get(i).invoke(annotation);
}
catch (Throwable ex) {
return false;
}
}
}
return true;
}
boolean canThrowTypeNotPresentException(int index) {
#检索数组中index位置存储的值,该位置是否可以抛出TypeNotPresentException
return this.canThrowTypeNotPresentException[index];
}
#org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition#setBodyRequired
public void setBodyRequired(boolean bodyRequired) {
this.bodyRequired = bodyRequired;
}
private <T> T getRequiredAttributeValue(String attributeName, Class<T> type) {
T value = getAttributeValue(attributeName, type);
if (value == null) {
throw new NoSuchElementException("No attribute named '" + attributeName +
"' present in merged annotation " + getType().getName());
}
return value;
}
protected <T> T getAttributeValue(String attributeName, Class<T> type) {
#获得该attributeName在属性中attributeName数组的位置,可能为-1
int attributeIndex = getAttributeIndex(attributeName, false);
return (attributeIndex != -1 ? getValue(attributeIndex, type) : null);
}
private int getAttributeIndex(String attributeName, boolean required) {
Assert.hasText(attributeName, "Attribute name must not be null");
#如果该注解的属性中存在该attributeName,返回相应的index,否则返回-1
int attributeIndex = (isFiltered(attributeName) ? -1 : this.mapping.getAttributes().indexOf(attributeName));
if (attributeIndex == -1 && required) {
throw new NoSuchElementException("No attribute named '" + attributeName +
"' present in merged annotation " + getType().getName());
}
return attributeIndex;
}
private boolean isFiltered(String attributeName) {
#如果存在attributeFilter
if (this.attributeFilter != null) {
#该Predicate的test和attributeName进行比较
return !this.attributeFilter.test(attributeName);
}
return false;
}
public Map<T, HandlerMethod> getHandlerMethods() {
#获取读锁
#为啥???
this.mappingRegistry.acquireReadLock();
try {
#将获得的mappingLookup封装到一个只读map中
return Collections.unmodifiableMap(this.mappingRegistry.getMappings());
}
finally {
#释放读锁
this.mappingRegistry.releaseReadLock();
}
}
#返回所有的mapping和handlerMethod
public Map<T, HandlerMethod> getMappings() {
return this.mappingLookup;
}
protected void handlerMethodsInitialized(Map<T, HandlerMethod> handlerMethods) {
// Total includes detected mappings + explicit registrations via registerMapping
int total = handlerMethods.size();
if ((logger.isTraceEnabled() && total == 0) || (logger.isDebugEnabled() && total > 0) ) {
logger.debug(total + " mappings in " + formatMappingName());
}
}
#提供了便捷的访问方法参数,参数类型,返回值,注解的类
public class HandlerMethod {
/** Logger that is available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
private final Object bean;
@Nullable
private final BeanFactory beanFactory;
private final Class<?> beanType;
private final Method method;
private final Method bridgedMethod;
private final MethodParameter[] parameters;
@Nullable
private HttpStatus responseStatus;
@Nullable
private String responseStatusReason;
@Nullable
private HandlerMethod resolvedFromHandlerMethod;
@Nullable
private volatile List<Annotation[][]> interfaceParameterAnnotations;
private final String description;}
至此,分析完了RequestMappingHandlerMapping在初始化所作的工作,就是将url和method的对应,将关系保存在RequestMappingHandlerMapping的mappingRegistry的相关属性中。
#RequestMappingHandlerMapping的工作流程
如果发起一个http请求,
#org.springframework.web.servlet.DispatcherServlet#getHandler
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
#遍历注册到spring mvc容器中的HandlerMapping(RequestMappingHandlerMapping是该类的子类)
for (HandlerMapping mapping : this.handlerMappings) {
#调用handlerMapping中的getHandler接口
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
#org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
#此时会调用AbstractHandlerMapping的gethandler接口
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
#getHandlerInternal为抽象接口,获得到最佳匹配的handlerMethod
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
#包含拦截器和handler
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#getHandlerInternal
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
#String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";
# 该属性可能在某些实现类中不支持,所以去掉
request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
try {
return super.getHandlerInternal(request);
}
finally {
ProducesRequestCondition.clearMediaTypesAttribute(request);
}
}
#org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
#获取请求路径
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
this.mappingRegistry.acquireReadLock();
try {
#该处为url匹配handlerMethod的核心逻辑,调用AbstractHandlerMethodMapping中的方法
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
#org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
#通过url查询RequestMappingInfo
#通过url获得info
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
#先是通过路径获得info,然后通过info列表获得handlerMethod,
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
#可能是由于通配符的问题没有匹配上
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
#假设第一个为最佳匹配的match
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
#使用request得到antpathcomparator
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
#返回第一个值
bestMatch = matches.get(0);
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
#如果是preflight,返回emptyHandler
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
Match secondBestMatch = matches.get(1);
#如果最大值有两个相等的,会抛出Ambiguous handler methods异常
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 + "}");
}
}
#String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler",将匹配好的handlermethod放入到request的attribute中
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
#抽象方法,给request设置相应的属性,比如pathvariable的解析值
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
#抛出方法不支持,比如HttpRequestMethodNotSupportedException,HttpMediaTypeNotSupportedException
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
#通过mapping和request进行匹配,判断request是否满足info中的condition条件,不满足说明该info和request不匹配返回null,
否则,返回该condition,然后通过所有的满足的conditon创建新的info对象返回
T match = getMatchingMapping(mapping, request);
if (match != null) {
#通过requestMappingInfo获得相应的HandlerMethod
matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
}
}
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#getMatchingMapping
protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, HttpServletRequest request) {
return info.getMatchingCondition(request);
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfo#getMatchingCondition
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
if (methods == null) {
return null;
}
#按照已经requestMappingInfo中的信息对request尽心匹配,匹配不上就返回
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;
}
#根据request中的path进行路径匹配,实现模糊匹配
PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request);
if (patterns == null) {
return null;
}
RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request);
if (custom == null) {
return null;
}
return new RequestMappingInfo(this.name, patterns,
methods, params, headers, consumes, produces, custom.getCondition());
}
#org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition#getMatchingCondition
public RequestMethodsRequestCondition getMatchingCondition(HttpServletRequest request) {
if (CorsUtils.isPreFlightRequest(request)) {
return matchPreFlight(request);
}
if (getMethods().isEmpty()) {
if (RequestMethod.OPTIONS.name().equals(request.getMethod()) &&
!DispatcherType.ERROR.equals(request.getDispatcherType())) {
return null; // We handle OPTIONS transparently, so don't match if no explicit declarations
}
return this;
}
return matchRequestMethod(request.getMethod());
}
#org.springframework.web.cors.CorsUtils#isPreFlightRequest
public static boolean isPreFlightRequest(HttpServletRequest request) {
#public static final String ORIGIN = "Origin";
# public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
#请求方法为OPTIONS,有origin和Access-Control-Request-Method请求头返回true
return (HttpMethod.OPTIONS.matches(request.getMethod()) &&
request.getHeader(HttpHeaders.ORIGIN) != null &&
request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null);
}
#如果是preflight请求,
private RequestMethodsRequestCondition matchPreFlight(HttpServletRequest request) {
if (getMethods().isEmpty()) {
return this;
}
String expectedMethod = request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD);
return matchRequestMethod(expectedMethod);
}
#org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition#getMethods
public Set<RequestMethod> getMethods() {
return this.methods;
}
#org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition#matchRequestMethod
private RequestMethodsRequestCondition matchRequestMethod(String httpMethodValue) {
RequestMethod requestMethod;
try {
requestMethod = RequestMethod.valueOf(httpMethodValue);
if (getMethods().contains(requestMethod)) {
#private static final Map<String, RequestMethodsRequestCondition> requestMethodConditionCache
return requestMethodConditionCache.get(httpMethodValue);
}
if (requestMethod.equals(RequestMethod.HEAD) && getMethods().contains(RequestMethod.GET)) {
#将head也是按照get处理吗?
return requestMethodConditionCache.get(HttpMethod.GET.name());
}
}
catch (IllegalArgumentException ex) {
// Custom request method
}
return null;
}
#org.springframework.web.servlet.mvc.condition.PatternsRequestCondition#getMatchingCondition
public PatternsRequestCondition getMatchingCondition(HttpServletRequest request) {
if (this.patterns.isEmpty()) {
return this;
}
String lookupPath = this.pathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
List<String> matches = getMatchingPatterns(lookupPath);
return !matches.isEmpty() ? new PatternsRequestCondition(new LinkedHashSet<>(matches), this) : null;
}
#org.springframework.web.util.UrlPathHelper#getLookupPathForRequest(javax.servlet.http.HttpServletRequest, java.lang.String)
public String getLookupPathForRequest(HttpServletRequest request, @Nullable String lookupPathAttributeName) {
if (lookupPathAttributeName != null) {
#request中的属性含有key-value:org.springframework.web.servlet.HandlerMapping.lookupPath -> /count/reuse
String result = (String) request.getAttribute(lookupPathAttributeName);
if (result != null) {
return result;
}
}
return getLookupPathForRequest(request);
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#getMappingComparator
@Override
protected Comparator<RequestMappingInfo> getMappingComparator(final HttpServletRequest request) {
return (info1, info2) -> info1.compareTo(info2, request);
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfo#compareTo
#实现接口方法org.springframework.web.servlet.mvc.condition.RequestCondition#compareTo
public int compareTo(RequestMappingInfo other, HttpServletRequest request) {
int result;
// Automatic vs explicit HTTP HEAD mapping
if (HttpMethod.HEAD.matches(request.getMethod())) {
result = this.methodsCondition.compareTo(other.getMethodsCondition(), request);
if (result != 0) {
return result;
}
}
#requestmapping定义中的模糊匹配问题
result = this.patternsCondition.compareTo(other.getPatternsCondition(), request);
if (result != 0) {
return result;
}
result = this.paramsCondition.compareTo(other.getParamsCondition(), request);
if (result != 0) {
return result;
}
result = this.headersCondition.compareTo(other.getHeadersCondition(), request);
if (result != 0) {
return result;
}
result = this.consumesCondition.compareTo(other.getConsumesCondition(), request);
if (result != 0) {
return result;
}
result = this.producesCondition.compareTo(other.getProducesCondition(), request);
if (result != 0) {
return result;
}
// Implicit (no method) vs explicit HTTP method mappings
result = this.methodsCondition.compareTo(other.getMethodsCondition(), request);
if (result != 0) {
return result;
}
result = this.customConditionHolder.compareTo(other.customConditionHolder, request);
if (result != 0) {
return result;
}
return 0;
}
#org.springframework.web.servlet.mvc.condition.PatternsRequestCondition#compareTo
public int compareTo(PatternsRequestCondition other, HttpServletRequest request) {
String lookupPath = this.pathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
#使用AntPatternComparator进行比较
Comparator<String> patternComparator = this.pathMatcher.getPatternComparator(lookupPath);
Iterator<String> iterator = this.patterns.iterator();
Iterator<String> iteratorOther = other.patterns.iterator();
while (iterator.hasNext() && iteratorOther.hasNext()) {
int result = patternComparator.compare(iterator.next(), iteratorOther.next());
if (result != 0) {
return result;
}
}
if (iterator.hasNext()) {
return -1;
}
else if (iteratorOther.hasNext()) {
return 1;
}
else {
return 0;
}
}
#org.springframework.util.AntPathMatcher#getPatternComparator
public Comparator<String> getPatternComparator(String path) {
return new AntPatternComparator(path);
}
#org.springframework.util.AntPathMatcher.AntPatternComparator#compare中的compare逻辑,该类实现Comparator接口
public int compare(String pattern1, String pattern2) {
PatternInfo info1 = new PatternInfo(pattern1);
PatternInfo info2 = new PatternInfo(pattern2);
#isLeastSpecific当pattern为空或者匹配所有
if (info1.isLeastSpecific() && info2.isLeastSpecific()) {
#等于
return 0;
}
else if (info1.isLeastSpecific()) {
#大于
return 1;
}
else if (info2.isLeastSpecific()) {
#小于
return -1;
}#排序的结果是全部匹配排在最后面
boolean pattern1EqualsPath = pattern1.equals(this.path);
boolean pattern2EqualsPath = pattern2.equals(this.path);
if (pattern1EqualsPath && pattern2EqualsPath) {
return 0;
}
else if (pattern1EqualsPath) {
return -1;
}
else if (pattern2EqualsPath) {
return 1;
}
if (info1.isPrefixPattern() && info2.isPrefixPattern()) {
#末尾以**结尾,路径长度更长的排在前面,路径更长意味更精确,如:/hello/ **和/hello/world/ **
return info2.getLength() - info1.getLength();
}
#以下为末尾以**开始排在最后
else if (info1.isPrefixPattern() && info2.getDoubleWildcards() == 0) {
return 1;
}
else if (info2.isPrefixPattern() && info1.getDoubleWildcards() == 0) {
return -1;
}
#更少数量的**,*,路径变量获胜,相等除外,比如:/hotels/abc*比/hotels/ * totalCount=1*(路径变量个数)+1*(*个数)+2*(**个数)
if (info1.getTotalCount() != info2.getTotalCount()) {
return info1.getTotalCount() - info2.getTotalCount();
}
#通配符的数量一样,长度长的获胜,长度长意味更精确,长度相等的情况下除外,比如://hotels/*和/hotels/{user}
if (info1.getLength() != info2.getLength()) {
return info2.getLength() - info1.getLength();
}
#拥有更少的*获胜,*个数相同除外
if (info1.getSingleWildcards() < info2.getSingleWildcards()) {
return -1;
}
else if (info2.getSingleWildcards() < info1.getSingleWildcards()) {
return 1;
}
#拥有更少的变量获胜
if (info1.getUriVars() < info2.getUriVars()) {
return -1;
}
else if (info2.getUriVars() < info1.getUriVars()) {
return 1;
}
return 0;
}
private static class PatternInfo {
@Nullable
private final String pattern;
private int uriVars;
private int singleWildcards;
private int doubleWildcards;
private boolean catchAllPattern;
private boolean prefixPattern;
@Nullable
private Integer length;
public PatternInfo(@Nullable String pattern) {
this.pattern = pattern;
if (this.pattern != null) {
initCounters();
#如果pattern是/ * *,表示匹配所有
this.catchAllPattern = this.pattern.equals("/**");
#如果是结尾,则是prefixPattern
this.prefixPattern = !this.catchAllPattern && this.pattern.endsWith("/**");
}
if (this.uriVars == 0) {
this.length = (this.pattern != null ? this.pattern.length() : 0);
}
}
protected void initCounters() {
int pos = 0;
if (this.pattern != null) {
while (pos < this.pattern.length()) {
#用于处理pathvariable,统计数量
if (this.pattern.charAt(pos) == '{') {
this.uriVars++;
pos++;
}
else if (this.pattern.charAt(pos) == '*') {
if (pos + 1 < this.pattern.length() && this.pattern.charAt(pos + 1) == '*') {
#统计**的个数
this.doubleWildcards++;
pos += 2;
}
else if (pos > 0 && !this.pattern.substring(pos - 1).equals(".*")) {
#统计*的格式
this.singleWildcards++;
pos++;
}
else {
pos++;
}
}
else {
pos++;
}
}
}
}
public int getUriVars() {
return this.uriVars;
}
public int getSingleWildcards() {
return this.singleWildcards;
}
public int getDoubleWildcards() {
return this.doubleWildcards;
}
#表示匹配所有
public boolean isLeastSpecific() {
return (this.pattern == null || this.catchAllPattern);
}
public boolean isPrefixPattern() {
return this.prefixPattern;
}
#变量个数,单*个数,双*个数 ,这样是合理的,因为变量可以通过个数参与路径匹配
public int getTotalCount() {
return this.uriVars + this.singleWildcards + (2 * this.doubleWildcards);
}
/**
* Returns the length of the given pattern, where template variables are considered to be 1 long.
*/
#pathvariable代表1个长度
public int getLength() {
if (this.length == null) {
this.length = (this.pattern != null ?
VARIABLE_PATTERN.matcher(this.pattern).replaceAll("#").length() : 0);
}
return this.length;
}
}
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
protected void handleMatch(RequestMappingInfo info, String lookupPath, HttpServletRequest request) {
#将lookupPath写入request的attribute中
super.handleMatch(info, lookupPath, request);
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();
#此时提取路径中的变量,用于支持pathvariable,https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/AntPathMatcher.html,核心是:extractUriTemplateVariables方法
uriVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath);
}
#String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
#支持MatrixVariables的写法
if (isMatrixVariableContentAvailable()) {
Map<String, MultiValueMap<String, String>> matrixVars = extractMatrixVariables(request, uriVariables);
request.setAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, matrixVars);
}
#将提取处的值只用获得request中的进行解密,String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables"
Map<String, String> decodedUriVariables = getUrlPathHelper().decodePathVariables(request, uriVariables);
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, decodedUriVariables);
if (!info.getProducesCondition().getProducibleMediaTypes().isEmpty()) {
Set<MediaType> mediaTypes = info.getProducesCondition().getProducibleMediaTypes();
request.setAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, mediaTypes);
}
}
#org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#handleMatch
protected void handleMatch(T mapping, String lookupPath, HttpServletRequest request) {
# String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping"
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, lookupPath);
}
#org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleNoMatch
protected HandlerMethod handleNoMatch(
Set<RequestMappingInfo> infos, String lookupPath, HttpServletRequest request) throws ServletException {
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);
}
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));
}
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;
}
public List<String> getMatchingPatterns(String lookupPath) {
List<String> matches = null;
for (String pattern : this.patterns) {
String match = getMatchingPattern(pattern, lookupPath);
if (match != null) {
matches = matches != null ? matches : new ArrayList<>();
matches.add(match);
}
}
if (matches == null) {
return Collections.emptyList();
}
if (matches.size() > 1) {
#
matches.sort(this.pathMatcher.getPatternComparator(lookupPath));
}
return matches;
}
private String getMatchingPattern(String pattern, String lookupPath) {
if (pattern.equals(lookupPath)) {
return pattern;
}
if (this.useSuffixPatternMatch) {
if (!this.fileExtensions.isEmpty() && lookupPath.indexOf('.') != -1) {
for (String extension : this.fileExtensions) {
if (this.pathMatcher.match(pattern + extension, lookupPath)) {
return pattern + extension;
}
}
}
else {
boolean hasSuffix = pattern.indexOf('.') != -1;
if (!hasSuffix && this.pathMatcher.match(pattern + ".*", lookupPath)) {
return pattern + ".*";
}
}
}
if (this.pathMatcher.match(pattern, lookupPath)) {
return pattern;
}
if (this.useTrailingSlashMatch) {
if (!pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath)) {
return pattern + "/";
}
}
return null;
}
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
#将adaptedInterceptors加入拦截链
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
总结:
controller中方法的解析流程
- 在requestMappingHandler的afterPropertiesSet进行初始化设置和调用父类的afterPropertiesSet
- 在父类AbstractHandlerMethodMapping的initHandlerMethods遍历spring mvc容器中的所有beanName,在processCandidateBean中根据 beanName判断该bean是否有@controller或者@requestMapping注解
- 在detectHandlerMethods中根据beanName获得实际使用的类型(代理类),遍历该类型中所有的method,解析方法和类上的requestmapping注解信息,将其进行combine为新的RequestMappingInfo进行返回,该类通过各种conditon封装了requestmapping注解的信息
- 在registerHandlerMethod方法中利用内部类mappingRegistry将info和handlerMethod保存到map中,完成方法的解析。
请求如何找到controller中的方法
-
在DispatcherServlet的getHandler方法中遍历所有注册是handlerMapping,分别调用它们的getHandler方法,返回HandlerExecutionChain对象,该对象包含了对应处理请求的handlerMethod和处理该请求的拦截器
-
requestMappingHandler的getHandler方法会调用父类AbstractHandlerMethodMapping的getHandler
-
AbstractHandlerMethodMapping的lookupHandlerMethod,mappingRegistry对象根据url得到info列表,通过info中的condition选择可以处理该次请求的info,新建matcher对象。设置comparator然后对match进行排序,然后选出最匹配的返回
-
涉及到对info进行排序,所以会调用RequestMappingInfo中的compareTo,该方法会调用各种condition的compareTo方法
-
在patternsCondition实际调用了AntPatternComparator中的compare方法,定义了路径的匹配规则:可以匹配所有路径/**的优先级最低,后缀为/**的优先级次之,
-
org.springframework.util.AntPathMatcher#combine是如何合并的??
根据spring介绍的combine的官方文档
public String combine(String pattern1,
String pattern2)
主要用于将pattern1和pattern2进行合并
pattern1 | pattern1 | result |
---|---|---|
null | null | |
/hotels | null | /hotels |
null | /hotels | /hotels |
/hotels | /books | /hotels/books |
/hotels | books | /hotels/books |
/hotels/* | /books | /hotels/books |
/hotels/** | /bookings | /hotels/**/bookings |
/hotels | {hotel} | /hotels/{hotel} |
/hotels/* | {hotel} | /hotels/{hotel} |
/hotels/** | {hotel} | /hotels/**/{hotel} |
- org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#pathPrefixes有何作用?
- org.springframework.beans.factory.config.EmbeddedValueResolver#resolveStringValue是如何工作的??
- SpringProxy的作用??
- KotlinType的作用??
- ReentrantReadWriteLock如何使用
- bridgeMethod的作用???
- StringJoiner 的使用
- Ambiguous mapping异常的过程
- CorsConfiguration的作用原理
- SearchStrategy原理
- 数组对象.copy
- LinkedHashMap 和hashmap的区别?LinkedHashSet和hashset?