Spring Session - 使用Spring Session从零到一构建分布式session
文章目录
- 快速入门 Spring Session + Redis
- 官网指导
- Demo
- pom 依赖
- 配置文件
- 配置类RedisHttpSessionConfiguration
- Redis中的session数据解析
- 附 其他相关类
- BaseController
- 统一返回结果相关的Code
- Jedis的POM依赖及配置
快速入门 Spring Session + Redis
官网指导
https://spring.io/projects/spring-session-data-redis#samples
我们就用spring boot 来演示下吧
Demo
pom 依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>boot2</artifactId><groupId>com.artisan</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>springsession</artifactId><dependencies><!-- 实现对 Spring MVC 的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- redis lettuce 需要使用--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!-- 实现对 Spring Session 使用 Redis 作为数据源的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 实现对 Spring Data Redis 的自动化配置 --><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
配置文件
server:port: 8888spring:redis:host: 127.0.0.1port: 6379password: # Redis密码timeout: 5000mslettuce:pool:max-active: 8max-wait: -1msmax-idle: 8min-idle: 0session:store-type: redis
max-active: 8 # 连接池最大连接数,默认为 8 。使用负数表示没有限制。
max-idle: 8 # 默认连接数最大空闲的连接数,默认为 8 。使用负数表示没有限制。
min-idle: 0 # 默认连接池最小空闲的连接数,默认为 0 。允许设置 0 和 正数。
max-wait: -1 # 连接池最大阻塞等待时间,单位:毫秒。默认为 -1 ,表示不限制。
session: store-type: redis 指定存储类型
配置类RedisHttpSessionConfiguration
package com.artisan.config;import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/2/16 14:12* @mark: show me the code , change the world*/
@Configuration
@EnableRedisHttpSession
public class RedisHttpSessionConfiguration {@Bean(name = "springSessionDefaultRedisSerializer")public RedisSerializer springSessionDefaultRedisSerializer() {return RedisSerializer.json();}
}
添加 @EnableRedisHttpSession 注解,开启自动化配置 Spring Session 使用 Redis 作为数据 。
我们来下 EnableRedisHttpSession 注解
maxInactiveIntervalInSeconds 属性,Session 不活跃后的过期时间,默认为 1800 秒。
redisNamespace 属性,在 Redis 的 key 的统一前缀,默认为 “spring:session” 。
flushMode 属性,Redis 会话刷新模式(RedisFlushMode)。支持两种,默认为
RedisFlushMode.ON_SAVE
RedisFlushMode.ON_SAVE ,在请求执行完成时,统一写入 Redis 存储。
RedisFlushMode.IMMEDIATE ,在每次修改 Session 时,立即写入 Redis 存储。cleanupCron 属性,清理 Redis Session 会话过期的任务执行 CRON 表达式,默认为
"0 * * * * *"
每分钟执行一次。虽然Redis 自带了 key 的过期,但是惰性删除策略,实际过期的 Session 还在 Redis 中占用内存。所以,Spring Session 通过定时任务,删除 Redis 中过期的 Session ,尽快释放 Redis 的内存。
默认情况下,采用 Java 自带的序列化方式 ,可读性很差。 所以在 springSessionDefaultRedisSerializer()
方法,定义了一个 Bean 名字为 springSessionDefaultRedisSerializer
的 RedisSerializer Bean ,采用 JSON 序列化方式 。
好了,截止到目前,核心的框架已经搭建起来了,我们来测试下
package com.artisan.controller;import com.artisan.common.CommonResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/2/16 14:42* @mark: show me the code , change the world*/
@RestController
public class ArtisanController extends BaseController {@GetMapping("/mockSet")public CommonResult set(@RequestParam("key") String key, @RequestParam("value") String value) {getHttpSession().setAttribute(key, value);return CommonResult.success("成功模拟登录");}@GetMapping("/mockGet") public CommonResult get(@RequestParam("key") String key) {return CommonResult.success( getHttpSession().getAttribute(key));}}
启动测试类,走一波
package com.artisan;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringSeesionDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringSeesionDemoApplication.class, args);}}
访问 http://localhost:8888/mockSet?key=artisan &value=avalue
http://localhost:8888/mockGet?key=artisan
Redis中的session数据解析
127.0.0.1:0>keys *1) "spring:session:sessions:expires:e0dd90b9-9551-4e8a-9609-cde0758b88c2"2) "spring:session:sessions:e0dd90b9-9551-4e8a-9609-cde0758b88c2"3) "spring:session:expirations:1613470560000"
每一个 Session 对应 Redis 二个 key-value 键值对
- 开头:以 spring:session 开头,可以通过 @EnableRedisHttpSession 注解的 redisNamespace 属性配置。
- 结尾:以对应 Session 的 sessionid 结尾。
- 中间:中间分别是
"session"、"expirations"、sessions:expires
一般情况下,只需要关注中间为 session
的 key-value 键值对即可,它负责真正存储 Session 数据
127.0.0.1:0>hgetall spring:session:sessions:ab7d40d8-cd3d-49d7-8b3a-d1ae71d409351) "lastAccessedTime" # 最后访问时间2) "1613469344975"3) "maxInactiveInterval" # Session 允许最大不活跃时长,单位:秒。4) "1800"5) "creationTime" # 创建时间6) "1613469342207"7) "sessionAttr:artisan" # 设置的属性值8) ""avalue""
127.0.0.1:0>
对于中间为 sessions:expires
和 expirations
的两个来说,主要为了实现主动删除 Redis 过期的 Session 会话,解决 Redis 惰性删除的问题。
spring:session:expirations:{时间戳}
,是为了获得每分钟需要过期的 sessionid 集合,即 {时间戳} 是每分钟的时间戳
附 其他相关类
BaseController
package com.artisan.controller;import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class BaseController {public HttpServletRequest getRequest(){return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();}public HttpServletResponse getResponse(){return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();}public HttpSession getHttpSession(){return getRequest().getSession();}}
统一返回结果相关的Code
【IErrorCode 】
package com.artisan.common;public interface IErrorCode {long getCode();String getMessage();
}
【ResultCode 】
package com.artisan.common;public enum ResultCode implements IErrorCode {SUCCESS(200, "操作成功"),FAILED(500, "操作失败"),VALIDATE_FAILED(404, "参数检验失败"),UNAUTHORIZED(401, "暂未登录或token已经过期"),FORBIDDEN(403, "没有相关权限");private long code;private String message;private ResultCode(long code, String message) {this.code = code;this.message = message;}public long getCode() {return code;}public String getMessage() {return message;}
}
【CommonResult】
package com.artisan.common;public class CommonResult<T> {private long code;private String message;private T data;protected CommonResult() {}protected CommonResult(long code, String message, T data) {this.code = code;this.message = message;this.data = data;}/*** 成功返回结果** @param data 获取的数据*/public static <T> CommonResult<T> success(T data) {return new CommonResult<T>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);}/*** 成功返回结果** @param data 获取的数据* @param message 提示信息*/public static <T> CommonResult<T> success(T data, String message) {return new CommonResult<T>(ResultCode.SUCCESS.getCode(), message, data);}/*** 失败返回结果* @param errorCode 错误码*/public static <T> CommonResult<T> failed(IErrorCode errorCode) {return new CommonResult<T>(errorCode.getCode(), errorCode.getMessage(), null);}/*** 失败返回结果* @param message 提示信息*/public static <T> CommonResult<T> failed(String message) {return new CommonResult<T>(ResultCode.FAILED.getCode(), message, null);}/*** 失败返回结果*/public static <T> CommonResult<T> failed() {return failed(ResultCode.FAILED);}/*** 参数验证失败返回结果*/public static <T> CommonResult<T> validateFailed() {return failed(ResultCode.VALIDATE_FAILED);}/*** 参数验证失败返回结果* @param message 提示信息*/public static <T> CommonResult<T> validateFailed(String message) {return new CommonResult<T>(ResultCode.VALIDATE_FAILED.getCode(), message, null);}/*** 未登录返回结果*/public static <T> CommonResult<T> unauthorized(T data) {return new CommonResult<T>(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data);}/*** 未授权返回结果*/public static <T> CommonResult<T> forbidden(T data) {return new CommonResult<T>(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);}/*** 请求异常返回结果#add by yangguo*/public static <T> CommonResult<T> badResponse(IErrorCode errorCode) {return new CommonResult<T>(errorCode.getCode(), errorCode.getMessage(), null);}public long getCode() {return code;}public void setCode(long code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}
}
Jedis的POM依赖及配置
Spring Boot 2 以上默认使用lettuce作为redis的客户端,如果想要用jedis ,我这里也给大家准备了一份,请参考
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><!-- 去掉对 Lettuce 的依赖, Spring Boot 优先使用 Lettuce 作为 Redis 客户端 --><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><!-- 引入 Jedis 的依赖 --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency></dependencies>
spring:# 对应 RedisProperties 类redis:host: 127.0.0.1port: 6379password: # Redis 服务器密码,默认为空。生产中,一定要设置 Redis 密码!database: 0 # Redis 数据库号,默认为 0 。timeout: 0 # Redis 连接超时时间,单位:毫秒。# 对应 RedisProperties.Jedis 内部类jedis:pool:max-active: 8 # 连接池最大连接数,默认为 8 。使用负数表示没有限制。max-idle: 8 # 默认连接数最大空闲的连接数,默认为 8 。使用负数表示没有限制。min-idle: 0 # 默认连接池最小空闲的连接数,默认为 0 。允许设置 0 和 正数。max-wait: -1 # 连接池最大阻塞等待时间,单位:毫秒。默认为 -1 ,表示不限制。
Spring Session - 使用Spring Session从零到一构建分布式session相关推荐
- Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架
Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloopimport tornado.webfrom myhash ...
- 170222、使用Spring Session和Redis解决分布式Session跨域共享问题
使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...
- 使用Spring Session和Redis解决分布式Session跨域共享问题
大家可以关注一下公众号"Java架构师秘籍" 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash.轮训.根据权重.随机等.不管对于哪一种负载 ...
- 基于Spring Session实现JIM分布式Session
基于Spring Session实现JIM分布式Session 前引 在实际项目中,应用程序经常会以集群方式部署线上,一般来说无状态的应用程序是理想的部署方式,一旦应用程序拥有状态(比如Session ...
- 使用springSession完成分布式session
系列文章目录 文章目录 系列文章目录 使用springSession完成分布式session 使用springSession完成分布式session 原文链接 https://zhhll.icu/20 ...
- 分布式Session一致性概述
分布式Session一致性问题 什么是SessionSession 是客户端与服务器通讯会话技术, 比如浏览器登陆.记录整个浏览会话信息 分布式SESSION一致性的问题,分布式SESSION到底如何 ...
- Spring Boot(十一)Redis集成从Docker安装到分布式Session共享
2019独角兽企业重金招聘Python工程师标准>>> 一.简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并 ...
- session传递参数_分布式 Session 之 Spring Session 架构与设计
作者 | 李增光 杏仁后端工程师.「只有变秃,才能变强!」 前言 开始进行 Web 开发时,我们可能会遇到这样的情况,当服务器重启之后,之前的登录状态会失效需要重新登录.又或者你的应用程序部署了不止 ...
- [译]Spring Session 与 Spring Security
原文:http://docs.spring.io/spring-session/docs/current-SNAPSHOT/reference/html5/guides/security.html 本 ...
最新文章
- 软件测试-PR录制脚本程序ie的时候闪退
- 神策数据:从技术视角看,如何更多、更好、更快地实施A/B试验
- 二值图像的距离变换研究
- Kubeflow使用Kubernetes进行机器学习GPU分布式训练
- java setlayout_Java Button.setLayoutX方法代码示例
- Oracle中的sequence对象
- Codeforces Round #197 (Div. 2): D. Xenia and Bit Operations(线段树)
- cloudare mysql 密码修改_CentOS7.3 LAMP环境搭建私有云NextCloud过程记录
- 伟大的通信使者——JSON(JavaScript版本)
- javascript_core之正则、Math、Date
- 规范JavaScript注释
- 软件开发生命周期的五个阶段
- truncate table(截断表)
- Qt之调用Windows图片查看器预览图片
- 诛仙斩龙墨雪服务器怎么找不到了,《诛仙3》5月13日服务器数据互通公告
- 华为确定发布鸿蒙的时间了吗,Mate40系列首发,华为鸿蒙OS手机版发布时间确定...
- OBS Studio安装教程以及录制等详细配置
- Unity FairyGUI(十二)
- DEM+谷歌地球取点工具获取场地地形矢量数据
- 2006电子商务大盘点
热门文章
- 下如何画出频率瀑布图_用maftools一行代码画出瀑布图
- Oracle的job(定时执行存储过程)
- python sin(x)/x 图像
- ubuntu 安装 anaconda
- Hierarchical Attention Networks for Document Classification 阅读笔记
- osmnx 补充笔记:get_edge_colors_by_attr get_node_colors_by_attr
- 机器学习笔记:Adagrad
- Python应用实战案例-Python实现K线图绘制
- MATLAB从入门到精通-新增返回数组高、宽数字特征的全新方式
- Linux疑难杂症解决方案100篇(九)-SHELL编程正则表达式