监听器Listener
今日内容介绍
u 案例:使用监听器完成定时发送生日祝福邮件
今日内容学习目标
u 了解监听器执行原理
u 阐述WEB开发中使用到8种监听器
u 了解邮件协议
u 了解Java程序发送邮件
第1章 案例:使用监听器发送生日祝福邮件
1.1 需求
当我们使用QQ时,在生日当天会收到QQ系统发送的祝福邮件。今天我们将实现相同的功能。
1.2 相关知识点
1.2.1 监听器Listener
1.2.1.1 概述
l 什么是监听器
n 所谓的监听器是指对整个WEB环境的监听,当被监视的对象发生改变时,立即调用相应的方法进行处理。
l 监听器最常见的应用场景:
n Java SE GUI编程
n Android 手机开发编程
l 监听器术语:
n 1.事件源:被监听对象。(目标对象)
n 2.监听器对象:用于监听“事件源”的对象
n 3.注册(绑定):将“监听器对象”注册给“事件源”。当“事件源”发生某些行为时,监听对象将被执行。
n 4.事件:事件源行为的称呼。
n 5.事件对象:在“监听器对象”中获得“事件源”.
l 监听器的编写流程
1. 编写监听器实现类,需要实现指定的接口
2. 在web.xml文件配置监听器(部分监听不需要配置)
<listener>
<listener-class></listener-class>
</listener>]
l JavaEE规范规定了8个监听器接口,用于监听不同的WEB对象。
n 监听域对象创建与销毁
n 监听域对象属性变更(添加,替换,删除)
n 监听session作用域特殊Javabean
1.2.1.2 域对象本身
l ServletRequest对象监听
ServletRequestListener | 监听Request对象创建或销毁 javax.servlet.ServletRequestListener | |
| request创建方法 * 请求开始创建 | requestInitialized(ServletRequestEvent sre) |
| request销毁方法 * 请求结束时销毁 | requestDestroyed(ServletRequestEvent sre) |
| 事件对象 | ServletRequestEvent l ServletContext getServletContext() l ServletRequest getServletRequest() |
l HttpSession对象监听
HttpSessionListener | 监听Session对象创建或销毁 javax.servlet.http.HttpSessionListener | |
| session创建方法 * 第一个调用getSession() | sessionCreated(HttpSessionEvent se) |
| session销毁方法 1. 默认30分钟,web.xml可配置 2. 执行api手动销毁,invalidate() 3. 服务器非正常关闭 | sessionDestroyed(HttpSessionEvent se) |
| 事件对象 | HttpSessionEvent l getSession() 获得session |
l ServletContext对象监听
ServletContextListener | 监听ServletContext对象创建或销毁 javax.servlet.ServletContextListener | |
| ServletContext创建方法 * 服务器启动时 | contextInitialized(ServletContextEvent sce) |
| ServletContext销毁方法 * 服务器正常关闭时 | contextDestroyed(ServletContextEvent sce) |
| 事件对象 | ServletContextEvent l ServletContext getServletContext() |
1.2.1.3 域对象属性
作用域属性操作:setAttribute(k,v) / getAttribute(k) / removeAttribute(k)
l request作用域属性
ServletRequestAttributeListener | 监听request对象属性attribute 添加、替换、删除 javax.servlet.ServletRequestAttributeListener | |
| 添加 * 第一次设置数据 | attributeAdded(ServletRequestAttributeEvent srae) |
| 替换 * 第二次设置数据 -- 通过event 获得old数据,如果希望获得new数据,需要request.getAttriubute 获得 | attributeReplaced(ServletRequestAttributeEvent srae) |
| 删除 | attributeRemoved(ServletRequestAttributeEvent srae) |
| 事件对象 | ServletRequestAttributeEvent l getName() l getValue() l getServletContext() l getServletRequest() |
l session作用域属性
HttpSessionAttributeListener | 监听session对象属性attribute 添加、替换、删除 javax.servlet.http.HttpSessionAttributeListener | |
| 添加 | attributeAdded(HttpSessionBindingEvent event) |
| 替换 | attributeReplaced(HttpSessionBindingEvent event) |
| 删除 | attributeRemoved(HttpSessionBindingEvent event) |
| 事件对象 | HttpSessionBindingEvent l getName() l getValue() l getSession() |
l servletContext作用域属性
ServletContextAttributeListener | 监听servletcontext对象属性attribute 添加、替换、删除 javax.servlet.ServletContextAttributeListener | |
| 添加 | attributeAdded(ServletContextAttributeEvent event) |
| 替换 | attributeReplaced(ServletContextAttributeEvent event) |
| 删除 | attributeRemoved(ServletContextAttributeEvent event) |
| 事件对象 | ServletContextAttributeEvent l getName() l getValue() l getServletContext() |
1.2.1.4 特殊javabean 在session作用域
--特殊的两个监听器不需要再web.xml配置,其他的6个都需配置<listener>。
l 绑定和解绑:实现指定接口javabean,从session作用域存放或异常监听
HttpSessionBindingListener | 监听特殊JavaBean在session作用域绑定或解绑 javax.servlet.http.HttpSessionBindingListener,javabean必须实现该接口 | |
| 绑定 * 给作用域添加数据 | valueBound(HttpSessionBindingEvent event) |
| 解绑 * 从作用域移除数据 | valueUnbound(HttpSessionBindingEvent event) |
| 事件对象 | HttpSessionBindingEvent
l getName() l getValue() l getSession() |
注意: 1.javabean必须实现接口,不需要再web.xml注册。 2. HttpSessionAttributeListener 和HttpSessionBindingListener 对比 HttpSessionAttributeListener 必须在web.xml注册,监听任意对象。 HttpSessionBindingListener 不需要再web.xml注册,只对当前javabean进行监听。
|
l 钝化和活化
HttpSessionActivationListener | 监听特殊JavaBean在session作用域钝化或活化 javax.servlet.http.HttpSessionActivationListener,javabean必须实现该接口 钝化:在服务器正常关闭时,将session作用域的数据写入到文件 活化:在服务器启动时,将指定文件中的内容加载到session作用域。 | |
| 活化 | sessionDidActivate(HttpSessionEvent se) |
| 钝化 | sessionWillPassivate(HttpSessionEvent se) |
| 事件对象 | HttpSessionEvent
l getSession() |
注意: 1. 必须实现序列号接口,java.io.Serializable,否则抛异常:java.io.NotSerializableException 2. 持久化session数据到指定的位置: %tomcat%\work\Catalina\localhost\项目名称\SESSIONS.ser
|
1.2.1.5 使用
l 步骤1:编写ServletContextListener接口实现类,用于监听ServletContext对象的创建与销毁
public class PathServletContextListener implements ServletContextListener {
//初始化方法
public void contextInitialized(ServletContextEvent sce) {
String contextLocation = sce.getServletContext().getInitParameter("contextLocation");
System.out.println("contextLocation " + contextLocation);
}
//销毁方法
public void contextDestroyed(ServletContextEvent sce) {
}
}
l 步骤2:在web.xml注册监听器
<!-- 配置系统初始化参数 -->
<context-param>
<param-name>contextLocation</param-name>
<param-value>/my2.xml</param-value>
</context-param>
l 步骤3:在web.xml配置全局初始化参数
<!-- 配置监听器 -->
<listener>
<listener-class>
cn.itcast.web.servlet.PathServletContextListener
</listener-class>
</listener>
1.2.2 电子邮件
1.2.2.1 概述
l 邮件服务器:
n 要在Internet上提供电子邮件功能,必须有专门的电子邮件服务器。例如现在Internet很多提供邮件服务的厂商:sina、sohu、163等等他们都有自己的邮件服务器。
n 这些服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
n 邮件服务器,按照提供的服务类型,可以分为发送邮件的服务器我接收邮件的服务器。
l 电子邮箱:
n 电子邮箱(E-mail地址)的获得需要在邮件服务器上进行申请 ,确切地说,电子邮箱其实就是用户在邮件服务器上申请的一个帐户。用户在邮件服务器上申请了一个帐号后,邮件服务器就会为这个帐号分配一定的空间,用户从而可以使用这个帐号以及空间,发送电子邮件和保存别人发送过来的电子邮件。
1.2.2.2 邮件协议
n SMTP协议-发邮件协议
n 全称为Simple Mail Transfer Protocol(简单邮件传输协议),它定义了邮件客户端软件与SMTP服务器之间、以及两台SMTP服务器之间的通讯规则。
n 端口号:25.
n POP3协议-收邮件协议
n 全称为Post Office Protocol(邮局协议),它定义了邮件客户端软件与POP3服务器的通讯规则。
n 端口号:110.
1.2.2.3 发送邮件流程
1.2.2.4 使用JavaMail发送邮件
l 导入jar包:
l 编写实现:
/* 邮件发送过程
* * smtp协议:邮件发送协议,端口号:25
* * pop3协议:邮件接收协议,端口号:110
* 使用java程序发送邮件,采用smtp协议。java提供 javamail用于发送邮件的,代码固定
* 126 --> itcast@126.com//账号不存在,需要自己注册
* 163 --> itheima@163.com//账号不存在,需要自己注册
*/
public static void main(String[] args) throws Exception {
//0.1 服务器的设置
Properties props = new Properties();
props.setProperty("mail.host", "smtp.126.com");
props.setProperty("mail.smtp.auth", "true");
//0.2 账号和密码
Authenticator authenticator = new Authenticator(){
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//126账号和密码(模拟账号,需要自己注册)
return new PasswordAuthentication("itcast","123456");
}
};
//1 与126服务器建立连接:Session
Session session = Session.getDefaultInstance(props, authenticator);
//2 编写邮件:Message
Message message = new MimeMessage(session);
//2.1 发件人(模拟账号)
message.setFrom(new InternetAddress("itcast@126.com"));
//2.2 收件人 , to:收件人 , cc :抄送,bcc:暗送(密送)。(模拟账号)
message.setRecipient(RecipientType.TO, new InternetAddress("itheima@163.com"));
//2.3 主题
message.setSubject("这是我们得第一份邮件");
//2.4 内容
message.setContent("哈哈,您到我的商城注册了。", "text/html;charset=UTF-8");
//3 将消息进行发送:Transport
Transport.send(message);
}
1.2.2.5 搭建本地环境
l 安装邮件服务器
l 安装客户端软件
l 参考:
1.2.3 定时器
l JDK提供工具类Timer,用于触发定时器,执行TimerTask执行任务
System.out.println(new Date().toLocaleString());
//1 定时器核心类
Timer timer = new Timer();
//2 定时执行指定任务
// 参数1:需要执行的任务
// 参数2:执行任务的延迟时间,单位:毫秒
// 参数3:执行任务的轮回时间(周期),单位:毫秒
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(new Date().toLocaleString());
}
}, 2000, 4000);
1.3 案例分析
1.4 案例实现
l 步骤1:导入jar包
l 步骤2:初始化数据库
create database day23_db;
use day23_db;
create table t_user(
id int primary key auto_increment,
username varchar(50),
birthday date,
email varchar(100)
);
insert t_user(username,birthday,email) values('jack','2015-12-12','itcast_lt@163.com');
insert t_user(username,birthday,email) values('rose','2015-12-12','itcast_lt@163.com');
insert t_user(username,birthday,email) values('tom','2015-12-12','itcast_lt@163.com');
l 步骤3:导入JdbcUtils和c3p0配置文件
l 步骤4:编写监听器
//实现类
public class SendMailListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
}
public void contextDestroyed(ServletContextEvent sce) {
}
}
//web.xml配置内容
<listener>
<listener-class>cn.itcast.web.listener.SendMailListener</listener-class>
</listener>
l 步骤5:导入时间工具类(了解)
l 步骤6:编写定时器
public class SendMailListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
//1 启动定时器,凌晨12点执行run()方法
new Timer().schedule(new TimerTask() {
@Override
public void run() {
try {
// 2.查询所有 查询所有的用户
UserService userService = new UserService();
// 3.查询当前过生日的所有人
List<User> findAll = userService.findAllWithBirthday();
for (User user : findAll) {
EmailUtils.send(user);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}, DateUtils.getDelayTime(), DateUtils.getOneDay());
//}, 100, DateUtils.getOneDay());//测试程序,运行后100毫秒执行
}
l 步骤7:编写JavaBean
public class User {
private Integer id;
private String username;
private String password;
private String email;
private String nickname;
private String gender;
private String birthday;
l 步骤8:编写service
public class UserService {
/**
* 查询当天过生日的用户
* @return
* @throws SQLException
*/
public List<User> findAllWithBirthday() throws SQLException {
UserDao userDao = new UserDao();
return userDao.findAllWithBirthday();
}
}
l 步骤9:编写dao
public class UserDao {
public List<User> findAllWithBirthday() throws SQLException {
// 查询条件:-06-12
String birthday = "-"+DateUtils.getCurrentMonth()+"-" + DateUtils.getCurrentDay();
System.out.println(birthday);
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from t_user where birthday like ?";
Object[] params = {"%"+birthday+"%"};
return queryRunner.query(sql, new BeanListHandler<User>(User.class), params);
}
}
第2章 总结