1.Listener概述
javaEE包括13门规范,在课程中主要学习servlet技术 和 jsp技术,其中 servlet规范包括三个技术点:servlet listener filter。
监听器就是监听某个对象的的状态变化的组件
监听器的相关概念:
事件源:被监听的对象 ----- 三个域对象 request session servletContext
2.监听器种类:6+2:
第一维度:按照被监听的对象划分:ServletRequest域 HttpSession域 ServletContext域
第二维度:按照监听的内容分:监听域对象的创建与销毁 监听域对象的属性变化

2.1 监听三大域对象的创建与销毁的监听器
(1)监听器ServletContextListener用于监听ServletContext域对象的创建与销毁。使用时需要实现这个接口
ServletContext域的生命周期:服务器启动时创建,服务器关闭时销毁。
ServletContextListener监听器的主要作用
- 初始化的工作:初始化对象,初始化数据 ---- 加载数据库驱动 连接池的初始化
- 加载一些初始化的配置文件 --- spring的配置文件
- 任务调度----定时器----Timer/TimerTask
示例:
package com.xing.servletContext;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javafx.scene.input.DataFormat;
public class ServletContextListener implements javax.servlet.ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
// ServletContext servletContext = sce.getServletContext();//获取被监听的servletContext域对象
// ServletContext source = (ServletContext) sce.getSource();//通用方法,获取被监听的对象
System.out.println("ServletContext域对象创建了");
//计息任务调度
/*Timer timer=new Timer();
//timer.scheduleAtFixedRate(task, firstTime, period);---task:任务 firstTime:第一次执行时间 period:间隔执行时间
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("每隔三秒开始计息.....");
}}, new Date(), 3000);*/
//银行真正计息业务
Timer timer=new Timer();
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
// String date = format.format(new Date());
Date parse=null;
try {
parse = format.parse("2018-09-01 10:29:00");//String转Date
} catch (ParseException e) {
e.printStackTrace();
}
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("银行开始计息");
}
}, parse, 24*60*60*1000);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
System.out.println("ServletContext域对象销毁了");
}
}
配置文件:
<listener>
<listener-class>com.xing.servletContext.ServletContextListener</listener-class>
</listener>
(2)监听器HttpSessionListener用于监听Httpsession域的创建于销毁
HttpSession对象的生命周期:第一次调用request.getSession时创建;服务器关闭销毁 session过期 手动销毁
public class HttpSessionListener implements javax.servlet.http.HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent se) {
// TODO Auto-generated method stub
HttpSession session = se.getSession();
HttpSession source = (HttpSession) se.getSource();
System.out.println("session创建了"+source.getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// TODO Auto-generated method stub
System.out.println("session销毁了");
}
}
(3)监听器ServletRequestListener用于监听ServletRequest域创建与销毁
ServletRequest的生命周期:每一次请求都会创建request;销毁:请求结束
2.2 监听三大域对象的属性变化的监听器
- ServletContextAttibuteListener监听器
- HttpSessionAttributeListener监听器
- ServletRequestAriibuteListenr监听器
ServletContextAttributeListener监听器示例:
package com.xing.attribute;
import javax.servlet.ServletContextAttributeEvent;
public class ServletContextAttributeListener implements javax.servlet.ServletContextAttributeListener{
@Override
public void attributeAdded(ServletContextAttributeEvent scab) {
// TODO Auto-generated method stub
System.out.println("放到域中的属性:"+scab.getName()+scab.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent scab) {
// TODO Auto-generated method stub
System.out.println("删除域中的属性:"+scab.getName()+scab.getValue());
}
@Override
public void attributeReplaced(ServletContextAttributeEvent scab) {
// TODO Auto-generated method stub
System.out.println("修改前的域中的属性:"+scab.getName()+scab.getValue());
}
}
2.3 对象感知监听器:与session中的对象相关的监听器
(1)将要被绑定到session中的对象有几种状态:
绑定状态:一个对象被放到session域中
解绑状态:这个对象从session域中移除
钝化状态:将session内存中的对象持久化(序列化)到磁盘
活化状态:将磁盘上的对象再次恢复到session内存中
面试题:当用户很多时,怎样对服务器进行优化?
(2)绑定与解绑的监听器HttpSessionBindingListener(第七个监听器)
package com.xing.domain;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class Persion implements HttpSessionBindingListener{
//不用再xml配置
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public void valueBound(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
System.out.println("person被绑定。。。"+event.getName());
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
System.out.println("person被解绑。。。"+event.getName());
}
}
钝化与活化的监听器HttpSessionActivationListener(第八个监听器)
(注意:还要实现io包的Serializable接口,对象才能真正被钝化到磁盘)
对象被钝化到work/catalina/localhost/下的文件夹
package com.xing.domain;
import java.io.Serializable;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
public class Customer implements HttpSessionActivationListener,Serializable{
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
// TODO Auto-generated method stub
System.out.println("customer被钝化,,,");
}
@Override
public void sessionDidActivate(HttpSessionEvent se) {
// TODO Auto-generated method stub
System.out.println("customer被活化,,,");
}
}
可以通过配置文件指定对象钝化时间 --- 对象多长时间不用被钝化:在META-INF下创建一个context.xml
<Context>
<!-- maxIdleSwap:session中的对象多长时间不使用就钝化 -->
<!-- directory:钝化后的对象的文件写到磁盘的哪个目录下 配置钝化的对象文件在 work/catalina/localhost/钝化文件 -->
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="itcast205" />
</Manager>
</Context>
案例:邮件发送程序(需要一个mail.jar)
发送邮件的协议:SMTP协议
接收邮件的协议:POP3,IMAP

package com.xing.mail;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
public class MailUtils {
//这个程序一般不需要自己写,会用就ok
//email:邮件发给谁 subject:主题 emailMsg:邮件的内容
public static void sendMail(String email, String subject, String emailMsg)
throws AddressException, MessagingException {
// 1.创建一个程序与邮件服务器会话对象 Session
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "SMTP");//发邮件的协议
props.setProperty("mail.host", "smtp.163.com");//发送邮件的服务器地址
props.setProperty("mail.smtp.auth", "true");// 指定验证为true
// 创建验证器
Authenticator auth = new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("xxxxx@163.com", "123");//发邮件的账号的验证
}
};
Session session = Session.getInstance(props, auth);
// 2.创建一个Message,它相当于是邮件内容
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("xxxxx@163.com")); // 设置发送者
message.setRecipient(RecipientType.TO, new InternetAddress(email)); // 设置发送方式与接收者
message.setSubject(subject);//邮件的主题
message.setContent(emailMsg, "text/html;charset=utf-8");
// 3.创建 Transport用于将邮件发送
Transport.send(message);
}
}
package com.xing.mail;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
public class SendMailTest {
public static void main(String[] args) throws AddressException, MessagingException {
MailUtils.sendMail("xxxx@163.com", "测试", "这是一个测试邮件");
}
}
案例:用户生日当天发送祝福邮件
package com.itheima.birthday;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.mail.MessagingException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import com.itheima.mail.MailUtils;
public class BirthdayListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
//当web应用启动 开启任务调动---功能在用户的生日当前发送邮件
//开启一个定时器
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// 为当前的生日的用户发邮件
//1、获得今天过生日的人
//获得今天的日期
SimpleDateFormat format = new SimpleDateFormat("MM-dd");
String currentDate = format.format(new Date());
//根据当前时间从数据查询今天过生日的人
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from customer where birthday like ?";
List<Customer> customerList = null;
try {
customerList = runner.query(sql, new BeanListHandler<Customer>(Customer.class) ,"%"+currentDate+"%");
} catch (SQLException e) {
e.printStackTrace();
} //08-18
//2、发邮件
if(customerList!=null&&customerList.size()>0){
for(Customer c : customerList){
String emailMsg = "亲爱的:"+c.getRealname()+",生日快乐!";
try {
MailUtils.sendMail(c.getEmail(), "生日祝福", emailMsg);
System.out.println(c.getRealname()+"邮件发送完毕");
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
}
}, new Date(), 1000*10);
//实际开发中起始时间是一个固定的时间
//实际开发中间隔时间是1天
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
本文详细介绍了JavaEE中Servlet技术的监听器概念及其应用场景。包括ServletContextListener、HttpSessionListener、ServletRequestListener等监听器的实现原理及示例代码,并探讨了如何利用监听器优化服务器资源管理和用户交互。

172

被折叠的 条评论
为什么被折叠?



