springboot的版本:<version>2.1.6.RELEASE</version>
搭建springboot框架涉及到session管理,交给springboot框架管理,同时为了以后分布式或集群等的扩展,故将session存储到Redis数据库中。
理解:: session交给spring管理, spring将session信息存储到redis数据库中,配置好相关配置就可以。至于spring怎么跟redis赋值、取值等spring框架自动去处理,不用开发者去管。
( 既然引入了redis。这里可不仅仅就存session。建一个redis的管理连接的公共类,这样其他地方就可以使用redis了(先建session相关,后面再弄这块))
一、引入maven依赖
<dependency><!--redis依赖包 --><!--spring boot 与redis应用基本环境配置 --><!--没写版本号。直接依赖spring-boot-starter-parent的了,这样避免兼容性问题-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency><!--spring-session依赖包 --><!--spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
二、Redis 和 Session 配置(application.properties****)
1. redis 和 redis连接池配置(application.properties)
#*************************************** Redis配置 *********************************************
# Redis数据库索引(默认为0)
spring.redis.database=1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接密码(默认为空)
spring.redis.password=
#连接超时时间(毫秒)(不能设置太短,我之前设置为0,导致服务启动不了,报错io.lettuce.core.RedisCommandTimeoutException: Command timed out)
spring.redis.timeout=5000
# ****************Redis连接池配置 #lettuce 是一个可以做缓冲池的插件,也可以不用,使用pool为三级参数,即spring.redis.pool...
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=100
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=5
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=60000
**注:::关于springboot各个版本的redis集成,参考springboot中各个版本的redis配置问题
2.Spring Session配置
有两种方式(我用的方式一)
方式一: application.properties中配置
#*************************************** Spring Session配置 *********************************************
#spring session使用存储类型(启动Redis管理session) 《springboot默认就是使用redis方式,如果不想用可以填none》
spring.session.store-type=redis
#自定义命名空间
spring.session.redis.namespace=gkzpSession
#RedisFlushMode有两个参数:ON_SAVE(表示在response commit前刷新缓存),IMMEDIATE(表示只要有更新,就刷新缓存)
spring.session.redis.flush-mode=on_save
#session超时时间(s) (要确定服务器时间与Redis数据库服务时间同步)
spring.session.timeout=1800
注:session存放在redis中的命名空间,以及``修改cookies中sessionId的名字。 参考:[https://blog.51cto.com/11864647/2287402](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fblog.51cto.com%2F11864647%2F2287402)
方式二:以springboot注解的方式
package com.nsoft.gkzp.syscore.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
/**
* session托管到redis
*
*/
//使用springboot-session处理,单位:秒;
//maxInactiveIntervalInSeconds session超时时间(s) 1800s=30m
//RedisFlushMode有两个参数:ON_SAVE(表示在response commit前刷新缓存),IMMEDIATE(表示只要有更新,就刷新缓存)
//redisNamespace
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=1800, redisFlushMode = RedisFlushMode.ON_SAVE, redisNamespace = "gkzpSession")//单位为秒
public class RedisSessionConfiguration {
}
**重要:::spingboot服务器和redis服务器时间必须同步
springsession会拿服务器时间 跟 redis存储的时间比对,看时间差是否超时、失效。如果时间不同步,可能有些请求就会session失效,或者自己往session中存放的需手工确认失效的功能 会偶尔出错;比如:短信验证码
关于linux时间同步,请看文章:https://www.cnblogs.com/yingsong/p/9857591.html
配置成功,redis的session如下:
三、RedisTemplate之opsForValue使用说明
上面配置好后。在java中可直接用StringRedisTemplate或RedisTemplate.posForValue对redis进行操作:
.posForValue有很多命令。请查看 https://blog.csdn.net/aoxiangzhe/article/details/93164823
@Autowired
StringRedisTemplate stringRedisTemplate; // k-v都是字符串
@Autowired
RedisTemplate redisTemplate; // k-v都是对象 如果是对象,对象需要实现序列号,否则报错,eg:public class Employee implements Serializable {xxxx} //序列化后,存入redis里的value值依然是乱码,其实默认的序列化是JDK的,我们需要自己优化一下,比如编程json的序列化。
json序列化参照:https://www.cnblogs.com/iceb/p/9479976.html 但用这个方式json序列号依然不起作用,后来在网上又查了其他的,配置成
package com.nsoft.gkzp.syscore.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* 使用RedisTemplate.opsForValue()方法向redis存储对象时,json串为乱码,故在这里配置下,设置序列化Key及Value的实例化对象
* @author zdyang
* @date 2019.09.05
*/
@Configuration
public class MyRedisConfig {
@Autowired
private RedisTemplate redisTemplate;
@Bean
public RedisTemplate redisTemplateInit() {
//设置序列化Key的实例化对象
redisTemplate.setKeySerializer(new StringRedisSerializer());
//设置序列化Value的实例化对象
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
}
例如:(以RedisTemplate为例)
@Autowiredprivate RedisTemplate redisTemplate;
SysUser sysUser = sysUserService.login(loginName, null);//账户校验 并获得其信息
redisTemplate.opsForValue().set("timeOutKey",sysUser,10, TimeUnit.SECONDS); String timeOutValue = redisTemplate.opsForValue().get("timeOutKey")+"";System.out.println("通过set(K key, V value, long timeout, TimeUnit unit)方法设置过期时间,过期之前获取的数据:"+timeOutValue); Thread.sleep(5*1000);timeOutValue = redisTemplate.opsForValue().get("timeOutKey")+""; System.out.print(",等待10s过后,获取的值:"+timeOutValue);
生成后台 和 redis数据如下:
成功了,json串不是乱码了,但spring管的session里存储的json串依然乱码。这个后面研究这了再完善吧。
例如:(以StringRedisTemplate为例)
package com.nsoft.gkzp.system.sysuser.controller;
import org.springframework.data.redis.core.StringRedisTemplate;
@Autowiredprivate StringRedisTemplate redisTemplate;
... ... redisTemplate.opsForValue().set("loginUser:" +sysUser.getId(), arg0.getSession().getId());//向redis里存储 用户ID-sessionID对,用于拦截器判断是否重复登录//这里Key值写成 "loginUser:" +sysUser.getId()。就会生成名字为loginUser的命名空间,其Key值为"loginUser:" +sysUser.getId()。如不带:的话,就不会生成命名空间
package com.nsoft.gkzp.syscore.config.interceptor;
import org.springframework.data.redis.core.StringRedisTemplate;
@Autowiredprivate StringRedisTemplate redisTemplate;... ...
String loginSessionId = redisTemplate.opsForValue().get("loginUser:" +userContext.getLoginUserId());//获得在redis存储的seesionID
if (loginSessionId != null && loginSessionId.equals(request.getSession().getId())) { return true; }
生成一个名为loginUser的namespace中。永久保存。
在做这块的时候,参照了网上一些文章:
https://www.cnblogs.com/jpfss/p/11016400.html