由于业务需要,昨天稍微研究了一下tomcat处理session的机制,对此有了更为深刻的理解,现在记下来,供大家参考和讨论。
大家也许都了解,tomcat为了维持和浏览器之间的session对应关系,主要采用三种方式:
1.cookie纪录sessionId;
2.url重写;
3.隐藏表单,这个几乎和url重写意义相同;
之前,我一直非常相信浏览器的cookie,即便浏览器端关闭了cookie,也相信tomcat会自动帮忙重写url,但是进入到wap这行后,cookie就不敢那么恭维了;
有些手机浏览器就只能保持一个cookie,并且对于cookie的维护性极差到一定地步,例如在“/”根目录下的sessionId存储与路径为“/”的cookie中,而遇到“/a/”的情况,由于手机浏览器只能保持一个cookie,它居然愚蠢到将这个cookie里的sesionid等同于“/”中的sessionid,就不再纪录了,也就是说“/a/”中的sessionid强制和“/”中的一样,并且每次访问“/a/”中的sessionid和“/”的一样;
大家都知道,对于很多时候“/”和“/a/”的目标路径,几乎不在同一个服务,甚至不在同一台服务器上,这点令我很是郁闷。
为了这个,我为每个链接的后面就加上了sessionid,这样居然还是不行,后来我查看了许多tomcat相关的文档,在配置文件的context中有个cookies选项,如果配置为false,则不信任浏览器的cookie,只信任url后面的jsessionid,但是公司的服务很大很杂,如果我更改了这个选项,怕影响到其它服务,最妥协的办法就是让tomcat先选择url后面的sessionid,如果没有再去cookie中去找,但是我没有发现这样的配置选项;
于是乎我查看起了tomcat的源代码,后来发现CoyoteAdapter类中对于sessionid的处理是这样的,显示运行parseSessionId(req, request),这个方法是在url中获取sessionid作为requestedSessionId,在同一方法的最后运行parseSessionCookiesId(req, request),这个方法负责在cookie中获取sessionid,这个方法之前会判断,如果配置中禁止cookie,则不取cookie中的了,也就是说无法优先选择url中的sessionid,只能选择或不选择cookie的:(
这样对于复写tomcat代码的梦想也几乎覆灭了,于是只能执行强加手段了。
由于cookie中的sessionid是通过协议的head头传给服务器的,于是在apache中,强制改写head头,使“/”目录下的sessionid在访问"/a/"的时候强制实效,才解决了这个问题。
纵观事件,难道我们就只能采取妥协的或者强制的方法才能解决一些郁闷的问题吗?呵呵(苦笑ing)
不知道大家有没有好的办法解决cookie和session的问题,有多少辛酸,大家都说说吧。