Session管理之超時設置和強制下線

    關於Session,在Java Web開發中,爲咱們提供了不少方便,Session是由瀏覽器和服務器之間維護的。好吧,閒話很少說,下面讓咱們一步一步來實現它們。javascript

    (一)首先來講下Session超時時間設置的三種方式,這些相對來講比較簡單:前端

    (1)在web.xml中設置session-configjava

<session-config>
  <session-timeout>2</session-timeout>
 </session-config>

    即交互間隔時間最長爲2分鐘(該處時間單位爲分鐘),2分鐘後session.getAttribute()獲取的值爲空。web

    (2)在Tomcat的/conf/web.xml中session-config,默認值爲:30分鐘ajax

<session-config>
     <session-timeout>30</session-timeout>
</session-config>

    同上,時間單位爲分鐘。瀏覽器

    (3)在Servlet中設置服務器

HttpSession session = request.getSession();
session.setMaxInactiveInterval(60);

    即在你的程序代碼中手動設置(該處時間單位爲秒)。session

    優先級:Servlet中設置 >web.xml設置 > Tomcat/conf/web.xml設置app

    (二)同一用戶強制下線jsp

    你們都知道在目前不少的web項目中,大多數狀況下都是可讓同一個用戶帳號在不一樣的登陸入口登陸的,但這樣其實就顯得不是很嚴謹了,畢竟信息修改等操做對於信息是否能徹底即時同步仍是個未知之數。因此,接下來,我要作的只是對於不一樣瀏覽器的同一個用戶帳號的強制下線處理,對於同一個瀏覽器暫不作考慮,先來看下面這張圖。大概的瞭解一下:

    從上面能夠看出:同一個瀏覽器對於不一樣的帳號,登陸時會產生相同的sessionId,這也就致使了用戶之間信息的覆蓋;不一樣瀏覽器對於不一樣的帳號登陸時,登陸時會產生不一樣的sessionId,這也就給了咱們可操做的空間了,正是要利用這一點來進行判斷和相應處理。

    (1)添加監聽器

    爲了方便這裏使用Session監控的方式,建立SessionListener,以下:

public class SessionListener implements HttpSessionBindingListener{

    @Override
    public void valueBound(HttpSessionBindingEvent event){
        // TODO Auto-generated method stub
        
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent event){
        // TODO Auto-generated method stub
        
    }
}

    這裏HttpSessionBindingListener和HttpSessionListener效果同樣,你們能夠任選其一。重載兩個方法:session的建立和銷燬。

    固然,在web.xml中添加相應配置是必不可少的:

<listener>
   <listener-class>com.yoki.util.SessionListener</listener-class>
</listener>

    因爲sessionId和userId須要存儲,方便後面的判斷,咱們在上面的類中添加兩個Map,以下:

//保存username和session的映射
public static HashMap<String,Session> MAP1 = new HashMap<String,Session>();
//保存sessionID和username的映射
public static HashMap MAP2 = new HashMap();

    最後,用戶登陸驗證成功時須要調用一個方法來判斷是否強制下線:

public static void userLogin(Session session,String sUserName){
    //已登陸
    if(MAP2.containsValue(sUserName)){
       Session l_session = MAP1.get(sUserName);
       //不一樣瀏覽器,同一用戶(強制下線前一個)
       if(l_session != null && l_session.getId() != session.getId()){
          MAP1.remove(sUserName);
          MAP2.remove(l_session.getId());
          l_session.setAttribute("msg", "您的帳號已在另外一處登陸!");
          MAP2.put(session.getId(), sUserName);
          MAP1.put(sUserName, session);
       }
       //同一瀏覽器,同一用戶(不作任何變更)
       
    }else{
       //未登陸
       if(MAP2.containsKey(session.getId())){
          //同一瀏覽器,不一樣用戶(不作任何變更)
       }else{
          //不一樣瀏覽器,不一樣用戶(正常添加)
          MAP2.put(session.getId(), sUserName);
          MAP1.put(sUserName, session);
       }
    }

}

    解釋一下:這裏使用username和userId效果同樣,看大家怎麼方便怎麼用了,方法中的邏輯是根據上面的圖來編寫的,首先判斷用戶是否登陸了,由於MAP中保存了相關的session關聯信息,因此能夠經過這個來判斷;因爲此處只對不一樣瀏覽器相同用戶進行處理,因此直接判斷是不是同一個瀏覽器。方法的參數session是用戶在當前瀏覽器登陸時的信息,咱們能夠從MAP中獲得以前保存過的相同用戶的session信息,與之進行比較,裏面的邏輯是:移除MAP中保存的以前的用戶信息(對應的session此時未銷燬),並給其session添加一個msg信息(後面用到,往下看),再添加新的用戶信息。

    上面的方法調用放在登陸驗證成功後,各自項目不一樣,但登陸驗證的類基本差很少:

SessionListener.userLogin(session, USERNAME);

    (2)添加前端頁面調用的方法

    在登陸驗證的類中添加以下方法:

/*
 * 判斷用戶是否重複登陸
 */
@RequestMapping(value="/checkUserOnline")
@ResponseBody
public void checkUserOnline(HttpServletRequest request,HttpServletResponse response) throws IOException{
    HttpSession session=request.getSession();  
    PrintWriter out = response.getWriter();
    String msg = "";
    if(session.getAttribute("msg") != null){
       msg = session.getAttribute("msg").toString();
       System.out.println(msg);
    }
    out.print(session.getAttribute("msg"));
}

    方法中獲取以前添加到session中的msg,用來判斷是否強制下線,繼續。

    (3)前端頁面循環調用

    選擇一個頁面,最好是全部頁面都用到的,好比我用的index.jsp,以下:

<script type="text/javascript">
   $(document).ready(function(){
      setInterval("checkUserOnline()",5000); //每隔5秒判斷一次
   }
   
   function checkUserOnline(){
      var msg = "";
      $.ajax({
        type : "POST",
        url : "checkUserOnline",
        data : {},
        async: false,
        success : function(data){
           msg = data;
        }
      });
      if (msg == 'null' || msg == '' || msg == 'undefined'){
         return;
      }else{
         //調用你的註銷用戶方法
         var url="<%=path%>/logout.do";
         $.get(url,function(data){});
      }
   }
</script>

    js中調用setInterval方法,設置調用的方法和間隔時間,方法裏經過ajax調用上面添加的類並返回msg,經過msg來判斷是否調用註銷方法(路徑啥的本身注意,能調用到就ok)。

    (4)註銷

    通常web項目登陸進去後都會有個退出按鈕,點擊即返回到登陸頁,此時在裏面添加一行代碼,防止錯誤,可能會出現從新登陸報session已被銷燬的錯誤提示,但第二次便會成功,這裏即是爲了消除該錯誤:

SessionListener.MAP2.remove(session.getId());

    好了,基本的設置完成了,啓動項目,打開兩個不一樣的瀏覽器,先登陸一個用戶,成功後,在另外一個瀏覽器中登陸相同的用戶,登陸成功後,會在控制檯上打印出msg:

您的帳號已在另外一處登陸!

    此時,刷新第一個瀏覽器用戶登陸界面,便會發現已經退出跳轉到登陸頁了,大功告成!!!

相關文章
相關標籤/搜索