Spring HandlerAdapter组件
阅读数:121 评论数:0
跳转到新版页面分类
python/Java
正文
一、概述
Spring 中的处理器的实现多变,比如用户的处理器可以实现 Controller 接口或者 HttpRequestHandler 接口,也可以用 @RequestMapping
注解将方法作为一个处理器等,这就导致 Spring MVC 无法直接执行这个处理器。所以这里需要一个处理器适配器,由它去执行处理器。
在DispatcherServlet的doDispatch方法中
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
ModelAndView mv = null;
// ... 省略相关代码
// <3> 获得请求对应的 HandlerExecutionChain 对象(HandlerMethod 和 HandlerInterceptor 拦截器们)
mappedHandler = getHandler(processedRequest);
// ... 省略相关代码
// <4> 获得当前 handler 对应的 HandlerAdapter 对象
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// ... 省略相关代码
// <6> 真正的调用 handler 方法,也就是执行对应的方法,并返回视图
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// ... 省略相关代码
}
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [...");
}
通过遍历 HandlerAdapter 组件们,判断是否支持处理该 handler
处理器,支持则返回该 HandlerAdapter 组件。获取处理器对应 HandlerAdapter 组件是有一定的先后顺序的,默认是HttpRequestHandlerAdapter -> SimpleControllerHandlerAdapter -> RequestMappingHandlerAdapter
二、HandlerAdapter
public interface HandlerAdapter {
/**
* 是否支持该处理器
*/
boolean supports(Object handler);
/**
* 执行处理器,返回 ModelAndView 结果
*/
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
/**
* 返回请求的最新更新时间,如果不支持该操作,则返回 -1 即可
*/
long getLastModified(HttpServletRequest request, Object handler);
}
在 DispatcherServlet
的 initHandlerAdapters(ApplicationContext context)
方法,会在 onRefresh
方法被调用,初始化 HandlerAdapter 组件
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
}
// Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
/**
* 如果未获得到,则获得默认配置的 HandlerAdapter 类
* {@link org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter}
* {@link org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter}
* {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter}
*/
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
基于 HttpRequestHandler
接口的 HandlerAdapter 实现类
public class HttpRequestHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
// 判断是 HttpRequestHandler 类型
return (handler instanceof HttpRequestHandler);
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// HttpRequestHandler 类型的调用
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
// 处理器实现了 LastModified 接口的情况下
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}
// org.springframework.web.HttpRequestHandler.java
@FunctionalInterface
public interface HttpRequestHandler {
/**
* 处理请求
*/
void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
}
如果这个处理器实现了 HttpRequestHandler
接口,则使用 HttpRequestHandlerAdapter
调用该处理器的 handleRequest(HttpServletRequest request, HttpServletResponse response)
方法去处理器请求,返回 null
3、SimpleControllerHandlerAdapter
基于 Controller
接口的 HandlerAdapter 实现类
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
// <1> 判断是 Controller 类型
return (handler instanceof Controller);
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// <2> Controller 类型的调用
return ((Controller) handler).handleRequest(request, response);
}
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
// 处理器实现了 LastModified 接口的情况下
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}
@FunctionalInterface
public interface Controller {
/**
* 处理请求
*/
@Nullable
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
如果这个处理器实现了 Controoler
接口,则使用 HttpRequestHandlerAdapter
调用该处理器的 handleRequest(HttpServletRequest request, HttpServletResponse response)
方法去处理器请求,直接返回处理器执行后返回 ModelAndView
4、AbstractHandlerMethodAdapter
实现 HandlerAdapter、Ordered 接口,继承 WebContentGenerator 抽象类,基于 HandlerMethod 的 HandlerMethodAdapter 抽象类
(1)构造方法
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
/** 最低优先级 */
private int order = Ordered.LOWEST_PRECEDENCE;
public AbstractHandlerMethodAdapter() {
// no restriction of HTTP methods by default
// 调用 WebContentGenerator 类的构造方法
// 参数 restrictDefaultSupportedMethods 参数为 false ,表示不需要严格校验 HttpMethod
super(false);
}
}
(2)supports方法
判断是否支持该处理器
@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
protected abstract boolean supportsInternal(HandlerMethod handlerMethod);
处理器必须是 HandlerMethod 类型,还需要调用抽象方法 supportsInternal(HandlerMethod handlerMethod)
判断是否支持, 交由子类去实现
(3)handle方法
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
@Nullable
protected abstract ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;
直接调用 handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
抽象方法,交由子类去实现
(4)getLastModified方法
获得最后更新时间
@Override
public final long getLastModified(HttpServletRequest request, Object handler) {
return getLastModifiedInternal(request, (HandlerMethod) handler);
}
protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);
5、RequestMappingHandlerAdapter
实现 BeanFactoryAware、InitializingBean 接口,继承 AbstractHandlerMethodAdapter 抽象类,基于 @RequestMapping
注解的 HandlerMethod 处理器的 HandlerMethodAdapter 实现类
(1)构造方法
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
/**
* MethodFilter that matches {@link InitBinder @InitBinder} methods.
*/
public static final MethodFilter INIT_BINDER_METHODS = method ->
AnnotatedElementUtils.hasAnnotation(method, InitBinder.class);
/**
* MethodFilter that matches {@link ModelAttribute @ModelAttribute} methods.
*/
public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method ->
(!AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) &&
AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class));
@Nullable
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
@Nullable
private HandlerMethodArgumentResolverComposite argumentResolvers;
@Nullable
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
@Nullable
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
@Nullable
private List<ModelAndViewResolver> modelAndViewResolvers;
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
private List<HttpMessageConverter<?>> messageConverters;
private List<Object> requestResponseBodyAdvice = new ArrayList<>();
@Nullable
private WebBindingInitializer webBindingInitializer;
private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync");
@Nullable
private Long asyncRequestTimeout;
private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0];
private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0];
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
private boolean ignoreDefaultModelOnRedirect = false;
private int cacheSecondsForSessionAttributeHandlers = 0;
/**
* 是否对相同 Session 加锁
*/
private boolean synchronizeOnSession = false;
private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
@Nullable
private ConfigurableBeanFactory beanFactory;
// ========== 缓存 ==========
private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64);
private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);
private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>();
private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64);
private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>();
// ... 省略 getter、setter 方法
public RequestMappingHandlerAdapter() {
// 初始化 messageConverters
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316
this.messageConverters = new ArrayList<>(4);
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(stringHttpMessageConverter);
try {
this.messageConverters.add(new SourceHttpMessageConverter<>());
}
catch (Error err) {
// Ignore when no TransformerFactory implementation is available
}
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}
}
在构造方法中默认会添加了四个 HttpMessageConverter 对象,当然,默认还会添加其他的,例如 MappingJackson2HttpMessageConverter 为 JSON 消息格式的转换器
HandlerMethodArgumentResolverComposite argumentResolvers |
参数处理器组合对象 |
HandlerMethodReturnValueHandlerComposite returnValueHandlers |
返回值处理器组合对象 |
List<HttpMessageConverter<?>> messageConverters |
HTTP 消息转换器集合对象 |
List<Object> requestResponseBodyAdvic |
RequestResponseAdvice 集合对象 |
(2)afterPropertiesSet方法
因为 RequestMappingHandlerAdapter 实现了 InitializingBean 接口,在 Sping 初始化该 Bean 的时候,会调用该方法,完成一些初始化工作
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
// <1> 初始化 ControllerAdvice 相关
initControllerAdviceCache();
// <2> 初始化 argumentResolvers 属性
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// <3> 初始化 initBinderArgumentResolvers 属性
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// <4> 初始化 returnValueHandlers 属性
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
(3)initControllerAdviceCache方法
private void initControllerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
// <1> 扫描 @ControllerAdvice 注解的 Bean 们,生成对应的 ControllerAdviceBean 对象,并将进行排序
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
AnnotationAwareOrderComparator.sort(adviceBeans);
List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();
// <2> 遍历 ControllerAdviceBean 数组
for (ControllerAdviceBean adviceBean : adviceBeans) {
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
// <2.1> 扫描有 `@ModelAttribute` ,无 `@RequestMapping` 注解的方法,添加到 `modelAttributeAdviceCache` 属性中
// 该类方法用于在执行方法前修改 Model 对象
Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
}
// <2.2> 扫描有 `@InitBinder` 注解的方法,添加到 `initBinderAdviceCache` 属性中
// 该类方法用于在执行方法前初始化数据绑定器
Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(adviceBean, binderMethods);
}
// <2.3> 如果是 RequestBodyAdvice 或 ResponseBodyAdvice 的子类,添加到 requestResponseBodyAdviceBeans 中
if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
}
}
// <2.3> 将 requestResponseBodyAdviceBeans 添加到 this.requestResponseBodyAdvice 属性种
if (!requestResponseBodyAdviceBeans.isEmpty()) {
this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
}
// 打印日志
if (logger.isDebugEnabled()) {
int modelSize = this.modelAttributeAdviceCache.size();
int binderSize = this.initBinderAdviceCache.size();
int reqCount = getBodyAdviceCount(RequestBodyAdvice.class);
int resCount = getBodyAdviceCount(ResponseBodyAdvice.class);
if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) {
logger.debug("ControllerAdvice beans: none");
}
else {
logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize +
" @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice");
}
}
}
(4)getDefaultArgumentResolvers
初始化默认的参数解析器
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new SessionAttributeMethodArgumentResolver());
resolvers.add(new RequestAttributeMethodArgumentResolver());
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
(5)getDefaultInitBinderArgumentResolvers方法
初始化默认的参数绑定器
private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new SessionAttributeMethodArgumentResolver());
resolvers.add(new RequestAttributeMethodArgumentResolver());
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
return resolvers;
}
(6)getDefaultReturnValueHandlers方法
初始化默认的返回值处理器
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();
// Single-purpose return value types
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
handlers.add(new StreamingResponseBodyReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
this.contentNegotiationManager, this.requestResponseBodyAdvice));
handlers.add(new HttpHeadersReturnValueHandler());
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
// Annotation-based return value types
handlers.add(new ModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
this.contentNegotiationManager, this.requestResponseBodyAdvice));
// Multi-purpose return value types
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
// Custom return value types
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
// Catch-all
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
handlers.add(new ModelAttributeMethodProcessor(true));
}
return handlers;
}
(7)supportsInternal方法
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
直接返回 true
,也就是说处理器只要是 HandlerMethod 对象就可以
(8)handleInternal
@Override
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response,
HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
// <1> 校验请求(HttpMethod 和 Session 的校验)
checkRequest(request);
// <2> 调用 HandlerMethod 方法
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) { // 同步相同 Session 的逻辑,默认情况false
HttpSession session = request.getSession(false);
if (session != null) {
// 获取Session的锁对象
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);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) { // 响应不包含'Cache-Control'头
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
三、ServletInvocableHandlerMethod
继承 HandlerMethod 类,可 invoke 调用的 HandlerMethod 实现类。
(1)构造方法
public class InvocableHandlerMethod extends HandlerMethod {
/** 无参时的入参,空数组 */
private static final Object[] EMPTY_ARGS = new Object[0];
/** 数据绑定器工厂 */
@Nullable
private WebDataBinderFactory dataBinderFactory;
/** 参数解析器组合对象 */
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
/** 方法的参数名称发现器 */
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
}
(2)invokeForRequest
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// <1> 解析参数
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
// <2> 执行调用
return doInvoke(args);
}
(3)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 对象,并设置 parameterNameDiscoverer 到其中
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
// <1> 先从 providedArgs 中获得参数。如果获得到,则进入下一个参数的解析,默认情况 providedArgs 不会传参
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
// <2> 判断 resolvers 是否支持当前的参数解析
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;
}
2、ServletInvocableHandlerMethod
继承 InvocableHandlerMethod 类,用于 DispatcherServlet 执行 HandlerMethod 处理器
(1)构造函数
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
private static final Method CALLABLE_METHOD = ClassUtils.getMethod(Callable.class, "call");
/** 返回结果处理器组合对象 */
@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
public ServletInvocableHandlerMethod(Object handler, Method method) {
super(handler, method);
}
public ServletInvocableHandlerMethod(HandlerMethod handlerMethod) {
super(handlerMethod);
}
}
(2)invokeAndHandle
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// <1> 执行调用
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// <2> 设置响应状态码
setResponseStatus(webRequest);
// <3> 设置 ModelAndViewContainer 为请求已处理,返回,和 @ResponseStatus 注解相关
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;
}
// <4> 设置 ModelAndViewContainer 为请求未处理
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
// <5> 处理返回值
this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
} catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
四、HandlerMethodArgumentResovler
在 HandlerAdapter
执行处理器的过程中,具体的执行过程交由 ServletInvocableHandlerMethod
对象来完成,其中需要先通过 HandlerMethodArgumentResolver 参数解析器从请求中解析出方法的入参,然后再通过反射机制调用对应的方法。
1、HandlerMethodArgumentResolverComposite
(1)构造方法
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
/**
* HandlerMethodArgumentResolver 数组
*/
private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>();
/**
* MethodParameter 与 HandlerMethodArgumentResolver 的映射,作为缓存
*/
private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache = new ConcurrentHashMap<>(256);
}
(2)getArgumentResolver
获得方法参数对应的 HandlerMethodArgumentResolver 对象
@Nullable
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
// 优先从 argumentResolverCache 缓存中,获得 parameter 对应的 HandlerMethodArgumentResolver 对象
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
// 获得不到,则遍历 argumentResolvers 数组,逐个判断是否支持。
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
// 如果支持,则添加到 argumentResolverCache 缓存中,并返回
if (resolver.supportsParameter(parameter)) {
result = resolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
(3)supportsParameter
如果能获得到对应的 HandlerMethodArgumentResolver 参数处理器,则说明支持处理该参数
@Override
public boolean supportsParameter(MethodParameter parameter) {
return getArgumentResolver(parameter) != null;
}
(4)resolveArgument
解析出指定参数的值
@Override
@Nullable
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
// 获取参数解析器
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
if (resolver == null) {
throw new IllegalArgumentException("Unsupported parameter type [" +
parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
}
/**
* 进行解析
*
* 基于 @RequestParam 注解
* {@link org.springframework.web.method.annotation.RequestParamMethodArgumentResolver#resolveArgument}
* 基于 @PathVariable 注解
* {@link org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver#resolveArgument}
*/
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
2、AbstractNamedValueMethodArgumentResolver
基于名字获取值的HandlerMethodArgumentResolver 抽象基类,其常见的两个子类,一个基于@RequestParam注解的RequestParamMethodArgumentResolver;另一个是基于@PathVariable注解的PathVariableMethodArgumentResolver。
(1)构造方法
public abstract class AbstractNamedValueMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Nullable
private final ConfigurableBeanFactory configurableBeanFactory;
@Nullable
private final BeanExpressionContext expressionContext;
/**
* MethodParameter 和 NamedValueInfo 的映射,作为缓存
*/
private final Map<MethodParameter, NamedValueInfo> namedValueInfoCache = new ConcurrentHashMap<>(256);
}
(2)NameValueInfo内部类
protected static class NamedValueInfo {
/**
* 名字
*/
private final String name;
/**
* 是否必填
*/
private final boolean required;
/**
* 默认值
*/
@Nullable
private final String defaultValue;
public NamedValueInfo(String name, boolean required, @Nullable String defaultValue) {
this.name = name;
this.required = required;
this.defaultValue = defaultValue;
}
}
(3)getNamedValueInfo
private NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
// <1> 从 namedValueInfoCache 缓存中,获得 NamedValueInfo 对象
NamedValueInfo namedValueInfo = this.namedValueInfoCache.get(parameter);
if (namedValueInfo == null) {
// <2> 获得不到,则创建 namedValueInfo 对象。这是一个抽象方法,子类来实现
namedValueInfo = createNamedValueInfo(parameter);
// <3> 更新 namedValueInfo 对象
namedValueInfo = updateNamedValueInfo(parameter, namedValueInfo);
// <4> 添加到 namedValueInfoCache 缓存中
this.namedValueInfoCache.put(parameter, namedValueInfo);
}
return namedValueInfo;
}
(4)resolveArgument
从请求中解析出指定参数的值
@Override
@Nullable
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
// <1> 获得方法参数对应的 NamedValueInfo 对象。
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
// <2> 如果 parameter 是内嵌类型(Optional 类型)的,则获取内嵌的参数。否则,还是使用 parameter 自身
MethodParameter nestedParameter = parameter.nestedIfOptional();
// <3> 如果 name 是占位符,则进行解析成对应的值
Object resolvedName = resolveStringValue(namedValueInfo.name);
if (resolvedName == null) {
// 如果解析不到,则抛出 IllegalArgumentException 异常
throw new IllegalArgumentException(
"Specified name must not resolve to null: [" + namedValueInfo.name + "]");
}
// <4> 解析 name 对应的值
Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
// <5> 如果 arg 不存在,则使用默认值
if (arg == null) {
// <5.1> 使用默认值
if (namedValueInfo.defaultValue != null) {
arg = resolveStringValue(namedValueInfo.defaultValue);
}
// <5.2> 如果是必填,则处理参数缺失的情况
else if (namedValueInfo.required && !nestedParameter.isOptional()) {
handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
}
// <5.3> 处理空值的情况
arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
}
// <6> 如果 arg 为空串,则使用默认值
else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
arg = resolveStringValue(namedValueInfo.defaultValue);
}
// <7> 数据绑定相关
if (binderFactory != null) {
WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
try {
arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
}
catch (ConversionNotSupportedException ex) {
throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
namedValueInfo.name, parameter, ex.getCause());
}
catch (TypeMismatchException ex) {
throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
namedValueInfo.name, parameter, ex.getCause());
}
}
// <8> 处理解析的值
handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
return arg;
}
对于 RequestParamMapMethodArgumentResolver 类,它的效果是,将所有参数添加到 Map 集合中
// Controller.java
@RequestMapping("/hello")
public String hello4(@RequestParam Map<String, Object> map) {
return "666";
}
发送请求 GET /hello?name=yyy&age=20
,name
和 age
参数,就会都添加到 map
中
对于 RequestParamMethodArgumentResolver 类,它的效果是,将指定名字的参数添加到 Map 集合中
// Controller.java
@RequestMapping("/hello")
public String hello5(@RequestParam(name = "map") Map<String, Object> map) {
return "666";
}
发送请求 GET /hello4?map={"name": "yyyy", age: 20}
, map
参数的元素则都会添加到方法参数 map
中
五、HandlerMethodReturnValueHandler
获取到执行结果后需要通过 HandlerMethodReturnValueHandler 结果处理器来进行处理。
主要是作为 Model 和 View 的容器
(1)构造方法
public class ModelAndViewContainer {
/**
* 是否在 redirect 重定向时,忽略 {@link #redirectModel}
*/
private boolean ignoreDefaultModelOnRedirect = false;
/**
* 视图,Object 类型。
*
* 实际情况下,也可以是 String 类型的逻辑视图
*/
@Nullable
private Object view;
/**
* 默认使用的 Model 。实际上是个 Map
*/
private final ModelMap defaultModel = new BindingAwareModelMap();
/**
* redirect 重定向的 Model ,在重定向时使用。
*/
@Nullable
private ModelMap redirectModel;
/**
* 处理器返回 redirect 视图的标识
*/
private boolean redirectModelScenario = false;
/**
* Http 响应状态
*/
@Nullable
private HttpStatus status;
private final Set<String> noBinding = new HashSet<>(4);
private final Set<String> bindingDisabled = new HashSet<>(4);
/**
* 用于设置 SessionAttribute 的标识
*/
private final SessionStatus sessionStatus = new SimpleSessionStatus();
/**
* 请求是否处理完的标识
*/
private boolean requestHandled = false;
}
2、HandlerMethodReturnValueHandlerComposite
(1)构造方法
public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler {
/** HandlerMethodReturnValueHandler 数组 */
private final List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<>();
}
3、RequestResponseBodyMethodProcessor
处理方法参数添加了 @RequestBody
注解方法入参,或者处理方法添加了 @ResponseBody
注解的返回值。
因为前后端分离之后,后端基本是提供 Restful API ,所以 RequestResponseBodyMethodProcessor 成为了目前最常用的 HandlerMethodReturnValueHandler 实现类。
4、ViewNameMethodReturnValueHandler
ViewNameMethodReturnValueHandler 适用于前后端未分离,Controller 返回视图名的场景,例如 JSP、Freemarker 等等。
六、HttpMessageConverter
@RequestBody
和 @ResponseBody
两个注解,分别完成请求报文到 Java 对象、Java 对象到响应报文的转换,底层的实现就是通过 Spring 3.x 中引入的 HttpMessageConverter 消息转换机制来实现的。
public interface HttpMessageConverter<T> {
/** 能否读取 */
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
/** 能够写入 */
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
/** 获取支持的 MediaType */
List<MediaType> getSupportedMediaTypes();
/** 读取请求体 */
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/** 设置响应体 */
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
1、AbstractHttpMessageConverter
(1)构造方法
public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> {
/**
* 支持的 MediaType
*/
private List<MediaType> supportedMediaTypes = Collections.emptyList();
/**
* 默认的字符集
*/
@Nullable
private Charset defaultCharset;
protected AbstractHttpMessageConverter() {
}
protected AbstractHttpMessageConverter(MediaType supportedMediaType) {
setSupportedMediaTypes(Collections.singletonList(supportedMediaType));
}
protected AbstractHttpMessageConverter(MediaType... supportedMediaTypes) {
setSupportedMediaTypes(Arrays.asList(supportedMediaTypes));
}
protected AbstractHttpMessageConverter(Charset defaultCharset, MediaType... supportedMediaTypes) {
this.defaultCharset = defaultCharset;
setSupportedMediaTypes(Arrays.asList(supportedMediaTypes));
}
}
(2)canRead
是否支持从请求中读取该类型的方法参数
@Override
public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType) {
return supports(clazz) && canRead(mediaType);
}
protected abstract boolean supports(Class<?> clazz);
protected boolean canRead(@Nullable MediaType mediaType) {
if (mediaType == null) {
return true;
}
for (MediaType supportedMediaType : getSupportedMediaTypes()) {
if (supportedMediaType.includes(mediaType)) {
return true;
}
}
return false;
}
其中 supports(Class<?> clazz)
抽象方法,交由子类去实现
(3)canWrite
是否支持往响应中写入该类型的返回结果
@Override
public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
return supports(clazz) && canWrite(mediaType);
}
protected abstract boolean supports(Class<?> clazz);
protected boolean canWrite(@Nullable MediaType mediaType) {
if (mediaType == null || MediaType.ALL.equalsTypeAndSubtype(mediaType)) {
return true;
}
for (MediaType supportedMediaType : getSupportedMediaTypes()) {
if (supportedMediaType.isCompatibleWith(mediaType)) {
return true;
}
}
return false;
}
(4)read
从请求中读取该类型的方法参数
@Override
public final T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
return readInternal(clazz, inputMessage);
}
protected abstract T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
其中 readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
抽象方法,交由子类去实现
(5)write
往响应中写入该类型的返回结果
@Override
public final void write(final T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
// <1> 获取响应头
final HttpHeaders headers = outputMessage.getHeaders();
// <2> 如果 Content-Type 为空则设置默认的
addDefaultHeaders(headers, t, contentType);
// <3> 往响应中写入数据
if (outputMessage instanceof StreamingHttpOutputMessage) { // <3.1> 如果是流,则再封装一层
StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
streamingOutputMessage.setBody(outputStream -> writeInternal(t, new HttpOutputMessage() {
@Override
public OutputStream getBody() {
return outputStream;
}
@Override
public HttpHeaders getHeaders() {
return headers;
}
}));
}
else { // <3.2> 普通对象
writeInternal(t, outputMessage);
outputMessage.getBody().flush();
}
}
protected abstract void writeInternal(T t, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
继承 AbstractHttpMessageConverter 抽象类,String 类型的消息转换器
3、AbstractJackson2HttpMessageConverter
继承 AbstractGenericHttpMessageConverter 抽象类,JSON 格式的消息读取或者写入,也就是我们熟悉的 @RequestBody
和 @ResponseBody
注解对应的 HttpMessageConverter 消息转换器
4、MappingJackson2HttpMessageConverter
继承 AbstractJackson2HttpMessageConverter 抽象类,JSON 格式的消息读取或者写入,也就是我们熟悉的 @RequestBody
和 @ResponseBody
注解对应的 HttpMessageConverter 消息转换器