開發了一個輪詢推送功能,網上也有不少文章講這個就不說怎麼作的了。如今發現兩個問題: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的初始化。