类图
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); }
|