redis自定义配置

1、为什么 依赖了web-session就可以使用redis了?

因为我们引入了 web-session.xml

问: 我们如何在项目中使用web-session呢?
答: redis session的使用

2、web-session.xml做了什么

场景介绍:HttpSession 是通过 Servlet 容器创建和管理的,像 Tomcat/Jetty 都是保存在内存中的。而如果我们把 web 服务器搭建成分布式的集群,然后利用 LVS 或 Nginx 做负载均衡,那么来自同一用户的 Http 请求将有可能被分发到两个不同的 web 站点中去。那么问题就来了,如何保证不同的 web 站点能够共享同一份 session 数据呢?
解决方案:使用框架的会话管理工具,也就是spring-session ,可以理解是替换了 Servlet 那一套会话管理,接管创建和管理 Session 数据的工作。既不依赖容器,又不需要改动代码,并且是用了 spring-data-redis 那一套连接池,可以说是最完美的解决方案。
具体实现: (已有同学提供实现文档)
spring-session 的介绍
spring-session 的使用
spring session官方文档

我们的session数据是存放在哪里的呢?我们是存放在redis中的。

redis概要:REmote DIctionary Server(Redis) 是一个高性能的key-value内存数据库。之所以说是内存数据库,是因为redis基于内存的读取和写入相比传统的数据库基于磁盘IO快上数倍。
jedis概要:那jedis就是集成了redis的一些命令操作,封装了redis的java客户端。提供了连接池管理。一般不直接使用jedis,而是在其上在封装一层,作为业务的使用。
由于我们项目是spring框架,可以使用spring 封装的 redis [Spring Data Redis]。Spring Data Redis提供了四种Redis服务的Java客户端包的集成,分别是 Jedis ,JRedis , SRP and Lettuce
参考文档:
redis 命令文档
可视化redis工具下载

image.png

3、自定义配置

由于技术保障部给大家提供了统一使用的包,自然需要提供大家可以自定义配置自己项目的功能。例如设置session或者cookie的过期时间。这也是这篇文档相对重点的部分。
在我们自定义配置过程中,我们不是使用继承的方式来覆盖配置的。我们实际做的是把它作为一个bean使用。Spring初始化的时候会扫描包, 然后 bean对象由Spring接管, 对象内可以注入其他bean对象, 在这里就是注入了 DefaultCookieSerializer 或RedisHttpSessionConfiguration的 bean对象, 而默认的bean对象都是单例的, 所以你这里修改了这个bean对象, 那么系统中这个配置也就改掉了。相当于直接覆盖。

1 . 配置存在于浏览器的cookie

image.png

具体分析:有兴趣可以看以下org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration的源码,里面提供的方法都会告诉你提供了哪些配置。摘自-自定义redisoperationssessionrepository官方文档

  • maxInactiveIntervalInSeconds - the amount of time before the session will expire in seconds

  • redisNamespace - allows configuring an application specific namespace for the sessions. Redis keys and channel IDs will start with the prefix of <redisNamespace>:.

  • redisFlushMode - allows specifying when data will be written to Redis. The default is only when save is invoked on SessionRepository. A value of RedisFlushMode.IMMEDIATE will write to Redis as soon as possible.

2.配置存在于服务器的session

image.png

具体分析:大家有兴趣可进入 org.springframework.session.web.http.DefaultCookieSerializer 看一下,里面分别设置哪些参数。以下是可以配置的参数列表:摘自-自定义cookie配置官方文档

  • cookieName - the name of the cookie to use Default "SESSION"
    // cookie名称,默认是SESSION
  • useSecureCookie - specify if a secure cookie be used Default use value of HttpServletRequest.isSecure() at the time of creation.// 在创建时默认使用HttpServletRequest.isSecure()的值
  • cookiePath - the path of the cookie Default is context root
    // cookie路径,默认是内容跟目录的路径
  • cookieMaxAge - specifies the max age of the cookie to be set at the time the session is created. Default is -1 which indicates the cookie will be removed when the browser is closed.
    // 指定在创建会话时要设置的Cookie的最大年龄。默认值是-1,这意味着当浏览器关闭时cookie将被删除。
  • jvmRoute - specifies a suffix to be appended to the session id and included in the cookie. Used to identify which JVM to route to for session affinity. With some implementations (i.e. Redis) this provides no performance benefit. However, this can help with tracing logs of a particular user.
  • domainName - allows specifying a specific domain name to be used for the cookie. This option is simple to understand, but will likely require a different configuration between development and production environments. See domainNamePattern as an alternative.
    // 允许指定用于Cookie的特定域名。建议使用domainNamePattern作为备选方案,因为正式和测试的选项不一样。
  • domainNamePattern - a case insensitive pattern used to extract the domain name from the HttpServletRequest#getServerName(). The pattern should provide a single grouping used to extract the value of the cookie domain. If the regular expression does not match, no domain is set and the existing domain will be used. If the regular expression matches, the first grouping will be used as the domain.
    // 正则匹配域名

4、配置后的现象

实验方案:建立2个页面,分别名为:about.page, help.page
我在 about.page 写如下代码

// 往redis设值的过程
String unionId = "bbbb";
WebUser user = userDelegator.weixinGetSession(unionId);

String uid = user.getUid();
String sessionId = user.getSessionId();
session.setAttribute("uid", uid);
session.setAttribute("sessionId", sessionId);
String sessionGetId = session.getId();
System.out.println("sessionGetId " + sessionGetId);
System.out.println("uid:" +  session.getAttribute("uid"));
System.out.println("sessionId:" +  session.getAttribute("sessionId"));

我在 help.page 写如下代码

// 从redis取值
System.out.println("uid" +  session.getAttribute("uid"));
System.out.println("sessionId" +  session.getAttribute("sessionId"));

运行页面 结果:


image.png

测试结论

  1. 当我打开about页面以后,我浏览器cookie中的JSSESSION就是我插入redis 的key,我根据cookie中JSESSIONID的值去redis里面查找,可以redis可视化街面上看见,我插入的参数。都是与我配置的相一致。
  2. 当我600s以内打开about页面或help页面,我的JSESSIONID没有变化,但当我600s以后再打开页面about页面或help页面,cookie中的JSESSIONID发生了改变。也就是说600s后,我之前的会话ID已经失效。页面对你这个人访问的记录已经重置。
  3. 600s+300s后(600s 是我在cookie里面设置的过期时间,而session中key的过期时间是在cookie过期时间的基础上+300s = 900s)可视化里的那条记录将提示您过期。提示文案如下:
    Cannot open value tab: Cannot load key spring:session:campaign:expirations:1538208900000 because it doesn't exist in database. Please reload connection tree and try again.

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 121,055评论 16 134
  • =========================================================...
    _灯火阑珊处阅读 1,860评论 0 3
  • 身体里怎么就有这么多寒,寒到底从何处来呀?以下就是寒湿进入身体的时机,认真仔细看看就明白,为什么身体会这么寒? 一...
    香左阅读 247评论 0 0
  • “鸟儿”的叫声是分类型的。大体为两种,鸟类学家分别将它们称做“鸣啭”和“叙鸣”。鸣啭是歌唱,主要为雄鸟在春天对爱情...
    HughJi阅读 1,296评论 5 4
  • 微风拂过脸颊,温柔舒适,漫步在梨花盛开的田野间,无意抬手间触碰到发间的金钗,思绪飘飞,慢慢失去了意识,等醒来时,发...
    心中的小火苗阅读 754评论 14 20