笔记:监听器

1. 监听器

1.1 概述

监听器: 主要是用来监听特定对象的创建或销毁、属性的变化的!

 是一个实现特定接口的普通java类!

 

对象:

自己创建自己用 (不用监听)

别人创建自己用 (需要监听)

 

Servlet中哪些对象需要监听?

request / session / servletContext

分别对应的是request监听器、session相关监听器、servletContext监听器

 

监听器(listener)

 

 

监听器接口:

一、监听对象创建/销毁的监听器接口

Interface ServletRequestListener     监听request对象的创建或销毁

Interface HttpSessionListener        监听session对象的创建或销毁

Interface ServletContextListener     监听servletContext对象的创建或销毁

二、监听对象属性的变化

Interface ServletRequestAttributeListener 监听request对象属性变化:添加、移除、修改

Interface HttpSessionAttributeListener    监听session对象属性变化:添加、移除、修改

Interface ServletContextAttributeListener  监听servletContext对象属性变化

 

三、session相关监听器

Interface HttpSessionBindingListener   监听对象绑定到session上的事件

    Interface HttpSessionActivationListener(了解)监听session序列化及反序列化的事件


1.2 生命周期监听器

声明周期监听器: 监听对象的创建、销毁的过程!

监听器开发步骤:

1. 写一个普通java类,实现相关接口;

2. 配置(web.xml)

 

A.  ServletRequestListener    

监听request对象的创建或销毁。

 

代码:

/**
 *  监听request对象的创建或销毁
 * @author Jie.Yuan
 *
 */
public class MyRequestListener implements ServletRequestListener{

	// 对象销毁
	@Override
	public void requestDestroyed(ServletRequestEvent sre) {
		// 获取request中存放的数据
		Object obj = sre.getServletRequest().getAttribute("cn");
		System.out.println(obj);
		System.out.println("MyRequestListener.requestDestroyed()");
	}

	// 对象创建
	@Override
	public void requestInitialized(ServletRequestEvent sre) {
		System.out.println("MyRequestListener.requestInitialized()");
	}
}

Web.xml


<!-- 监听request对象创建、销毁 -->
	<listener>
		<listener-class>cn.itcast.a_life.MyRequestListener</listener-class>
	</listener>

B. HttpSessionListener

监听session对象的创建或销毁。

 

C. ServletContextListener

监听servletContext对象的创建或销毁。

1.3 属性监听器

监听:request/session/servletContext对象属性的变化!

ServletRequestAttributeListener

HttpSessionAttributeListener

ServletContextAttributeListener

 

总结:先写类,实现接口;  再配置

 

 

1.4 其他监听器: session相关监听器

 

 

HttpSessionBindingListener   

监听对象绑定/解除绑定到sesison上的事件!

 

步骤:

对象实现接口; 再把对象绑定/解除绑定到session上就会触发监听代码。

作用:

(例如上线提醒!)

/**
 * 监听此对象绑定到session上的过程,需要实现session特定接口
 * @author Jie.Yuan
 *
 */
public class Admin implements HttpSessionBindingListener {
   … 省略get/set
// 对象放入session
	@Override
	public void valueBound(HttpSessionBindingEvent event) {
		System.out.println("Admin对象已经放入session");
	}
	// 对象从session中移除
	@Override
	public void valueUnbound(HttpSessionBindingEvent event) {
		System.out.println("Admin对象从session中移除!");
	}
}

思考:

这个session监听器,和上面的声明周期、属性监听器区别?

--à 不用再web.xml配置

   -à 因为监听的对象是自己创建的对象,不是服务器对象!

 

 

 

1.5 案例

需求:做一个在线列表提醒的功能!

      用户--à 登陆

               ---à 显示登陆信息,列表展示。(list.jsp)

   --à  显示在线用户列表        (list.jsp)

-à 列表点击进入“在线列表页面”   onlineuser.jsp

 

实现:

1. 先增加登陆、退出功能;;

login.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
  </head>
  
  <body>
  <form name="frmLogin" action="${pageContext.request.contextPath }/admin?method=login" method="post">
  	<table align="center" border="1">
  		<tr>
  			<td>用户名</td>
  			<td>
  				<input type="text" name="userName">
  			</td>
  		</tr>
  		<tr>
  			<td>密码</td>
  			<td>
  				<input type="password" name="pwd">
  			</td>
  		</tr>
  		<tr>
  			<td>
  				<input type="submit" value="亲,点我登陆!">
  			</td>
  		</tr>
  	</table>
  </form>
  </body>
</html>


web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- 登陆验证过滤器 -->
	<filter>
		<filter-name>loginFilter</filter-name>
		<filter-class>cn.itcast.filter.LoginFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>loginFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
	<!-- 监听器: 监听ServletContext对象 -->
	<listener>
		<listener-class>cn.itcast.listener.OnlineAdminListener</listener-class>
	</listener>
	
	<!-- 监听器:监听session对象 -->
	<listener>
		<listener-class>cn.itcast.listener.SessionListener</listener-class>
	</listener>

	<servlet>
		<servlet-name>IndexServlet</servlet-name>
		<servlet-class>cn.itcast.servlet.IndexServlet</servlet-class>
	</servlet>
	
	
	
	<servlet>
		<servlet-name>AdminServlet</servlet-name>
		<servlet-class>cn.itcast.servlet.AdminServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>AdminServlet</servlet-name>
		<url-pattern>/admin</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>IndexServlet</servlet-name>
		<url-pattern>/index</url-pattern>
	</servlet-mapping>




	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>


2. 写监听器,监听servletContext对象的创建: 初始化集合(onlineuserlist)

package cn.itcast.listener;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import cn.itcast.entity.Admin;

/**
 * 初始化在线列表集合监听器
 * 
 * @author Jie.Yuan
 * 
 */
public class OnlineAdminListener implements ServletContextListener {

	//1. ServletContext对象创建
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		// 创建集合:存放在线用户
		// 每次当用户登陆后,就往这个集合中添加添加当前登陆者
		List<Admin> onlineList = new ArrayList<Admin>();
		// 放入ServletContext中
		sce.getServletContext().setAttribute("onlineList", onlineList);
	}

	//2. ServletContext对象销毁
	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		// 获取ServletContext
		ServletContext sc = sce.getServletContext();
		// 获取在线列表
		Object obj = sc.getAttribute("onlineList");
		// 移除在线列表集合
		if (obj != null) {
			sc.removeAttribute("onlineList");
		}
	}

}


3. 登陆功能: 用户登陆时候,把数据保存到servletContext

package cn.itcast.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import cn.itcast.entity.Admin;
import cn.itcast.service.IAdminService;
import cn.itcast.service.impl.AdminService;

/**
 * 用户管理servlet 1. 登陆 2. 退出
 * 
 * @author Jie.Yuan
 * 
 */
public class AdminServlet extends HttpServlet {

	// Service实例
	private IAdminService adminService = new AdminService();
	// 跳转资源
	private String uri;

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		// 区别不同的操作类型
		String method = request.getParameter("method");
		// 判断
		if ("login".equals(method)) {
			// 登陆操作, 调用登陆方法
			login(request, response);
		}

		else if ("out".equals(method)) {
			// 退出操作,调用推出方法
			out(request, response);
		}
	}

	// 1 登陆
	private void login(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");

		// 1. 获取参数
		String userName = request.getParameter("userName");
		String pwd = request.getParameter("pwd");
		// 封装
		Admin admin = new Admin();
		admin.setUserName(userName);
		admin.setPwd(pwd);

		try {
			// 2. 调用service处理业务
			Admin loginInfo = adminService.findByNameAndPwd(admin);
			// 判断:
			if (loginInfo == null) {
				// 登陆失败
				uri = "/login.jsp";
			} else {
				// 登陆成功
				// 先,保存数据到session
				request.getSession().setAttribute("loginInfo", loginInfo);
				//【在线列表: 1. 先从servletContext中拿到在线列表集合;  (onLineUserList)
				//           2. 当前用户放入“在线列表集合中”】
				// 实现1:先得到servletContext对象
				ServletContext sc = getServletContext();
				// 实现2: 再获取在线列表集合
				List<Admin> onlineList = (List<Admin>) sc.getAttribute("onlineList");
				// 判断
				if (onlineList != null){
					// 实现3: 添加当前登陆者
					onlineList.add(loginInfo);
					//sc.setAttribute("onlineList", onlineList);  // 对象引用传递,不需要写也可以
				}
				
				// 再,跳转到首页显示servlet(/index)
				uri = "/index";
			}
		} catch (Exception e) {
			// 测试
			e.printStackTrace();
			// 错误
			uri = "/error/error.jsp";
		}

		// 3. 跳转
		request.getRequestDispatcher(uri).forward(request, response);

	}

	// 2 退出
	private void out(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//1. 获取session
		HttpSession session = request.getSession(false);
		//2.判断: 
		if (session!=null) {
			// 从session中移除用户
			// session.removeAttribute("loginInfo");  //?
			// 销毁session
			session.invalidate();			
		}
		//3. 跳转(登陆)
		response.sendRedirect(request.getContextPath() + "/login.jsp");
	}

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


4. List.jsp  增加超链接, 点击时候提交直接跳转到online.jsp

list.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!-- 引入jstl核心标签库 -->
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
  </head>
  
  <body>
  	
  	<!-- 引入头部页面 -->
  	<jsp:include page="/public/head.jsp"></jsp:include>
  	
  	<!-- 列表展示数据 -->
  	<table align="center" border="1" width="80%" cellpadding="3" cellspacing="0">
  		<tr>
  			<td>序号</td>
  			<td>编号</td>
  			<td>员工名称</td>
  		</tr>
  		<c:if test="${not empty requestScope.listEmp}">
	  		<c:forEach var="emp" items="${requestScope.listEmp}" varStatus="vs">
		  		<tr>
		  			<td>${vs.count }</td>
		  			<td>${emp.empId }</td>
		  			<td>${emp.empName }</td>
		  		</tr>
	  		</c:forEach>
  		</c:if>
  	</table>
  </body>
</html>

online.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!-- 引入jstl核心标签库 -->
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>在线用户列表</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
  </head>
  
  <body>
  	
  	<!-- 引入头部页面 -->
  	<jsp:include page="/public/head.jsp"></jsp:include>
  
  	<!-- 在线用户 -->
  	<table align="center" border="1" width="80%" cellpadding="3" cellspacing="0">
  		<tr>
  			<td colspan="2" align="center"><h3>在线列表展示:</h3></td>
  		</tr>
  		<tr>
  			<td>编号</td>
  			<td>员工名称</td>
  		</tr>
  		<c:if test="${not empty applicationScope.onlineList}">
	  		<c:forEach var="admin" items="${applicationScope.onlineList}">
		  		<tr>
		  			<td>${admin.id }</td>
		  			<td>${admin.userName }</td>
		  		</tr>
	  		</c:forEach>
  		</c:if>
  	</table>
  </body>
</html>

head.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<h3 align="center">
 	欢迎你,${sessionScope.loginInfo.userName }; 
 	<a href="${pageContext.request.contextPath }/admin?method=out">退出</a>
 		
 	<a href="${pageContext.request.contextPath }/online.jsp">在线列表展示</a>
</h3>


5. 写监听器: 监听session销毁,把当前登陆用户从onlineuserlist移除!

package cn.itcast.listener;

import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import cn.itcast.entity.Admin;

/**
 * 监听Session销毁的动作:
 *  当服务器销毁session的时候,从在线列表集合中移除当亲的登陆用户
 * @author Jie.Yuan
 *
 */
public class SessionListener implements HttpSessionListener{

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		//1. 获取Session对象、ServletContext对象
		HttpSession session = se.getSession();
		ServletContext sc = session.getServletContext();
		
		//2. 获取Session中存储的当前登陆用户
		Object obj = session.getAttribute("loginInfo");//?
		
		//3. 获取ServletContext中存储的在线用户列表集合
		List<Admin> list = (List<Admin>) sc.getAttribute("onlineList");
		// 先判断
		if (obj != null){
			//4. 把“当前登陆用户”从在线列表集合中移除
			list.remove(obj);
		}
	}
	
	@Override
	public void sessionCreated(HttpSessionEvent se) {
	}

}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值