问题描述
目前浏览器发起一个请求访问我们的A服务的a方法,这个请求在请求头里携带了一个cookie数据。而在a方法中因业务需要,需要通过Fegin远程调用B服务中的b方法,但是B服务中的b方法也需要浏览器携带的cookie数据。此时通过Fegin远程调用B服务时,Fegin会给我们新创建一个Request请求(不要问我为什么要创建一个新的请求,因为人家底层就只这么做的),这个新创建的Request里面是没有携带任何浏览器cookie数据。然后再去访问B服务的b方法,此时由于没有携带请求头数据,B服务就认为这个请求不合法。所以得不到想要的结果数据。
总的来说就是一个原因,Fegin远程调用会创建一个新的请求去访问服务。由于没有携带请求头数据,所以访问失败。
解决:
Fegin在构造新的请求时,会调用很多拦截器对整个请求进行一个增强。所以我们在A服务中添加一个Fegin的拦截器。让新的请求共享原来的请求头数据,这样再去远程访问就没问题了
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @ClassName : FeginConfig
* @Description : FeginConfig
* @Author : 萧先生
* @Date: 2022-10-03 21:26
*/
@Configuration
public class FeginConfig {
@Bean("requestInterceptor")
public RequestInterceptor requestInterceptor(){
return new RequestInterceptor(){
@Override
public void apply(RequestTemplate template) {
/*RequestContextHolder 拿到刚进来的请求*/
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
RequestContextHolder.setRequestAttributes(attributes,true);//设置子线程共享
if (attributes != null){
HttpServletRequest request = attributes.getRequest();/*得到原来的请求*/
if (request != null){
/*同步请求头数据, --cookie*/
String cookie = request.getHeader("Cookie");
/*给新请求同步了原来请求的cookie*/
template.header("Cookie",cookie);
}
}
}
};
}
}