监听器Listener
对于我的理解,我感觉监听器Listener的作用没有过滤器Filter的作用大,在接下来我会总结下javaweb三大技术Filter的学习心得,这里我通过一个案例来说明Listerner的作用
- 需要了解监听器执行原理
- 阐述WEB开发中使用到8种监听器
- 需要了解邮件协议
- 需要了解Java程序发送邮件
案例:使用监听器完成定时发送生日祝福邮件
一,需求分析
当我们使用QQ时,在生日当天会收到QQ系统发送的祝福邮件,现在我们模拟将实现相同的功能。项目启动的时候,开启一个任务,查找(数据库)当前过生日的用户,在凌晨的时候给他们发送邮件.
二,技术分析
1.Listener
1.1Listener的概述
1.1.1什么是Listener
监听器就是一个Java类(狗仔)用来监听其他的JavaBean的变化
在javaweb中监听器就是监听三个域对象的状态的。request,session,servletContext
1.1.2监听器的应用
主要在Swing编程.
在Android大量应用
1.1.3监听器的术语
一个狗仔偷拍明星出轨
事件源 :被监听的对象.(目标对象) 明星
监听器对象:监听的对象. 狗仔
注册(绑定):将"监听器"对象注册给"事件源". 当事件源发生某些行为,监听对象将被执行 在偷拍明星楼下蹲点
事件:事件源行为的称呼. 出轨
事件对象:在”监听器对象”中获得”事件源”
1.2javaweb的监听器
javaweb的监听器:监听ServletContext,HttpSession,ServletRequest三个域对象状态
事件源和监听器绑定的过程:通过配置web.xml完成
Servlet中提供了8个监听器
- 一类:监听三个域对象的创建和销毁的监听器
对象类型 | 对应的监听器 |
---|---|
ServletContext | ServletContextListener |
HttpSession | HttpSessionListener |
HttpServletRequest | ServletRequestListener |
- 二类:监听三个域对象的属性变更的监听器.(属性添加,属性移除,属性替换)
对象类型 | 对应的监听器 |
---|---|
ServletContext | ServletContextAttributeListener |
HttpServletRequest | ServletRequestAttributeListener |
HttpSession | HttpSessionAttributeListener |
- 三类:监听HttpSession对象中的JavaBean的状态的改变.(绑定,解除绑定,钝化和活化)2个
对象类型 | 对应的监听器 |
---|---|
HttpSession | HttpSessionBindingListener(绑定,解除绑定) |
HttpSession | HttpSessionActivationListener(钝化和活化) |
编写步骤:
1.编写一个类
实现监听器接口
重写方法
2.编写配置文件(大部分需要)
注册listener
1.3一类监听器:监听三个域对象的创建和销毁的监听器
1.3.1ServletContextListener
监听ServletContext对象的创建和销毁
- 方法
问题
ServletContext对象何时创建和销毁:应用在,它就在
创建:服务器启动时候,服务器可以为每个WEB应用创建一个单独的ServletContext. 销毁:服务器关闭的时候,或者项目从服务器中移除.
企业中应用
初始化工作.
加载配置文件:Spring框架,ContextLoaderListener
1.3.2HttpSessionListener
监听HttpSession对象的创建和销毁
方法
问题
HttpSession对象何时创建和销毁的:
创建:服务器第一次访问Servlet时,调用getSession()方法的时候. 如果访问的是jsp则直接创建。 销毁:session过期了(默认30分钟) session.invalidate()手动销毁 非正常关闭服务器(正常关闭序列化到硬盘)
1.3.3ServletRequestListener
监听request对象的创建和销毁
方法
问题
ServletRequest对象何时创建和销毁
创建:客户端向服务器发送请求的时候 销毁:服务器为这次请求作出了响应时候
1.4二类监听器:监听三个域对象属性变更的监听器
1.4.1ServletContextAttributeListener
监听ServletContext对象中的属性变更的监听器
- 方法
1.4.2HttpSessionAttributeListener
监听HttpSession对象中的属性变更的监听器
- 方法
1.4.3ServletRequestAttributeListener
监听ServletRequest对象中的属性变更的监听器
- 方法
1.5三类监听器:监听HttpSession中的JavaBean的状态改变的监听器
注意:
第三类监听器非常特殊:
监听器作用在JavaBean上.JavaBean可以自己感知在session中状态.
这类监听器不用配置.
1.5.1HttpSessionBindingListener
监听HttpSession中的JavaBean的绑定和解除绑定的状态
方法
1.5.2HttpSessionActivationListener
监听HttpSession中的JavaBean的钝化和活化的状态
- 方法
sessionDidActivate(HttpSessionEvent se); – 活化,反序列化
SessionWillPassivate(HttpSessionEvent se); – 钝化,序列化
2.定时器
2.1java.util.Timer
JDK提供工具类Timer,用作定时任务。可安排任务执行一次,或者定期重复执行。
2.1Timer的使用
创建Timer对象
new Timer();创建Time对象
Timer常用方法
void schedule(TimerTask task, Date firstTime, long period) : 安排指定的任务在指定的时间开始进行重复的固定时间间隔执行。 void schedule(TimerTask task, long delay, long period): 安排指定的任务从指定的延迟后开始进行重复的固定时间间隔执行。
eg:
Timer timer = new Timer();
// 打印当前时间
System.out.println(new Date().toLocaleString());
timer.schedule(new TimerTask() {
@Override
public void run() {
// 打印当前时间
System.out.println(new Date().toLocaleString());
}
}, new Date(), 1000);
2.3Calendar:日历对象
获取Calendar对象
static getInstance();
Calendar常用方法
get(int field):获取 set(int field,int value):设置
eg:
Calendar calendar = Calendar.getInstance();
//获取年月日(注意月份+1)
//System.out.println("年:"+calendar.get(Calendar.YEAR));
//System.out.println("月:"+calendar.get(Calendar.MONTH));
//System.out.println("日:"+calendar.get(Calendar.DATE));
//获得时分秒
//System.out.println("时:"+calendar.get(Calendar.HOUR_OF_DAY));
//System.out.println("分:"+calendar.get(Calendar.MINUTE));
//System.out.println("秒:"+calendar.get(Calendar.SECOND));
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
System.out.println(calendar.getTime().toLocaleString())
设置明日凌晨开始每隔1s打印当前时间:
Timer timer = new Timer();
//设置明日凌晨的时间
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DATE, 6);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
System.out.println(calendar.getTime().toLocaleString());
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(new Date().toLocaleString());
}
}, calendar.getTime(), 1000);
3.邮件
3.1邮件服务器
- 要在Internet上提供电子邮件功能,必须有专门的电子邮件服务器。例如现在Internet很多提供邮件服务的厂商:sina、sohu、163 , QQ等等他们都有自己的邮件服务器。
- 这些服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
- 邮件服务器,按照提供的服务类型,可以分为发送邮件的服务器和接收邮件的服务器。
3.2电子邮箱
电子邮箱(E-mail地址)的获得需要在邮件服务器上进行申请 ,确切地说,电子邮箱其实就是用户在邮件服务器上申请的一个帐户。用户在邮件服务器上申请了一个帐号后,邮件服务器就会为这个帐号分配一定的空间,用户从而可以使用这个帐号以及空间,发送电子邮件和保存别人发送过来的电子邮件。
就是在服务器开辟了一块空间
3.3协议
规定邮件数据的格式
3.3.1 SMTP协议-发邮件协议
全称为Simple Mail Transfer Protocol(简单邮件传输协议),它定义了邮件客户端软件与SMTP服务器之间、以及两台 SMTP服务器之间的通讯规则。
端口号:25.
3.3.2 POP3协议-收邮件协议
- 全称为Post Office Protocol(邮局协议),它定义了邮件客户端软件与POP3服务器的通讯规则。
- 端口号:110.
3.4.收发邮件的方式
浏览器(一般不用)
客户端(常用)eg:outlook(微软收费),foxmail(腾讯免费)
3.5.收发邮件的流程
3.6java语言发送邮件:(了解)
1.导入mail.jar
2.调用api
三个核心对象
session对象, 登录
message对象(设置收件人,设置主题,设置内容)
transport对象
三,思路分析
创建数据库, 实体
创建一个ServletContextListener, ===> 凌晨给过生日的人发邮件
创建一个定时任务:
任务:调用业务获得过生日的人(List)
什么时候开始: 凌晨
周期执行: 一天
编写Service
编写dao
获得过生日的人: 1990-10-18 select *from user where birthday like "%-?-?"
四,代码实现
创建数据库
create database web; use web; create table user( id int primary key auto_increment, username varchar(20), birthday date, email varchar(60) ); insert into user values(null,'zs','1990-10-18','zs@store.com'); insert into user values(null,'ls','1921-07-01','ls@store.com'); insert into user values(null,'liubei','221-11-18','sunquan@store.com');
实体
package com.cd.bean; public class User { private int id; private String username; private String birthday; private String email; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getBirthday() { return birthday; } public void setBirthday(String birthday) { this.birthday = birthday; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", birthday=" + birthday + ", email=" + email + "]"; } }
BirthdayLisener
package com.cd.web; import java.sql.SQLException; import java.util.List; import java.util.Timer; import java.util.TimerTask; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import com.cd.bean.User; import com.cd.service.UserService; import com.cd.utils.DateUtils; import com.cd.utils.MailUtils; public class BirthdayListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { try { System.out.println("服务器启动..."); Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { UserService userService = new UserService(); List<User> list; try { list = userService.getUsers(); for (User user : list) { System.out.println("当前过生日的人有:"+user.getUsername()); MailUtils.sendMail(user.getEmail(), "亲爱的会员,"+user.getUsername()+":生日快乐!"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, 5000,5000);// DateUtils.getDelayTime(), DateUtils.getOneDay() } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void contextDestroyed(ServletContextEvent sce) { } }