J2EE用監聽器實現同一使用者只能有一個線上

來源:互聯網
上載者:User

標籤:

這裡我們討論的是已登陸或將要登陸的使用者,遊客不在討論的範圍之內。這一點大家應該很容易就能理解的吧。 
               
那麼我們應該怎樣去實現同一使用者只能有一個線上這樣的一個小功能呢? 
有人可能就會這樣設想了:"這不是很簡單嗎?只要在資料庫中用一個欄位來標記使用者的狀態就行了,比如如果使用者登陸了就將狀態設為1,退出了就將這個使用者的狀態設為0,OK,搞定。" 
                
但是,實際上是不是這樣呢?其實不全是。為什麼這樣說呢?其實如果你的想法跟上面那樣或相似的話,應該說是犯了一個比較嚴重的錯誤。我還是舉個例子來說明吧。現在絕大多數的網站中都有登陸和退出兩項功能吧?好了,上面的設想僅僅是針對這兩項功能來說使用。但是你有沒有想過?假如現在有一個使用者正常登陸上了,但是這回情況有點特殊了,這個使用者登陸上但是這個使用者就偏偏不點退出,然後就走了或者離開了或者忙別的事情去了,反正這個使用者登陸上就不管別的了,他就掛在那裡。這種情況是允許發生了,而且也是比較常見的一種情況。那如果是這種情況,上面的那種設想你還認為是正確的嗎?那就不正確了!對session有過一點瞭解的人員應該都知道,在java中session的預設的銷毀時間是大於或等於30分鐘,如果你對session的生命週期不做任何配置的話,按照上面的設想,那麼只要使用者登陸上之後,這時該使用者的狀態設定為1,在大於30分鐘的時間內如果該使用者沒有向伺服器端發起任何請求的話,那麼這個session就會被銷毀掉,注意了,這時session生命週期結束以後自動銷毀的,並不是使用者點退出按鈕來銷毀的,那這樣就不能觸發使用者退出事件,那這個使用者的狀態你就沒法改變了,也就是說,如果按照上面的設想,你想想,如果遇到這樣的情況,那這個使用者的狀態就一直都是1了,那這個使用者以後再想登陸就再也登陸不上了。很明顯,這樣是不對的。 
                
那應該怎樣來解決這個問題呢?大家看到我這篇文章的標題就應該知道了的吧。可以使用java的監聽器來解決這個問題。在編程的開始你應該有這樣一個瞭解: 
                 
當使用者通過網路來訪問一個網站的時候,如果是首次訪問,那麼在這個網站的伺服器端都會建立一個session來儲存一些屬於這個使用者的資訊。在建立session的時候其實是會觸發一個sessionCreated事件的,同樣的,當使用者正常退出或者是使用者登陸了不退出併當session生命週期結束的時候,就會觸發一個sessionDestroyed事件。這兩個事件我們可以通過HttpSessionListener監聽器來監聽到並可以把它捕捉。那這樣問題就好解決了。 
                
我話說的也有點多了,朋友們不要介意哈。好了,下面來看一下代碼 
                 
註:為了示範簡單,我就不對使用者做封裝了,也不使用資料庫了,同樣的我也不添加任何的SSH架構支援了,我知道你們都懂的。不懂的可以給我留言。在這裡我就直接用servlet來類比了。我直接將使用者登陸後的資訊儲存到一個ServletContext對象中。順便我也簡單說一下ServletContext吧,怕有人對ServletContext不瞭解的。ServletContext對象是在你項目第一次啟動伺服器的時候被建立的,這個對象是只被建立一次,是唯一的,你可以用ServletContextListener這個監聽器來監聽的到。

        

          

login.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>使用者登入</title>
</head>

<body>
<form action="/online/servlet/LoginServlet" method="post">
<table>
<tr>
<td>使用者暱稱:</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>使用者密碼:</td>
<td><input type="password" name="pwd" size="20"/></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value=" 登陸 "/></td>
</tr>
</table>
</form>
</body>
</html>

           

home.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>使用者首頁</title>
</head>

<body>
使用者 ${user} 登陸成功!<BR/>
<a href="/online/servlet/LogoutServlet">安全退出</a>
</body>
</html>

         

error.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>友情提示</title>
<script type="text/javascript">
function warn(){
alert("您已經登入線上,不能重複登入!");
}
</script>
</head>

<body onload="warn();">
您已經登陸線上,不能重複登陸! <br>
<a href="/online/login.jsp">返回首頁</a>
</body>
</html>

        

下面來看一下登陸的servlet 
    
LoginServlet:

package com.ljq.servlet;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class LoginServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//在項目啟動第一次時建立,該項目只建立一次,唯一的
ServletContext context = this.getServletContext();

String url="/online/home.jsp";

String username=request.getParameter("username");
username=new String(username.getBytes("ISO-8859-1"));

//擷取使用者列表,第一次擷取時候為空白
ArrayList<String> users=(ArrayList<String>)context.getAttribute("users");
//第一個使用者登入時
if(users==null){
users = new ArrayList<String>();
users.add(username);
context.setAttribute("users", users); //將第一個使用者的名字儲存到ServletContext對象中
//非第一個使用者登入
}else{
for(String user : users){
//如果該使用者已經登入,請求error.jsp不讓其再登入
if(username.equals(user)){
url = "/online/error.jsp";
break;
}
}
//如果該使用者沒登入,就將該使用者的名字儲存到ServletContext對象中
users.add(username);
}

request.getSession().setAttribute("user", username); //儲存一下該使用者資訊以備後用
response.sendRedirect(url);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

          

接下來是使用者點擊安全退出需要的servlet: 
         
LogoutServlet:

package com.ljq.servlet;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class LogoutServlet extends HttpServlet {

@SuppressWarnings("unchecked")
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

//擷取使用者資訊
String user = (String)request.getSession().getAttribute("user");
ArrayList<String> users = (ArrayList<String>)this.getServletContext().getAttribute("users");
for(String u:users){
//將這個使用者從ServletContext對象中移除
if(user.equals(u)){
users.remove(u);
break;
}
}

//將session設定成無效
request.getSession().invalidate();
response.sendRedirect("/online/login.jsp");
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

         

最後就是監聽器了,寫監聽器類也是很簡單的,只要實現相應的監聽器介面並實現未實現的方法就行了。下面我寫一個SessionListener,它實現了HttpSessionListener介面:

package com.ljq.servlet;

import java.util.ArrayList;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
* 當使用者通過網路來訪問一個網站的時候,如果是首次訪問,那麼在這個網站的伺服器端都會建立一個session來儲存一些屬於這個使用者的資訊。
*
* 在建立session的時候其實是會觸發一個sessionCreated事件的,同樣的,當使用者正常退出或者是使用者登陸了不退出併當session生命週期結束的時候,
*
* 就會觸發一個sessionDestroyed事件。這兩個事件我們可以通過HttpSessionListener監聽器來監聽到並可以把它捕捉。
*
* @author Administrator
*
*/
public class SessionListener implements HttpSessionListener{

public void sessionCreated(HttpSessionEvent event) {
System.out.println("---Session被建立!---");
}

@SuppressWarnings("unchecked")
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
String user = (String)session.getAttribute("user");
ArrayList<String> users = (ArrayList<String>)session.getServletContext().getAttribute("users");
for(String u:users){
//將這個使用者從ServletContext對象中移除
if(u.equals(user)){
users.remove(u);
break;
}
}
//將session設定成無效
session.invalidate();
System.out.println("一個Session被銷毀了!");
}

}

       

工作還沒結束呢,我還得配置一下web.xml檔案,不然伺服器是不會認識到這個監聽器的:

    <!-- 監聽器註冊 -->
<listener>
<!-- 監聽器類的路徑 -->
<listener-class>com.ljq.servlet.SessionListener</listener-class>
</listener>

     

為了測試能及時看到效果,我再來配置一下session的存在時間,下面我將session的生命週期配置成一分鐘:

<session-config>   
<session-timeout>1</session-timeout>
</session-config>

OK,完事了。這樣就能實現同一使用者只能有一個線上了 

J2EE用監聽器實現同一使用者只能有一個線上

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.