在Feign RequestInterceptor / RequestTemplate中访问URITemplate或RequestLine值

Jan*_*Jan 8 java spring-boot netflix-feign

我正在针对具有严格api速率限制的云应用程序开发一个应用程序。为了让我的团队感觉到我们在这些限制方面的差距,我想以有意义的方式计算从我们的应用程序发出的所有API调用。

我们使用Feign作为访问层,我希望能够使用RequestInterceptor来计算我们称为的不同API端点:

RequestInterceptor ri = rq -> addStatistics(rq.url());
Run Code Online (Sandbox Code Playgroud)

现在这行不通,因为生成的URL之后几乎总是计数为“ 1”,因为它们已经包含所有解析的路径变量,因此我得到了

1 - /something/id1valueverycryptic/get
1 - /something/anothercrypticidkey/get
Run Code Online (Sandbox Code Playgroud)

等等。

我希望以某种方式访问@ResuqestLine映射值(GET /something/{id}/get)或至少访问uri模板的pre-resolve(/somethine/{id}/get

有没有办法做到这一点?

谢谢!

Tom*_*łło 3

也许您可以尝试使用自定义 feign InvocableHandlerFactory。

我设法使用如下代码记录 RequestInterceptor:

  • 更改 EnableFeignClients 并添加 defaultConfiguration

    @EnableFeignClients(defaultConfiguration = FeignConfig.class)
    
    Run Code Online (Sandbox Code Playgroud)
  • 添加默认的 feign 配置

    @Configuration
    public class FeignConfig {
    
    @Bean
    @ConditionalOnMissingBean
    public Retryer feignRetryer() {
        return Retryer.NEVER_RETRY;
    }
    
    @Bean
    @Scope("prototype")
    @ConditionalOnMissingBean
    public Feign.Builder feignBuilder(Retryer retryer) {
        return Feign.builder()
                .retryer(retryer)
                .invocationHandlerFactory((target, dispatch) -> new CountingFeignInvocationHandler(target, dispatch));
    }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 创建您的调用处理程序(基于 feign.ReflectiveFeign.FeignInitationHandler 的代码)

    public class CountingFeignInvocationHandler implements InvocationHandler {
    
        private final Target target;
        private final Map<Method, MethodHandler> dispatch;
    
        public CountingFeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) {
            this.target = checkNotNull(target, "target");
            this.dispatch = checkNotNull(dispatch, "dispatch for %s", target);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if ("equals".equals(method.getName())) {
                try {
                    Object otherHandler =
                            args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
                    return equals(otherHandler);
                } catch (IllegalArgumentException e) {
                    return false;
                }
            } else if ("hashCode".equals(method.getName())) {
                return hashCode();
            } else if ("toString".equals(method.getName())) {
                return toString();
            }
    
            RequestLine requestLine = method.getAnnotation(RequestLine.class);
            addStatistics(requestLine.value());
    
            return dispatch.get(method).invoke(args);
        }
    
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof CountingFeignInvocationHandler) {
                CountingFeignInvocationHandler other = (CountingFeignInvocationHandler) obj;
                return target.equals(other.target);
            }
            return false;
        }
    
        @Override
        public int hashCode() {
            return target.hashCode();
        }
    
        @Override
        public String toString() {
            return target.toString();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

请小心并检查您是否假装配置并不更复杂,在这种情况下,请根据需要扩展类。