您的位置:首页 > 运维架构 > 网站架构

java 统计网站在线人数

2013-09-23 15:05 507 查看
下面,我们利用HttpSessionBindingListener接口Java语言,编写一个在线人数统计的程序。当一个用户登录后,显示欢迎信息,同时显示出当前在线的总人数和用户名单。当一个用户退出登录或者Session超时值发生时,从在线用户名单中删除这个用户,同时将在线的总人数减1。这个功能的完成,主要是利用一个实现了HttpSessionBindingListener接口的对象,当这个对象被绑定到Session中或者从Session中被删除时,更新当前在线的用户名单。实例的开发主要有以下步骤。

Step1:配置Web应用程序的运行目录

在%CATALINA_HOME%\conf\Catalina\localhost\目录下新建ch15.xml文件,输入如例15-4所示的内容。

例15-4 ch15.xml

<Context docBase="F:\JSPLesson\ch15" reloadable="true"/>

Step2:编写login.html

将编写好的login.html文件放到F:\JSPLesson\ch15\online目录下。完整的代码如例15-5所示。

例15-5 login.html

<html>

<head>

<title>登录页面</title>

</head>

<body>

<form action="online" method="post">

<table>

<tr>

<td>请输入用户名:</td>

<td><input type="text" name="user"></td>

</tr>

<tr>

<td>请输入密码:</td>

<td><input type="password" name="password"></td>

</tr>

<tr>

<td><input type="reset" value="重填"></td>

<td><input type="submit" value="登录"></td>

</tr>

</table>

</form>

</body>

</html>

Step3:编写UserList.java,User.java,OnlineUserServlet.java和LogoutServlet.java

为了和本章其他例子中的类相区别,本例中的类定义在org.sunxin.ch15.online包中。编写UserList.java,User.java,OnlineUserServlet.java和LogoutServlet.java源文件,将编写好的源文件放到F:\JSPLesson\ch15\src\online目录下。

UserList.java的完整代码如例15-6所示。

例15-6 UserList.java

1.package org.sunxin.ch15.online;

2.

3.import java.util.Vector;

4.import java.util.Enumeration;

5.

6.public class UserList

7.{

8. private static final UserList userList=new UserList();

9. private Vector<String> v;

10.

11. private UserList()

12. {

13. v=new Vector<String>();

14. }

15.

16. public static UserList getInstance()

17. {

18. return userList;

19. }

20.

21. public void addUser(String name)

22. {

23. if(name!=null)

24. v.addElement(name);

25. }

26.

27. public void removeUser(String name)

28. {

29. if(name!=null)

30. v.remove(name);

31. }

32.

33. public Enumeration<String> getUserList()

34. {

35. return v.elements();

36. }

37.

38. public int getUserCount()

39. {

40. return v.size();

41. }

42.}

那么为什么要将UserList设计成单例类呢?这是因为UserList类的对象是用于存储和获取在线用户的列表,而这个用户列表对于所有的页面来说都应该是同一个,所以将UserList类设计成单例类,这样,所有的类访问的就是同一个UserList对象了。

代码的第9行,定义了一个私有的Vector类型的变量,在UserList类的构造方法中,对Vector类型的变量v进行了初始化,用于存放String类型的对象。注意,在这个地方没有使用ArrayList,是考虑到UserList对象可能会被多个线程同时访问,因为ArrayList不是同步的,而Vector是同步的,所以采用Vector来保存用户列表。

User.java的完整代码如例15-7所示。

例15-7 User.java

1. package org.sunxin.ch15.online;

2.

3. import javax.servlet.http.HttpSessionBindingListener;

4. import javax.servlet.http.HttpSessionBindingEvent;

5.

6. public class User implements HttpSessionBindingListener

7. {

8. private String name;

9. private UserList ul=UserList.getInstance();

10.

11. public User()

12. {

13. }

14. public User(String name)

15. {

16. this.name=name;

17. }

18. public void setName(String name)

19. {

20. this.name=name;

21. }

22. public String getName()

23. {

24. return name;

25. }

26. public void valueBound(HttpSessionBindingEvent event)

27. {

28. ul.addUser(name);

29. }

30. public void valueUnbound(HttpSessionBindingEvent event)

31. {

32. ul.removeUser(name);

33. }

34.}

User类实现了HttpSessionBindingListener接口,表示登录的用户。代码第9行,通过UserList类的静态方法getInstance()得到UserList类的对象,第26~29行,当User对象加入到Session中时,Servlet容器将调用valueBound()方法,我们将用户的名字保存到用户列表中。第30~33行,当User对象从Session中被删除时,Servlet容器将调用valueUnbound()方法,我们从用户列表中删除该用户。

OnlineUserServlet.java的完整代码如例15-8所示。

例15-8 OnlineUserServlet.java

1.package org.sunxin.ch15.online;

2.

3.import javax.servlet.*;

4.import java.io.*;

5.import javax.servlet.http.*;

6.import java.util.Enumeration;

7.

8.public class OnlineUserServlet extends HttpServlet

9.{

10. public void doGet(HttpServletRequest req, HttpServletResponse resp)

11. throws ServletException,IOException

12. {

13. req.setCharacterEncoding("gb2312");

14. String name=req.getParameter("user");

15. String pwd=req.getParameter("password");

16.

17. if(null==name || null==pwd || name.equals("") || pwd.equals(""))

18. {

19. resp.sendRedirect("login.html");

20. }

21. else

22. {

23. HttpSession session=req.getSession();

24. User user=(User)session.getAttribute("user");

25. if(null==user || !name.equals(user.getName()))

26. {

27. user=new User(name);

28. session.setAttribute("user",user);

29. }

30.

31. resp.setContentType("text/html;charset=gb2312");

32. PrintWriter out=resp.getWriter();

33.

34. out.println("欢迎用户<b>"+name+"</b>登录");

35. UserList ul=UserList.getInstance();

36. out.println("<br>当前在线的用户列表:<br>");

37. Enumeration<String> enums=ul.getUserList();

38. int i=0;

39. while(enums.hasMoreElements())

40. {

41. out.println(enums.nextElement());

42. out.println("    ");

43. if(++i==10)

44. {

45. out.println("<br>");

46. }

47. }

48. out.println("<br>当前在线的用户数:"+i);

49. out.println("<p><a href=logout>退出登录</a>");

50. out.close();

51. }

52. }

53.

54. public void doPost(HttpServletRequest req, HttpServletResponse resp)

55. throws ServletException,IOException

56. {

57. doGet(req,resp);

58. }

59.}

OnlineUser类用于向用户显示欢迎信息、当前在线用户列表和在线用户数。代码的第24~29行,首先从Session中获取名为user的属性对象,通过判断它是否为空来判断在此次会话中用户是否已经登录。如果user对象不为null,那么接着判断在同一个会话中,用户是否更换了一个用户名登录。如果user对象为空或者当前登录的用户名和先前登录的用户名不同,则以用户的当前登录名创建一个User对象,将这个对象绑定到Session中,这个时候,Servlet容器就会调用User对象的valueBound()方法,将这个用户的名字保存在用户列表中。第35行,得到UserList类的对象。第37行,得到用户列表的枚举对象。第39~47行,循环取出在线用户的名字并输出,一旦输出超过10个用户名,就输出一个换行(<br>)。第48行,输出当前在线的用户数。第49行,输出“退出登录”的链接。

LogoutServlet.java的完整代码如例15-9所示。

例15-9 LogoutServlet.java

1. package org.sunxin.ch15.online;

2.

3. import javax.servlet.*;

4. import java.io.*;

5. import javax.servlet.http.*;

6.

7. public class LogoutServlet extends HttpServlet

8. {

9. public void doGet(HttpServletRequest req, HttpServletResponse resp)

10. throws ServletException,IOException

11. {

12. resp.setContentType("text/html;charset=gb2312");

13.

14. HttpSession session=req.getSession();

15. User user=(User)session.getAttribute("user");

16. session.invalidate();

17.

18. PrintWriter out=resp.getWriter();

19. out.println("<html><head><title>退出登录</title></head><body>");

20. out.println(user.getName()+",你已退出登录<br>");

21. out.println("<a href=login.html>重新登录</a>");

22. out.println("</body></html>");

23. out.close();

24. }

25.}

LogoutServlet类用于退出登录。代码第16行,调用HttpSession对象的invalidate()方法,使Session失效,从而删除绑定到这个Session中的User对象,Servlet容器就会调用这个User对象的valueUnbound()方法,从用户列表中删除该用户。

Step4:编译上述四个Java源文件

打开命令提示符,进入到源文件所在的目录F:\JSPLesson\ch15\src\online下,然后执行

javac -d ..\..WEB-INF\classes *.java

在WEB-INF\classes目录下生成4个源文件对应的包和类文件。

Step5:部署Servlet

编辑WEB-INF目录下的web.xml文件,添加对本例中的Servlet的配置,内容如例15-10所示。

例15-10 web.xml



<servlet>

<servlet-name>OnlineUserServlet</servlet-name>

<servlet-class>

org.sunxin.ch15.online.OnlineUserServlet

</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>OnlineUserServlet</servlet-name>

<url-pattern>/online/online</url-pattern>

</servlet-mapping>

<servlet>

<servlet-name>logout</servlet-name>

<servlet-class>org.sunxin.ch15.online.LogoutServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>logout</servlet-name>

<url-pattern>/online/logout</url-pattern>

</servlet-mapping>



实现HttpSessionBindingListener接口的监听器类不需要在web.xml中进行配置。

Step6:运行在线人数统计程序

启动Tomcat服务器,打开IE浏览器,首先在地址栏中输入

http://localhost:8080/ch15/online/login.html

出现登录页面后,输入用户名和密码,将看到如图15-1所示的页面。

读者可以再打开一个浏览器,输入http://localhost:8080/ch15/online/login.html,然后登录,将看到如图15-2所示的页面。

图15-1 OnlineUserServlet显示一个用户在线 图15-2 OnlineUserServlet显示有两个用户在线

读者可以退出其中一个用户的登录,然后刷新另外一个窗口中的页面,可以看到显示的在线用户数为1。读者可以多打开几个浏览器,进行测试。

本文来源于:IT学习网(www.ITxuexi.com

详文请参考:http://www.itxuexi.com/tech/java/web/5181250227071.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: