登录信息的显示 (初识拦截器)

业务实现:

创建 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)



posted @ 2022-04-07 21:43  ChouchouYa  阅读(55)  评论(0)    收藏  举报