SpringMVC及其HandlerMapping、HandlerInterceptor、HandlerAdapter等组件的原理解析
SpringMVC的原理
加载的过程
关于加载,在SpringIOC的加载过程中,并不会直接将HandlerMapping
等组件给加载进去,而是在第一次请求的时候,进行初始化
SpringMVC核心类,DispatcherServlet的类图
关于DispatcherServlet
的初始化过程:由HttpServletBean
调用init()
,再由FrameworkServlet
实现initServletBean()
,最终由DispatcherServlet
实现onRefresh()
,并在其中加载初始化各个组件。
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);//加载上传解析器
initLocaleResolver(context);
initThemeResolver(context);//
initHandlerMappings(context);//加载初始化HandlerMapping
initHandlerAdapters(context);//加载初始化HandlerAdapter
initHandlerExceptionResolvers(context);//加载初始化HandlerException
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
HandlerMapping初始化过程
通过SpringBean工厂获取已经加载了的HandlerMapping
的实现类对象
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
//通过SpringIOC获取已经加载了的HandlerMapping的实现类对象
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
//省略。。。
}
在初始化的过程中,通过类型type从SpringIOC容器中去获取HandlerMapping的实现类
SpringBoot默认加载了5个HandlerMapping
的实现类:
RequestMappingHandlerMapping
:通过@RequestMapping映射的路径寻找到对应方法的类
WelcomePageHandlerMapping
:配置默认欢迎页时需要配置的类
BeanNameUrlHandlerMapping
:和下面的SimplerUrlHandlerMapping类似,都是通过xml文件的方式配置url,将url与对应的Controller的方法进行绑定
SimpleUrlHandlerMapping
:如上所说
在SpringMVC初始化之前,SpringIOC加载RequestMappingHandlerMapping
的时候,在AbstractAutowireCapableBeanFactory
构建好对象,并进行初始化(initializeBean()
)的时候,将各个@RequestMapping对应的Controller方法映射的String地址给注册到RequestMappingHandlerMapping
中
protected void detectHandlerMethods(Object handler) {
//...
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);
}
});
//...
//
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
//将对应的url映射到对应的Controller方法上
this.mappingRegistry.register(mapping, handler, method);
}
HandlerInterceptor在加载的时候
HandlerInterceptor
随着RequestMappingHandlerMapping
在SpringIOC中创建对象的同时,进行加载与初始化
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 实例化对象
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
//在实例化对象的包装器的时候,将HandlerInterceptor进行了加载与初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
// 对实例对象初始化
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
//
return exposedObject;
}
HandlerAdapter在加载的时候
和HandlerMapping
的流程类似,都是现在SpringIOC中加载、初始化对象,然后在SpringMVC第一次请求来的时候,将HandlerAdapter
的实现对象初始化到SpringMVC的上下文中。
HandlerAdapter
的常见实现类:
RequestMappingHandlerAdapter
:通过RequestMapping请求的处理器
HttpRequesthandlerAdapter
:静态资源处理器
SimpleControllerHandlerAdapter
:Controller
接口实现类的处理器,处理Controller
实现类的请求
``
SpringMVC的工作流程
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);
//1.通过请求的url找到应该使用哪个HandlerMapping,并获取到HandlerMapping的HandlerExecutionChain
//HandlerInterceptor就是在这里进行初始化的,每次请求来时,都会在HandlerExecutionChain对象中赋值
mappedHandler = getHandler(processedRequest);
//2.通过HandlerMethod找到其应该用哪个HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//3.执行HandlerInterptor中的preHandler
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//4.通过HandlerAdapter调用Contoller中的具体方法,并返回ModelAndView
//如果不返回ModelAndView,则直接响应用户了
//在这里面,有HandlerAdapter决定了如果处理请求体、响应体
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
//5.执行HandlerInterptor中的postHandler
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
}