在使用SpringMvc
时,通过Controller
跟RequestMapping
,就能实现网络请求的处理。那么,这是怎么实现的呢?请求是如何从Tomcat
进入到controller
里的方法的呢?
宏观上看,流程如下:
DispatcherServlet
实例Tomcat
实例ServletContainerInitializer
以及ServletContextInitializer
将DispatcherServlet
注册到Tomcat
的Servlet
容器里HandlerMapping
绑定到DispatcherServlet
Tomcat
进到DispatcherServlet
DispatcherServlet
根据request path
到HandlerMapping
查找请求处理方法Spring
在初始化RequestMappingHandlerMapping
这个Bean时会将Controller
层带有RequestMapping等相关注解的方法跟注解信息的PATH分别作为key value注册到RequestMappingHandlerMapping
中。然后RequestMappingHandlerMapping
会在第一次请求到来时被注册到DispatcherServlet
RequestMappingHandlerMapping
继承了InitializingBean
,在Spring创建RequestMappingHandlerMapping
的实例时会去调用其afterPropertiesSet
方法进行初始化
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//判断当前bean是否继承了InitializingBean
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean) {
//初始化
((InitializingBean) bean).afterPropertiesSet();
}
}
}
RequestMappingHandlerMapping
会把所有的Spring Bean
对应的类里有Controller
或者RequestMapping
注解的类拿出来处理
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
...
}
//只处理有相应注解的bean
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
//判断是否有相应注解
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
}
把1.2里得到的类里的所有带有RequestMapping
注解的方法拿出来包装成RequestMappingInfo
并塞到RequestMappingHandlerMapping
内部的hashMap
中
public final class MethodIntrospector {
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;
handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType));
for (Class<?> currentHandlerType : handlerTypes) {
final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);
//通过反射找到targetType下的所有method
ReflectionUtils.doWithMethods(currentHandlerType, method -> {
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
//判断method上是否有@RequestMapping,没有则返回null
T result = metadataLookup.inspect(specificMethod);
if (result != null) {
//如果是桥接方法,就返回被桥接的方法。否则返回specificMethod
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
//如果specificMethod是桥接方法,则不添加到methodMap中。否则同一个方法就会被添加两次
if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
methodMap.put(specificMethod, result);
}
}
}, ReflectionUtils.USER_DECLARED_METHODS);
}
return methodMap;
}
}
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
// metadataLookup.inspect(specificMethod)是MetadataLookup#inspect的一个匿名实现
protected void detectHandlerMethods(Object handler) {
...
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
//根据方法是否被RequestMapping.class标注来判断方法是否可以被注册
return getMappingForMethod(method, userType);
});
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
//准备注册
registerHandlerMethod(handler, invocableMethod, mapping);
});
...
}
}
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
implements MatchableHandlerMapping, EmbeddedValueResolverAware {
//判断方法是否应该被注册
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
//判断方法上是否有RequestMapping.class
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition<?> condition = (element instanceof Class ?
getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
//创建RequestMappingInfo
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
}
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
//注册
public void register(T mapping, Object handler, Method method) {
...
//把类名handler跟方法method包装成一个HandlerMethod对象
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
//把方法注解里的path跟mapping的关系保存下来,
//后面访问的时候会先从httpRequest解析出path,再根据path找到mapping
Set<String> directPaths = AbstractHandlerMethodMapping.this.getDirectPaths(mapping);
for (String path : directPaths) {
this.pathLookup.add(path, mapping);
}
//mapping是上面创建的RequestMappingInfo
this.registry.put(mapping,
new MappingRegistration<>(mapping, handlerMethod, directPaths, name, corsConfig != null));
}
}
将HandlerMapping
注册到DispatcherServlet
。在第一次请求时进行初始化时触发
public class DispatcherServlet extends FrameworkServlet {
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
//从spring上下文里拿到所有实现了HandlerMapping的bean
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
//绑定
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
}
}
将DispatcherServlet
注册到Tomcat
的Servlet
容器里
public class ServletWebServerApplicationContext extends GenericWebApplicationContext
implements ConfigurableWebServerApplicationContext {
private void createWebServer() {
...
//创建webServer并添加下面的ServletContextInitializer匿名实现
this.webServer = factory.getWebServer(getSelfInitializer());
...
}
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
return this::selfInitialize;
}
private void selfInitialize(ServletContext servletContext) throws ServletException {
...
//找到所有实现了ServletContextInitializer接口的Spring bean
//这里拿到的是DispatcherServletRegistrationBean
//而DispatcherServletRegistrationBean里持有DispatcherServlet的Spring bean
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
//将DispatcherServlet注册到Tomcat的Servlet容器中
beans.onStartup(servletContext);
}
}
}
@Configuration(proxyBeanMethods = false)
protected static class DispatcherServletRegistrationConfiguration {
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
//通过DispatcherServlet创建DispatcherServletRegistrationBean
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
webMvcProperties.getServlet().getPath());
return registration;
}
}
public abstract class RegistrationBean implements ServletContextInitializer, Ordered {
@Override
public final void onStartup(ServletContext servletContext) throws ServletException {
//注册DispatcherServlet。最终会注册到StandardWrapper#setServlet
register(description, servletContext);
}
}
//Tomcat启动时触发
class TomcatStarter implements ServletContainerInitializer {
public void onStartup(Set<Class<?>> classes, ServletContext servletContext) throws ServletException {
//这里会拿到上面添加的匿名ServletContextInitializer
for (ServletContextInitializer initializer : this.initializers) {
initializer.onStartup(servletContext);
}
}
}
Tomcat
从Servlet容器中取出DispatcherServlet
,并将请求交给DispatcherServlet
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//根据request的url跟http method从RequestMappingHandlerMapping.registry中获取对应的
//请求处理器
mappedHandler = getHandler(processedRequest);
...
//调用请求处理方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
//遍历大步骤1小步骤4时注册进来的handlerMappings
for (HandlerMapping mapping : this.handlerMappings) {
//根据request path查找handler
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
}
RequestMappingHandlerMapping
根据HttpServletRequest
查找请求处理器
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
//解析出url的path
String lookupPath = initLookupPath(request);
this.mappingRegistry.acquireReadLock();
try {
//根据path找到对应的HandlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
//通过lookupPath找到mapping
List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
if (directPathMatches != null) {
//根据mapping从RequestMappingHandlerMapping#registry里
//找到对应的RequestMappingInfo并包装成Match对象,放入matches中
addMatchingMappings(directPathMatches, matches, request);
}
if (!matches.isEmpty()) {
Match bestMatch = matches.get(0);
//从RequestMappingInfo获取HandlerMethod
return bestMatch.getHandlerMethod();
}
}
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
T match = getMatchingMapping(mapping, request);
if (match != null) {
//根据mapping找到RequestMappingInfo并包装成Match对象
matches.add(new Match(match, this.mappingRegistry.getRegistrations().get(mapping)));
}
}
}
public Map<T, MappingRegistration<T>> getRegistrations() {
//第一步里的registry
return this.registry;
}
}