类图

HandlerMethod

处理器的方法的封装对象

InvocableHandlerMethod

继承 HandlerMethod 类,可 invoke 调用的 HandlerMethod 实现类。

HandlerMethod 只提供了处理器的方法的基本信息,不提供调用逻辑。

构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// InvocableHandlerMethod.java

@Nullable
private WebDataBinderFactory dataBinderFactory;

private HandlerMethodArgumentResolverComposite argumentResolvers = new HandlerMethodArgumentResolverComposite();

private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

public InvocableHandlerMethod(HandlerMethod handlerMethod) {
super(handlerMethod);
}

public InvocableHandlerMethod(Object bean, Method method) {
super(bean, method);
}

public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
throws NoSuchMethodException {
super(bean, methodName, parameterTypes);
}

dataBinderFactory、argumentResolvers、parameterNameDiscoverer 参数,是通过 setting 方法,进行设置。

invokeForRequest

1
2
3
4
5
6
7
8
9
10
11
@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);
}

解析方法的参数们

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
private Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 方法的参数信息的数组
MethodParameter[] parameters = getMethodParameters();
// 解析后的参数结果数组
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 中获得参数。如果获得到,则进入下一个参数的解析
args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
// <2> 判断 argumentResolvers 是否支持当前的参数解析
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
// 执行解析。解析成功后,则进入下一个参数的解析
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
} catch (Exception ex) {
// 解析失败,打印日志,并抛出异常
// Leave stack trace for later, e.g. AbstractHandlerExceptionResolver
if (logger.isDebugEnabled()) {
String message = ex.getMessage();
if (message != null && !message.contains(parameter.getExecutable().toGenericString())) {
logger.debug(formatArgumentError(parameter, message));
}
}
throw ex;
}
}
// 解析失败,抛出 IllegalStateException 异常
if (args[i] == null) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
}

// 返回结果
return args;
}
  • 先从 providedArgs 中获得参数。如果获得到,则进入下一个参数的解析。默认情况下,providedArgs 参数不会传递,所以可以暂时先忽略。保证核心逻辑的理解。
  • 判断 argumentResolvers 是否支持当前的参数解析。如果支持,则进行解析。

doInvoke

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
// InvocableHandlerMethod.java

protected Object doInvoke(Object... args) throws Exception {
// 设置方法为可访问
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
// 执行调用
return getBridgedMethod().invoke(getBean(), args);
} catch (IllegalArgumentException ex) {
assertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
throw new IllegalStateException(formatInvokeError(text, args), ex);
} catch (InvocationTargetException ex) {
// Unwrap for HandlerExceptionResolvers ...
Throwable targetException = ex.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException) targetException;
} else if (targetException instanceof Error) {
throw (Error) targetException;
} else if (targetException instanceof Exception) {
throw (Exception) targetException;
} else {
throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
}
}
}

ServletInvocableHandlerMethod

继承 InvocableHandlerMethod 类,考虑 Servlet 的 InvocableHandlerMethod 实现类。

构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 返回结果处理器
*/
@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;

public ServletInvocableHandlerMethod(Object handler, Method method) {
super(handler, method);
}

public ServletInvocableHandlerMethod(HandlerMethod handlerMethod) {
super(handlerMethod);
}

returnValueHandlers 属性的设置,通过 setting 方法

invokeAndHandle

请求调用,并处理返回结果

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
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// <1> 执行调用
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// <2> 设置响应状态码
setResponseStatus(webRequest);

// <3> 设置 ModelAndViewContainer 为请求已处理,返回
if (returnValue == null) { // 返回 null
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
} else if (StringUtils.hasText(getResponseStatusReason())) { // 有 responseStatusReason
mavContainer.setRequestHandled(true);
return;
}

// <4> 设置 ModelAndViewContainer 为请求未处理
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
// <5> 处理器返回值
try {
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
} catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}

setResponseStatus 设置响应的状态码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void setResponseStatus(ServletWebRequest webRequest) throws IOException {
// 获得状态码。
// 此处,想要非空,需要通过 @ResponseStatus 注解方法
HttpStatus status = getResponseStatus();
if (status == null) { // 若为空,则返回
return;
}

// 设置响应的状态码
HttpServletResponse response = webRequest.getResponse();
if (response != null) {
String reason = getResponseStatusReason();
if (StringUtils.hasText(reason)) { // 有 reason ,则设置 status + reason
response.sendError(status.value(), reason);
} else { // 无 reason ,则仅设置 status
response.setStatus(status.value());
}
}

// To be picked up by RedirectView
// 为了 RedirectView ,所以进行设置
webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, status);
}