以为feign调用请求头里添加cookie为例
一、场景
我们有两个服务A、B,现在用户通过浏览器访问A服务的某个接口,在A接口中通过Feign调用了B服务。
B服务中定义拦截器,对所有的请求都进行拦截,检查请求头中是否包含了cookie,如果有cookie这放行,如果没有cookie则进行拦截。
解决:创建feign调用拦截器 RequestInterceptor 并注入容器
@Configuration
public class FeignConfig {
@Bean("requestInterceptor")
public static RequestInterceptor requestInterceptor() {
// 创建拦截器
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
// 1、使用RequestContextHolder拿到原生请求的请求头信息(下文环境保持器)
// 从ThreadLocal中获取请求头(要保证feign调用与controller请求处在同一线程环境)
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
// 获取controller请求对象
HttpServletRequest request = requestAttributes.getRequest();
// 如果使用线程池进行远程调用,则request是空的(因为RequestContextHolder.getRequestAttributes()是从threadlocal里拿的值)
if (Objects.nonNull(request)) {
//2、获取老请求里的cookie信息
String cookie = request.getHeader("Cookie");
// 同步Cookie (将老请求里的cookie信息放入新请求里(RequestTemplate))
template.header("Cookie", cookie);
}
}
}
};
}
}
原理解析
SynchronousMethodHandler 类中的executeAndDecode()
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
// 1、构建request,核心就在这里了,点进去
Request request = targetRequest(template);
Response response;
long start = System.nanoTime();
try {
// 2、真正发起调用的地方
response = client.execute(request, options);
response = response.toBuilder()
.request(request)
.requestTemplate(template)
.build();
} catch (IOException e) {
throw errorExecuting(request, e);
}
// 省略部分无关代码
}
targetRequest()
// 这里也就是我们自定义RequestInterceptor被调用的地方
// 可以看到,他拿到容器中所有实现了RequestInterceptor接口的bean,然后依次执行他们的apply方法
Request targetRequest(RequestTemplate template) {
for (RequestInterceptor interceptor : requestInterceptors) {
interceptor.apply(template);
}
return target.apply(template);
}
本文介绍了在SpringCloud微服务架构中,如何通过Feign调用并在请求头中添加cookie的场景。具体做法是创建一个RequestInterceptor,从RequestContextHolder获取原始请求的cookie信息,并在Feign调用时同步到新请求中,确保B服务能接收到cookie。
888

被折叠的 条评论
为什么被折叠?



