以前一直用feign发起请求,但是不知道怎么在header加参数,今天试了一下自定义header参数。
controller层代码
@RestController
@Slf4j
@RequestMapping("/test")
public class TestController {
@GetMapping("")
public R<?> testController(HttpServletRequest httpServletRequest){
String param = httpServletRequest.getHeader("param");
System.out.println(param);
return R.success(param);
}
}
调用方代码:
@RequestLine("GET /test")
@Headers({"param:really"})
JSONObject test();
调用结果:
@Resource
private TestClient testClient;
@Test
public void test(){
JSONObject res = testClient.test();
System.out.println(res);
System.out.println("done");
}
结果如下:
{"msg":"操作成功","code":1,"data":"really","success":true}
done
说明取出了放入的参数,常用于指定post请求的body类型:
@Headers({"Content-Type: application/json", "Accept: application/json"})
当然也可以自定义参数:
@RequestLine("GET /test")
@Headers({"param:{pp}"})
JSONObject test(@Param("pp")String pp);
但是上边的方法需要每个请求接口上都写一遍,对于通用的header参数设置还有另外一种方法,借助于拦截器:
@Component
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("param","another");
}
}
由于我重写了feignBuilder,所以要在builder时加上拦截器配置,
@Bean(name = "custom")
public Feign.Builder getFeignBuilder() {
return Feign.builder()
.logLevel(Level.NONE)
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.logger(new ErrorLogger())
.errorDecoder(errorDecoder())
.options(getOptions())
.requestInterceptor(new FeignInterceptor())
.client(apacheHttpClient());
}
这样就可以了,第一种方法里的test方法运行结果如下
{"msg":"操作成功","code":1,"data":"another","success":true}
此种方法可以统一加入header参数,但是无法给特定的请求加(加的话只能去根据url进行匹配),如果需要拦截器转发自定义的header参数,则采用如下写法:
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);
requestTemplate.header(name, values);
}
}
@RestController
@Slf4j
@RequestMapping("/test")
public class TestController {
@Resource
private TestClient testClient;
@GetMapping()
public R<?> test(HttpServletRequest httpServletRequest){
String res = httpServletRequest.getHeader("test");
System.out.println(res);
testClient.test();
return R.success(res);
}
}
拦截器配置:
@Component
public class FeignHeaderInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
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);
requestTemplate.header(name, values);
}
}
}
}
项目1feign调用接口:
public interface TestClient {
@RequestLine("GET /test")
JSONObject test();
}
项目2代码:
@RequestMapping("/test")
@RestController
public class TestController {
@GetMapping()
public Result<?> test(HttpServletRequest httpServletRequest){
String res = httpServletRequest.getHeader("test");
System.out.println(res);
return Result.successWithData(res);
}
}
项目1,2控制台都输出了really:
但是注意复制header参数时不要一股脑都放进去,会出问题,具体见我的博客Feign问题排查
参考博客
参考1
参考2