概述
目录
onRefresh
HandlerMapping
SimpleUrlHandlerMapping
BeanNameUrlHandlerMapping
RequestMappingHandlerMapping
detectHandlerMethods
getMappingForMethod
registerHandlerMethod
HandlerAdapter
SimpleControllerHandlerAdapter
RequestMappingHandlerAdapter
afterPropertiesSet
handle
SpringMVC的核心就是DispatcherServlet,本质还是一个Servlet,用于分发HTTP请求,调用相应的Handler处理请求。Servlet的生命周期是初始化init(),处理请求service(),销毁destroy(),挨个学习之
public final void init() throws ServletException {
initServletBean();
}
protected final void initServletBean() throws ServletException {
try {
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();// 空方法
}
catch (ServletException | RuntimeException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
}
protected WebApplicationContext initWebApplicationContext() {
// 从ServletContext获取Spring父容器,如果有,那么springmvc子容器需要和父容器进行关联
// 没有也不影响
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
// 为什么init时context会不为空?
// 因为FrameworkServlet实现了ApplicationContextAware 接口,在作为bean交给spring容器管理时会调用setApplicationContext将容器注入进来
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
if (!cwac.isActive()) {
// 如果容器还没有调用refresh方法,关联父容器,然后调用refresh
// 但是我还不知道哪种方式能走到这,被ApplicationContextAware 注入了webApplicationContext,一般容器已经refresh过了
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
// 若当前ServletContext已存在刷新好的webapplicationcontext,提供了路子去查询,web.xml配置
// <init-param>
// <param-name>contextAttribute</param-name>
// <param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
// </init-param>
// 像上边配置这样,就是spring和springmvc容器使用同一个容器了
wac = findWebApplicationContext();
}
if (wac == null) {
// 既没注入又没配置,则创建,实例默认是XmlWebApplicationContext
// 并调用context.refresh,加载xml文件中的配置
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
// 加载springmvc的九组件,组件此时已经被实例化为bean,这一步其实是在选择相应的组件实例
onRefresh(wac);
}
if (this.publishContext) {
// 将当前context设置到ServletContext中
// attrName = org.springframework.web.servlet.FrameworkServlet.CONTEXT. + servlet名
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
}
return wac;
}
onRefresh
各组件的bean已经被加载到当前springmvc容器中,这一步是选择相应的组件实例关联到dispatcherServlet中 。组件除了文件解析之外都有默认组件,默认组件配置在DispatcherServlet同目录的DispatcherServlet.properties中,如下
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
// context.getBean("multipartResolver", MultipartResolver.class)
// 关联配置的文件解析,没有默认空
initMultipartResolver(context);
// context.getBean("localeResolver", LocaleResolver.class)
// 国际化处理,没配默认org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
initLocaleResolver(context);
// context.getBean("themeResolver", ThemeResolver.class)
// 主题处理,没有默认org.springframework.web.servlet.theme.FixedThemeResolver
initThemeResolver(context);
// 查询context下处理器映射器HandlerMapping.class实现类,一般都会使用下边两个
// BeanNameUrlHandlerMapping和RequestMappingHandlerMapping
initHandlerMappings(context);
// 查询context下处理器适配器HandlerAdapter.class实现类,常见的
// RequestMappingHandlerAdapter、SimpleControllerHandlerAdapter、HttpRequestHandlerAdapter
initHandlerAdapters(context);
// 异常处理器
initHandlerExceptionResolvers(context);
// 视图名称翻译器
initRequestToViewNameTranslator(context);
// 页面渲染处理器
initViewResolvers(context);
// 参数传递管理器
initFlashMapManager(context);
}
下边阅读最常见的HandlerMapping和HandlerAdapter组件,其他的再说吧
HandlerMapping
HandlerMapping组件充当url和Controller之间映射关系配置的角色,接口如下,根据请求获取对应的处理器Handler,HandlerExecutionChain是Handler的马甲,封装了一层
public interface HandlerMapping {
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
来看常用的几个实现类的源码
SimpleUrlHandlerMapping
配置方法如图
配置一个class为SimpleUrlHandlerMapping的Bean,mappings属性中配置处理器路径和处理器类的对应关系,每个处理器类也需要作为bean配置。
类核心代码如下,在创建bean实例的时候,Spring调用setMappings将xml中的mappings配置设置到urlMap,这时只是url和beanName的对应关系,AbstractUrlHandlerMapping父类实现了ApplicationContextAware接口,所以会进入initApplicationContext方法中初始化,在registerHandlers()方法中取出urlMap中的beanName,根据beanName获取对应Bean对象,然后组成真正的url和Controller的对应关系存放在父类属性handlerMap中
public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
private final Map<String, Object> urlMap = new LinkedHashMap<>();
public SimpleUrlHandlerMapping() {
}
public void setMappings(Properties mappings) {
CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap);
}
@Override
public void initApplicationContext() throws BeansException {
super.initApplicationContext();
registerHandlers(this.urlMap);
}
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
if (urlMap.isEmpty()) {
logger.trace("No patterns in " + formatMappingName());
}
else {
urlMap.forEach((url, handler) -> {
// 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);
});
}
}
}
getHandler(HttpServletRequest request)
处理请求的时候使用getHandler()来获取请求对应的处理器,核心就是从handlerMap中根据url获取对应的handler,套层马甲HandlerExecutionChain返回
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 = obtainApplicationContext().getBean(handlerName);
}
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
//。。。
return executionChain;
}
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
Object handler = lookupHandler(lookupPath, request);
return handler;
}
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
// 看了半天,核心就是这里,从handlerMap中根据url获取
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
return buildPathExposingHandler(handler, urlPath, urlPath, null);
}
return handler;
}
BeanNameUrlHandlerMapping
配置如下
与SimpleUrlHandlerMapping同源,都是继承自AbstractUrlHandlerMapping,都是将url和handler对应关系放到handlerMap,不同的是BeanNameUrlHandlerMapping将xml配置文件中所有beanName是斜杠开头的bean都视为handler注册到BeanNameUrlHandlerMapping的handlerMap
public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping {
private boolean detectHandlersInAncestorContexts = false;
public void setDetectHandlersInAncestorContexts(boolean detectHandlersInAncestorContexts) {
this.detectHandlersInAncestorContexts = detectHandlersInAncestorContexts;
}
@Override
public void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();
detectHandlers();
}
protected void detectHandlers() throws BeansException {
// 获取当前容器所有的beanName
ApplicationContext applicationContext = obtainApplicationContext();
String[] beanNames = (this.detectHandlersInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
applicationContext.getBeanNamesForType(Object.class));
for (String beanName : beanNames) {
// 获取符合条件的bean,注册为handler
String[] urls = determineUrlsForHandler(beanName);
if (!ObjectUtils.isEmpty(urls)) {
// 从容器中根据beanName获取bean并放入handlerMap中
registerHandler(urls, beanName);
}
}
}
protected abstract String[] determineUrlsForHandler(String beanName);
}
public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {
// ‘/’开头的beanName,注册为handler
protected String[] determineUrlsForHandler(String beanName) {
List<String> urls = new ArrayList<>();
if (beanName.startsWith("/")) {
urls.add(beanName);
}
String[] aliases = obtainApplicationContext().getAliases(beanName);
for (String alias : aliases) {
if (alias.startsWith("/")) {
urls.add(alias);
}
}
return StringUtils.toStringArray(urls);
}
}
RequestMappingHandlerMapping
注解方式的handlerMapping(@Controller)
在Bean初始化后的afterPropertiesSet()方法中进行Controller的处理,获取controller中被@RequestMapping注解的方法,并封装相关信息到RequestMappingHandlerMapping中
private static final String SCOPED_TARGET_NAME_PREFIX = "scopedTarget.";
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
for (String beanName : getCandidateBeanNames()) {
// springaop的狸猫换太子,将原bean对象的beanName前缀改为scopedTarget.beanName
// 而beanName对应的bean对象替换为了代理对象,这里只处理代理对象
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
}
protected void processCandidateBean(String beanName) {
// 获取bean类的class
Class<?> beanType = null;
try {
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);
}
}
// 判断如果类有controller注解或RequestMapping,表示是个handlerMapping
// 再进一步获取其中定义的处理方法
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
detectHandlerMethods
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
// 如果是CGLIB代理的类,获取源类
Class<?> userType = ClassUtils.getUserClass(handlerType);
// MethodIntrospector.selectMethods工具类方法,是用来获取类中某些符合条件的method列表
// MetadataLookup函数式接口是选择符合条件方法的具体逻辑
// 这里用来获取被requestMapping注解的方法
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);
}
});
// 将查找出来的方法列表挨个注册到RequestMappingHandlerMapping中
methods.forEach((method, mapping) -> {
// 这里没搞懂,看着是用来获取AOP代理包装后的Method,但是我测了测invocableMethod==method,暂时没弄明白,略过
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
// 注册handler方法和mapping的对应关系
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
getMappingForMethod
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
// 获取方法上注解的@RequestMapping注解,并封装为RequestMapypingInfo对象
RequestMapypingInfo info = createRequestMappingInfo(method);
if (info != null) {
// 获取Controller类上注解的@RequestMapping注解,并封装为RequestMapypingInfo对象
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
// 合并相关信息,请求路径合并
if (typeInfo != null) {
info = typeInfo.combine(info);
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
}
}
return info;
}
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
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);
}
protected RequestMappingInfo createRequestMappingInfo(
RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {
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();
}
registerHandlerMethod
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 {
// controller类和对应method 封一个马甲
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
// 校验请求路径是否有重复
validateMethodMapping(handlerMethod, mapping);
// 以下就是保存mapping和方法的对应关系、请求路径和mapping对应等等
this.mappingLookup.put(mapping, handlerMethod);
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
getHandler(HttpServletRequest request)
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
this.mappingRegistry.acquireReadLock();
try {
// 从上边各种对应关系中获取匹配的HandlerMethod返回,详细的代码暂时没看
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
HandlerAdapter
public interface HandlerAdapter {
boolean supports(Object handler);
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);
}
SpringMVC的HandlerMapping定义了多种配置处理器的方式,每种方式的处理器不同的实现方式,例如实现Controller接口、@Controller/@RequestMapping注解配置等等,实现不同所以调用方式也不同,那么在springmvc通过handlerMapping查找到具体的Handler实例时,就需要写很多if...else...来根据不同的实现方式进行调用。
而HandlerAdapter就用来解决这个if..else。采用适配器模式(通过组合、继承的方式将某个不符合预期的接口转换为所需要的接口)。
- supports(handler) 返回本适配器是否支持该类型的处理器
- handle(request, response, handler) 进行适配调用
下边是我的测试代码,随便一个类作为实现的handler,增加一个HandlerAdapter使这个类能由springmvc管理并进行调用
handler
public class Test2Controller {
public ModelAndView aaaa(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("dadasda");
return null;
}
}
xml配置
<bean name="/tests" class="com.lyq.enjoy.test.Test2Controller"></bean>
adapter
@Component
public class MyHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
// 表示本适配器只支持Test2Controller类型的处理器
Class clazz = handler.getClass();
if (handler instanceof String) {
clazz = SpringBeanUtil.getBean((String) handler).getClass();
}
return clazz.equals(Test2Controller.class);
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 适配调用
return ((Test2Controller) handler).aaaa(request, response);
}
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
return 0;
}
}
SimpleControllerHandlerAdapter
比较简单,这就是继承Controller方式所使用的适配器
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}
RequestMappingHandlerAdapter
@RequestMapping
类型的Handler的适配器
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
}
主要的作用是
- 调用handler前,@RequestParam/@ModelAttribute相关的参数转换,将参数转换为controller中方法所需要的参数
- 调用handler执行处理
- 对handler返回值处理,统一封装为ModelAndView
来详细看源码处理,RequestMappingHandlerAdapter实现了InitializingBean,那么先来看afterPropertiesSet()初始化方法
afterPropertiesSet
各种组件的初始化:@ControllerAdvice配置的获取、参数解析器、返回值解析器的获取等
public void afterPropertiesSet() {
// 先处理@ControllerAdvice注解,这都是些全局配置
// 全局异常处理、请求入参处理、响应参数处理
initControllerAdviceCache();
// handlerMethod的请求参数转换器,可以自定义(WebMvcConfigurer.addArgumentResolvers)
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// 参数绑定
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// 返回值处理器,将返回值处理为ModleAndView
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
private void initControllerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
// 获取容器中所有@ControllerAdvice注解的bean
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
// 获取类中定义的全局的@ModelAttribute注解方法,优先于Controller中定义的@ModelAttribute
Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
}
// 获取类中定义的全局的@InitBinder注解方法,优先于Controller中定义的@InitBinder
Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(adviceBean, binderMethods);
}
// RequestBodyAdvice/ResponseBodyAdvice用于在请求前后进行统一参数处理
// 如果该ControllerAdvice还实现了RequestBodyAdvice/ResponseBodyAdvice
if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
}
}
if (!requestResponseBodyAdviceBeans.isEmpty()) {
this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
}
}
handle
判断是否需要对session加锁,然后调用handlerMethod
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// 判断当前session是否只允许单线程处理请求,如果是,加锁处理
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);
}
// Cache-Control请求头相关处理,暂时不懂,先看主干逻辑
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
1、获取全局和Controller中的InitBinder 和 ModelAttribute
2、执行ModelAttribute方法
3、参数转换、调用handlerMethod、返回值转换
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
// 获取ControllerAdvice定义的全局InitBinder和Controller中定义的InitBinder
// 准备进行参数绑定
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
// 获取ControllerAdvice定义的全局ModelAttribute和Controller中定义的ModelAttribute
// 在调用HandlerMethod方法之前调用
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// handlerMethod的一层封装
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
// 设置方法入参解析器
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
// 设置返回值解析器
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
// 调用上边查找到的ModelAttribute方法
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
// 异步请求处理的代码,暂时忽略
。。。。。
// 对请求参数进行处理
// 调用HandlerMethod
// 将返回值封装为一个ModelAndView对象
invocableMethod.invokeAndHandle(webRequest, mavContainer);
// 如果请求已经返回客户端,返回null,否则构造ModelAndView
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 参数转换和调用handlermethod
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// 如果方法被@ResponseStatus注解,重置响应状态码和响应信息
setResponseStatus(webRequest);
// 如果方法被@ResponseStatus注解,返回值为null,直接返回处理完毕
// 如果注解配置了Reason属性,不管有没有返回值都不予理睬
// returnValue == null的其他两个或分支不知道
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
disableContentCachingIfNecessary(webRequest);
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
// 处理返回值,封装为ModelAndView
mavContainer.setRequestHandled(false);
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
return doInvoke(args);
}
getMethodArgumentValues
获取方法参数类型,循环挑选对应的解析器进行转换,默认的转换器列表见下图,详细的后续有空写写
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
}
return args;
}
this.returnValueHandlers.handleReturnValue
对返回值的处理也是类似,有很多的处理器,从中挑选相应的处理器进行处理
过两天有空再准备将上边的某些部分,比如@InitBinder、@ModelAttribute、异步请求、HandlerMethodArgumentResolver、HandlerMethodReturnValueHandler还有异常处理HandlerExceptionResolver拉出来详细看看
最后
以上就是小巧冰淇淋为你收集整理的SpringMVC源码笔记(一) DispatcherServlet.initonRefreshHandlerMappingHandlerAdapter 的全部内容,希望文章能够帮你解决SpringMVC源码笔记(一) DispatcherServlet.initonRefreshHandlerMappingHandlerAdapter 所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复