专栏首页Java帮帮-微信公众号-技术文章全总结Web-第十七天 监听器Listener【悟空教程】

Web-第十七天 监听器Listener【悟空教程】

Web-第十七天 监听器Listener【悟空教程】

监听器Listener

今日内容介绍

  • 案例:使用监听器完成定时发送生日祝福邮件

今日内容学习目标

  • 了解监听器执行原理
  • 阐述WEB开发中使用到8种监听器
  • 了解邮件协议
  • 了解Java程序发送邮件

第1章 案例:使用监听器发送生日祝福邮件

1.1 需求

当我们使用QQ时,在生日当天会收到QQ系统发送的祝福邮件。今天我们将实现相同的功能。

1.2 相关知识点

1.2.1 监听器Listener

1.2.1.1 概述

  • 什么是监听器
    • 所谓的监听器是指对整个WEB环境的监听,当被监视的对象发生改变时,立即调用相应的方法进行处理。
  • 监听器最常见的应用场景:
    • Java SE GUI编程
    • Android 手机开发编程
  • 监听器术语:
    • 1.事件源:被监听对象。(目标对象)
    • 2.监听器对象:用于监听“事件源”的对象
    • 3.注册(绑定):将“监听器对象”注册给“事件源”。当“事件源”发生某些行为时,监听对象将被执行。
    • 4.事件:事件源行为的称呼。
    • 5.事件对象:在“监听器对象”中获得“事件源”.
  • 监听器的编写流程
    • 1. 编写监听器实现类,需要实现指定的接口
    • 2. 在web.xml文件配置监听器(部分监听不需要配置)

<listener>

<listener-class></listener-class>

</listener>

  • JavaEE规范规定了8个监听器接口,用于监听不同的WEB对象。
    • 监听域对象创建与销毁
    • 监听域对象属性变更(添加,替换,删除)
    • 监听session作用域特殊Javabean

王医生告诉你——幼儿保健的锦囊妙计

作者:王红 著

当当 广告

购买

1.2.1.2 域对象本身

  • ServletRequest对象监听

ServletRequestListener

监听Request对象创建或销毁javax.servlet.ServletRequestListener

request创建方法* 请求开始创建

requestInitialized(ServletRequestEvent sre)

request销毁方法* 请求结束时销毁

requestDestroyed(ServletRequestEvent sre)

事件对象

ServletRequestEventl ServletContext getServletContext() l ServletRequest getServletRequest()

  • HttpSession对象监听

HttpSessionListener

监听Session对象创建或销毁javax.servlet.http.HttpSessionListener

session创建方法* 第一个调用getSession()

sessionCreated(HttpSessionEvent se)

session销毁方法1. 默认30分钟,web.xml可配置2. 执行api手动销毁,invalidate()3. 服务器非正常关闭

sessionDestroyed(HttpSessionEvent se)

事件对象

HttpSessionEventl getSession() 获得session

  • ServletContext对象监听

ServletContextListener

监听ServletContext对象创建或销毁javax.servlet.ServletContextListener

ServletContext创建方法* 服务器启动时

contextInitialized(ServletContextEvent sce)

ServletContext销毁方法* 服务器正常关闭时

contextDestroyed(ServletContextEvent sce)

事件对象

ServletContextEventl ServletContext getServletContext()

1.2.1.3 域对象属性

作用域属性操作:setAttribute(k,v) / getAttribute(k) / removeAttribute(k)

  • request作用域属性

ServletRequestAttributeListener

监听request对象属性attribute 添加、替换、删除javax.servlet.ServletRequestAttributeListener

添加* 第一次设置数据

attributeAdded(ServletRequestAttributeEvent srae)

替换* 第二次设置数据-- 通过event 获得old数据,如果希望获得new数据,需要request.getAttriubute 获得

attributeReplaced(ServletRequestAttributeEvent srae)

删除

attributeRemoved(ServletRequestAttributeEvent srae)

事件对象

ServletRequestAttributeEventl getName() l getValue() l getServletContext() l getServletRequest()

  • session作用域属性

HttpSessionAttributeListener

监听session对象属性attribute 添加、替换、删除javax.servlet.http.HttpSessionAttributeListener

添加

attributeAdded(HttpSessionBindingEvent event)

替换

attributeReplaced(HttpSessionBindingEvent event)

删除

attributeRemoved(HttpSessionBindingEvent event)

事件对象

HttpSessionBindingEvent l getName() l getValue() l getSession()

  • 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>。

  • 绑定和解绑:实现指定接口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进行监听。

  • 钝化和活化

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.NotSerializableException2. 持久化session数据到指定的位置: %tomcat%\work\Catalina\localhost\项目名称\SESSIONS.ser

1.2.1.5 使用

  • 步骤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) {

}

}

  • 步骤2:在web.xml注册监听器

<!-- 配置系统初始化参数 -->

<context-param>

<param-name>contextLocation</param-name>

<param-value>/my2.xml</param-value>

</context-param>

  • 步骤3:在web.xml配置全局初始化参数

<!-- 配置监听器 -->

<listener>

<listener-class>

cn.com.javahelp.web.servlet.PathServletContextListener

</listener-class>

</listener>

1.2.2 电子邮件

1.2.2.1 概述

  • 邮件服务器:
    • 要在Internet上提供电子邮件功能,必须有专门的电子邮件服务器。例如现在Internet很多提供邮件服务的厂商:sina、sohu、163等等他们都有自己的邮件服务器。
    • 这些服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
    • 邮件服务器,按照提供的服务类型,可以分为发送邮件的服务器我接收邮件的服务器。
  • 电子邮箱:
    • 电子邮箱(E-mail地址)的获得需要在邮件服务器上进行申请 ,确切地说,电子邮箱其实就是用户在邮件服务器上申请的一个帐户。用户在邮件服务器上申请了一个帐号后,邮件服务器就会为这个帐号分配一定的空间,用户从而可以使用这个帐号以及空间,发送电子邮件和保存别人发送过来的电子邮件。

1.2.2.2 邮件协议

  • SMTP协议-发邮件协议
    • 全称为Simple Mail Transfer Protocol(简单邮件传输协议),它定义了邮件客户端软件与SMTP服务器之间、以及两台SMTP服务器之间的通讯规则。
    • 端口号:25.
    • POP3协议-收邮件协议
    • 全称为Post Office Protocol(邮局协议),它定义了邮件客户端软件与POP3服务器的通讯规则。
    • 端口号:110.

1.2.2.3 发送邮件流程

1.2.2.4 使用JavaMail发送邮件

  • 导入jar包:
  • 编写实现:

/* 邮件发送过程

* * smtp协议:邮件发送协议,端口号:25

* * pop3协议:邮件接收协议,端口号:110

* 使用java程序发送邮件,采用smtp协议。java提供 javamail用于发送邮件的,代码固定

* 126 --> javahelp@126.com //账号不存在,需要自己注册

* 163 --> javahelp@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("javahelp","123456");

}

};

//1 与126服务器建立连接:Session

Session session = Session.getDefaultInstance(props, authenticator);

//2 编写邮件:Message

Message message = new MimeMessage(session);

//2.1 发件人(模拟账号)

message.setFrom(new InternetAddress("javahelp@126.com"));

//2.2 收件人 , to:收件人 , cc :抄送,bcc:暗送(密送)。(模拟账号)

message.setRecipient(RecipientType.TO, new InternetAddress("javahelp@163.com"));

//2.3 主题

message.setSubject("这是我们得第一份邮件");

//2.4 内容

message.setContent("哈哈,您到我的商城注册了。", "text/html;charset=UTF-8");

//3 将消息进行发送:Transport

Transport.send(message);

}

1.2.2.5 搭建本地环境

  • 安装邮件服务器
  • 安装客户端软件
  • 参考:

1.2.3 定时器

  • 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 案例实现

  • 步骤1:导入jar包
  • 步骤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','javahelp_lt@163.com');

insert t_user(username,birthday,email) values('rose','2015-12-12','javahelp_lt@163.com');

insert t_user(username,birthday,email) values('tom','2015-12-12','javahelp_lt@163.com');

  • 步骤3:导入JdbcUtils和c3p0配置文件
  • 步骤4:编写监听器

//实现类

public class SendMailListener implements ServletContextListener {

public void contextInitialized(ServletContextEvent sce) {

}

public void contextDestroyed(ServletContextEvent sce) {

}

}

//web.xml配置内容

<listener>

<listener-class>cn.com.javahelp.web.listener.SendMailListener</listener-class>

</listener>

  • 步骤5:导入时间工具类(了解)
  • 步骤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毫秒执行

}

  • 步骤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;

  • 步骤8:编写service

public class UserService {

/**

* 查询当天过生日的用户

* @return

* @throws SQLException

*/

public List<User> findAllWithBirthday() throws SQLException {

UserDao userDao = new UserDao();

return userDao.findAllWithBirthday();

}

}

  • 步骤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);

}

}

本文分享自微信公众号 - Java帮帮(javahelp)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-07-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Docker2 docker commit方法镜像制作

    Java帮帮
  • Java虚拟机内存模型【小白版】

    同样的java代码在不同平台生成的机器码肯定是不一样的,因为不同的操作系统底层的硬件指令集是不同的。

    Java帮帮
  • Java企业面试——SSH框架

    SSH框架阶段SSH的优缺点,使用场景? Hibernate优点: (1) 对象/关系数据库映射(ORM) 它使用时只需要操纵对象,使开发更对象化,抛弃了数据...

    Java帮帮
  • 谁是最好的Coder

    输入数据有多组。 输入一个数n,代表计科班的总人数。 接下来有n行数,一行数有两个数a,b。 其中a代表该同学的编程水平,b代表该同学的帅气程度。 n=0表示输...

    书童小二
  • Windows 独立启动方式安装 Archiva

    你可以将安装文件拷贝到任何你希望运行的目录中,下面的步骤中。我们没有将 Archiva 安装成服务,所以你需要通过控制台的方式来进行启动。

    HoneyMoose
  • 文件上传413 错误解决办法

    可以选择在http{ }中设置:client_max_body_size 20m;

    ITer.996
  • 0571-5.16.1-Redhat7的CDH集群外配置Kerberos环境SUSE12的Gateway节点

    在前面的文章中,Fayson介绍过非Kerberos环境下跨操作系统的Gateway节点配置,参考《0567-6.1.0-非Kerberos环境下集群外跨操作系...

    Fayson
  • 优步中国将对司机进行面部识别认证

    据科技资讯网站The Verge(www.theverge.com)报道,优步公司将对中国司机实施面部识别认证。 这一举措旨在减少司机共用帐户或使用假帐户的行为...

    人工智能快报
  • 字节码文件的内部结构之谜

    如果计算机的 CPU 只有「x86」这一种,或者操作系统只有 Windows 这一类,那么或许 Java 就不会诞生。Java 诞生之初就曾宣扬过它的初衷,「一...

    Single
  • TensorFlow 聊天机器人

    上一次提到了不错的学习聊天机器人的资源,不知道小伙伴们有没有去学习呢。 自己动手做聊天机器人教程 我最近每天都会学一点,拿出解读来和大家分享一下。 本文结...

    MachineLP

扫码关注云+社区

领取腾讯云代金券