Redis實現(xiàn)Session共享
這幾天在做session共享這么一個小模塊,也查了好多資料,給我的感覺,就是太亂了,一直找不到我想要的東西,幾乎全部實現(xiàn)方法都與我的想法不一樣,在這里,我總結(jié)一下自己是如何用Redis實現(xiàn)session共享的,方便自己以后查詢,也希望能給有這方面需求的朋友一些幫助。
創(chuàng)新互聯(lián)建站專注于樟樹網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供樟樹營銷型網(wǎng)站建設(shè),樟樹網(wǎng)站制作、樟樹網(wǎng)頁設(shè)計、樟樹網(wǎng)站官網(wǎng)定制、小程序定制開發(fā)服務(wù),打造樟樹網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供樟樹網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。相關(guān)專題推薦:php session (包含圖文、視頻、案例)
先說一下我的開發(fā)環(huán)境:nginx、redis、tomcat,用moven構(gòu)建項目,jetty服務(wù)器運行,所以在這里,下面也會涉及一下如何用maven打war包,部署在tomcat上運行。
redis是一個key-value數(shù)據(jù)庫,存值取值,全靠這個key了,這里啰嗦一句,因為原創(chuàng),專業(yè)的介紹我就不粘貼了,想了解的官方介紹的可以自行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 id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="${jedisPoolConfig.maxTotal}"/> <property name="maxIdle" value="${jedisPoolConfig.maxIdle}"/> <property name="maxWaitMillis" value="${jedisPoolConfig.maxWaitMillis}"/> <property name="testWhileIdle" value="true"/> <property name="testOnBorrow" value="false"/> <property name="testOnReturn" value="false"/> </bean> <bean id="readJedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${jedis.read.host}" /> <property name="port" value="${jedis.read.port}" /> <property name="password" value="${jedis.read.password}" /> <property name="timeout" value="${jedis.read.timeout}" /> <property name="database" value="${jedis.read.database}" /> <property name="poolConfig" ref="jedisPoolConfig" /> </bean> <bean id="writeJedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${jedis.write.host}" /> <property name="port" value="${jedis.write.port}" /> <property name="password" value="${jedis.write.password}" /> <property name="timeout" value="${jedis.write.timeout}" /> <property name="database" value="${jedis.write.database}" /> <property name="poolConfig" ref="jedisPoolConfig" /> </bean> <bean id="readRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="readJedisConnectionFactory" /> </bean> <bean id="writeRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="writeJedisConnectionFactory" /> </bean>
配置完畢后,開始代碼實現(xiàn):
在LoginController里:
第一步,引入RedisTemplate
@Autowired @Qualifier("writeRedisTemplate") private StringRedisTemplate writeTemplate;
這里只需要引入writeRedisTemplate即可,在登陸的時候,只負責寫,只有在再次刷新的時候,經(jīng)過過濾器,才需要讀
第二步,正常登陸流程,登陸成功之后,request還要保存session信息
第三步,設(shè)置cookie值,把作為保存userSession信息在redis中的key值存入cookie,刷新瀏覽器的時候,過濾器可以從cookie中取到key
值,進而去redis取對應(yīng)的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設(shè)置
第四步,把userSession
信息存入redis中
RedisTemplate中寫入redis的值要為String類型,需要把userSession對象轉(zhuǎn)成Json字符串
userSessionString = JSON.toJSONString(userSession);
在轉(zhuǎn)Json的時候,遇到問題,導入import com.alibaba.fastjson.JSON;一直失敗,發(fā)現(xiàn)pom中沒有依賴Json的關(guān)系,如果有遇到相同的問題,可以檢查下在pom.xml中是否有關(guān)于json的依賴關(guān)系,沒的話,在pom.xml中導入json的依賴關(guān)系,如下:
<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);//設(shè)置redis中值的有效期
完成這一操作,用戶的session信息已經(jīng)存入到redis中,可在redis中查看是否存入。
第五步:進入頁面后,刷新頁面,請求會經(jīng)過過濾器,在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字符串轉(zhuǎn)換為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; }
在這里,另外附上關(guān)于web.xml關(guān)于LoginFilter的配置,有需要的可以參考下:
<!-- Spring監(jiān)聽器 --> <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實現(xiàn)session共享的功能,但我在開發(fā)的時候,遇到一個蛋疼的問題,在測試環(huán)境上,
把項目部署在兩臺tomcat
服務(wù)器上的時候,cookie里一直存不進去redis的key值,單臺可以存進去,經(jīng)過長期的檢測,
終于發(fā)現(xiàn)是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值。
相關(guān)學習推薦:redis視頻教程
分享題目:Redis實現(xiàn)Session共享詳解
轉(zhuǎn)載來于:http://m.rwnh.cn/article48/cjhsep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊、小程序開發(fā)、企業(yè)建站、網(wǎng)站制作、App開發(fā)、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)