• [Java] JSP笔记


    Java Web 开发时,可以使用 Listener 来监听来监听一些事件,从而实现一些功能。实际上这个监听器,原理就是 Delphi 中大家常用的各种事件。

    1. 那么,监听器的主要用途用哪些呢:

    • 统计在线人数和在线用户
    • 系统启动时加载初始化信息: 包括各种缓存、共公的定制器、数据库链接等等
    • 统计网站访问量
    • 路Spring结合

    2. 监听器可以按监听的对象来分类:

    • ServletContext (ServletContextListener):用于监听应用程序环境对象的事件监听器(一个项目中只有一个),可以用来启动定时器、初始化全局对象。
    • HttpSession (HttpSessionListener): 用于监听用户会话对象的事件监听器。
    • ServletRequest (ServletRequestListener): 用于监听请求消息对象的事件监听器,可以用来读取参数,记录访问历史等。

    3. 按监听的事件来划分:

    • 监听域对象自身的创建和销毁的事件监听器(2中的三类)。
    • 监听域对象中的属性的增加和删除的事件监听器:  ServletContextAttributeListenerHttpSessionAttributeListenerServletRequestAttributeListener
    • 监听绑定到 HttpSession 域中的某个对象的状态的事件监听器。它分为这几种状态:
      • 绑定: 将状态通过 set 保存到 Session 中。
      • 解除绑定 : 使用 remove 删除状态。
      • 钝化: 将 session 对象持久化到存储设备上。(Session本身是存在于服务器内存中。Session 钝化机制由SessionManager管理: 第一种管理器是 org.apache.catalina.session.StandardManger, 当 tomcat服务器被关闭或重启时,tomcat服务器会将当前内存中的session钝化到服务器文件系统中。另一种情况是web应用程序被重新加载时,内存中的session对象也会被钝化到服务器的文件系统中。钝化后的文件被保存到 Tomcat安装路径下的 /work/Catalina/hostname/applicationname/SESSION.ser 中。第二种管理器是 org.apache.catalina.session.Persistentmanager ,它是在钝化基础上进行了扩张,前两种情况和StandardManager相同,第三种情况,可以配置主流内存的Session对象数目,将不常用的Session对象保存到文件系统或数据库中,当要使用时再进行加载。默认情况下,Tomcat提供两个钝化驱动类:org.apache.Catalina.FileStore 和 org.apache.Catalina.JDBCStore。)
      • 活化: 从存储设备上恢复。

      绑定、解除绑定使用 HttpSessionBindingListener 接口, 钝化、活化使用 HttpSessionActivationListener 接口。这两个监听器不需要注册。

    4. 注册方法

    在 Servlet 3.0 之前的版本中, 需要在 web.xml 中进行注册。也比较简单,就是一个声明:

    <listener>
        <listener-class>com.imooc.listener.FirstListener</listener-class>
    </listener>

    在 servlet 3.0 之后, 可以不再到 web.xml 中进行配置, 直接给监听器类加上注解 @WebListener 就可以。

    package com.imooc.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    import com.demo.utils.UserManager;
    
    @WebListener
    public class FirstListener implements ServletContextListener {
        
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            System.out.println("contextInitialized");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            System.out.println("contextDestroyed");
        }
    
    }

    5. 示例: 使用监听器实现的显示在线用户列表

    效果如下:

    此示例综合用到了这些技术: jstl和el标签、jsp脚本、listener监听器 、单例全局对象、javabean、线程同步。

    主要代码:

    index.jsp 

    <%@ page language="java" contentType="text/html; charset=UTF-8" %>
    <%@ page import="com.demo.utils.*" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>欢迎访问</title>
    </head>
    <body>
    <% request.setAttribute("users", UserManager.getInstance().getItems()); %>
    <h1>在线用户列表</h1><hr>
    <!-- 使用 JSTL 输出在线用户列表 -->
    <table>
    <tr><th width="80px">name</th><th width="320px">sessionID</th><th width="180px">IP地址</th><th>登录时间</th><tr>
    <c:forEach var="user" items="${requestScope.users}">
    <tr>
    <td>${user.name}</td>
    <td>${user.sessionID}</td>
    <td>${user.ipaddr}</td>
    <td>${user.firstTimeStr}</td>
    </tr>
    </c:forEach></table>
    <br>
    当前在线: <c:out value="${fn:length(users)}"></c:out>人。
    </body>
    </html>

    RequestListener.java

    package com.demo.listener;
    
    import javax.servlet.ServletRequestEvent;
    import javax.servlet.ServletRequestListener;
    import javax.servlet.annotation.WebListener;
    import javax.servlet.http.HttpServletRequest;
    
    import com.demo.utils.User;
    import com.demo.utils.UserManager;
    
    @WebListener
    public class RequestListener implements ServletRequestListener {
    
        @Override
        public void requestDestroyed (ServletRequestEvent sre) {
            System.out.println("requestDestroyed");
        }
    
        @Override
        public void requestInitialized (ServletRequestEvent sre) {
            HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
            UserManager mgr = UserManager.getInstance();
            // 用户请求时,如果 mgr 中不存在当前会放原 sessionID, 则新建一个User对象,加入管理器中
            if (!mgr.existSession(req.getSession().getId())) {
                User item = new User();
                item.setFirstTime(System.currentTimeMillis());
                item.setIpaddr(req.getRemoteAddr() + ":" + req.getRemotePort());
                item.setName(req.getParameter("name"));
                item.setSessionID(req.getSession().getId());
                mgr.addSession(item);
            }
            System.out.println("requestInitialized: " + req.getRequestURI() + ", " + req.getParameter("name"));
        }
    }

    SessionListener.java

    package com.demo.listener;
    
    import javax.servlet.annotation.WebListener;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    import com.demo.utils.UserManager;
    
    @WebListener
    public class SessionListener implements HttpSessionListener {
        
        @Override
        public void sessionCreated(HttpSessionEvent se) {
            System.out.println("sessionCreated");
        }
        
        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            System.out.println("sessionDestroyed");        
            // Session 失效时,从列表中删除
            UserManager.getInstance().removeSession(se.getSession().getId());
        }    
    }

    UserManager.java

    package com.demo.utils;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /** 用户管理 */
    public class UserManager {
        private static UserManager Instance;
        
        private Map<String, User> items = new HashMap<String, User>();
        
        /** 单例 */
        public static UserManager getInstance() {
            if (Instance == null)
                Instance = new UserManager();
            return Instance;
        }
        
        private UserManager() {}
        
        // 由于 Web 请求是并发的,对列表的操作,需要使用 synchronized 关键字线程同步,防止出现异常
        public synchronized boolean existSession(String sessionID) {
            return items.containsKey(sessionID);
        }
        
        public synchronized void addSession(User v) {
            if (v != null) 
                items.put(v.getSessionID(), v);
        }
        
        public synchronized void removeSession(String sessionID) {
            if (items.containsKey(sessionID))
                items.remove(sessionID);
        }
        
        public int size() {
            return items.size();
        }
        
        public synchronized User get(String sessionID) {
            return items.get(sessionID);
        }
        
        public synchronized List<User> getItems() {
            ArrayList<User> list = new ArrayList<User>();
            for (Map.Entry<String, User> entry : items.entrySet()) 
                list.add(entry.getValue());
            return list;
        }
    }

    User.java

    package com.demo.utils;
    
    import java.io.Serializable;
    import java.text.SimpleDateFormat;
    
    /** 用户对象 Java Bean */
    public class User implements Serializable {
        private static final long serialVersionUID = 1L;
        
        private String name;
        private String sessionID;
        private String ipaddr;
        private long firstTime;
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getSessionID() {
            return sessionID;
        }
        public void setSessionID(String sessionID) {
            this.sessionID = sessionID;
        }
        public String getIpaddr() {
            return ipaddr;
        }
        public void setIpaddr(String ipaddr) {
            this.ipaddr = ipaddr;
        }
        public long getFirstTime() {
            return firstTime;
        }
        public void setFirstTime(long firstTime) {
            this.firstTime = firstTime;
        }
        
        public String getFirstTimeStr() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(firstTime).toString();
        }
    }

    完整项目下载:

    链接: http://pan.baidu.com/s/1jI2fVqm 密码: wjr5

    【感谢】

    慕课网、Fcming 老师

  • 相关阅读:
    基本数据类型(int, bool, str)
    万恶之源之运算符
    python基础初识
    leetcode 653. Two Sum IV
    leetcode 16 3Sum Closest
    leetcode15 3Sum
    leetcode 1 Two Sum
    【站立会议】第四天
    【站立会议】第三天
    【站立会议】第二天
  • 原文地址:https://www.cnblogs.com/yangyxd/p/5629901.html
Copyright © 2020-2023  润新知