redis + Tomcat 8 的session共享解决
转载: https://blog.csdn.net/u013358378/article/details/53670023
如果英文不错的看,建议直接看官网吧,官网写的挺清楚。下面的内容是转载的一篇文章,自己补充了一些,供大家参考,也欢迎大家一起讨论
官方截止到2015-10-12前是不支持Tomcat8的,详情见官网:https://github.com/jcoleman/tomcat-redis-session-manager
锐洋智能修改的支持Tomcat8的 reyo.redis.session.manager.tomcat8


修改的源代码:RedisSessionManager.java
@SuppressWarnings("deprecation")
private void initializeSerializer() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
log.info("Attempting to use serializer :" + serializationStrategyClass);
serializer = (Serializer) Class.forName(serializationStrategyClass).newInstance();
Loader loader = null;
if (getContainer() != null) {
loader = getContainer().getLoader();
}
ClassLoader classLoader = null;
if (loader != null) {
classLoader = loader.getClassLoader();
}
serializer.setClassLoader(classLoader);
}
修改后的内容
private void initializeSerializer() throws ClassNotFoundException, IllegalAccessException, InstantiationException { log.info("Attempting to use serializer :" + serializationStrategyClass); serializer = (Serializer) Class.forName(serializationStrategyClass).newInstance(); Loader loader = null; Context context = this.getContext(); if (context != null) { loader = context.getLoader(); } ClassLoader classLoader = null; if (loader != null) { classLoader = loader.getClassLoader(); } serializer.setClassLoader(classLoader); }
前提:你已经部署了Redis,尚未学会的略过
其实很简单,就几个步骤:
1.配置Tomcat的conf目录下的context.xml文件:
1> 单点Reids配置
<Valve className="reyo.redis.session.manager.tomcat8.RedisSessionHandlerValve" /> <Manager className="reyo.redis.session.manager.tomcat8.RedisSessionManager" host="localhost" port="6379" database="0" password="reyo" maxInactiveInterval="60"/>
2> Sentinel集群配置:
<Valve className="reyo.redis.session.manager.tomcat8.RedisSessionHandlerValve" /> <Manager className="reyo.redis.session.manager.tomcat8.RedisSessionManager" maxInactiveInterval="60" sentinelMaster="mymaster" sentinels="127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382" />
2.添加jar

3.测试
1>
存储Session:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("hello"); //取得Session对象 HttpSession session=request.getSession(); //设置Session属性 for(int i=0;i<100000;i++){ session.setAttribute("name"+i, "Magci_"+i); } } |
2>重启Tomcat:假如Session保存在tomcat下,重启后Session不存在;如果保存在Redis下,Tomcat重启对Session无影响
3>取出Session:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("hello"); HttpSession session=request.getSession(); //取出Session属性 for(int i=0;i<100000;i++){ System.out.println(session.getAttribute("name"+i)); } } |
注意事项:从Tomcat6开始默认开启了Session持久化设置,测试时可以关闭本地Session持久化,其实也很简单,在Tomcat的conf目录下的context.xml文件中,取消注释下面那段配置即可:
<!-- Uncomment this to disable session persistence across Tomcat restarts --> <!-- <Manager pathname="" /> --> |
需要注意的是:
web.xml中的配置是有效的,即使是context.xml总配置maxInactiveInterval默认60秒,只要web.xml中的sessionConfig配置30分钟,则session的失效时间还是30分钟
tomcat中sessionCookieName和SESSION_PARAMETER_NAME
tomcat服务端和客户端通过sessionCookieName参数(默认值:JSESSIONID)的值来识别session,

并在此session中共享数据。在浏览器首次请求服务的时候,tomcat服务器会在响应头信息信息里面返回:

在下次浏览器请求的时候会将此cookie值返回给服务器,当然cookie的名称同(sessionCookieName参数,确切的来说是同浏览器保存的会话cookie的名称),当服务器接受到此参数的时候,就不会在响应头信息信息里面返回Set-cookie告诉浏览器保存cookie名为JSESSIONID的cookie,当然此时为会话cookie,此cookie是保存在浏览器当前会话中的。过期时间为当前会话结束时。(当然前提是浏览器要设置为接受第三方cookie)

当然sessionCookieName参数的值是可以修改的,查看官方文档:
| sessionCookieName |
The name to be used for all session cookies created for this Context. If not set, the default of JSESSIONID will be used. Note that this default will be overridden by the org.apache.catalina.SESSION_COOKIE_NAME system property. |
1:通过在contex.xml中设置: <Context sessionCookieName="BGSESSIONID" >
2:通过java虚拟机参数: -Dorg.apache.catalina.SESSION_COOKIE_NAME=BGSESSIONID
3:动过设置:System.setProperty("org.apache.catalina.SESSION_COOKIE_NAME", "BGSESSIONID");
当然后两种的优先级高,但是tomcat6以后,后两种设置无效了。
修改之后在首次请求服务查看服务器返回:

当浏览器设置了不接受第三方cookie的时候。Tomcat支持通过URLRewrit(将sessionid放在url中)来将session的id传给服务器来维持会话(当然如果浏览器接受会话cookie优先级是从会话cookie中去,也就是url里面的session参数会被抛弃)。
例如:get.do;jsessionid=1682268A851B4B6A3BAE18871C63AF30
查看tomcat相关源码:
/**
* Determine the name to use for the session path parameter for the provided
* context.
*
* @param context
*/
public static String getSessionUriParamName(Context context) {
String result = getConfiguredSessionCookieName(context);
if (result == null) {
result = DEFAULT_SESSION_PARAMETER_NAME;
}
return result;
}
此时的SESSION_PARAMETER_NAME和sessionCookieName是可以不相同的(默认相同),通过修改org.apache.catalina.SESSION_PARAMETER_NAME参数来修改,
1: 通过java虚拟机参数: -Dorg.apache.catalina.SESSION_PARAMETER_NAME=bgsessionid
2:System.setProperty("org.apache.catalina.SESSION_PARAMETER_NAME", "bgsessionid");
在tomcat的源码中,org.apache.jasper.Constants.java
/**
* The name of the path parameter used to pass the session identifier back
* and forth with the client.
*/
public static final String SESSION_PARAMETER_NAME = System.getProperty("org.apache.catalina.SESSION_PARAMETER_NAME", "jsessionid");
这样通过URLRewrit的方式session就不限于么个浏览器或者浏览器页了。只要有此seesionid任何浏览器任地方都能够进行访问,当然就带来了安全问题。可通过以下参数来禁止URLRewrit传sessionid,仍然是在tomcat的context.xml文件内设置:
<Context disableURLRewriting="true">
官方文档:
| isableURLRewriting |
Set to true to disable support for using URL rewriting to track session IDs for clients of this Context. URL rewriting is an optional component of the servlet 2.5 specification but disabling URL rewriting will result in non-compliant behaviour since the specification requires that there must be a way to retain sessions if the client doesn't allow session cookies. If not specified, the specification compliant default value of false will be used. |
设置完成后即使你在url里面加了sessionid的值,服务器仍然会在返回头信息里面返回Set-cookie信息。

浙公网安备 33010602011771号