基于 SpringWeb(5.3.23)的接口请求分析
1、案例说明
假定当前 Web 项目中有如下实体类和接口:
package com.example.entity;
public class WebUser {
private String name;
private Integer age;
private LocalDate birthday;
private Boolean gender;
// getter、setter、toString ...
}
package com.example.controller;
@RestController @RequestMapping("/test")
public class WebController {
@RequestMapping("/1")
public WebUser test1(HttpServletRequest request, @RequestParam Map<String, Object> params, WebUser webUser) {
System.out.println("request.getClass() = " + request.getClass());
System.out.println("params = " + params);
System.out.println("webUser = " + webUser);
return webUser;
}
}
使用 Postman 发送请求测试,结果符合预期:
下面就一些关键点进行探究分析。
2、请求处理的整体流程总览
注意到 org.springframework.web.servlet.DispatcherServlet#doDispatch 方法中有如下代码片段:
// Determine handler for the current request.
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Actually invoke the handler.
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
即总的来说,处理请求可以分三步:获取处理器、获取适配器、使用适配器执行处理器。
2.1 获取处理器
SpringMVC 中定义了一个“处理器映射规则”接口 HandlerMapping
,用来根据特定的请求返回对应的处理器(handler)。源码如下:
package org.springframework.web.servlet;
public interface HandlerMapping {
// 根据具体的请求返回一个处理器执行器链
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
这里的返回值是一个处理器执行器链 HandlerExecutionChain
,它由处理器和围绕该处理器的所有处理器拦截器 HandlerInterceptor
组成,是对处理器的一层封装(下文中“处理器”一词也代指“处理器执行器链”,如无特殊说明不再区分)。
SpringMVC 中默认的处理器映射规则有以下5种:
0 = {RequestMappingHandlerMapping@7031} (order=0)
1 = {BeanNameUrlHandlerMapping@7032} (order=2)
2 = {RouterFunctionMapping@7033} (order=3)
3 = {SimpleUrlHandlerMapping@7034} (order=2147483646)
4 = {WelcomePageHandlerMapping@7035} (order=2147483647)
获取处理器,就是按照次序遍历所有的处理器映射规则,挨个尝试获取处理器,直至找到第一个非空的处理器:
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings == null) {
return null;
}
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
最常用的处理器映射规则就是第一种 RequestMappingHandlerMapping
,本案例使用到的也是它。由它获取到的处理器的类型是 HandlerMethod
。
2.2 获取适配器
处理器需要由处理器适配器 HandlerAdapter
来执行。处理器适配器的接口声明如下:
package org.springframework.web.servlet;
public interface HandlerAdapter {
// 判断是否支持给定的处理器
boolean supports(Object handler);
// 使用给定的处理器对本次请求进行处理
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
SpringMVC 中默认的处理器适配器有如下4个:
0 = {RequestMappingHandlerAdapter@6792}
1 = {HandlerFunctionAdapter@6793}
2 = {HttpRequestHandlerAdapter@6794}
3 = {SimpleControllerHandlerAdapter@6795}
它们各自对 supports 方法的实现如下:
-
RequestMappingHandlerAdapter(order=2147483647)
public final boolean supports(Object handler) { return (handler instanceof HandlerMethod); }
即当处理器类型为
org.springframework.web.method.HandlerMethod
时支持处理。 -
HandlerFunctionAdapter(order=2147483647)
public boolean supports(Object handler) { return (handler i