登录信息的显示 (初识拦截器)
业务实现:
创建 CookieUtil 工具类,通过 name 查询对应 cookie 的 value。
public class CookieUtil {
public static String getValue(HttpServletRequest request,String name){
if(request == null || name == null){
throw new IllegalArgumentException("参数错误");
}
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
if(cookie.getName().equals(name)){
return cookie.getValue();
}
}
}
return null;
}
}
在 UserService 中新增 findLoginTicket 方法,根据 ticket 查询 LoginTicket。
@Autowired
private LoginTicketMapper loginTicketMapper;
public LoginTicket findLoginTicket(String ticket){
return loginTicketMapper.selectByTicket(ticket);
}
附录1:
@Mapper
public interface LoginTicketMapper {
@Insert({
"insert into login_ticket(user_id,ticket,status,expired) " ,
"values(#{userId},#{ticket},#{status},#{expired})"
})
@Options(useGeneratedKeys = true,keyProperty = "id")
int insertLoginTicket(LoginTicket loginTicket);
@Select({
"select id,user_id,ticket,status,expired ",
"from login_ticket where ticket=#{ticket}"
})
LoginTicket selectByTicket(String ticket);
@Update({
"<script>",
"update login_ticket set status=#{status} where ticket=#{ticket} ",
"<if test=\"ticket!=null\">",
"and 1=1 ",
"</if>",
"</script>"
})
int updateStatus(String ticket,int status);
}
创建 HostHolder 类用来模拟 session 的功能,利用 ThreadLocal 实现,存储用户信息。
package com.nowcoder.community.util;
/**
* 持有用户的信息,用于代替session对象
*/
@Component
public class HostHolder {
private ThreadLocal<User> users = new ThreadLocal<>();
public void setUsers(User user) {
users.set(user);
}
public User getUser(){
return users.get();
}
public void clear(){
users.remove();
}
}
创建 LoginTicketInterceptor 拦截器,实现 HandlerInterceptor 接口。
@Component
public class LoginTicketInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Autowired
private HostHolder hostHolder;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//通过cookie获取凭证ticket
String ticket = CookieUtil.getValue(request,"ticket");
if(ticket != null){
//查询凭证
LoginTicket loginTicket = userService.findLoginTicket(ticket);
//检查凭证是否有效 超时时间晚于当前时间
if(loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())){
//根据凭证查询用户
User user = userService.findUserById(loginTicket.getUserId());
//在本次请求中持有用户 线程的隔离
hostHolder.setUsers(user);
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception{
User user = hostHolder.getUser();
if(user != null && modelAndView!=null){
modelAndView.addObject("loginUser",user);
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
hostHolder.clear();
}
}
在 preHandle 方法中通过 CookieUtil 的 getValue 方法查询是否有凭证 cookie,如果有则通过 UserService 的 findloginTicket 方法查询用户 ID,
再通过用户 ID 查询用户。最后将用户放入 hostHolder 中。
在 postHandle 方法中通过 hostHolder 的 get 方法获取用户,并将其存入视图中。
在 afterCompletion 方法中清除 hostHolder 中存放的用户信息。

创建 WebMvcConfig 配置类,实现 WebMvcConfigurer接口,配置 LoginTicketInterceptor,拦截除了静态资源之外的所有路径。
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private AlphaInterceptor alphaInterceptor;
@Autowired
private LoginTicketInterceptor loginTicketInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(alphaInterceptor)//表示拦截所有
.excludePathPatterns("/**/*.css","/**/*.js","/**/*.png","/**/*.jpg","/**/*.jpeg")//css js 等不拦截
.addPathPatterns("/register","/login");
registry.addInterceptor(loginTicketInterceptor)
.excludePathPatterns("/**/*.css","/**/*.js","/**/*.png","/**/*.jpg","/**/*.jpeg");
}
}
有关拦截器可参考:
(10条消息) Spring Boot拦截器(Interceptor)详解_hresh的博客-CSDN博客_spring 拦截器
有关ThreadLocal:
ThreadLocal,一篇文章就够了 - 知乎 (zhihu.com)

浙公网安备 33010602011771号