前言:
session共享策略有很多,常見的有粘性復制,高並發下效率查。tomcat-redis-session-manager無疑是一個挺好的方案,缺點要配置tomcat,有點復雜。最優的方案莫過於使用Spring-Session無縫整合redis,只要項目修改即可。
測試項目結構:
項目結構很簡單:
Test.java
就是一個頁面跳轉,傳輸一下sessionid
@Controller
public class Test {
@RequestMapping("/test")
public String test(HttpSession session, HttpServletRequest request) {
request.setAttribute("id", session.getId());
return "index";
}
}
index.jsp
單純的打印一下sessionid
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%-- <%@ page isELIgnored ="false" %> --%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'TestUpload.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
我的session:${id}
<br> sessionid=<%=session.getId()%>
</body>
</html>
當項目部署到nginx上的兩個tomcat上時,每次訪問地址,打印出來的sessionId都發生變化,這樣在一些登錄的操作中,用戶明明在tomcatA上登錄了,但是用戶的其他操作負載到了TomcatB中,然而B不知道用戶已經在A登錄了,又讓用戶登錄一次,這樣用戶體驗極差。使用Spring-Session就是把用戶的session緩存到redis中,讓大家都從redis中獲取用戶session,這樣就保證了session的共享。
使用Spring-Session
- pom.xml 增加依賴
<!-- 使用Spring Session來解決Session共享問題 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.3.0.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>3.5.0.Final</version>
</dependency>
- web.xml增加配置
<!-- Spring session -->
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
- Spring.xml增加配置
作用是導入redis配置redis.properties
,導入新建的一個配置文件spring-session.xml
<context:property-placeholder location="classpath:db.properties,classpath*:redis.properties" ignore-unresolvable="true"/>
...
<import resource="classpath:spring-session.xml"/>
- 新增配置spring-session.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 創建名為springSessionRepositoryFilter 的Spring Bean,繼承自Filter。 springSessionRepositoryFilter替換容器默認的HttpSession支持為Spring Session, 將Session實例存放在Redis中 -->
<bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" />
<!-- 使用LettuceConnectionFactory -->
<bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory">
<property name="hostName" value="${redis.ip}" />
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.password}" />
</bean>
<!-- 也可以將使用LettuceConnectionFactory改成使用JedisConnectionFactory,兩者保留其一就好 -->
<!--<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> -->
<!--<property name="hostName" value="${redis.ip}"/> -->
<!--<property name="port" value="${redis.port}"/> -->
<!--<property name="password" value="${redis.password}"/> -->
<!--</bean> -->
<!-- 讓Spring Session不再執行config命令 -->
<!-- <util:constant static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP" /> -->
</beans>
- 增加redis.properties
redis.ip=193.112.76.194
redis.port=6379
redis.password=xxxxxx
redis.pool.maxTotal=10
redis.pool.minIdle=4
redis.pool.maxIdle=8
redis.pool.testOnBorrow=true
發布到服務器上。訪問index頁面。無論刷新多少次結果都一樣。session沒變
我的session:a4b2fe35-aaa5-40c2-a7de-b1d60180ca04
sessionid=a4b2fe35-aaa5-40c2-a7de-b1d60180ca04
使用redis客戶端查看
剛好有個seession一致。
原理:
DelegatingFilterProxy攔截器攔截, springSessionRepositoryFilter替換容器默認的HttpSession支持為SpringSession每個請求都會訪問它。
原文地址:https://blog.csdn.net/qq_35830949/article/details/79995318