Redis實現Session共享詳解

Redis實現Session共享詳解

redis實現Session共享

這幾天在做session共享這么一個小模塊,也查了好多資料,給我的感覺,就是太亂了,一直找不到我想要的東西,幾乎全部實現方法都與我的想法不一樣,在這里,我總結一下自己是如何用Redis實現session共享的,方便自己以后查詢,也希望能給有這方面需求的朋友一些幫助。

相關專題推薦:php session (包含圖文、視頻、案例)

先說一下我的開發環境:nginxredistomcat,用moven構建項目,jetty服務器運行,所以在這里,下面也會涉及一下如何用maven打war包,部署在tomcat上運行。

redis是一個key-value數據庫,存值取值,全靠這個key了,這里啰嗦一句,因為原創,專業的介紹我就不粘貼了,想了解的官方介紹的可以自行search.

?pom.xml中配置:

<!-- redis -->?? <dependency>?? <groupid>redis.clients</groupid>?? <artifactid>jedis</artifactid>?? <version>2.8.1</version>?? </dependency>?? <dependency>?? <groupid>org.springframework.data</groupid>?? <artifactid>spring-data-redis</artifactid>?? <version>1.7.2.RELEASE</version>?? </dependency>

aplicationContext-redis.xml中配置

<!-- redis 客戶端配置 -->?? ???<bean>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???</bean>?? ???<bean>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???</bean>?? ???<bean>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???????<property></property>?? ???</bean>?? ???<bean>?? ???????<property></property>?? ???</bean>?? ???<bean>?? ???????<property></property>?? ???</bean>

配置完畢后,開始代碼實現:

在LoginController里:

第一步,引入RedisTemplate

@Autowired?? @Qualifier("writeRedisTemplate")?? private?StringRedisTemplate?writeTemplate;

這里只需要引入writeRedisTemplate即可,在登陸的時候,只負責寫,只有在再次刷新的時候,經過過濾器,才需要讀

第二步,正常登陸流程,登陸成功之后,request還要保存session信息

Redis實現Session共享詳解

第三步,設置Cookie值,把作為保存userSession信息在redis中的key值存入cookie,刷新瀏覽器的時候,過濾器可以從cookie中取到key值,進而去redis取對應的value值,即userSession

String?domain?=?request.getServerName();?? ???????String?cookieId=MD5Util.MD5Encode("uasLoginer",?"UTF-8");?? ???????//生成token,用作session在redis存儲中的key值?????? ???????StringredisSessionKey=?UUID.randomUUID().toString();?? ???????Cookie?uasLoginer?=?new?Cookie(cookieId,?redisSessionKey);?? ???????if?(domain.startsWith("uas."))?{?? ????uasLoginer.setDomain(domain.substring(4,domain.length()));?? }else?{?? ????uasLoginer.setDomain(domain);?? }?? ???????uasLoginer.setMaxAge(60000);?? ???????uasLoginer.setPath("/");?? ???????response.addCookie(uasLoginer);

這里cookie跨域setDomain和setPath設置

第四步,把userSession信息存入redis中

RedisTemplate中寫入redis的值要為String類型,需要把userSession對象轉成json字符串

userSessionString?=?JSON.toJSONString(userSession);

在轉Json的時候,遇到問題,導入import com.alibaba.fastjson.JSON;一直失敗,發現pom中沒有依賴Json的關系,如果有遇到相同的問題,可以檢查下在pom.xml中是否有關于json的依賴關系,沒的話,在pom.xml中導入json的依賴關系,如下:

<dependency>?? ????<groupid>net.sf.json-lib</groupid>?? ????<artifactid>json-lib</artifactid>?? ????<version>2.3</version>?? ????<classifier>jdk15</classifier>?? </dependency>

寫入redis的代碼如下:

writeTemplate.opsForHash().put(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey,redisSessionKey,?userSessionString);?? writeTemplate.expire(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey,?1800L,?TimeUnit.SECONDS);//設置redis中值的有效期

完成這一操作,用戶的session信息已經存入到redis中,可在redis中查看是否存入。

第五步:進入頁面后,刷新頁面,請求會經過過濾器,在Filter.Java中讀取redis的值并進行一些處理

在過濾器這里,就無法通過注解的方式引入redisTemplate,可以通過如下的方式引入:

BeanFactory?beans?=?WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());?? ?????StringRedisTemplate?readTemplate?=?(StringRedisTemplate)?beans.getBean("readRedisTemplate");?? ?????StringRedisTemplate?writeTemplate?=?(StringRedisTemplate)?beans.getBean("writeRedisTemplate");

過濾器從cookie中取出redis的key值,用readTemplate讀出value值

String?cookid=MD5Util.MD5Encode("uasLoginer",?"UTF-8");?? Cookie[]?cookies?=?req.getCookies();?? String?redisSessionKey?=?"";?? if(cookies?!=?null){?? ????for?(Cookie?cookie?:?cookies)?{?? ????????if(cookie.getName().equals(cookid)){?? ????????????redisSessionKey?=?cookie.getValue()?;?? ????????}?? ????}?? }?? UserSession?userSession?=?null;?? String?userSessionString?=?(String)?readTemplate.boundHashOps(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey).get(redisSessionKey);?? if(null?!=?userSessionString?){?? ????@SuppressWarnings("static-access")?? ????JSONObject?obj?=?new?JSONObject().fromObject(userSessionString);//將json字符串轉換為json對象?? ????userSession?=?(UserSession)JSONObject.toBean(obj,UserSession.class);?? ????writeTemplate.expire(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey,?1800L,?TimeUnit.SECONDS);?? ????request.getSession().setAttribute(UasContants.USER_SESSION,?userSession);?? }?? if?(userSession?!=?null)?{?? ????chain.doFilter(req,?res);?? ????return;?? }else?{?? ????res.sendRedirect(UasContants.LOGIN_URL);?? ????return;?? }

在這里,另外附上關于web.xml關于LoginFilter的配置,有需要的可以參考下:

<!-- Spring監聽器 -->   <listener>       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>   </listener>   <filter>       <filter-name>loginFilter</filter-name>       <filter-class>com.sfbest.uas.filter.LoginFilter</filter-class>       <init-param>           <param-name>excludePaths</param-name>           <param-value>/login,/user/login,/user/auth</param-value>       </init-param>   </filter>   <filter-mapping>       <filter-name>loginFilter</filter-name>       <url-pattern>/*</url-pattern>   </filter-mapping>

按照上面的配置,就可以用redis實現session共享的功能,但我在開發的時候,遇到一個蛋疼的問題,在測試環境上,

把項目部署在兩臺tomcat服務器上的時候,cookie里一直存不進去redis的key值,單臺可以存進去,經過長期的檢測,

終于發現是nginx配置出的問題,引以為戒,深深的陰影。下面我貼出我正常運行時nginx的配置代碼

upstream uassessiontest.d.com {           server 10.103.16.226:8088;           server 10.103.16.226:8089;           }          server {                    log_format  sf_uastest  '$remote_addr - $remote_user [$time_local] "$request" '                                           '$status $body_bytes_sent "$http_referer" '                                           '"$http_user_agent" $http_cookie';                   listen 80;                   server_name uassessiontest.d.com;                   access_log /var/log/nginx/uassessiontest.log sf_uastest;                     location / {                           rewrite ^/$ /uas/ break;                           proxy_pass http://uassessiontest.d.com;                   }           }

紅色的為當初少配的部分,這些部分是的作用是往瀏覽器端寫入cookie值。

相關學習推薦:redis視頻教程

? 版權聲明
THE END
喜歡就支持一下吧
點贊14 分享