1.1 前言

  • 前几章介绍了HandlerMapping处理流程, HandlerMapping负责根据request请求找到对应的Handler处理器及Interceptor拦截器,得到处理器Handler之后,Spring MVC 又根据该Handler 找出对应的 HandlerAdapter,这一章节来介绍HandlerAdapterHandlerAdapter是具体使用Handler 来干活的

  • 下面还是方法体doDispatch(HttpServletRequest request, HttpServletResponse response) 的处理代码,可以看到得到Handler处理器之后就是遍历所有的 HandlerAdapter,找到可以处理该 HandlerHandlerAdapter,找到之后就是mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 调用真正的处理方法了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
// 获取当前请求的WebAsyncManager,如果没找到则创建并与请求关联
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {
ModelAndView mv = null;
Exception dispatchException = null;

try {
// 检查是否是文件上传请求 Multipart,有则将请求转换为 Multipart 请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

// Determine handler for the current request.
// 遍历所有的 HandlerMapping 找到与请求对应的 Handler,并将其与一堆拦截器封装到 HandlerExecution 对象中
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}

// Determine handler adapter for the current request.
// 遍历所有的 HandlerAdapter,找到可以处理该 Handler 的 HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// Process last-modified header, if supported by the handler.
// 处理 last-modified 请求头
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 执行相应拦截器Interceptor的preHandle
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

// Actually invoke the handler.
// 执行实际的处理程序,执行Controller里的方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

2.1 处理适配器HanlderAdapter解析

2.1.1 HanlderAdapter 解析

  • 先看HanlderAdapter 这个接口有哪些方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
* Handler 处理适配器, 适配不同的 Handler
*
* MVC framework SPI, allowing parameterization of the core MVC workflow.
*
* <p>Interface that must be implemented for each handler type to handle a request.
* This interface is used to allow the {@link DispatcherServlet} to be indefinitely
* extensible. The {@code DispatcherServlet} accesses all installed handlers through
* this interface, meaning that it does not contain code specific to any handler type.
*
* <p>Note that a handler can be of type {@code Object}. This is to enable
* handlers from other frameworks to be integrated with this framework without
* custom coding, as well as to allow for annotation-driven handler objects that
* do not obey any specific Java interface.
*
* <p>This interface is not intended for application developers. It is available
* to handlers who want to develop their own web workflow.
*
* <p>Note: {@code HandlerAdapter} implementors may implement the {@link
* org.springframework.core.Ordered} interface to be able to specify a sorting
* order (and thus a priority) for getting applied by the {@code DispatcherServlet}.
* Non-Ordered instances get treated as lowest priority.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
* @see org.springframework.web.servlet.handler.SimpleServletHandlerAdapter
*/
public interface HandlerAdapter {

/**
* 检测 HandlerAdapter 是否支持这个 handler
*
* Given a handler instance, return whether or not this {@code HandlerAdapter}
* can support it. Typical HandlerAdapters will base the decision on the handler
* type. HandlerAdapters will usually only support one handler type each.
* <p>A typical implementation:
* <p>{@code
* return (handler instanceof MyHandler);
* }
* @param handler handler object to check
* @return whether or not this object can use the given handler
*/
boolean supports(Object handler);

/**
* 处理 HttpServletRequest 的入口方法
*
* Use the given handler to handle this request.
* The workflow that is required may vary widely.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler to use. This object must have previously been passed
* to the {@code supports} method of this interface, which must have
* returned {@code true}.
* @throws Exception in case of errors
* @return ModelAndView object with the name of the view and the required
* model data, or {@code null} if the request has been handled directly
*/
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

/**
* 获取Http 请求中的lastModifiedTime
*
* Same contract as for HttpServlet's {@code getLastModified} method.
* Can simply return -1 if there's no support in the handler class.
* @param request current HTTP request
* @param handler handler to use
* @return the lastModified value for the given handler
* @see javax.servlet.http.HttpServlet#getLastModified
* @see org.springframework.web.servlet.mvc.LastModified#getLastModified
*/
long getLastModified(HttpServletRequest request, Object handler);

}
  • 下图是HanlderAdapter涉及子类的继承关系,看方法名是不是很熟悉,没错和前几章的HandlerMapping是差不多是一一对应的
image
image
  • 查看这些类可以看到除了RequestMappingHandlerAdapter 的实现比较复杂之外,其他的HandlerAdapter都是调用Handler里固定的方法,比如下图的SimpleControllerHandlerAdapter

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class SimpleControllerHandlerAdapter implements HandlerAdapter {

    @Override
    public boolean supports(Object handler) {
    return (handler instanceof Controller);
    }

    @Override
    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;
    }

    }
  • 查看AbstractHandlerMethodAdapter可以看到内容也很少,HandlerAdapter 接口的实现都转发到自己的抽象方法里去了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* Abstract base class for {@link HandlerAdapter} implementations that support
* handlers of type {@link HandlerMethod}.
*
* @author Arjen Poutsma
* @since 3.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
super(false);
}


/**
* Specify the order value for this HandlerAdapter bean.
* <p>Default value is {@code Integer.MAX_VALUE}, meaning that it's non-ordered.
* @see org.springframework.core.Ordered#getOrder()
*/
public void setOrder(int order) {
this.order = order;
}

@Override
public int getOrder() {
return this.order;
}


/**
* 先判断是否是HandlerMethod,然后转向抽象方法supportsInternal
* This implementation expects the handler to be an {@link HandlerMethod}.
* @param handler the handler instance to check
* @return whether or not this adapter can adapt the given handler
*/
@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

/**
* Given a handler method, return whether or not this adapter can support it.
* @param handlerMethod the handler method to check
* @return whether or not this adapter can adapt the given method
*/
protected abstract boolean supportsInternal(HandlerMethod handlerMethod);

/**
* 转向抽象方法 handleInternal()
* This implementation expects the handler to be an {@link HandlerMethod}.
*/
@Override
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {

return handleInternal(request, response, (HandlerMethod) handler);
}

/**
* Use the given handler method to handle the request.
* @param request current HTTP request
* @param response current HTTP response
* @param handlerMethod handler method to use. This object must have previously been passed to the
* {@link #supportsInternal(HandlerMethod)} this interface, which must have returned {@code true}.
* @return ModelAndView object with the name of the view and the required model data,
* or {@code null} if the request has been handled directly
* @throws Exception in case of errors
*/
protected abstract ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;

/**
* 转向抽象方法 getLastModifiedInternal()
* This implementation expects the handler to be an {@link HandlerMethod}.
*/
@Override
public final long getLastModified(HttpServletRequest request, Object handler) {
return getLastModifiedInternal(request, (HandlerMethod) handler);
}

/**
* Same contract as for {@link javax.servlet.http.HttpServlet#getLastModified(HttpServletRequest)}.
* @param request current HTTP request
* @param handlerMethod handler method to use
* @return the lastModified value for the given handler
*/
protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);

}

2.1.2 各个 HandlerAdapter作用

AnnotationMethodHandlerAdapter

AnnotationMethodHandlerAdapter主要是适配注解类处理器,注解类处理器就是我们经常使用的@Controller的这类处理器,不过该类已经被@Deprecated 标记了(@deprecated as of Spring 3.2, in favor of`)

1
2
3
4
@Override
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}

HttpRequestHandlerAdapter

HttpRequestHandlerAdapter 主要是适配静态资源处理器,静态资源处理器就是实现了HttpRequestHandler接口的处理器,这类处理器的作用是处理通过SpringMVC来访问的静态资源的请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
```

#### SimpleControllerHandlerAdapter
`SimpleControllerHandlerAdapter` 是`Controller`处理适配器,适配实现了`Controller`接口或`Controller`接口子类的处理器,比如我们经常自己写的`Controller`来继承`MultiActionController`

```java
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return ((Controller) handler).handleRequest(request, response);
}

SimpleServletHandlerAdapter

SimpleServletHandlerAdapterServlet处理适配器,适配实现了Servlet接口或Servlet的子类的处理器,我们不仅可以在web.xml里面配置Servlet,其实也可以用SpringMVC来配置Servlet,不过这个适配器很少用到,而且SpringMVC默认的适配器没有他,默认的是前面的三种。

1
2
3
4
5
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
((Servlet) handler).service(request, response);
return null;
}

2.1.3 HandlerAdapter 注册过程

  • HandlerAdapter 注册过程 和 HandlerMapping 的注册过程是一样的,回到DispatcherServlet 类中onRefresh 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    /**
    * Initialize the strategy objects that this servlet uses.
    * <p>May be overridden in subclasses in order to initialize further strategy objects.
    */
    protected void initStrategies(ApplicationContext context) {
    // 上传组件组件初始化
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    // 请求映射处理组件初始化
    initHandlerMappings(context);
    // 处理适配器组建初始化
    initHandlerAdapters(context);
    // 异常处理组件初始化
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    // 视图处理组件初始化
    initViewResolvers(context);
    initFlashMapManager(context);
    }
  • 进入initHandlerAdapters(context); 从下面代码也可以看到也是通过扫描HandlerAdapterbean的形式来注册HandlerAdapter

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    /**
    * Initialize the HandlerAdapters used by this class.
    * <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace,
    * we default to SimpleControllerHandlerAdapter.
    */
    private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;

    if (this.detectAllHandlerAdapters) {
    // 加载所有实现了HandlerAdapter接口的bean
    // 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<HandlerAdapter>(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.
    if (this.handlerAdapters == null) {
    this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
    if (logger.isDebugEnabled()) {
    logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
    }
    }
    }

3.1 适配器设计模式

  • HanlderAdapter看后缀名就可以理解它使用了适配器模式

  • Spring MVChandler有多种形式,由于实现方式不一样, Handler 有可能是一个 HandlerMethod(封装了 Controller 中的方法)对象,也有可能是一个 Controller 对象、 HttpRequestHandler 对象或 Servlet 对象,而这个 Handler 具体是什么对象,调用方式就不确定了。

  • 如果正常编写调用,就需要使用多个if else判断instance of,再添加实现方式,就需要修改源码,不符合对扩展开放,对修改关闭原则, 所以针对这种情况设计了HanlderAdapter,如果是添加了新的Handler只要添加一个新的HanlderAdapter就可以完成扩展

4.1 总结

  • HanlderAdapter 从字面上的意思就是处理适配器,他的作用就是根据用户的请求调用具体的方法,根据HandlerMapping传过来Hanler与注册好的HandlerAdapter一一匹配,如果找到了其中一种HandlerAdapter是支持传过来的controller类型,那么该HandlerAdapter会调用自己的handle方法
  • 不同的HanlderAdapter可以适应不同的request需求

5.1 参考

官方文档: https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html

https://www.jianshu.com/p/3d6df6b725e4

https://blog.csdn.net/weixin_38399962/article/details/85288660