现状
项目在使用Spring Cloud搭建微服务框架,其中分布式session采用spring session+redis 模式
需求
希望可以在配置文件(application.yml)里设置应用的cookiename、session超时时间以及redis存储的namespace
目前已知可以通过下面的方式设置session超时时间和redis存储session的namespace。
1.@EnableRedisHttpSession(maxInactiveIntervalInSeconds=3600,redisNamespace="xxx")--硬编码,自己未测试
2.使用vm参数-Dspring.session.redis.namespace=xxx来设置redis的nameapce --已测试可以生效
但这都不是我们想要的效果。。我们希望可以在配置文件里设置这些参数。
设计的配置文件的相关参数如下
app: product: session: redisnamespace: ${app.product.name} #存储分布式session时redis的命名空间 timeout: 60 #session超时时间,单位:分钟。 cookiename: ${app.product.name}SESSION #注意每个不同的应用此cookiename应该不相同
其中
app.product.cookiename的值是希望设置的cookiename
app.product.session.timeout是希望设置的session超时时间
app.product.session.redisnamespace是希望设置的redis存储session的namespace
解决方案
在一个@Configuration类里
1.使用@Bean方式定义CookieHttpSessionStrategy 对象来解决cookiename的设置问题
2.通过@PostConstruct 方式修改RedisOperationsSessionRepository对象的session超时时间、namespace
具体代码如下:
设置cookiename
默认的cookiename是SESSION,不同的应用一般要求cookiename不相同,所以需要修改。。修改的方式可参考下文:
//从配置里读取cookiename,如果没有配置,则使用默认的DEFAULTSESSION @Value("${app.product.cookiename:DEFAULTSESSION}") String cookieName; @Bean public CookieHttpSessionStrategy cookieHttpSessionStrategy(){ CookieHttpSessionStrategy strategy=new CookieHttpSessionStrategy(); DefaultCookieSerializer cookieSerializer=new DefaultCookieSerializer(); cookieSerializer.setCookieName(cookieName);//cookies名称 strategy.setCookieSerializer(cookieSerializer); return strategy; }
设置session超时时间(默认的超时时间是30分钟)、redis存放的namespace
具体见下文:通过@PostConstruct 方式修改RedisOperationsSessionRepository对象的属性
/** * 从配置的yml文件里取设置session超时时间,单位是分钟 * 如果没配置,则默认30分钟,即1800s */ @Value("${app.product.session.timeout:30}") int sessionTimeoutInMinuts; /** * 从配置的yml文件里取设置session存储到redis时对应的namespace */ @Value("${app.product.session.redisnamespace:}") String redisnamespace; @Autowired private RedisOperationsSessionRepository sessionRepository; @PostConstruct private void afterPropertiesSet() { log.info("setting sesion 超时时间 = [{}]分钟",sessionTimeoutInMinuts); sessionRepository.setDefaultMaxInactiveInterval(sessionTimeoutInMinuts * 60); log.info("setting sesion 存储到redis时的namespace = [{}]",redisnamespace); sessionRepository.setRedisKeyNamespace(redisnamespace); }
测试代码如下:增加一个/hello的http服务来获取session,以及session的最大活跃间隔,即session超时时间。。
@GetMapping("/hello")
public String hello(){
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = servletRequestAttributes.getRequest().getSession();
return "hello,sessonId="+session.getId()+"
"+
"MaxInactiveInterval="+session.getMaxInactiveInterval()+" CreationTime="+session.getCreationTime()+" LastAccessedTime="+session.getLastAccessedTime();
}
在浏览器里输入对应的url验证(见下图),并用fiddler抓包。
下图为验证结果:可见session超时时间被设置成了3600s,即60分钟。
fiddler抓包情况如下,可见cookiename修改为xxxSession。
redis里存储的namespace多了一级xxx(见下图)。。原来直接是spring.session.sessions,现在是spring.session.xxx.sessions