拦截器(Interceptor)
- * 是一种动态拦截方法调用的机制;
- * 类似于Servlet 开发中的过滤器Filter,用于对处理器进行前置处理和后置处理。
ThreadLocal
- * 线程内部的存储类,赋予了线程存储数据的能力。
- * 线程内调用的方法都可以从ThreadLocal中获取同一个对象。
- * 多个线程中ThreadLocal数据相互隔离
代码实现
1.定义ThreadLocal工具类,仅需要调用set方法即可将数据存入ThreadLocal中
public class UserHolder {
private static ThreadLocal<User> threadLocal=new ThreadLocal<>();
//存入用户
public static void set(User user){
threadLocal.set(user);
}
//提取用户
public static User get(){
return threadLocal.get();
}
//手机号
public static String getMobile(){
return threadLocal.get().getMobile();
}
//提取id
public static Long getId(){
return threadLocal.get().getId();
}
//清空
public static void remove(){
threadLocal.remove();
}
}
2、定义拦截器
定义拦截器,在前置拦截方法preHandle中解析token并验证有效性,如果失效返回状态码401。如果有效,解析User对象,存入ThreadLocal中
import com.tanhua.commons.JwtUtils;
import com.tanhua.model.admin.User;
import io.jsonwebtoken.Claims;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
定义拦截器,在前置拦截方法preHandle中解析token并验证有效性
*/
public class TokenInterceptor implements HandlerInterceptor {
//拦截器执行之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头
String token = request.getHeader("Authorization");
//判断token是否过期
boolean b = JwtUtils.verifyToken(token);
if (!b){
response.setStatus(401);
}
Claims claims = JwtUtils.getClaims(token);
String mobile = (String) claims.get("mobile");
Integer id = (Integer) claims.get("id");
User user = new User();
user.setId(Long.valueOf(id));
user.setMobile(mobile);
//存储ThreadLocal
UserHolder.set(user);
//返回结果
return b;
}
//拦截器执行后
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
UserHolder.remove();
}
}
3、注册拦截器
拦截器需要注册到MVC容器中
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TokenInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(new String[]{"/user/login","/user/loginVerification"});
}
}