handlerMapping的初始化以及查找handler
前提:HttpServletBean初始化了一些servlet配置,接着FrameWorkServlet创建了WebApplicationContext,最后DispatcherServlet初始化一些解析器,mapping(九大组件)。 一、从DispatcherServlet的doDispatch开始。
但WebApplicationContext加载完毕后FrameWorkdServlet调用DispatcherServlet的onRefresh方法
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
initStrategies方法如下:
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
这里初始化了九大组件,如果在初始化组件的时候没有明确规定使用那个组件时,会使用默认策略。 现在我们只关心initHandlerMappings(context);这个方法
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null; if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
//从applicationContext获取HandlerMapping.class类型的bean
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
} // Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
} 将找到的HandlerMapping全部存到DispatcherServlet的this.handlerMappings中 二、doDispatch方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try {
ModelAndView mv = null;
Exception dispatchException = null; try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request); // Determine handler for the current request.通过request获取HandlerExecutionChain,这个执行链中保存了handler和需要做拦截的拦截器
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
} // Determine handler adapter for the current request.通过handler寻找能够处理这个handler的handlerAdapter。
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
} if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
} // Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) {
return;
} applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
} 来看看getHandler方法
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
//遍历所有的HandlerMapping,如果这个handlerMapping能够找到handler,那么就会返回
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
} //调用handlerMpping的getHandler方法
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//调用模板方法getHandlerInternal,这个方法由子类实现
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?如果是String类型就从applicationContext中查找
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
//获取处理器链,内部在构造HandlerExecutionChain的同时会查找符合条件的拦截器
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
} AbstractHandlerMethodMapping的继承结构: 这个处理器映射是用来查找方法处理器 AbstractUrlHandlerMapping: 这种处理器是通过url来查找handler的,比如我们在配置文件中配置
<bean name=''/index" class="com.test.indexContrller" />
它的url是/index,如果有比较复杂的,那么就会使用PatchMatcher来匹配url,如果匹配就返回对应的handler。 @Override
public void initApplicationContext() throws BeansException {
super.initApplicationContext();
registerHandlers(this.urlMap);
} 初始化initApplicationContext方法初始化了一些拦截器。
registerHandlers注册了处理器。 protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
if (urlMap.isEmpty()) {
logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
}
else {
for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
String url = entry.getKey();
Object handler = entry.getValue();
// Prepend with slash if not already present.
if (!url.startsWith("/")) {
url = "/" + url;
}
// Remove whitespace from handler bean name.
if (handler instanceof String) {
handler = ((String) handler).trim();
}
registerHandler(url, handler);
}
}
} protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
Assert.notNull(urlPath, "URL path must not be null");
Assert.notNull(handler, "Handler object must not be null");
Object resolvedHandler = handler; // Eagerly resolve handler if referencing singleton via name.
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String) handler;
if (getApplicationContext().isSingleton(handlerName)) {
resolvedHandler = getApplicationContext().getBean(handlerName);
}
} Object mappedHandler = this.handlerMap.get(urlPath);
if (mappedHandler != null) {
if (mappedHandler != resolvedHandler) {
throw new IllegalStateException(
"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
}
}
else {
if (urlPath.equals("/")) {
if (logger.isInfoEnabled()) {
logger.info("Root mapping to " + getHandlerDescription(handler));
}
setRootHandler(resolvedHandler);
}
else if (urlPath.equals("/*")) {
if (logger.isInfoEnabled()) {
logger.info("Default mapping to " + getHandlerDescription(handler));
}
setDefaultHandler(resolvedHandler);
}
else {
this.handlerMap.put(urlPath, resolvedHandler);
if (logger.isInfoEnabled()) {
logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
}
}
}
} 以UrlPath handler的方式存入map。 @Override
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
//获取出去了ContextPath的uri
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
Object handler = lookupHandler(lookupPath, request);
if (handler == null) {
// We need to care for the default handler directly, since we need to
// expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
Object rawHandler = null;
//如果是web Contextpath的根路径就直接获取根处理器,这个处理器在registHandler方法时就set进去了
if ("/".equals(lookupPath)) {
rawHandler = getRootHandler();
}
if (rawHandler == null) {
rawHandler = getDefaultHandler();
}
if (rawHandler != null) {
// Bean name or resolved handler?
if (rawHandler instanceof String) {
String handlerName = (String) rawHandler;
rawHandler = getApplicationContext().getBean(handlerName);
}
//检验处理器,比如检验请求方法,看看是不是支持的请求方法。
validateHandler(rawHandler, request);
//
handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
}
}
if (handler != null && logger.isDebugEnabled()) {
logger.debug("Mapping [" + lookupPath + "] to " + handler);
}
else if (handler == null && logger.isTraceEnabled()) {
logger.trace("No handler mapping found for [" + lookupPath + "]");
}
return handler;
} buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);方法是这样的,设置了一些拦截器
protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
String pathWithinMapping, Map<String, String> uriTemplateVariables) { HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
}
return chain;
} 查找到handler后通过handler去寻找匹配的handlerAdapter,像simpleHandlerMapping弄出来的handler,其对应的adapter是SimpleControllerHandlerAdapter 它有个方法:@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
从这里可以看到它只支持实现了Controller的类。
看到这里其实我们也可以定义自己的HandlerMapping,实现getHandlerInterna方法,从applicationContext中寻找,加入我们自定义一个借口叫做IController package com.booway.custominterface; import org.springframework.web.servlet.ModelAndView; public interface IController { public ModelAndView IHandlerRequest() throws Exception; } 定义一个HandlerMapping package com.booway.customhandlermapping; import javax.servlet.http.HttpServletRequest; import org.springframework.util.PathMatcher;
import org.springframework.web.servlet.handler.AbstractHandlerMapping; import com.booway.custominterface.IController; public class ISimapleHandlerMapping extends AbstractHandlerMapping { @Override
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
String[] beanNames = super.getApplicationContext().getBeanNamesForType(IController.class);
String lookupPath = super.getUrlPathHelper().getLookupPathForRequest(request);
PathMatcher pathMatcher = getPathMatcher();
for (String beanName : beanNames) {
if(pathMatcher.match(beanName, lookupPath))
{
return super.getApplicationContext().getBean(beanName);
}
} return null;
} } 定义一个adapter
package com.booway.customhandleradapter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.LastModified; import com.booway.custominterface.IController; public class ISimpleHandlerAdapter implements HandlerAdapter { @Override
public boolean supports(Object handler) { return handler instanceof IController;
} @Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception { return ((IController)handler).IHandlerRequest();
} @Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
} } 定义一个controller package com.booway.controller; import org.springframework.web.servlet.ModelAndView; import com.booway.custominterface.IController; public class TestController implements IController { @Override
public ModelAndView IHandlerRequest() throws Exception { ModelAndView mav = new ModelAndView();
mav.setViewName("test");
return mav;
} } 在配置文件中配置响应的bean <bean name="/*" class="com.booway.controller.TestController"></bean> <bean id="handlerAdapter" class="com.booway.customhandleradapter.ISimpleHandlerAdapter"></bean> <bean id="handlerMapping" class="com.booway.customhandlermapping.ISimapleHandlerMapping">
//定义顺序,防止spring的HandlerMapping处理
<property name="order" value="1"></property>
</bean>
jsp页面
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>hello world</title>
</head>
<body>
<h1>hello world</h1>
</body>
</html> 结果: 三、来看看AbstractHandlerMethodMapping系列 由于AbstractHandlerMethodMapping实现了InitializingBean接口,所以会自动调用afterPropertiesSet方法,这个方法里面直接调用了initHandlerMethods方法
获取handler
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
//获取applicationContext中的所有bean,Obejct类是所有bean的基类
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class)); for (String beanName : beanNames) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
Class<?> beanType = null;
try {
//获取对应beanName的Bean的类型
beanType = getApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
}
handlerMethodsInitialized(getHandlerMethods());
} 看到isHandler方法: @Override
protected boolean isHandler(Class<?> beanType) {
return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
} 只要类上面标注了controller或者requestMapping就属于它能够处理的handler。 protected void detectHandlerMethods(final Object handler) {
//如果handler是String类型的就从ApplicationContext中获取它的类型,如果不是就直接获取它的类型
Class<?> handlerType = (handler instanceof String ?
getApplicationContext().getType((String) handler) : handler.getClass());
//获取用户的class,如果是Cglib代理类,那么就会获取它的父类class
final Class<?> userType = ClassUtils.getUserClass(handlerType); Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
new MethodIntrospector.MetadataLookup<T>() {
@Override
public T inspect(Method method) {
return getMappingForMethod(method, userType);
}
}); if (logger.isDebugEnabled()) {
logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);
}
for (Map.Entry<Method, T> entry : methods.entrySet()) {
registerHandlerMethod(handler, entry.getKey(), entry.getValue());
}
} MethodIntrospector.selectMethods public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) {
final Map<Method, T> methodMap = new LinkedHashMap<Method, T>();
Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>();
Class<?> specificHandlerType = null;
//目标类型是否是代理类
if (!Proxy.isProxyClass(targetType)) {
handlerTypes.add(targetType);
specificHandlerType = targetType;
}
handlerTypes.addAll(Arrays.asList(targetType.getInterfaces())); for (Class<?> currentHandlerType : handlerTypes) {
final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType); ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method 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;
} ReflectionUtils.doWithMethods public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
// Keep backing up the inheritance hierarchy.
//获取这个handler类的所有方法,当然也可能是接口的方法
Method[] methods = getDeclaredMethods(clazz);
for (Method method : methods) {
//mf.matches(method)使用的是传进来的匿名类
if (mf != null && !mf.matches(method)) {
continue;
}
try {
mc.doWith(method);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
}
}
if (clazz.getSuperclass() != null) {
doWithMethods(clazz.getSuperclass(), mc, mf);
}
else if (clazz.isInterface()) {
for (Class<?> superIfc : clazz.getInterfaces()) {
doWithMethods(superIfc, mc, mf);
}
}
} //这是doMatch方法中调用的一个方法
public static Method getMostSpecificMethod(Method method, Class<?> targetClass) {
//如果方法不为空,并且是可以重载的,即不是private修饰的,
if (method != null && isOverridable(method, targetClass) &&
targetClass != null && targetClass != method.getDeclaringClass()) {
try {
if (Modifier.isPublic(method.getModifiers())) {
try {
return targetClass.getMethod(method.getName(), method.getParameterTypes());
}
catch (NoSuchMethodException ex) {
return method;
}
}
else {
Method specificMethod =
ReflectionUtils.findMethod(targetClass, method.getName(), method.getParameterTypes());
return (specificMethod != null ? specificMethod : method);
}
}
catch (SecurityException ex) {
// Security settings are disallowing reflective access; fall back to 'method' below.
}
}
return method;
} getMappingForMethod(method, userType); @Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
info = typeInfo.combine(info);
}
}
return info;
} private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
//如果当前方法包含RequestMapping注解
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition<?> condition = (element instanceof Class<?> ?
getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
} 如果这个方法有requestMapping注解,那么就创建RequestMappingInfo对象
protected RequestMappingInfo createRequestMappingInfo(
RequestMapping requestMapping, RequestCondition<?> customCondition) { return RequestMappingInfo
.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
.methods(requestMapping.method())
.params(requestMapping.params())
.headers(requestMapping.headers())
.consumes(requestMapping.consumes())
.produces(requestMapping.produces())
.mappingName(requestMapping.name())
.customCondition(customCondition)
.options(this.config)
.build();
} 此方法返回后又回到了
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
info = typeInfo.combine(info);
}
}
return info;
}
这个方法
如果info 不为空,那么就检测类上面是否有requestMapping注解,如果有也创建一个requestMappingInfo对象,最后进行合并(combine)。
createRequestMappingInfo里面有判断当前方法是否为桥接方法,桥接方法是在泛型中出现的,这是因为编译器在编译时会擦除泛型,比如子类实现带泛型的父类,并且在实现的时候指定了这个泛型的类型,比如 public interface Action<T> {
public void eat(T t);
} public class DogAction implements Action<Dog> {
public void eat(Dog t) {
System.out.println("");
}
} 在编译字节码的时候会在DogAction 出现连个方法,一个是擦除泛型的方法
public void eat(Dog t) {
System.out.println("");
} 另一个是桥接方法
public void eat(Object t) {
this.eat((Dog)t);
} 由于在jdk5以前是没有泛型的,为了能得到兼容,所以就有了桥接方法,在jdk5以前是没有泛型的,
所以以前不管是什么都会当做Object的对象来处理,此时,如果传入了Object类型(实际类型是Dog)的,那么就会调用桥接方法,如果出入一个真实类型为Object的对象,那么在运行的时候就会报错。 最后构造methodMap.put(specificMethod, result);一个用method做为key,用requestMappingInfo做值的Map 接下来注册处理器存在HandlerMapping中等待使用
for (Map.Entry<Method, T> entry : methods.entrySet()) {
registerHandlerMethod(handler, entry.getKey(), entry.getValue());
} protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
} public void register(T mapping, Object handler, Method method) {
//获取写锁
this.readWriteLock.writeLock().lock();
try {
//创建handlerMethod对象
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
//判断该handle人Mthod是不是唯一的处理器,如果不是就抛出错误
assertUniqueMethodMapping(handlerMethod, mapping); if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
}
//将处理器方法按照requestMappingInfo-》handle人Mthod键值对的方式存入mappingLookup
this.mappingLookup.put(mapping, handlerMethod);
//获取可以映射到这个requestMappingInfo的url
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
//URLLookup是一个继承了Map的容器,不过它的值是一个list
this.urlLookup.add(url, mapping);
} String name = null;
if (getNamingStrategy() != null) {
//name-》handlermethod,命名策略使用的类名中大写字母的组合加#和方法名组成的key
name = getNamingStrategy().getName(handlerMethod, mapping);
//将以name-》handlermethod的方式加入到nameLookup这个map中,一样的值是一个list,这个list存着handlermethod
addMappingName(name, handlerMethod);
}
//初始化跨域配置
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
} this.registry.put(mapping, new MappingRegistration<T>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
} //创建handlermethod实例
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
HandlerMethod handlerMethod;
if (handler instanceof String) {
String beanName = (String) handler;
handlerMethod = new HandlerMethod(beanName,
getApplicationContext().getAutowireCapableBeanFactory(), method);
}
else {
handlerMethod = new HandlerMethod(handler, method);
}
return handlerMethod;
}
//handleMthod的构造方法
public HandlerMethod(Object bean, Method method) {
Assert.notNull(bean, "Bean is required");
Assert.notNull(method, "Method is required");
this.bean = bean;
this.beanFactory = null;
this.beanType = ClassUtils.getUserClass(bean);
this.method = method;
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
this.parameters = initMethodParameters();
this.resolvedFromHandlerMethod = null;
} //获取handlerMthod
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Looking up handler method for path " + lookupPath);
}
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
} protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
//这个match是一个内部类,有两个属性,分别为条件(默认是requestMappingInfo),handlerMethod
List<Match> matches = new ArrayList<Match>();
//通过url来查找条件(这里默认是requestMappinginfo)
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
//找到匹配的条件,比如比较他们的请求方法,参数,headers等
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()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
//排序,排序方法是根据条件进行排序的,其中url的匹配优先级最高
Collections.sort(matches, comparator);
if (logger.isTraceEnabled()) {
logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
lookupPath + "] : " + matches);
}
//第一个匹配的做为最佳
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
Match secondBestMatch = matches.get(1);
//对比连个匹配的处理器,如果完全相等,那么就抛出异常
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
}
}
//重新封装成handlermethod
handleMatch(bestMatch.mapping, lookupPath, request);
//返回新的处理器方法
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
} 获取到handler以后返回到
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
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 = getApplicationContext().getBean(handlerName);
}
//获取到handlerExecutionChain
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
} protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
//通过url找到需要拦截的拦截器
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
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;
} 得到HandlerExecutionChain 后回到doDispatcher()方法 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
} 找打匹配的适配器
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav;
//检查request的请求方法是否是允许的
checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
} if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
} return mav;
}
handlerMapping的初始化以及查找handler的更多相关文章
- SpringMVC源码解读 - HandlerMapping - RequestMappingHandlerMapping初始化
RequestMappingHandlerMapping ,用于注解@Controller,@RequestMapping来定义controller. @Controller @RequestMapp ...
- SpringMVC源码解读 - HandlerMapping - SimpleUrlHandlerMapping初始化
摘要: SimpleUrlHandlerMapping只是参与Handler的注册,请求映射时由AbstractUrlHandlerMapping搞定. 初始化时,通过setMappings(Prop ...
- SpringMVC请求处理流程源码
我们首先引用<Spring in Action>上的一张图来了解Spring MVC 的核心组件和大致处理流程: 从上图中看到①.DispatcherServlet 是SpringMVC ...
- SpringMVC笔记总结
文章所有代码见:gitee 1.回顾MVC 1.1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务逻辑.数据.显示分离 ...
- SpringMVC学习之使用注解编写SpringMVC程序
SpringMVC介绍 Spring的web框架围绕DispatcherServlet设计.DispatcherServlet的作用是将请求分发到不同的处理器.从Spring 2.5开始,使用Java ...
- Java系列教程-SpringMVC教程
SpringMVC教程 1.SpringMVC概述 1.回顾MVC 1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务 ...
- SpringMVC-初见
目录 什么是SpringMVC? DispatcherServlet 第一个MVC程序 配置版 Maven可能存在资源过滤的问题 注解版 RestFul和控制器 实现Controller接口 使用注解 ...
- SpringMVC配置版到注解版
什么是springmvc? 1.1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务逻辑.数据.显示分离的方法来组织代码 ...
- Spring核心原理分析之MVC九大组件(1)
本文节选自<Spring 5核心原理> 1 什么是Spring MVC Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,本质上相当于 S ...
随机推荐
- Application生命周期(一)
1.Application是什么? Application和Activity,Service一样,是android框架的一个系统组件,当android程序启动时系统会创建一个 application对 ...
- 老雷socket编程之websocket实现
老雷socket编程之websocket实现 我们主要实现私聊和群聊两个功能,要在web端实现想微信QQ那样的即时通讯的功能,我们需要了解一下websocket.websocket是一种可以双向通讯的 ...
- SQLPLUS执行PL/SQL语句块
1.首先登录Oracle HR schema: 2.对于PL/SQL程序,分号表示语句的结束:而使用 "." 号表示整个语句块的结束,也可以省略.按回车键后,该语句块不会执行,即 ...
- json数据转为对象,一般在前台把数据传回后端中使用 转https://www.cnblogs.com/zxtceq/p/6610214.html
public static JArray GetData2JArray(string url, string key) { string jsonData = HttpHelper.HttpGet(u ...
- Delphi7中Unicode,ANSI,UTF编码问题
注解: ANSI 'American Standard Code for Information Interchange' 美国信息互换标准代码 ANSI的'Ascii'编码 Unicode ...
- 【名额有限】云开发AI拓展能力等你来体验!
这次来了个超厉害的新能力! 人脸智能打马赛克.人脸智能裁剪--各种操作,都能一步到位! 迫不及待想体验,戳链接:https://wj.qq.com/s2/3986990/e0ef/ 还没有搞懂,继续往 ...
- 开源SFTP客户端 WinSCP v5.13.5 Build 8967 绿色便携版
下载地址:点我 基本介绍 WinSCP 是一款可以在微软 Windows 系统环境下使用的支持 SSH 命令的开源图形化 SFTP 客户端工具.同时也支持 SCP 文件传输协议,它的主要功能是在本地与 ...
- Excel中PMT函数的Java实现
public class PMT { /** * * 计算月供 * * @param rate * 年利率 年利率除以12就是月利率 * @param nper * 贷款期数,单位月 该项贷款的付款总 ...
- 剑指offer第二版-2.实现单例模式
面试题2:实现单例模式 题目要求: 设计一个类,只能生成该类的一个实例. /** * 单例模式 * 定义:指实现了特殊模式的类,该类仅能被实例化一次,产生唯一的一个对象 * 应用举例:windows的 ...
- HTML&CSS构建和设计网站
1.a链接:两个特性,href.target,href里添加mailto:邮箱可以直接链接到其它人的邮箱,添加#id,可以把窗口位置直接定位到该id的元素位置, target:_black可以在新的窗 ...