All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cc.shacocloud.mirage.web.InvocableHandlerMethod Maven / Gradle / Ivy


package cc.shacocloud.mirage.web;

import cc.shacocloud.mirage.utils.FutureUtils;
import cc.shacocloud.mirage.web.bind.WebDataBinderFactory;
import io.vertx.core.Future;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.jetbrains.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 基于{@link HandlerMethod}的扩展
 * 

* 通过 {@link HandleMethodArgumentResolver} 列表支持当前请求解析的处理来处理解析 */ public class InvocableHandlerMethod extends HandlerMethod { private static final Log logger = LogFactory.getLog(InvocableHandlerMethod.class); private static final Future EMPTY_ARGS = Future.succeededFuture(new Object[0]); /** * 参数名称发现器 */ @Nullable protected ParameterNameDiscoverer parameterNameDiscoverer; /** * 处理方法参数解析器 */ @Nullable protected HandleMethodArgumentResolverComposite resolvers; 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); } /** * 设置 {@link HandleMethodArgumentResolverComposite} 以用于解析方法参数值 */ public void setHandlerMethodArgumentResolvers(HandleMethodArgumentResolverComposite argumentResolvers) { this.resolvers = argumentResolvers; } /** * 设置 {@code ParameterNameDiscoverer} 以在需要时解析参数名称(例如默认请求属性名称)。 *

* 默认为{@link org.springframework.core.DefaultParameterNameDiscoverer} */ public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) { this.parameterNameDiscoverer = parameterNameDiscoverer; } public Future invokeForRequest(HttpRequest request, WebDataBinderFactory binderFactory, Object... providedArgs) throws Exception { if (logger.isDebugEnabled()) { logger.debug("方法 '" + this + "' 进入参数解析过程..."); } return getMethodArgumentValues(request, binderFactory, providedArgs) .compose(args -> { if (logger.isDebugEnabled()) { logger.debug("\n执行目标方法:" + getBridgedMethod() + "\n参数:" + Arrays.toString(args)); } try { return (Future) doInvoke(args); } catch (Exception e) { return Future.failedFuture(e); } }); } /** * 获取当前请求的方法参数值,检查提供的参数值并返回配置的参数解析器。 *

* 结果数组将传递到{@link #doInvoke}中 */ protected Future getMethodArgumentValues(HttpRequest request, WebDataBinderFactory binderFactory, @Nullable Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) return EMPTY_ARGS; Assert.state(this.parameterNameDiscoverer != null, "未设置 ParameterNameDiscoverer"); Assert.state(this.resolvers != null, "未设置 HandleMethodArgumentResolverComposite"); final Object[] args = new Object[parameters.length]; final AtomicInteger index = new AtomicInteger(0); return FutureUtils.sequential(parameters, (parameter, t) -> { parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); // 根据参数类型,尝试填充提供的参数, Object providedArgument = findProvidedArgument(parameter, providedArgs); if (providedArgument != null) { args[index.getAndIncrement()] = providedArgument; return Future.succeededFuture(); } if (!this.resolvers.supportsParameter(parameter)) { return Future.failedFuture(new IllegalStateException(formatArgumentError(parameter, "未找到支持的参数解析器!"))); } return this.resolvers.resolveArgument(request, parameter, binderFactory) .onSuccess(arg -> args[index.getAndIncrement()] = arg) .onFailure(ex -> { // 将堆栈跟踪留给以后使用,实际上可以解决和处理异常... if (logger.isDebugEnabled()) { String exMsg = ex.getMessage(); if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) { logger.debug(formatArgumentError(parameter, exMsg)); } } }); }) .compose(r -> Future.succeededFuture(args)); } /** * 使用给定的参数值调用处理程序方法 */ protected Object doInvoke(Object... args) throws Exception { ReflectionUtils.makeAccessible(getBridgedMethod()); try { return getBridgedMethod().invoke(getBean(), args); } catch (IllegalArgumentException ex) { assertTargetBean(getBridgedMethod(), getBean(), args); throw new IllegalStateException(formatInvokeError("非法参数异常:", args), ex); } catch (InvocationTargetException ex) { // 展开 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("目标对象方法调用失败异常:", args), targetException); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy