javaweb中的监听器-
学习javaweb时我们会用到很多种域对象,
request域,session域,以及application域这三种时servlet中的三大域对象;
每一个域中都可以存放一些信息,但是是有针对性的,并不是随便放置的,这个暂且不提;
今天主要学习的是监听器------->
什么是监听器?
类似于前端的事件绑定,java中的监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。
监听器的分类
按监听的对象划分
a.ServletContext对象监听器
b.HttpSession对象监听器
c.ServletRequest对象监听器
按监听的事件划分
a.对象自身的创建和销毁的监听器
b.对象中属性的创建和消除的监听器
c.session中的某个对象的状态变化的监听器
java中一共给我们提供了八个监听器接口,分别用于监听三个域对象,每个监听器都有专门监听的事件
Request域监听器
监听器并不是一个有实体方法的类,而是一个接口,接口中的方法需要我们去实现;
创建一个Request域监听器----->
实现requestInitialized和requestDestroyed方法
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class MyListener_demo2 implements ServletRequestListener {
//监听request对象创建
@Override
public void requestInitialized(ServletRequestEvent sre) {
ServletRequest servletRequest = sre.getServletRequest();//可以得到请求对象;
System.out.println(servletRequest.hashCode());
System.out.println(servletRequest);
// 通过请求对象做出一些处理
System.out.println(servletRequest.getAttribute("user"));//取出域中的信息
}
//监听request对象销毁
@Override
public void requestDestroyed(ServletRequestEvent sre) {
ServletRequest servletRequest = sre.getServletRequest();
System.out.println(servletRequest.hashCode()+"请求对象销毁了");
System.out.println(servletRequest+"请求对象销毁了");
}
}
创建好之后还需要将监听器部署到项目中;
配置监听器—
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- //配置监听器-->
<listener>
<listener-class>MyListener.MyListener_demo2</listener-class>
</listener>
</web-app>
创建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 java.io.IOException;
@WebServlet("/MyServlet_demo01.do")
public class MyServlet_demo01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet1----invoked");
req.setAttribute("user","张三");
System.out.println("请求对象1"+req.hashCode());
}
}
部署项目后运行
运行后发现该监听器只能监听request对象的创建和销毁,要想监听request域中内容得增删改,那么该如何操作呢?
创建一个Request域属性监听器----->
public class MyListener_demo2 implements ServletRequestAttributeListener {
//监听request中属性的添加
@Override
public void attributeAdded(ServletRequestAttributeEvent srae) {
String name = srae.getName();
Object value = srae.getValue();
//获得request对象;
ServletRequest servletRequest = srae.getServletRequest();
System.out.println("请求行中的user="+servletRequest.getParameter("user"));
System.out.println("请求域中添加了"+name+"="+value);
}
//监听request中属性的移除
@Override
public void attributeRemoved(ServletRequestAttributeEvent srae) {
String name = srae.getName();
Object value = srae.getValue();
System.out.println("请求域中删除了"+name+"="+value);
}
//监听request中属性的修改
@Override
public void attributeReplaced(ServletRequestAttributeEvent srae) {
String name = srae.getName();
Object value = srae.getValue();
System.out.println("请求域中修改了"+name+"="+value);
}
}
创建servlet
@WebServlet("/MyServlet_demo03.do")
public class MyServlet_demo03 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//添加Attribute
req.setAttribute("user","张三");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//修改Attribute
req.setAttribute("user","李四");
//添加新的
req.setAttribute("password","123456");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 移除
req.removeAttribute("password");
}
}
运行------>
session域监听器
跟request监听器搭建类似,实现接口然后调用方法等;
监听sessio的创建与销毁—HttpSessionListener
监听session中的属性增删改—HttpSessionAttributeListener
import javax.servlet.http.*;
public class MySessionListener_demo01 implements HttpSessionListener, HttpSessionAttributeListener {
//监听session对象的创建
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println("哈希值为--"+session.hashCode()+"session对象创建了");
}
//监听session对象的销毁
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println("哈希值为--"+session.hashCode()+"session对象销毁了");
}
//监听session中的属性添加
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
HttpSession session = se.getSession();
System.out.println("哈希值为--"+session.hashCode()+"对象中增加了属性");
System.out.println(se.getName()+"="+se.getValue());
}
//监听session中的属性移除
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
HttpSession session = se.getSession();
System.out.println("哈希值为--"+session.hashCode()+"对象中移除了属性");
System.out.println(se.getName()+"="+se.getValue());
}
//监听session中的属性修改
@Override
public void attributeReplaced(HttpSessionBindingEvent se) {
HttpSession session = se.getSession();
System.out.println("哈希值为--"+session.hashCode()+"对象中修改了属性");
System.out.println(se.getName()+"="+se.getValue());
}
}
可以绑定监听器与某一个session相关联
HttpSessionBindingListener
创建一个监听器----->>>实现
HttpSessionBindingListener
HttpSessionActivationListener
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
@WebListener
public class MySessionBindListener_demo01 implements HttpSessionBindingListener, HttpSessionActivationListener {
//绑定事件
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println(event.getName());
System.out.println(event.getValue());
System.out.println("该监听器与"+event.getSession().hashCode()+"绑定了");
}
//解绑事件
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println(event.getName());
System.out.println(event.getValue());
System.out.println("该监听器与"+event.getSession().hashCode()+"解绑了");
}
//session钝化
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println(se.getSession().hashCode()+"session钝化");
}
//session活化
@Override
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println(se.getSession().hashCode()+"session活化");
}
}
session活化与session钝化
session是有自己生命周期的,当我们创建一个session时,在浏览器保存一个cookie,下次浏览器访问时就可以跳过一些环节,但是当session 失效时后者session被清除时(服务器重启,那么浏览器中的cookie对象也就会失效,服务器回重新生成一个session),如果服务器不想这样的化,就需要在服务器重启时 钝化session------简单的说就是将session对象序列化后写入到磁盘,—这就时session的钝化,当服务器重启时读取这个session那么服务器就会检查到浏览器发过来的cookie,这叫session的活化;
application域监听器
监听器
package MyListener;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyApplicationListener_demo1 implements ServletContextListener, ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("被添加的信息---");
System.out.println(scae.getName()+"---"+scae.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("被移除的信息---");
System.out.println(scae.getName()+"---"+scae.getValue());
}
@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("被修改的信息---");
System.out.println(scae.getName()+"---"+scae.getValue());
}
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println(sce.getServletContext().hashCode()+"被实例化了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println(sce.getServletContext().hashCode()+"被销毁了");
}
}
servlet
@WebServlet("/MyServlet_demo06.do")
public class MyServlet_demo06 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet6----invoked");
ServletContext servletContext = req.getServletContext();
servletContext.setAttribute("username","王二麻子");
servletContext.setAttribute("password","WangEr");
servletContext.setAttribute("username","李代张冠");
servletContext.removeAttribute("username");
}
}
用request监听器记录请求日志
package MyListenerdemo;
import org.apache.log4j.Logger;
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.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
@WebListener
public class MyListenerDemo01 implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
Logger logger = Logger.getLogger(MyListenerDemo01.class);
ServletRequest servletRequest = sre.getServletRequest();
HttpServletRequest req=(HttpServletRequest)servletRequest;
String remoteHost = req.getRemoteHost();
System.out.println(remoteHost);
String requestURI = req.getRequestURI();
String requestUrl = req.getRequestURL().append(requestURI).toString();
System.out.println(requestUrl);
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(new Date());
System.out.println(date);
//用打印流记录,但是会遇到阻塞等,比较繁琐;
try {
PrintWriter pw= new PrintWriter(new FileOutputStream("d:/gavin.txt"),true);
pw.println(remoteHost+" "+requestUrl+" "+date);
pw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
logger.info(remoteHost+" "+requestUrl+" "+date);
}
}
}
用session监听器记录在线人数
package MyListenerdemo;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class MySessionListener_01 implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
// 拿到session
HttpSession session = se.getSession();
ServletContext application = session.getServletContext();
//查看session中是否有值
Object attribute = application.getAttribute("count");
// 如果count为null,说明是第一次访问
if(attribute==null){
application.setAttribute("count",1);
}else{//不是第一次访问
Integer count=(Integer)attribute;
application.setAttribute("count",++count);
}
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// 拿到session
HttpSession session = se.getSession();
ServletContext application = session.getServletContext();
Integer count=(Integer)application.getAttribute("count");
application.setAttribute("count",--count);
}
}
session的钝化与活化监听器实现
这种方式用于用户七天之内免登录的路况!
框架搭建!!
准备一个jsp页面------->>>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
当前在线人数:${applicationScope.count}
<form method="post" action="myServlet01.do">
账号:<input type="text" name="username" placeholder="请输入账号">
密码:<input type="text" name="userpwd" placeholder="请输入密码">
<input type="submit" value="登录">
</form>
</body>
</html>
准备一个user实体类,
package MyPojo;
import java.io.Serializable;
import java.util.ArrayList;
public class User implements Serializable {
private static final long serialVersionUID = 88591L;
private String username;
private String userpwd;
public User() {
}
public User(String username, String userpwd) {
this.username = username;
this.userpwd = userpwd;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpwd() {
return userpwd;
}
public void setUserpwd(String userpwd) {
this.userpwd = userpwd;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", userpwd='" + userpwd + '\'' +
'}';
}
}
准备两个servlet,一个用于检测是否登录成功,另一个用于检测设置七天免登录是否成功
import MyPojo.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;
@WebServlet(urlPatterns = "/myServlet01.do")
public class myServlet01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String userpwd = req.getParameter("userpwd");
if ("gavin".equals(username)&&"123".equals(userpwd)){
HttpSession session = req.getSession();
User user= new User(username,userpwd);
session.setAttribute("user",user);
}else{
resp.sendRedirect("index.jsp");
}
}
}
package MyServletdemo;
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;
import java.io.PrintWriter;
@WebServlet(urlPatterns = "/myServlet02.do")
public class myServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
// resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=UTF-8");
HttpSession session = req.getSession();
Object attribute = session.getAttribute("user");
PrintWriter writer = resp.getWriter();
String Mes;
if(null!=attribute){
Mes="您已登录过!";
}else{
Mes="你还未登录!";
}
writer.write(Mes);
}
}
在没有添加配置文件的时候—重启服务器后用户就需要重新登录,
添加配置文件后用户仍然处于登陆状态!
添加配置文件如下---->>
在web文件夹下添加 META-INF文件夹,然后创建Context.xml配置文件;
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Manager className="org.apache.catalina.session.PersistentManager">
<Store className="org.apache.catalina.session.FileStore" directory="d:/session"/>
</Manager>
</Context>
之后你就会发现-----
原理就是服务器会在重启关闭后将session持久化到文件中,重启之后读取该文件,恢复session对象;
之前提到过session的钝化与活化,这里有一个监听器来监测session的钝化与活化-----
既然session是序列化后写入到文件中,那么 该监听器就需要实现监听器接口和实现序列化接口
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
@WebListener
public class MySessionListener_o2 implements HttpSessionActivationListener , Serializable {
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println("检测到session"+session.hashCode()+"钝化了");
}
@Override
public void sessionDidActivate(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println("检测到session"+session.hashCode()+"活化了");
}
}