补充一波SpringMVC源码分析, 请求至响应分析 (版本:
v5.3.6
)
会扫描创建好URL : 处理器, 封装进一个Map;
入口类:
RequestMappingHandlerMapping
当应用上下文创建该
RequestMappingHandlerMapping
时候, 创建完Bean后会触发后续一些操作, 进行注册URL : 处理器 封装进一个Map中;
// RequestMappingHandlerMapping.java
public void afterPropertiesSet() {
// 映射一些配置
this.config = new RequestMappingInfo.BuilderConfiguration();
this.config.setTrailingSlashMatch(useTrailingSlashMatch());
this.config.setContentNegotiationManager(getContentNegotiationManager());
if (getPatternParser() != null) {
this.config.setPatternParser(getPatternParser());
Assert.isTrue(!this.useSuffixPatternMatch && !this.useRegisteredSuffixPatternMatch,
"Suffix pattern matching not supported with PathPatternParser.");
}
else {
this.config.setSuffixPatternMatch(useSuffixPatternMatch());
this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
this.config.setPathMatcher(getPathMatcher());
}
// 调用父类AbstractHandlerMethodMapping 的afterPropertiesSet方法
super.afterPropertiesSet();
}
// AbstractHandlerMethodMapping
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
// obtainApplicationContext().getBeanNamesForType(Object.class) 获取应用上下文所有注册的bean名称
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
// 所有URL => 处理器 映射完毕后调用, 获取到对应Map, 然后handlerMethodsInitialized 输出日志
handlerMethodsInitialized(getHandlerMethods());
}
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
// 获取对应Bean类型
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);
}
}
// 判断是否是处理器
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
// RequestMappingHandlerMapping.java
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
// AbstractHandlerMethodMapping
protected void detectHandlerMethods(Object handler) {
// 获取处理器类型
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
// 获取定义类型, 防止获取到生成的子类
Class<?> userType = ClassUtils.getUserClass(handlerType);
//
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);
}
});
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
else if (mappingsLogger.isDebugEnabled()) {
mappingsLogger.debug(formatMappings(userType, methods));
}
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
入口
WebMvcConfigurationSupport # requestMappingHandlerAdapter()
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcValidator") Validator validator) {
// 创建请求映射处理器适配器
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
adapter.setContentNegotiationManager(contentNegotiationManager);
// 设置消息转换器集合
adapter.setMessageConverters(getMessageConverters());
// 设置数据绑定
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
// 设置自定义参数转换解析器
adapter.setCustomArgumentResolvers(getArgumentResolvers());
// 设置自定义返回值转换处理程序
adapter.setCustomReturnValueHandlers(getReturnValueHandlers());
if (jackson2Present) {
adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
}
AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
if (configurer.getTaskExecutor() != null) {
adapter.setTaskExecutor(configurer.getTaskExecutor());
}
if (configurer.getTimeout() != null) {
adapter.setAsyncRequestTimeout(configurer.getTimeout());
}
adapter.setCallableInterceptors(configurer.getCallableInterceptors());
adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());
return adapter;
}
RequestBodyAdvice和ResponseBodyAdvice接口 (针对于
@RequestBody
、@ResponseBody
, 参数处理增强)非使用
@RequestBody
、@ResponseBody
, 参考 框架提供的 自定义实现一个参数解析器、响应参数处理 (扩展1.0有个简单例子)
1
请求是如何找到对应控制器类中对应方法, 转换参数进行执行的呢?
入口类:
org.springframework.web.servlet.DispatcherServlet # doService()
doService()
方法只是设置了请求域中的一些属性, 然后会接着调用doDispatch(request, response)
这个方法才是真正的请求后续大量处理入口
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
// 获取异步请求管理器 (https://www.cnblogs.com/deityjian/p/11503218.html)
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 (根据请求获取映射处理器)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request. 通过处理器找适配器
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 (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;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", 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);
}
}
}
}
mappedHandler = getHandler(processedRequest)
同时找到了处理器和执行链
HandlerExecutionChain handler = mapping.getHandler(request)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler())
,
到此整个请求处理过程的关键步骤都分析完了。理解了SpringMVC
V5.x版本上
中的请求处理流程;
甚至可以定义添加Converters参数转换器来实现
@Configuration
public class MyMVCConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new HandlerMethodArgumentResolver() {
// post请求 json交互可以使用实现Advice接口增加请求前参数处理
// 非json交互 post, get请求, 方法参数实体, 参考 ServletModelAttributeMethodProcessor实现
// 非json交互 get 请求, 方法参数非实体 参考 RequestParamMethodArgumentResolver实现
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameter().getParameterizedType() == UserOne.class;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Class parameterizedType = (Class) parameter.getParameter().getParameterizedType();
Object target = parameterizedType.newInstance();
WebDataBinder binder = binderFactory.createBinder(webRequest, target, parameter.getParameter().getName());
ServletRequest servletRequest = webRequest.getNativeRequest(ServletRequest.class);
ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
servletBinder.bind(servletRequest);
return binder.getBindingResult().getTarget();
}
});
WebMvcConfigurer.super.addArgumentResolvers(resolvers);
}
一般使用
@ResponseBody
返回的使用Advice接口返回视图的参考:
ViewNameMethodReturnValueHandler
, 或者在源码HandlerMethodReturnValueHandlerComposite#handleReturnValue()
参考返回值使用的是那个, 参考着写
1