@RequestHeader注解
第一种方式,这个很简单,在方法参数列表里上加注解@RequestHeader就行。
@PostMapping(value = "/getStuDetail")public ReturnInfo getStudentDetail(@RequestBody Map map,@RequestHeader(name = "id") String id);
RequestInterceptor接口
第二种方法,实现RequestInterceptor接口,重写apply函数。
@Configurationpublic class FeignRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();Enumeration<String> headerNames = request.getHeaderNames();if (headerNames != null) {while (headerNames.hasMoreElements()) {String name = headerNames.nextElement();String values = request.getHeader(name);// 调用 template.header设置header信息template.header(name, values);}}}}@Component@FeignClient(value = "xxxxxxxxx",configuration = FeignRequestInterceptor.class)public interface FeignProvider {}
在apply调用template.header设置header信息即可,然后发起feign请求的Provider设置configuration = FeignRequestInterceptor.class即可。
正确使用多个FeignRequestInterceptor
在FeignRequestInterceptor上加@Configuration这种方式,会影响所有的Feign请求。
如果有多个RequestInterceptor实现类并加上了@configuration,不管configuration参数指定与否,
所有的Feign请求会循环走完所有RequestInterceptor的apply函数。
这个时候你想要每个不同的FeignProvider走指定的RequestInterceptor的apply函数怎么办呢?
那就是在每个FeignRequestInterceptor上不要添加@Configuration以及@Component注解,什么注解都不要加,然后在每个单独的@FeignClient去指定不同的FeignRequestInterceptor。
FeignRequestInterceptor特殊的使用方式
当你想要多FeignRequestInterceptor时,又想要用@Configuration或者@Component注入一些Bean到FeignRequestInterceptor中怎么办呢?
我就遇到了此种情形,我的FeignRequestInterceptor需要使用到RedisTemplate对象来操作Redis,但是如果你加@Configuration声明为组件,则多RequestInterceptor时会乱套。
如果你不加@Configuration声明为组件,则你无法注入RedisTemplate。
这个时候可以绕过这个接口。下面是操作方法。
import feign.RequestInterceptor;// 接口继承feign的RequestInterceptorpublic class ApiConfiguration implements RequestInterceptor {// 内部包含一个自定义的requestInterceptorprivate RedisRequestInterceptor requestInterceptor;public ApiConfiguration(RedisRequestInterceptor requestInterceptor) {this.requestInterceptor = requestInterceptor;}@Overridepublic void apply(RequestTemplate template) {requestInterceptor.apply(template);}}// 自己模仿feign的RequestInterceptor定义一个ApiRequestInterceptorpublic interface ApiRequestInterceptor {/*** 自定义的feign 请求拦截** @param template*/void apply(RequestTemplate template);}// 操作redis的请求拦截器@Configurationpublic class RedisRequestInterceptor implements ApiRequestInterceptor {private final RedisTemplate<String, String> redisTemplate;public RedisRequestInterceptor(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}@Overridepublic void apply(RequestTemplate template) {// 从redis中取header, 只是一个示例。String header = redisTemplate.opsForValue().get("header");// 写到header中template.header("header", header);}}@FeignClient(name = Const.SERVICE_NAME, configuration = {ApiConfiguration.class})@Primarypublic interface ServiceProvider {}
ServiceProvider指定的ApiConfiguration没有加任何注解,内部定义了一个RedisRequestInterceptor对象。
然后真正的RedisRequestInterceptor上加上@Configuration注解并实现ApiRequestInterceptor接口。
这样feign运行时就会找到RedisRequestInterceptor这个bean并运行。
