有这样一个场景,A网站会多次调用B网站返回数据,前提是需要每次都携带B网站的token,由于A网站用户与B网站用户做了一个关联,很容易拿到B的token,然后通过RestTemplate把token设置给请求头,问题就是每次请求都要先获取再设置,那么能不能获取一次呢,于是就想到了ThreadLocal,记录一下吧。
三个步骤:1、创建拦截器——>2、注册拦截器——>3、设置给RestTemplate的请求头。
- 创建拦截器LoginInterceptor
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Value("${environment}")
private String environment;
// 声明线程的局部变量
public static final ThreadLocal<String> THREE_TOKEN = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String jwt = request.getHeader("authorization");
Claims claims = JwtHelper.parseJWT(jwt);
if (claims == null) {
return true;
}
// threeId为第三方用户id
String token = TokenHelper.getTokenByThreeId((Integer) claims.get("threeId"), environment);
THREE_TOKEN.set(token);
// 这里不做拦截,只为获取用户登录信息,不管有没有登录都要放行
return true;
}
/**
* 封装了一个获取线程局部变量值的静态方法
* @return
*/
public static String getToken(){
return THREE_TOKEN.get();
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
THREE_TOKEN.remove();
}
}
2、注册拦截器
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//拦截所有路径
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/pay/**");
}
}
一般上面代码就注册成功了,可是我在这里拦截器没有生效,原因是项目为了解决跨域,有一个WebConfig类继承了WebMvcConfigurationSupport,那么就需要重新注册一下,可以把addInterceptors直接写在Webconfig类里面,代码如下:
public class WebConfig extends WebMvcConfigurationSupport {
@Autowired
private LoginInterceptor loginInterceptor;
@Resource
private SessionArgumentResolver sessionArgumentResolver;
@Value("${imgBaseDir}")
private String imgBaseDir;
/**
* 注册拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//拦截所有路径
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/pay/**");
}
@Override
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(sessionArgumentResolver);
super.addArgumentResolvers(argumentResolvers);
}
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/static/**").addResourceLocations("file:" + imgBaseDir);
super.addResourceHandlers(registry);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/static/svga/**")
.allowedOrigins("http://xx.xx.xx.xx:xxxx")
.allowedMethods("GET", "POST")
.allowCredentials(false).maxAge(3600);
}
}
3、给RestTemplate设置请求头。
public JSONObject getJsonData(String powerStationId, String url) {
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");
headers.set("language", "zh");
// 设置Token
headers.set("Authorization", LoginInterceptor.getToken());
JSONObject forObject = restTemplate.getForObject(THREE_PROD_CLOUD_IP + url, JSONObject.class, headers);
return forObject;
}
当命运之神把你推向那勇敢的时刻,希望你能像你想象中那么勇敢。