• Java项目SpringMVC拦截器+Redis优化登录功能


    一、项目中添加Spring MVC拦截器,拦截器怎么实现的,它的作用是什么?

    拦截器的作用:让未登录的用户不能访问某些页面。 拦截器是在controller代码执行之前,根据用户请求做出相应的处理;

    Spring Boot中的拦截器和Spring MVC中的一样,流程是:
    1、先定义一个拦截器类,并且这个类需要实现HandlerInterceptor接口,重写接口中的三个方法:preHandle、postHandler、afterCompletion;

    preHandle:此方法在进入controller之前执行,如果该方法返回ture,则程序继续向下执行处理器中的方法,否则程序将不再往下继续执行;
    注意:会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则执行用户请求的url方法。
    postHandler:此方法将在controller执行后执行;
    afterCompletion:此方法在整个请求结束(请求结束,但是并未返回给客户端)之后执行;

    2、将拦截器注入到配置类中(Config/WebMvcConfig.java)
    配置拦截器,通过实现WebMvcConfigurer接口,重写addInterceptors方法,具体代码如下:

    public class WebMvcConfig implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(alphaInterceptor)
    .excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg")
    .addPathPatterns("/register", "/login");}}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    excludePathPatterns:表示不拦截的资源(这里主要是静态资源:图片,js、css也属于静态资源);
    addPathPatterns:表示需要拦截的资源(即登录、注册)

    拦截器执行流程:
    1)单个拦截器执行流程:prehandle()—Handle(也就是控制器里的方法)—postHandle()—afterCompletion()。
    2)多个拦截器执行流程:
    preHandleA—preHandleC——Handle——postHandleC—postHandleA——afterCompletionC—afterCompletionA。

    二、项目中使用redis优化登录功能,怎么优化?

    1、为什么需要使用Redis的原因?
    1)使用Redis存储验证码kaptcha;
    a.验证码需要频繁的访问与刷新,对性能要求比较高;
    b.验证码不需要永久保存,通常在很短的时间后就会失效;
    c.分布式部署时,存在Session共享问题。
    Session 是保存在服务器的⽂件中,如果是集群服务,同⼀个⽤户过来可能落在不同机器上,这就会导致⽤户频繁登陆;采⽤ Redis 保存 Session 后,无论⽤户落在那台机器上都能够获取到对应的Session 信息。
    2)使用Redis存储登录凭证ticket;
    a.处理每次请求时,都需要查询用户的登录凭证,访问的频率非常高。
    3)使用Redis缓存用户信息user。
    a.处理每次请求时,都要根据凭证查询用户信息,访问的频率非常高。

    2、为什么Redis速度快、性能好?
    (1)数据存放在内存中:内存的读写速度比磁盘(数据库)快的多;
    (2)数据结构简单,对数据操作也简单;
    (3)采⽤单线程,没有多线程竞争锁的性能消耗,也没有多线程导致的切换而消耗CPU, 或者多线程死锁等问题;
    (4)使⽤多路 I/O 复⽤模型(解决单线程速度慢的问题),⾮阻塞 IO。

    3、之前基于Session的登录功能怎么使用Redis优化?
    1)登录注册功能的验证码之前是存放在Session中,会增加服务端的内存压力,现在通过Cookie获取信息存储到Redis中,Redis的key存随机字符串,Value存生成的字符串;并且设置60s后自动清理;然后就从redis中获取验证码,赋值给kaptcha;
    Key值的获取:

    String kaptchaOwner = CommunityUtil.generateUUID();
    String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
    
    • 1
    • 2

    Key和Value值存储到Redis中:(其中text是value)

    String text = kaptchaProducer.createText();
    redisTemplate.opsForValue().set(redisKey, text,60, TimeUnit.SECONDS);
    
    • 1
    • 2

    2)使用Redis存储登录凭证

    String redisKey = RedisKeyUtil.getTicketKey(ticket.getTicket());     
    redisTemplate.opsForValue().set(redisKey, ticket);        
    map.put("ticket", ticket.getTicket());
    
    • 1
    • 2
    • 3

    3)每次请求,根据登录凭证,查询用户信息
    a.优先从缓冲中取值;
    b.取不到时初始化缓冲数据(redis存值);
    c.数据变更时清除缓存(删除redis的Key)

  • 相关阅读:
    Elasticsearch 如何保证写入过程中不丢失数据的
    C语言经典面试题目(十六)
    【LeetCode刷题-树】--1367.二叉树中的链表
    LeetCode_674_最长连续递增序列
    RXJS概念的个人理解:响应式编程思想
    JQuary---获取文本内容,正则表达式
    go 链表
    10道不得不会的Docker面试题
    C++初始化列表使用与否的区别
    Java 8实战(八)- 数值流与构建流
  • 原文地址:https://blog.csdn.net/qq_41894176/article/details/126828752