东方飘雪

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
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

 

方式二:以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为例)

@Autowired
private 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;
@Autowired
private 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;
@Autowired
private 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

https://www.cnblogs.com/yingsong/p/9838198.html

 https://blog.51cto.com/11864647/2287402

posted on 2019-08-31 14:56  东方飘雪  阅读(677)  评论(0编辑  收藏  举报