开发了一个轮询推送功能,网上也有不少文章讲这个就不说怎么作的了。如今发现两个问题:html
一:就是登陆进主页面后,因为浏览器在不停轮询,致使后端认为前端一直在操做,而正常设定的session超时就跳转到登陆页面的功能就失效了。由于服务器认为这个session一直活跃着的。前端
本觉得tomcat会有配置,特定的url不算入session的accessTime,找了好久没有这个功能。那就想有没有办法控制浏览器发送请求的时候不带上JSSESSIONID的cookie,也没办法实现。因此只有用本身写代码的形式来控制了。web
总的思路有两种,一种是后端控制,另外一种是前端控制。apache
后端控制的思路就是用过滤器过滤全部请求,把轮询的请求排除,本身来计算session超时的时间,到了就调用session销毁的方法。特别说明一点映射到实现tomcat6的CometProcessor的servlet的url不会通过Filter,这样自动就排除了(一开始不晓得,我还去在struts.xml的配置里把这个url设为excludePattern,其实彻底不必,由于都不会通过struts2的过滤器)。后端
前端控制的思路是用一些js框架监控前端的事件,若是长时间没有操做,就发送logout请求到服务器。浏览器
---------------------------------------------------------------------------------------------------------------------------tomcat
tomcat6一个特殊属性:服务器
org.apache.catalina. STRICT_SERVLET_COMPLIANCE |
If this is
If this is
If not specified, the default value of |
这个属性默认值是false。
也就是说咱们不设这个值的话,tomcat6去更新session的最后使用时间会在getsession方法被调用的时候才去执行。也就是说若是咱们代码里不显示的去获取session的话,即便带着jssessionId这个cookie的请求进来,tomcat也不会去更新session访问时间。因此就很好办了,只要咱们轮询url访问的servlet里不显示调用session就OK啦。
反编译tomcat源码出来看了下,若是在tomcat\conf目录下的catalina.properties里把org.apache.catalina. STRICT_SERVLET_COMPLIANCE为true了。那么容器在org.apache.catalina.core.StandarHostValue的invoke方法会执行request.getSession(false);这样时间就被更新了。
二:CometProcessor的线程局部变量问题。
发现一个请求的生命周期里 CometEvent是BEGIN和ERROR的时候CurrentThread并非同一个(其余两种事件类型的状况没试),而Request是同一个(不是同一个岂不乱套了)。推测tomcat在使用NIO的时候不一样的CometEvent并无必定要同一个Thread来执行,而是从线程池里取一个来执行,固然上下文(主要是Request,Respose)是要保持着的,每次执行的时候要传进来。这也是能理解的,毕竟NIO就是为了大并发处理嘛,执行Begin的那个线程把Begin的逻辑执行完了就该放入线程池里供其余请求使用,若是必定要Error的时候再用这个线程来执行,那这段时间这个线程就不能复用了,也就失去了NIO的意义。
项目里用了一个ThreadLoacl,都在一个全局的Filter里进行设置。开发完轮询功能正常,后来发现轮询的请求根本没进入那个设置ThreadLoacl的Filter,(前面说了CometProcessor的servlet不会通过普通Filter),那怎么还在正常使用呢,ThreadLoacl还有值。缘由是其余请求在线程上设置了这个值,线程完了进入线程池并无执行清除的操做,因此如今从线程池取出来ThreadLoacl也是有值的。(线程对象就是ThreadLoaclMap的一个Key而已)。因此为了正确,CometProcessor里也要进行ThreadLocal的初始化。