原文地址:feign RequestInterceptor 拦截器统一修改post表单请求体
RequestInterceptor介绍
现在很多开发都是用feign来请求三方接口。feign很方便,通过接口的方式来请求三方,有助于我们以面向接口编程,也简化了之前手工创建httpclient等麻烦的流程。但是对于三方接口中需要统一添加签名要怎么办呢?
莫慌,Feign给我们预留了一个RequestInterceptor接口,它可以在我们的请求发送之前对请求内容(包装成一个RequestTemplate)做统一的处理。那我们就可以在这里对请求参数做一些统一处理了
拦截并修改post json请求体
我们有一个三方的接口是post json的,并且有统一的参数如下
{
"appId": xxx,
"sign": xxx,
"timestampe": xxx,
"data": {
"a": xxx} //真正的数据以json格式放在data中
}
那我们声明的feign接口,使用的时候不可能每次都去构造这些通用的参数,应该只需要传变化的东西进来就好了。例如上面的{“a”: xxx}。那么不变的部分在哪里添加呢?答案就是我们的RequestInterceptor
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 通过template获取到请求体(已经被转成json)
String jsonBody = template.requestBody().asString();
// 构造通用的请求体
BaseReq baseReq = translateToBaseReq(jsonBody);
// 替换请求体
String baseReqStr = JSON.toJSONString(baseReq);
template.body(baseReqStr);
}
}
然后在我们需要的Feign接口的注解中配置configuration,标明使用这个拦截器配置就可以了
@FeignClient(name = "hello", url = "hello", configuration = FeignInterceptor.class)
public interface HelloFeign {
@PostMapping("test")
void test(@RequestBody ConcreteData data);
}
这样就ok了,是不是很简单,然后我们的接口参数中只需要写实际要传的具体数据的类就行了。
拦截并修改post form请求体
post json搞定了,但接下来又出现了一个三方。它的接口是post表单形式的。有同学说,post表单我会。
网上也有很多这方面的教程,例如:2018-06-19 SpringCloud Feign Post表单请求,但是关键是post表单了之后,怎么处理统一的请求体呢?很明显,像上面直接通过template.body方式替换是不行的,这样请求体就是json字符串了。而form格式是a=xxx&b=xxx这样的。那有同学就说,我自己这样构造不就可以了?可以是可以,但是这就是在重复造轮子了。feign既然能发送post form的请求,说明它已经实现过了。那我们是不是可以借鉴下呢?
一览源码
那我们就顺着请求来看看feign是怎么post form的吧。(debug模式中在调用feign接口的地方step into)
首先来到了ReflectiveFeign类的 public Object invoke(Object proxy, Method method, Object[] args)方法。继续往下走在return dispatch.get(method).invoke(args);这里继续step into来到了SynchronousMethodHandler类的invoke方法。
public Object invoke(Object[] argv) throws Throwable