Quarkus Rest-Client-Reactive:如何解包RestClientCdiWrapper获取方法参数信息?
解决Quarkus RestClient Reactive拦截器无法获取原接口方法元数据的问题
方法一:通过CDI获取原始REST Client接口的方法元数据
由于Reactive版本的RestClient是CDI动态生成的代理包装类,直接从InvocationContext拿到的方法是代理类的方法,所以需要通过原始接口类型匹配获取真实方法:
@Inject BeanManager beanManager; public void intercept(InvocationContext context) throws Exception { // 提取被代理的原始RestClient接口 Class<?> originalInterface = context.getTarget().getClass().getInterfaces()[0]; // 根据方法名和参数类型匹配原始方法 Method originalMethod = originalInterface.getMethod( context.getMethod().getName(), context.getMethod().getParameterTypes() ); // 现在可以正常获取参数注解和真实参数名 Parameter[] originalParams = originalMethod.getParameters(); for (Parameter param : originalParams) { Annotation1 anno = param.getAnnotation(Annotation1.class); String realParamName = param.getName(); // 需开启编译参数保留参数名 } // 执行原方法逻辑 context.proceed(); }
关键配置:
编译时必须开启-parameters参数,才能保留参数名(否则还是显示arg0)。在pom.xml中配置Maven编译器:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <parameters>true</parameters> </configuration> </plugin> </plugins> </build>
方法二:使用Reactive RestClient专用拦截器机制
Quarkus Reactive RestClient推荐使用JAX-RS标准的ClientRequestFilter或者Quarkus扩展的RestClientRequestFilter,这种方式能直接拿到请求关联的原始方法元数据:
@Provider public class MyReactiveRequestFilter implements ClientRequestFilter { @Override public void filter(ClientRequestContext requestContext) throws IOException { // 从请求上下文获取原始方法对象 Method originalMethod = (Method) requestContext.getProperty("org.jboss.resteasy.reactive.common.core.Method"); if (originalMethod != null) { Parameter[] params = originalMethod.getParameters(); // 处理参数注解和名称 for (Parameter param : params) { Annotation2 anno = param.getAnnotation(Annotation2.class); String paramName = param.getName(); } } } }
然后在RestClient接口上注册该拦截器:
@RegisterRestClient(configKey = "someKey") @RegisterProvider(MyReactiveRequestFilter.class) public interface MyRestClient { @GET @Path("/something") User getSomething(@Annotation1 @Annotation2 final String someParameter); }
方法三:解包CDI代理对象(备选方案)
如果需要直接处理代理对象,可通过Quarkus的ArcContainer获取Bean元数据,但本质还是通过原始接口类型匹配方法:
@Inject ArcContainer arcContainer; public void intercept(InvocationContext context) throws Exception { Class<?> originalInterface = context.getTarget().getClass().getInterfaces()[0]; Bean<?> restClientBean = arcContainer.beanManager().resolve( arcContainer.beanManager().getBeans(originalInterface) ); Method originalMethod = restClientBean.getBeanClass().getMethod( context.getMethod().getName(), context.getMethod().getParameterTypes() ); // 后续处理同方法一 context.proceed(); }
内容的提问来源于stack exchange,提问作者Wolf95
相关产品推荐
相关产品推荐

