微服务之间调用时时常遇到需要将服务A的token传递给服务B的情况,如果每个服务调用单独写就太僵硬了,之前试过自己写AOP去处理这个问题,功能上虽然没问题,但是总感觉比较low,最近在解决另外一个问题时,意外学到了一个解决方法。
这里贴一下核心代码
@Slf4j
@Service
public class FeignServiceImpl implements FeignService {
@Autowired
private ConfigurableEnvironment environment;
@Autowired
private FeignClientRequestInterceptor requestInterceptor;
private final Feign.Builder nameBuilder;
@Autowired
public FeignServiceImpl(Decoder decoder, Encoder encoder, Client client, Contract contract) {
// nameBuilder直接使用client,它会使用负载均衡
nameBuilder = Feign.builder()
.client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract);
}
@Override
public T newInstanceByTenantName(ClassapiType, String shortName) {
String bsServiceName = environment.getProperty("feign.name");
String instanceName = "http://" + shortName.toLowerCase() + "-" + bsServiceName;
return nameBuilder
.requestInterceptor(requestInterceptor)
.target(apiType, instanceName);
}
}
@Configuration
public class FeignClientRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader(AUTHORIZATION);
requestTemplate.header(AUTHORIZATION, token);
}
}
这个例子里面,主要就是使用feignbuilder动态的根据url得到目标服务的地址,在去请求对应的服务B(这一步可以无视啦,项目的业务场景)。而在此之前添加了一个拦截器,强行把自己的token塞给对别人的请求header。
很简单,也很简洁,比我之前的方法好。