Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 669|回复: 0

Spring Boot 解决方案 - 会话

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-9-4 13:09:47 | 显示全部楼层 |阅读模式

    连接无状态

    使用 HTTP 的连接是无状态的,因此为了应对需要状态的服务例如用户登录,诞生了适合保存状态的设计-会话(session),本文就来探讨一下会话。

    会话的使用

    Spring Mvc 中使用会话很简单,在控制器类的方法参数列表中,直接编写 HttpSession 类型的参数,或者参数列表中编写 HttpServletRequest 类,然后使用 getSession() 方法获取会话。

    下面是使用会话的简单例子,第一次访问时会创建一个无数据的会话,因此获取到的 access 属性为 null ,而当不是第一次访问时,由于属性不为 null 会得到 "NOT THE FIRST TIME ACCESS" 。

    @RestController
    public class DemoController {
        private static final String ACCESS = "access";
        @RequestMapping("/")
        public String index(HttpSession session) { // or `index(HttpServletRequest req)`
            // then `HttpSession session = request.getSession();`
            if (session.getAttribute(ACCESS) == null) {
                session.setAttribute(ACCESS, true);
                return "FIRST TIME ACCESS";
            }
            return "NOT THE FIRST TIME ACCESS";
        }
    }
    

    注意:由于用 Mock Mvc 测试获取不到第一次请求 Cookies,因此无法模拟得到正确结果,请使用浏览器或者请求工具测试。

    常用方法

    上面例子展示了会话的简单使用,其中 HttpSession 接口是 servlet 的标准,而 Spring Mvc 中的会话默认使用 Tomcat 的实现。下面来介绍几个常用方法,更多方法使用请参考这篇文章

    • Object getAttribute(String) 方法用来获取会话的属性,若不存在则返回 null
    • void setAttribute(String, Object) 方法用来设置会话的属性
    • void removeAttribute(String) 方法用来删除会话的属性
    • void setMaxInactiveInterval(int) 方法用来设置会话失效时间,单位为秒,设置小于等于零的数则会话永不过期
    • void invalidate() 手动使会话失效并清理会话数据

    会话监听器

    会话的生命周期分别为创建、失效和创建与失效之间,而会话监听器是为了满足会话生命周期中触发相应事件的需要,HttpSessionListenerHttpSessionAttributeListener 两个监听器接口分别满足了会话的各个生命周期。使用监听器只需实现这些接口然后标注 @WebListener 注解即可,下面会有实现的例子。

    针对会话的监听器

    HttpSessionListener 接口可以算是针对会话的监听器接口,因为它的两个方法分别在会话创建和失效时调用,下面为一个简单的例子,参数列表中 HttpSessionEvent 类可以用 getSession 获取会话。

    @WebListener
    public class SessionListener implements HttpSessionListener {
    	public void sessionCreated(HttpSessionEvent event) {
    		// ...
        }
    	public void sessionDestroyed(HttpSessionEvent event) {
    		// ...
        }
    }
    

    针对会话属性的监听器

    HttpSessionListener 监听器接口接管会话生命周期的创建与失效不同,HttpSessionAttributeListener 监听器接口负责会话属性的创建、销毁与替换,下面为该监听器的简单例子,参数列表中 HttpSessionBindingEvent 类除了可以用 getSession 获取会话,最主要的是可用 getNamegetValue 分别获取属性的名字和值。

    @WebListener
    public class SessionListener implements HttpSessionBindingListener {
    	public void attributeAdded(HttpSessionBindingEvent event) {
    		// ...
    	}
    	
    	public void attributeRemoved(HttpSessionBindingEvent event) {
    		// ...
        }
        
        public void attributeReplaced(HttpSessionBindingEvent event) {
    		// ...
        }
    }
    

    使监听器生效

    上面的例子只是编写了监听器的实现,为了使得监听器在项目里生效,还必须在启动类或者配置类上标注 @ServletComponentScan 来扫描这些属于 servlet 组件的监听器,例如下面在配置类上启动 servlet 组件扫描。

    @Configuration
    @ServletComponentScan  // enable scan servlet component
    public class ApplicationConf {
    	// ...
    }
    

    分布式会话

    若是有多台 Web 服务器提供不同的服务,且要求属于同一会话,上面的单机会话例子就无法满足要求,于是就有了分布式会话即可以共享会话数据。

    利用 Spring Session 就可以实现分布式会话,而 Spring Session 的实现可依赖关系数据库或内存数据库,下面例子为 Spring Boot 中导入基于 Redis 实现的 Spring Session 的依赖。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
    	<groupId>org.springframework.session</groupId>
    	<artifactId>spring-session-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
    

    接着在 Spring Boot 的属性配置文件中,添加如下的属性即可,而对于会话的使用和单机会话操作是一样的

    spring:
      session:
        store-type: redis
      redis:
        host: 127.0.0.1
        port: 6379
    

    会话安全问题

    关于会话安全问题,由于了解知识尚浅,暂且不做探讨,后续会补充该部分。

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 12:59 , Processed in 0.057324 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表