這幾天在做session共享這麼一個小模組,也查了很多資料,給我的感覺,就是太亂了,一直找不到我想要的東西,幾乎全部實現方法都與我的想法不一樣,在這裡,我總結一下自己是如何用Redis實現session共享的,方便自己以後查詢,也希望能給有這方面需求的朋友一些幫助。
相關專題推薦:php session (包含圖文、影片、案例)
先說一下我的開發環境:nginx、redis、tomcat,用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 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>
在LoginController裡:
第一步,引入RedisTemplate
@Autowired @Qualifier("writeRedisTemplate") private StringRedisTemplate writeTemplate;
這裡只需要引入writeRedisTemplate即可,在登陸的時候,只負責寫,只有在再次刷新的時候,經過過濾器,才需要讀
第二步,正常登陸流程,登陸成功之後,request還要保存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);
#第四步,把userSession訊息存入redis中
在转Json的时候,遇到问题,导入import com.alibaba.fastjson.JSON;一直失败,发现pom中没有依赖Json的关系,如果有遇到相同的问题,可以检查下在pom.xml中是否有关于json的依赖关系,没的话,在pom.xml中导入json的依赖关系,如下: 写入redis的代码如下: 完成这一操作,用户的session信息已经存入到redis中,可在redis中查看是否存入。 第五步:进入页面后,刷新页面,请求会经过过滤器,在Filter.Java中读取redis的值并进行一些处理 在过滤器这里,就无法通过注解的方式引入redisTemplate,可以通过如下的方式引入: 过滤器从cookie中取出redis的key值,用readTemplate读出value值 在这里,另外附上关于web.xml关于LoginFilter的配置,有需要的可以参考下: 按照上面的配置,就可以用redis实现session共享的功能,但我在开发的时候,遇到一个蛋疼的问题,在测试环境上, 把项目部署在两台 终于发现是nginx配置出的问题,引以为戒,深深的阴影。下面我贴出我正常运行时nginx的配置代码userSessionString = JSON.toJSONString(userSession);
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.3</version>
<classifier>jdk15</classifier>
</dependency>
writeTemplate.opsForHash().put(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey,redisSessionKey, userSessionString);
writeTemplate.expire(UasContants.REDIS_USER_SESSION_KEY+"_"+redisSessionKey, 1800L, TimeUnit.SECONDS);//设置redis中值的有效期
BeanFactory beans = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
StringRedisTemplate readTemplate = (StringRedisTemplate) beans.getBean("readRedisTemplate");
StringRedisTemplate writeTemplate = (StringRedisTemplate) beans.getBean("writeRedisTemplate");
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;
}
<!-- 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>
tomcat
服务器上的时候,cookie里一直存不进去redis的key值,单台可以存进去,经过长期的检测,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视频教程
以上是Redis實現Session共享詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!