在feign调用时统一获取token,加入header时报错
报错如下
no thread-bound request found: are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? if you are actually …
1.如何给所有的feign加入token
@Component
public class TokenInterceptor implements RequestInterceptor {
private final HttpServletRequest request;
@Autowired
public TokenInterceptor(HttpServletRequest request) {
this.request = request;
}
@Override
public void apply(RequestTemplate template) {
String token = request.getHeader("X-Access-Token"); // 从原始请求头中获取 Token
template.header("Authorization", "Bearer " + token); // 将 Token 添加到 Feign 请求头中
template.header("X-Access-Token", token); // 将 Token 添加到 Feign 请求头中
}
}
原理:TokenInterceptor 实现了 RequestInterceptor 接口,该接口是 Feign 提供的拦截器接口。当你将 TokenInterceptor 注册为 Feign 的拦截器后,它会在每次 Feign 调用时被调用。
Feign 在发送请求之前会执行拦截器链,包括注册的所有拦截器。在拦截器链中,每个拦截器都可以对请求进行修改或者添加额外的处理逻辑。
RequestInterceptor 接口定义了一个 apply 方法,该方法在发送请求之前被调用,可以通过 RequestTemplate 对象来修改请求的相关信息,比如请求头、请求参数等。
因此,当你注册了 TokenInterceptor 作为 Feign 的拦截器之后,在每次 Feign 调用发起之前,apply 方法都会被调用,你可以在其中添加你的 Token 处理逻辑,将 Token 添加到请求头中,以实现在 Feign 调用中自动携带 Token。
需要注意的是,为了让 Feign 客户端生效,你需要将 TokenInterceptor 注册为一个 Bean,并将其加入到 Spring 容器中。具体的方式取决于你使用的 Spring Boot 版本和配置方式。
总结来说,TokenInterceptor 可以拦截 Feign 调用是因为它实现了 RequestInterceptor 接口,并且在拦截器链中被调用,可以对请求进行修改和添加额外处理逻辑。
如果在没有实际的 web 请求的情况下调用 Feign 接口,将导致无法获取到 HttpServletRequest 对象,从而引发异常。
no thread-bound request found: are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? if you are actually …
为了避免这个问题,你可以将 HttpServletRequest 对象封装为一个 ThreadLocal,如下处理
解决:
public class TokenHolder {
private static final ThreadLocal<String> tokenHolder = new ThreadLocal<>();
private static Boolean TokenValidationFlag=true;
public static Boolean getTokenValidationFlag() {
return TokenValidationFlag;
}
public static void setTokenValidationFlag(Boolean tokenValidationFlag) {
TokenValidationFlag = tokenValidationFlag;
}
public static void setToken(String token) {
tokenHolder.set(token);
}
public static void removeToken() {
tokenHolder.remove();
}
public static String getToken() {
return tokenHolder.get();
}
}
@Component
public class TokenInterceptor implements RequestInterceptor {
private final HttpServletRequest request;
@Autowired
public TokenInterceptor(HttpServletRequest request) {
this.request = request;
}
@Override
public void apply(RequestTemplate template) {
boolean validateToken = TokenHolder.getTokenValidationFlag();
if (validateToken) {
String token = request.getHeader("X-Access-Token"); // 从原始请求头中获取 Token
template.header("Authorization", "Bearer " + token); // 将 Token 添加到 Feign 请求头中
template.header("X-Access-Token", token); // 将 Token 添加到 Feign 请求头中
}
}
}
定时任务处理
@Scheduled(fixedDelay =30 * 60 * 1000)
// @PostConstruct
public void initGoods(){
TokenHolder.setTokenValidationFlag(false);
Result<List<SysApplicationPermissionDto>> applicationAndPermissions = sysUserCenterApi.getApplicationAndPermissions();
TokenHolder.setTokenValidationFlag(true);