什么是监听器?
类似于前端的事件绑定,java中的监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。
监听器怎么分类?
按监听的对象划分
按监听的事件划分
一共有哪些监听器?分别处理的是什么事情?
java中一共给我们提供了八个监听器接口,分别用于监听三个域对象,每个监听器都有专门监听的事件
Request
Session
Application
监听器如何使用?
两步走使用
接下来我们就挨个认识一下每个监听器及内部方法的作用
Requet域共有两个监听器接口,分别是
ServletRequestListener
ServleRequestAttributeListener
接下来我们就认识一些每个接口和接口中每个方法的用处
定义监听器类
package com.msb.listener;
import javax.servlet.*;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
public class MyRequestListener implements ServletRequestListener, ServletRequestAttributeListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
// 监听HttpServletRequest对象的销毁 项目中任何一个Request对象的销毁都会触发该方法的执行
ServletRequest servletRequest = sre.getServletRequest();
System.out.println("request"+servletRequest.hashCode()+"对象销毁了");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
// 监听HttpServletRequest对象的创建并初始化 项目中任何一个Request对象的创建并初始化都会触发该方法的执行
ServletRequest servletRequest = sre.getServletRequest();
System.out.println("request"+servletRequest.hashCode()+"对象初始化");
}
@Override
public void attributeAdded(ServletRequestAttributeEvent srae) {
// 任何一个Request对象中调用 setAttribute方法增加了数据都会触发该方法
ServletRequest servletRequest = srae.getServletRequest();
String name = srae.getName();
Object value = srae.getValue();
System.out.println("request"+servletRequest.hashCode()+"对象增加了数据:"+name+"="+value);
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent srae) {
// 任何一个Request对象中调用 removeAttribute方法移除了数据都会触发该方法
ServletRequest servletRequest = srae.getServletRequest();
String name = srae.getName();
Object value = srae.getValue();
System.out.println("request"+servletRequest.hashCode()+"对象删除了数据:"+name+"="+value);
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent srae) {
// 任何一个Request对象中调用 setAttribute方法修改了数据都会触发该方法
ServletRequest servletRequest = srae.getServletRequest();
String name = srae.getName();
Object value = srae.getValue();
Object newValue=servletRequest.getAttribute(name);
System.out.println("request"+servletRequest.hashCode()+"对象增修改了数据:"+name+"="+value+"设置为:"+newValue);
}
}
配置监听器 使用web.xml 或者通过@WebListener注解都可以
com.msb.listener.MyRequestListener
准备Servlet
@WebServlet(urlPatterns = "/myServlet3.do")
public class MyServlet3 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("name", "zhangsan");
req.setAttribute("name", "lisi");
req.removeAttribute("name");
}
}
Session域共有四个监听器接口,分别是
HttpSessionListener
HttpSessionAttributeListener
HttpSessionBindingListener
HttpSessionActivationListener
接下来我们就认识一些每个接口和接口中每个方法的用处
监听器代码
HttpSessionListener
HttpSessionAttributeListener
package com.msb.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
@WebListener
public class MySessionListener implements HttpSessionListener , HttpSessionAttributeListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("任何一个Session对象创建");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("任何一个Session对象的销毁");
}
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("任何一个Session对象中添加了数据");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("任何一个Session对象中移除了数据");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("任何一个Session对象中修改了数据");
}
}
HttpSessionBindingListener
package com.msb.listener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
/*
* 可以监听具体的某个session对象的事件的
*
* HttpSessionListener 只要在web.xml中配置或者通过@WebListener注解就可以注册监听所有的Session对象
* HttpSessionBindingListener 必须要通过setAttribute方法和某个session对象绑定之后,监听单独的某个Session对象
* */
public class MySessionBindingListener implements HttpSessionBindingListener {
// 绑定方法
/*
session.setAttribute("mySessionBindingListener",new MySessionBindingListener())
*/
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("监听器和某个session对象绑定了");
}
// 解除绑定方法
/*
* 当发生如下情况,会触发该方法的运行
* 1 session.invalidate(); 让session不可用
* 2 session到达最大不活动时间,session对象回收 ;
* 3 session.removeAttribute("mySessionBindingListener");手动解除绑定
* */
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
}
}
HttpSessionActivationListener
package com.msb.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
public class MySessionActivationListener implements HttpSessionActivationListener {
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println("session即将钝化");
}
@Override
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println("session活化完毕");
}
}
Application域共有两个监听器接口,分别是
ServletContextListener
ServletContextAttributeListener
接下来我们就认识一些每个接口和接口中每个方法的用处
监听器代码
package com.msb.listener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
public class MyApplicationListener implements ServletContextListener , ServletContextAttributeListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext创建并初始化了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext销毁了");
}
@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("ServletContext增加了数据");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("ServletContext删除了数据");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("ServletContext修改了数据");
}
}
1.需求:记录每次请求中如下的信息并存储进入日志文件请求的来源
监听器代码
package com.msb.listener;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
@WebListener
public class RequestLogListener implements ServletRequestListener {
private SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void requestDestroyed(ServletRequestEvent sre) {
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
// 获得请求发出的IP
// 获得请求的URL
// 获得请求产生的时间
HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
String remoteHost = request.getRemoteHost();
String requestURL = request.getRequestURL().toString();
String reqquestDate = simpleDateFormat.format(new Date());
// 准备输出流
try {
PrintWriter pw =new PrintWriter(new FileOutputStream(new File("d:/msb.txt"),true));
pw.println(remoteHost+" "+requestURL+" "+reqquestDate );
pw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
2.需求:
1当任何一个账户处于登录状态时,在线统计总数+1,离线时-1
2通过session监听器实现计数,但是在线人数要保存在Application域中
准备监听器
package com.msb.listener;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
@WebListener
public class OnLineNumberListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
// 向application域中 增加一个数字
HttpSession session = se.getSession();
ServletContext application = session.getServletContext();
Object attribute = application.getAttribute("count");
if(null == attribute){// 第一次放数据
application.setAttribute("count", 1);
}else{
int count =(int)attribute;
application.setAttribute("count", ++count);
}
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// 向application域中 减少一个数字
HttpSession session = se.getSession();
ServletContext application = session.getServletContext();
int count =(int)application.getAttribute("count");
application.setAttribute("count", --count);
}
}
准备销毁监听的servlet
package com.msb.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
@WebServlet(urlPatterns = "/logout.do")
public class Logout extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.invalidate();
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$Title%sSourceCode%lt;/title>
当前在线人数为:${applicationScope.count}
3.项目重启免登录
Session序列化和反序列化
1、序列化与反序列
把对象转化为字节序列的过程称为序列化(保存到硬盘,持久化)
把字节序列转化为对象的过程称为反序列化(存放于内存)
2、序列化的用途
把对象的字节序列永久保存到硬盘上,通常放到一个文件中。
把网络传输的对象通过字节序列化,方便传输本节作业
3、实现步骤
要想实现序列化和反序列化需要手动配置
A、新建文件如图所示:
B、 Context.xml中文件如下
C、注意实体类必须实现serializable 接口
开发过程
1 准备实体类
package com.msb.pojo;
import java.io.Serializable;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
public class User implements Serializable {
private String username;
private String pwd;
2.开发登录信息输入页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$Title%sSourceCode%lt;/title>
3开发登录信息验证Servlet
package com.msb.controller;
import com.msb.listener.MySessionActivationListener;
import com.msb.pojo.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
@WebServlet("/loginController.do")
public class LoginController extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("user");
String pwd = req.getParameter("pwd");
// user
User user =new User(username,pwd);
// session
HttpSession session = req.getSession();
session.setAttribute("user", user);
}
}
4 开发校验当前是否已经登录的Controller
package com.msb.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
@WebServlet(urlPatterns = "/loginCheckController.do")
public class LoginCheckController extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 判断是否登录
HttpSession session = req.getSession();
Object user = session.getAttribute("user");
Object listener = session.getAttribute("listener");// 获得对应的监听器
String message ="";
if(null != user){
message="您已经登录过";
}else{
message="您还未登录";
}
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println(message);
}
}
5测试, 先登录,然后请求loginCheckController.do 校验是否登录过,然后重启项目,再起请求loginCheckController.do 校验是否登录过,发现重启后,仍然是登录过的
6监听钝化和活化
准备监听器
package com.msb.listener;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
public class MySessionActivationListener implements HttpSessionActivationListener, Serializable {
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println(se.getSession().hashCode()+"即将钝化");
}
@Override
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println(se.getSession().hashCode()+"已经活化");
}
}
登录时绑定监听器
@WebServlet("/loginController.do")
public class LoginController extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("user");
String pwd = req.getParameter("pwd");
// user
User user =new User(username,pwd);
// session
HttpSession session = req.getSession();
session.setAttribute("user", user);
// 绑定监听器
session.setAttribute("listener", new MySessionActivationListener());
}
}
重启项目 重复测试即可