zoukankan      html  css  js  c++  java
  • [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 老师

  • 相关阅读:
    基本技能训练之线程
    关于UEditor的使用配置(图片上传配置)
    PAT 乙级练习题1002. 写出这个数 (20)
    codeforces 682C Alyona and the Tree DFS
    codeforces 681D Gifts by the List dfs+构造
    codeforces 678E Another Sith Tournament 概率dp
    codeforces 680E Bear and Square Grid 巧妙暴力
    codeforces 678D Iterated Linear Function 矩阵快速幂
    codeforces 679A Bear and Prime 100 交互
    XTUOJ 1248 TC or CF 搜索
  • 原文地址:https://www.cnblogs.com/yangyxd/p/5629901.html
Copyright © 2011-2022 走看看