使用新的请求拦截器假装客户端重试器?
Posted
技术标签:
【中文标题】使用新的请求拦截器假装客户端重试器?【英文标题】:Feign client Retryer with a new request interceptor? 【发布时间】:2019-04-29 06:11:09 【问题描述】:我目前正在手动构建一个 feign 客户端并将拦截器传递给它以进行授权。我想为一些响应代码提供一个更智能的重试器。
public class myErrorEncoder extends ErrorDecoder.Default
@Override
public Exception decode(final String methodKey, final Response response)
if (response.status() == 401)
String token = refreshToken(); // I would like to refresh the token and Edit the client
return new RetryableException("Token Expired will retry it", null);
else
return super.decode(methodKey, response);
拦截器
@Bean public CustomInterceptor getInterceptor(String token)
return new CustomInterceptor(token);
假装建造者
private <T> T feignBuild(final Class<T> clazz, final String uri, final String token)
return Feign
.builder().client(new ApacheHttpClient())
.encoder(new GsonEncoder())
.decoder(new ResponseEntityDecoder(feignDecoder())
.retryer(new Retryer.Default(1,100,3))
.errorDecoder(new ErrorDecoder())
.requestInterceptor(getInterceptor(token))
.contract(new ClientContract())
.logger(new Slf4jLogger(clazz)).target(clazz, uri);
现在我想用刷新的令牌更新 feign 客户端并重试。 有没有办法访问客户端实例并对其进行配置。
【问题讨论】:
【参考方案1】:您对拦截器的使用不正确。拦截器在重试期间被重新应用,但它们只被实例化一次并且被期望是线程安全的。要实现您要寻找的内容,需要将令牌生成与拦截器分开,并让拦截器请求新令牌。
public class TokenInterceptor()
TokenService tokenService;
public TokenInterceptor(TokenService tokenService)
this.tokenService = tokenService;
public void apply(RequestTemplate template)
/* getToken() should create a new token */
String token = this.tokenService.getToken();
template.header("Authorization", "Bearer " + token);
这将确保每个重试周期都会创建一个新令牌。
【讨论】:
以这种方式处理它意味着为每个请求生成一个新令牌。这不是最佳的。我希望仅在 401 错误代码上生成令牌。 您需要添加逻辑以确定在请求新令牌之前是否需要令牌。您可以使用ErrorDecoder
捕获401
并清除令牌并返回RetryableException
以重试请求。
@KevinDavis 如果我错了,请纠正我,但您提出的解决方案将在另一个 Authorization 标头中附加新令牌。你如何替换现有的?以上是关于使用新的请求拦截器假装客户端重试器?的主要内容,如果未能解决你的问题,请参考以下文章
Angular 7 - 如何在某些响应状态代码上重试 http 请求?