servlet中監(jiān)聽器主要的監(jiān)聽對(duì)象有三個(gè):
ServletContext HttpSession ServletRequest.
分別可以監(jiān)聽三個(gè)對(duì)象的創(chuàng)建 銷毀躏哩,以及屬性的更改。
=========================================
實(shí)現(xiàn)監(jiān)聽在線人數(shù):
在開始實(shí)現(xiàn)功能之前首先創(chuàng)建一個(gè)用戶模型,為了區(qū)別每個(gè)用戶,我們用sessionId來作為一個(gè)用戶的id囚枪,代碼實(shí)現(xiàn):
package model;
public class User {
private String ipStr;
private String address;
private String sessionId;
public User() {
super();
// TODO Auto-generated constructor stub
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public String getIpStr() {
return ipStr;
}
public void setIpStr(String ipStr) {
this.ipStr = ipStr;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
第一步:創(chuàng)建出存放在線用戶的容器
當(dāng)應(yīng)用服務(wù)一旦啟動(dòng)赊级,就創(chuàng)建出一個(gè)容器來存放在線的人數(shù)。這里使用到ServletContextListener敢辩。實(shí)現(xiàn)這個(gè)接口的監(jiān)聽器將監(jiān)聽到我們的服務(wù)器程序的啟動(dòng)和銷毀。代碼實(shí)現(xiàn):
package listener;
import java.util.ArrayList;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import model.User;
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("===================servlet 服務(wù)銷毀===================");
}
@Override
public void contextInitialized(ServletContextEvent event) {
ServletContext context = event.getServletContext();
ArrayList<User> userList = new ArrayList<>();
context.setAttribute("userList", userList);
System.out.println("===================servlet 服務(wù)啟動(dòng)===================");
}
}
把用戶列表存放到servletContext這個(gè)對(duì)象中误褪,這個(gè)對(duì)象的生命周期是整個(gè)服務(wù)程序的生命周期责鳍。
第二步:獲得每個(gè)用戶,并存放到容器中兽间。
在一般的web程序中历葛,用戶一旦登錄,我們會(huì)把用戶的信息存放到session對(duì)象中嘀略。當(dāng)用戶退出登錄時(shí)恤溶,從session對(duì)象中移除我們的用戶信息。為了獲取到用戶的ip地址等詳細(xì)信息帜羊。要用到ServletRequestListener這個(gè)接口咒程。代碼實(shí)現(xiàn):
package listener;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.ArrayList;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import model.User;
@WebListener
public class MyHttpRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent event) {
System.out.println("===================一個(gè)request銷毀===================");
}
@Override
public void requestInitialized(ServletRequestEvent event) {
System.out.println("===================一個(gè)request創(chuàng)建===================");
HttpServletRequest request = (HttpServletRequest) event.getServletRequest();
HttpSession session = request.getSession();
ServletContext app = session.getServletContext();
ArrayList<User> userList = (ArrayList<User>) app.getAttribute("userList");
//遍歷用戶列表,如果用戶已經(jīng)存放就不做操作
for (User user : userList) {
//這里用sessionID來模擬一個(gè)登陸的用戶讼育,正常應(yīng)該是從session中g(shù)etAttribute 到當(dāng)前登錄的用戶
if(user.getSessionId().equals(session.getId())){
return;
}
}
//如果用戶沒有存放到我們的容器中帐姻,就吧這個(gè)用戶存放到容器里面稠集。這里只是模擬生成了一個(gè)用戶。正常應(yīng)該是直接把用戶存放到servletContext 的 userList 這個(gè)容器中就可以了饥瓷。
User currentUser = new User();
try {
currentUser.setIpStr(InetAddress.getLocalHost().getHostAddress());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
currentUser.setSessionId(session.getId());
currentUser.setAddress("test");
URL url = null;
URLConnection connection = null;
try {
url = new URL("http://ip.taobao.com/service/getIpInfo.php?ip="+currentUser.getIpStr());
connection = url.openConnection();
connection.setConnectTimeout(2000);// 設(shè)置連接超時(shí)時(shí)間剥纷,單位毫秒
connection.setReadTimeout(2000);// 設(shè)置讀取數(shù)據(jù)超時(shí)時(shí)間,單位毫秒
connection.setDoOutput(true);// 是否打開輸出流 true|false
connection.setDoInput(true);// 是否打開輸入流true|false
connection.setUseCaches(false);// 是否緩存true|false
connection.connect();// 打開連接端口
DataOutputStream out = new DataOutputStream(connection
.getOutputStream());// 打開輸出流往對(duì)端服務(wù)器寫數(shù)據(jù)
out.flush();// 刷新
out.close();// 關(guān)閉輸出流
BufferedReader reader = new BufferedReader(new InputStreamReader(
connection.getInputStream(), "gbk"));// 往對(duì)端寫完數(shù)據(jù)對(duì)端服務(wù)器返回?cái)?shù)據(jù)
// ,以BufferedReader流來讀取
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
reader.close();
currentUser.setAddress(buffer.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
userList.add(currentUser);
app.setAttribute("userList", userList);
}
}
第三步:當(dāng)用戶退出后呢铆,從容器中移除用戶
這里我們要監(jiān)聽到session的生命周期晦鞋,用到HttpSessionListener這個(gè)接口。如果實(shí)現(xiàn)用戶一段時(shí)間內(nèi)不操作棺克,銷毀session的話要在web.xml中配置session超時(shí):
<session-config>
<session-timeout>1</session-timeout>
</session-config>
HttpSessionListener悠垛,代碼實(shí)現(xiàn):
package listener;
import java.util.ArrayList;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import model.User;
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent event) {
System.out.println("===================一個(gè)session創(chuàng)建===================");
}
@Override
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
@SuppressWarnings("unchecked")
ArrayList<User> userList =(ArrayList<User>) session.getServletContext().getAttribute("userList");
ArrayList<User> newUserList = new ArrayList<>();
for (User user : userList) {
if (! user.getSessionId().equals(session.getId())) {
newUserList.add(user);
}
}
session.getServletContext().setAttribute("userList", newUserList);
System.out.println("===================一個(gè)session銷毀===================");
}
}
至此大概思路已經(jīng)完成。剩下的操作娜谊,按照需求完善确买。