I use code to teach you (3): Listener monitors online user statistics

1 Introduction

When you first started to work on Java Web projects, after mastering Servlet, you may not have a good grasp of the role of Listener and code writing. This article through the realization of online user statistics and online user list code practice, so that everyone can understand and use the Listener through actual operations.

2. Business scenario

Do you want to display an online number of people in the project without knowing how to start? ? ?
Do you want to view the list of currently logged in users on your platform? ? ?
This article implements it for you through JSP+Servlet+Listener, take a look at it in 5 minutes.

3. Effect display

Open a different browser to log in. You can see the number of people currently logged in and the list of users.
Insert picture description here
When the user logs out, the current user is logged out. And see the number of online users -1, and the user list also reduces this user.
Insert picture description here

4. Code implementation

4.1 Project structure

Insert picture description here

4.2 page preparation

4.2.1 Homepage (index.jsp)

index.jsp is used to display the currently logged-in user (the user exists in the Session), as well as display the number of logged-in users and the list of logged-in users. There are also login.jsp and register.jsp page jumps. Since the data of the logged-in user is stored in the application domain, it needs to be registered in index.jsp before logging in. You can see the user login list.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<html>
  <head>
    <title>主页</title>
  </head>
  <body>
  <h1>welcome to index.jsp!</h1>
  <c:if test="${session_user!=null}">
    欢迎您,${
    
    session_user.userName}
    <a href="loginOut">退出</a>
    <a href="">用户列表</a>
  </c:if>
  <c:if test="${session_user==null}">
    <a href="login.jsp">登录</a>
    <a href="register.jsp">注册</a>
  </c:if>
<a href="index.jsp">主页</a>
  <span style="color: red">${
    
    tip}</span>
  <hr/>
  <h3>在线用户</h3>
  当前在线用户人数:[${
    
    fn:length(onlineUser)}]<br/>
  用户列表:<br/>
  <c:forEach items="${onlineUser}" var="user"  varStatus="u">[${
    
    u.index+1}]位,在线[${
    
    user}]用户。<br/>
  </c:forEach>
  </body>
</html>

4.2.2 Login page (login.jsp)

PS: Before logging in, please register users in register.jsp. There is no database connection here, and the data is stored in the cache. Therefore, you need to register before you can log in.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录页面</h1>
<form action="login.do" method="post">
    用户:<input type="text" name="username">
    <br/>
    密码:<input type="password" name="pwd"/>
    <br/>
    <input type="submit" value="登录" />
</form>
<span style="color: red">${
    
    tip}</span>
</body>
</html>

4.2.3 Registration page (register.jsp)

PS: After the registration is successful, the data will be stored in the application domain. When the user logs in, the user input is compared with the data in the application domain. If the user exists, the login is successful.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>注册页面</h1>
<form action="register.do" method="post">
    用户:<input type="text" name="username">
    <br/>
    密码:<input type="password" name="pwd"/>
    <br/>
    性别:<input type="radio" name="sex" value="1"/><input type="radio" name="sex" value="0"/><br/>
    <input type="submit" value="注册" />
</form>
</body>
</html>

4.2 Controller preparation

4.2.1 Controller that handles login

@WebServlet(name = "LoginServlet", urlPatterns = "/login.do")
public class LoginServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        String username = request.getParameter("username");
        String pwd = request.getParameter("pwd");
        //先从缓存中拿出users
        ServletContext sc = request.getServletContext();
        List<User> users = (List<User>) sc.getAttribute("users");
       for (User u : users) {
    
    
           if(u.getUserName().equals(username)&&u.getPwd().equals(pwd)){
    
    
               //跳转到index.jsp
               HttpSession session = request.getSession();
               session.setAttribute("session_user",u);
               request.getRequestDispatcher("index.jsp").forward(request,response);
           }
        }
       //提示用户名密码不正确
        request.setAttribute("tip","用户名密码不正确!");
        request.getRequestDispatcher("login.jsp").forward(request, response);
    }

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

4.2.2 Controller that handles exit

@WebServlet(name = "LoginOutServlet",urlPatterns = "/loginOut")
public class LoginOutServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        HttpSession session  = request.getSession();
        session.removeAttribute("session_user");
        request.setAttribute("tip","退出成功!");
        request.getRequestDispatcher("index.jsp").forward(request,response);
    }

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

4.2.3 Controller with registration function

@WebServlet(name = "RegisterServlet",urlPatterns = "/register.do")
public class RegisterServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //接收参数
       String username =  request.getParameter("username");
       String pwd =  request.getParameter("pwd");
        String sex = request.getParameter("sex");
        User user = new User(username,pwd,Integer.parseInt(sex));
       //把注册用户存储起来
       ServletContext sc =  request.getServletContext();
       List<User> users = (List<User>) sc.getAttribute("users");
        //把user存到缓存中(application)
        users.add(user);
        sc.setAttribute("users",users);
        request.setAttribute("tip","注册成功!请登录");
        request.getRequestDispatcher("login.jsp").forward(request,response);
    }

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

4.3 Listener preparation

In the listener, Guagua wrote a lot of comments. Concise and easy to understand, you can read it with confidence.

/**
 *在线用户监听器
 */
@WebListener()
public class OnLineListener implements ServletContextListener,
        HttpSessionListener, HttpSessionAttributeListener {
    
    
    //创建一个application变量
    ServletContext  application = null;

    // Public constructor is required by servlet spec
    public OnLineListener() {
    
    
    }

    //监听服务器启动的method
    public void contextInitialized(ServletContextEvent sce) {
    
    

        System.out.println("------------服务器启动了---------------");
        //创建一个List<user>,并把该list存到application中
        List<User> users = new ArrayList<>();
        application =  sce.getServletContext();
        //创建一个onlineUser来存在线用户
        List<String> onlineUser = new ArrayList<>();
        application.setAttribute("users",users);
        application.setAttribute("onlineUser",onlineUser);
    }

    public void contextDestroyed(ServletContextEvent sce) {
    
    
        System.out.println("--------------服务器关闭了----------------");
    }

    // HttpSessionListener implementation
    //session是基于服务器端创建的。当一个浏览器访问服务器就会创建一个唯一session
    public void sessionCreated(HttpSessionEvent se) {
    
    
        System.out.println("-----session被创建了-----------");
        /**
         * 可以统计当前有多少人连接我们的服务器。(统计在线访问人数)
         */
    }

    public void sessionDestroyed(HttpSessionEvent se) {
    
    
        /* Session is destroyed. */
        System.out.println("--------session被销毁了------------");
        /**
         * 可以统计当前有多少人连接我们的服务器。(统计在线访问人数)
         */
    }

   /*
      attributeAdded()方法:监听session执行setAttr()时触发
      统计登录到该系统的用户
    */
    public void attributeAdded(HttpSessionBindingEvent sbe) {
    
    
        System.out.println("-----session设值----"+sbe.getName()+","+sbe.getValue());
        User user = (User) sbe.getValue();
        //创建一个list来记录在线用户
        HttpSession session = sbe.getSession();
        application  = session.getServletContext();
        //先从缓存application域中拿到  onlineUser
        List<String> onlineUser = (List<String>) application.getAttribute("onlineUser");
        if(onlineUser.indexOf(user.getUserName())==-1){
    
    //新增加的userName在onlineUser中不存在
            onlineUser.add(user.getUserName());
            //存储到application中
            application.setAttribute("onlineUser",onlineUser);
        }
    }

    /**
     * attributeRemoved方法:监听session.removeAttr(key,val)
     * 当用户退出时,则注销,并且更新在线用户数量与列表
     */
    public void attributeRemoved(HttpSessionBindingEvent sbe) {
    
    
        System.out.println("-----session销毁----"+sbe.getName()+","+sbe.getValue());
        //创建一个list来记录在线用户
        HttpSession session = sbe.getSession();
        application  = session.getServletContext();
        User user = (User) sbe.getValue();
        //先从缓存application域中拿到  onlineUser
        List<String> onlineUser = (List<String>) application.getAttribute("onlineUser");
        onlineUser.remove(user.getUserName());
        application.setAttribute("onlineUser",onlineUser);
    }

    public void attributeReplaced(HttpSessionBindingEvent sbe) {
    
    
      
    }
}

5. Summary of knowledge points

5.1 Listener allows us to better grasp the 4 scopes

Listener can monitor the creation and destruction of Session; it can also monitor the creation and destruction of application domain; it can also monitor the setAttribute(key,val) and removeAttribute(key,val) methods of Session domain. All of these require us to have a certain understanding and knowledge of the 4 scopes in order to better use the Listener in development. ( The difference between the 4 scopes is still not?? Hurry up and click me )

5.2 Listener other extensions

5.2.1 Achieve website click-through rate

sessionCreated(HttpSessionEvent se){
    
    }
sessionDestroyed(HttpSessionEvent se){
    
    }

When opening a browser to access the project 127.0.0.1:8080/project name, the sessionCreated(){} method will be executed. When the browser is closed, sessionDestroyed(){} will be executed. Therefore, we can achieve a number of visitors or click-through rate function through these two methods.

5.2.2 Server log

contextInitialized(ServletContextEvent sce){
    
    }
contextDestroyed(ServletContextEvent sce){
    
    }

These two methods are used to monitor the application domain. In this blog, Guagua also uses these two methods to create a list of online login people. These two methods monitor the life cycle of the entire web container, and we can expand many functions.

6. Attach the complete source code

Source code download: https://download.csdn.net/download/u010312671/12562328

Guess you like

Origin blog.csdn.net/u010312671/article/details/107029776