为了账号安全,请及时绑定邮箱和手机立即绑定

访问 URI 模板或请求线值假装请求接收器/请求模板

访问 URI 模板或请求线值假装请求接收器/请求模板

aluckdog 2022-09-22 13:54:59

我正在针对具有硬 API 速率限制的云应用程序开发一个应用程序。为了让我的团队了解我们在这些限制方面的接近程度,我想以有意义的方式计算从我们的应用程序进行的所有API调用。

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

RequestInterceptor ri = rq -> addStatistics(rq.url());

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

1 - /something/id1valueverycryptic/get
1 - /something/anothercrypticidkey/get

等等。

我希望以某种方式访问映射值()或至少uri模板预解析(@ResuqestLineGET /something/{id}/get/somethine/{id}/get)

有没有办法做到这一点?


查看完整描述

3 回答

?
交互式爱情

TA贡献1384条经验 获得超3个赞

也许你可以尝试使用自定义假装调用处理程序工厂。


我已经设法使用如下代码记录请求感知器:


更改启用特征客户端并添加默认配置


@EnableFeignClients(defaultConfiguration = FeignConfig.class)

添加默认的假装配置


@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));

}


}

创建调用处理程序(基于假装的代码。反光费恩.假装调用手)


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();

    }

}

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


查看完整回答
反对 回复 2022-09-22
?
ITMISS

TA贡献1499条经验 获得超8个赞

   If you are using spring-cloud-starter-openfeign ,  You could do something like below 

    

    add the a primary contract bean 

    @Bean("YourContract")

    @Primary

        public Contract springpringContract() {

            return (targetType) -> {

    

                List<MethodMetadata> parseAndValidatateMetadata = new SpringMvcContract().parseAndValidatateMetadata(targetType);

                parseAndValidatateMetadata.forEach(metadata -> {

                    RequestTemplate template = metadata.template();

                    template.header("unresolved_uri", template.path().replace("{", "[").replace("}", "]"));

    

                });

                return parseAndValidatateMetadata;

            };

        }

    

    Add the contract to the feign client builder 

    @Bean

     public <T> T feignBuilder(Class<T> feignInterface, String targetURL) {

            return Feign.builder().client(getClient())

                    .contract(contract)

                    .

                    .

    }

    

    Once you are done with the above you should be able to access the unresolved path in the RequestTemplate


@component

public class FeignRequestFilter  implements RequestInterceptor {

    @Override

        public void apply(RequestTemplate template) {

            String unresolvedUri = template.headers().getOrDefault("unresolved_uri", Collections.singleton(template.path()))

                    .iterator().next();

    }

}


查看完整回答
反对 回复 2022-09-22
?
烙印99

TA贡献1485条经验 获得超11个赞

也许你可以尝试覆盖假装记录器。


假设我们有一个假装的客户,


@FeignClient(name = "demo-client", url = "http://localhost:8080/api", configuration = FeignConfig.class)

public interface DemoClient {


    @GetMapping(value = "/test/{id}")

    void test(@PathVariable(name = "id") Integer id) {

    }

}



import feign.Logger;

import feign.Request;

import feign.Response;


import java.io.IOException;


public class CustomFeignRequestLogging extends Logger {

    @Override

    protected void logRequest(String configKey, Level logLevel, Request request) {

        super.logRequest(configKey, logLevel, request);

        // targetUrl = http://localhost:8080/api

        String targetUrl = request.requestTemplate().feignTarget().url();

        // path = /test/{id}

        String path = request.requestTemplate().methodMetadata().template().path();

    }

}


查看完整回答
反对 回复 2022-09-22

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信