剑指源码-springmvc-(三)-HandlerMapping和HandlerAdapter细节
本文最后更新于:2024年4月22日 下午
HandlerMapping的几种实现与HandlerAdapter几种原理及其内部细节剖析
初始化
HandlerMapping和HandlerAdapter初始化流程基本一致
1、DispatcherServlet创建对象后,Tomcat调用初始化回调钩子initServletBean()
2、容器启动完成后,Spring发送事件,执行到DispatcherServlet.onRefresh()
3、onRefresh执行九大组件的初始化
HandlerMapping初始化流程(RequestMappingHandlerMapping为例)
- 创建配置中的HandlerMapping对象3种
- 启动createBean使用IOC创建容器
- 基于Spring的原理,实现了InitializingBean,容器启动后续执行afterPropertiesSet
- 拿到子容器(Web容器)的所有组件,扫描@Controller或者@RequestMapping
- 将分析到的信息放于HandlerMapping的registry对象中,以便后续使用
HandlerMapping的实现类
BeanNameUrlHandlerMapping 以bean的名字作为url路径,进行映射
SimpleUrlHandlerMapping 手动配置url与handler的映射
RequestMappingHandlerMapping 使用注解的形式来标识url与handler的映射,平时这种使用最多,重点分析
RouterFunctionMapping 支持函数式以及webFlux相关的功能
BeanNameUrlHandlerMapping
public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {
/**
* Checks name and aliases of the given bean for URLs, starting with "/".
*/
@Override
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);
}
}
该实现类可以把IOC容器中name以”/“ 开头的Bean注册为handler,
SimpleUrlHandlerMapping
手动配置url与handler的映射,初始化的时候就注册进去了
RequestMappingHandlerMapping
这是最常用的HandlerMapping实现,通过它,我们可以使用注解的形式来标识url与handler的映射:
AbstractHandlerMethodMapping.initHandlerMethods然后执行到 processCandidateBean->detectHandlerMethods再到交由子类实现getMappingForMethod
RequestMappingHandlerMapping中getMappingForMethod
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);
}
会去判断实现RequestMapping的方法实现,而加入RequestMappingInfo信息中
RouterFunctionMapping
支持webflux相关
HandlerAdapter的实现类
- HttpRequestHandlerAdapter 判断是否是实现HttpRequestHandler接口
- SimpleControllerHandlerAdapter判断是否实现Controller接口
- RequestMappingHandlerAdapter 判断是不是HandlerMethod,注解类型的都是这种
public interface HandlerAdapter {
/**
* 是否支持该处理器
*/
boolean supports(Object handler);
/**
* 执行处理器,返回 ModelAndView 结果
*/
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
/**
* 返回请求的最新更新时间,如果不支持该操作,则返回 -1 即可
*/
@Deprecated
long getLastModified(HttpServletRequest request, Object handler);
}
HttpRequestHandlerAdapter
如果这个处理器实现了 HttpRequestHandler
接口,则使用 HttpRequestHandlerAdapter
调用该处理器的 handleRequest(HttpServletRequest request, HttpServletResponse response)
方法去处理器请求
SimpleControllerHandlerAdapter
和 HttpRequestHandlerAdapter 差不多,如果这个处理器实现了 Controoler
接口,则使用 HttpRequestHandlerAdapter
调用该处理器的 handleRequest(HttpServletRequest request, HttpServletResponse response)
方法去处理器请求,直接返回处理器执行后返回 ModelAndView
RequestMappingHandlerAdapter
实现 BeanFactoryAware、InitializingBean 接口,继承 AbstractHandlerMethodAdapter 抽象类,基于 @RequestMapping
注解的 HandlerMethod 处理器的 HandlerMethodAdapter 实现类
几个主要的属性对象:
HandlerMethodArgumentResolverComposite argumentResolvers
:参数处理器组合对象HandlerMethodReturnValueHandlerComposite returnValueHandlers
:返回值处理器组合对象List<HttpMessageConverter<?>> messageConverters
:HTTP 消息转换器集合对象List<Object> requestResponseBodyAdvice
: RequestResponseAdvice 集合对象
InitializingBean对参数初始化
这个时候会准备参数解析器和返回值处理器
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
initControllerAdviceCache();
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);
}
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
参数解析器和返回值处理器的前置工作
RequestMappingHandlerAdapter.invokeHandlerMethod
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
/**
* 用于组合执行期间所需要的一些组件
*/
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);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
LogFormatUtils.traceDebug(logger, traceOn -> {
String formatted = LogFormatUtils.formatValue(result, !traceOn);
return "Resume with async result [" + formatted + "]";
});
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
/**
* 具体执行期间,会传入临时容器mavContainer
*/
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
/**
* 从mavContainer抽取ModelAndView
*/
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
未来反射解析目标方法中的每一个值 argumentResolvers
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
返回值处理器,未来用于处理目标方法执行后的返回值,无论目标方法返回什么会转换为适配器所使用的ModelAndView
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
把该有的组件组合到ServletInvocableHandlerMethod对象中去,最终使用ServletInvocableHandlerMethod进行invokeAndHandle,将数据最后封装到ModelAndViewContainer中去,最后再将ModelAndViewContainer(临时容器,每一次请求都是新new 的对象,同一次请求期间共享数据)抽取ModelAndView(数据和视图)。
参数解析器
27个参数解析器
ServletInvocableHandlerMethod.invokeAndHandle–>invokeForRequest–>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;
}
/**
* 这里判断采用门面以27种都去判断一遍
*/
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
try {
/**
* 支持了就开始解析
*/
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
}
catch (Exception ex) {
// Leave stack trace for later, exception may actually be resolved and handled...
if (logger.isDebugEnabled()) {
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
logger.debug(formatArgumentError(parameter, exMsg));
}
}
throw ex;
}
}
return args;
}
返回值处理器
15个返回值处理器
ServletInvocableHandlerMethod.invokeAndHandle
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
/**
* 目标方法的放射执行
*/
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
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;
}
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
找到 returnValueHandlers 执行handleReturnValue
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
/**
* 找到合适的返回值处理器
*/
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
/**
* 执行返回值处理器的处理方法
*/
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
逻辑依然是以先找到为准
接下来执行后置的视图解析器相关业务流程
视图解析器
核心接口
public interface View {
String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
String PATH_VARIABLES = View.class.getName() + ".pathVariables";
String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";
@Nullable
default String getContentType() {
return null;
}
void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception;
}
public interface ViewResolver {
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
View 视图
ViewResolver 视图解析
流程分析
HandlerAdapter执行完成后会返回ModelAndView对象(里面包含viewName)
所有ViewResolver去解析viewName,一得到就返回,得到View对象,最后调用VIew对象render渲染