Spring MVC : 概念模型 InvocableHandlerMethod

编程入门 行业动态 更新时间:2024-10-24 06:32:05

Spring MVC : 概念<a href=https://www.elefans.com/category/jswz/34/1771358.html style=模型 InvocableHandlerMethod"/>

Spring MVC : 概念模型 InvocableHandlerMethod

InvocableHandlerMethod是对HandlerMethod的扩展,基于一组HandlerMethodArgumentResolver从请求上下文中解析出控制器方法的参数值,然后调用控制器方法。

除此之外,InvocableHandlerMethodHandlerMethod的不同在于:

  • HandlerMethod被容器在启动过程中搜集控制器方法阶段用于记录每个控制器方法,
  • InvocableHandlerMethod用于在某个请求被控制器方法处理时,包装处理所需的各种参数和执行处理逻辑。

源代码分析

package org.springframework.web.method.support;/*** Extension of HandlerMethod that invokes the underlying method with* argument values resolved from the current HTTP request through a list of* HandlerMethodArgumentResolver.** @author Rossen Stoyanchev* @author Juergen Hoeller* @since 3.1*/
public class InvocableHandlerMethod extends HandlerMethod {private static final Object[] EMPTY_ARGS = new Object[0];@Nullableprivate WebDataBinderFactory dataBinderFactory;// 一组控制器方法参数值解析器,用于从请求上下文信息中解析控制器方法参数对应的参数值private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();// 用于发现控制器方法参数的名称,参数名称在从请求上下文信息中解析控制器方法参数值时会被使用private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();/*** 基于一个 HandlerMethod 构造一个 InvocableHandlerMethod 对象,* 通常用在请求处理过程中,根据请求信息找到了相应的 HandlerMethod,然后准备调用底层的控制器方法了,* 此时调用该构造函数形成一个 InvocableHandlerMethod 实例,然后传递其它必要的参数给该 * InvocableHandlerMethod 实例,然后执行目标控制器方法的调用。* Create an instance from a HandlerMethod.*/public InvocableHandlerMethod(HandlerMethod handlerMethod) {super(handlerMethod);}/*** Create an instance from a bean instance and a method.* 基于一个 Web 控制器对象和相应的控制器方法构造一个 InvocableHandlerMethod 对象*/public InvocableHandlerMethod(Object bean, Method method) {super(bean, method);}/*** Construct a new handler method with the given bean instance, method name and parameters.* @param bean the object bean* @param methodName the method name* @param parameterTypes the method parameter types* @throws NoSuchMethodException when the method cannot be found*/public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)throws NoSuchMethodException {super(bean, methodName, parameterTypes);}/*** Set the WebDataBinderFactory to be passed to argument resolvers allowing them to create* a WebDataBinder for data binding and type conversion purposes.* @param dataBinderFactory the data binder factory.*/public void setDataBinderFactory(WebDataBinderFactory dataBinderFactory) {this.dataBinderFactory = dataBinderFactory;}/*** Set HandlerMethodArgumentResolver HandlerMethodArgumentResolvers to use to use for resolving * method argument values.* 设置所需要的控制器方法参数解析器*/public void setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {this.resolvers = argumentResolvers;}/*** Set the ParameterNameDiscoverer for resolving parameter names when needed* (e.g. default request attribute name).* 设置参数名称发现器* Default is a org.springframework.core.DefaultParameterNameDiscoverer.*/public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {this.parameterNameDiscoverer = parameterNameDiscoverer;}/*** Invoke the method after resolving its argument values in the context of the given request.* Argument values are commonly resolved through*  HandlerMethodArgumentResolver HandlerMethodArgumentResolvers.* The providedArgs parameter however may supply argument values to be used directly,* i.e. without argument resolution. Examples of provided argument values include a* WebDataBinder, a SessionStatus, or a thrown exception instance.* Provided argument values are checked before argument resolvers.* Delegates to #getMethodArgumentValues and calls #doInvoke with the* resolved arguments.* @param request the current request* @param mavContainer the ModelAndViewContainer for this request* @param providedArgs "given" arguments matched by type, not resolved* @return the raw value returned by the invoked method* @throws Exception raised if no suitable argument resolver can be found,* or if the method raised an exception* @see #getMethodArgumentValues* @see #doInvoke*/@Nullablepublic Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {// 从请求上下文中解析控制器方法参数对应的参数值 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);if (logger.isTraceEnabled()) {logger.trace("Arguments: " + Arrays.toString(args));}// 执行目标控制器方法调用 return doInvoke(args);}/*** Get the method argument values for the current request, checking the provided* argument values and falling back to the configured argument resolvers.* The resulting array will be passed into #doInvoke.* @since 5.1.2*/protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {if (ObjectUtils.isEmpty(getMethodParameters())) {// 控制器方法没有参数的情况return EMPTY_ARGS;}MethodParameter[] parameters = getMethodParameters();Object[] args = new Object[parameters.length];for (int i = 0; i < parameters.length; i++) {// 获取一个控制器方法参数 MethodParameter parameter = parameters[i];// 发现控制器方法参数的名称parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);// 看看针对该参数,有没有通过 providedArgs 提供的参数值args[i] = findProvidedArgument(parameter, providedArgs);if (args[i] != null) {continue;}// 如果针对该参数,没有通过 providedArgs 提供的参数值,则尝试使用属性 resolvers,// 其实是一组 HandlerMethodArgumentResolver 实例的一个组合对象,从请求上下文中解析// 该参数的参数值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 error = ex.getMessage();if (error != null && !error.contains(parameter.getExecutable().toGenericString())) {logger.debug(formatArgumentError(parameter, error));}}throw ex;}}return args;}/*** Invoke the handler method with the given argument values.*/@Nullableprotected 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);}}}}

参考文章

Spring MVC : 概念模型 HandlerMethod
Spring MVC : 概念模型 HandlerMethodArgumentResolver

更多推荐

Spring MVC : 概念模型 InvocableHandlerMethod

本文发布于:2024-03-23 14:37:03,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1739335.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模型   概念   Spring   MVC   InvocableHandlerMethod

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!