現狀
項目在使用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()+"\r\n"+ "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