监听器Listener(二)

钝化和活化(HttpSessionActivationListener)

HttpSessionActivationListener作为JavaBean实现接口,当JavaBean添加到session中,钝化与活化都会被执行相应方法

配置以及如何触发

配置

<Context>
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="d:/session"/>
    </Manager>
</Context>

参数:

  • Manager —- tomcat内部对象专门进行对话工作,写死
  • maxIdleSwap —- session对象n分钟不用钝化到磁盘,n符号为分钟
  • Store —- tomcat提供存储功能的对象
  • directory —- Session对象钝化存储的路径

触发

钝化触发

客户端对服务器发送请求,服务器request.getSession()等待n分钟,期间不对服务器发起请求,触发Session钝化操作,序列化session对象存储到磁盘上

活化触发

客户端与服务器再次进行会话,服务器reqeust.getSession(),从硬盘获取序列化的session对象,并且取出

使用方式

  1. JavaBean类实现HttpSessionActivationListener以及序列化接口
  2. 编写钝化和活化(序列化和反序列化)方法
  3. 将其放置到session域中
  4. 测试

示例

JavaBean对象

package domain;

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
import java.util.Date;

public class Person1 implements Serializable, HttpSessionActivationListener {
    /**
     * 对象被序列化前执行的方法
     *
     * @param httpSessionEvent
     */
    @Override
    public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
        System.out.println(new Date() + "我被序列化了....");
    }

    /**
     * 对象被反序列化执行的方法
     *
     * @param httpSessionEvent
     */
    @Override
    public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
        System.out.println(new Date() + "我被反序列化了....");
    }
}

Servlet

import domain.Person1;

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(name = "ActivationListener", urlPatterns = "/ActivationListener")
public class ActivationListenerServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //        获取session,将实现了序列化与反序列化监听器的对象放置到session域中
        HttpSession session = request.getSession();
        session.setAttribute("demo",new Person1());
    }
}

代码运行演示

题目

当用户很多时,怎么样对服务器进行优化?
session的钝化与活化

电子邮件

发送邮件流程

配置环境

安装邮件服务器

eyoumailserversetup.exe

安装客户端软件

foxmail.exe

使用程序发送邮件

  1. 导入mail的jar包
  2. 使用发送邮件的工具类
  3. 配置工具类
  4. 编写代码发送邮件

配置工具类

  1. 设置发送邮件的服务器,设置发邮件协议
  2. 创建验证器,将发送邮件的服务器账户密码信息传入验证器
  3. 将设置的信息以及验证器对象传给判断连接成功标志对象的方法getInstance()
  4. 创建一个Message,用于发送邮件内容,分别设置发送对象、设置发送方式和接受者、设置邮件主题、设置编码邮件信息的方式
  5. 发送邮件
package Utils;

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 {

    /**
     * 工具类,用于发送邮件
     *
     * @param email    发送目标地址
     * @param emailMsg 发送邮件内容
     * @throws AddressException
     * @throws MessagingException
     */
    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", "localhost"); //发邮件的服务器地址,这里设置为本地
        props.setProperty("mail.smtp.auth", "true");// 指定验证为true

        // 创建验证器
        Authenticator auth = new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("lucy", "12345");
            }//发邮件的账号的验证
        };

        //        连接成功的标识
        Session session = Session.getInstance(props, auth);

        // 2.创建一个Message,它相当于是邮件内容
        Message message = new MimeMessage(session);

        message.setFrom(new InternetAddress("lucy@demo.com")); // 设置发送者

        message.setRecipient(RecipientType.TO, new InternetAddress(email)); // 设置发送方式与接收者

        message.setSubject(subject); //设置邮件主题
        // message.setText("这是一封激活邮件,请<a href='#'>点击</a>");

        message.setContent(emailMsg, "text/html;charset=utf-8");

        // 3.创建 Transport用于将邮件发送

        Transport.send(message);
    }
}

发送邮件

import Utils.MailUtils;
import javax.mail.MessagingException;

public class SendEmailDemo {
    public static void main(String[] args) throws MessagingException {
        MailUtils.sendMail("fy@demo.com", "小明是小鸡", "小明打不过小鸡");
    }
}

测试

测试平台为qq邮箱向qq邮箱发送邮件

重新编写工具类

package Utils;

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 {

    public static void sendMail(String email, String subject, String emailMsg,String senderEmail,String sslPWd)
            throws AddressException, MessagingException {

        // 1.创建一个程序与邮件服务器会话对象 Session
        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", "SMTP"); //发邮件协议
        props.setProperty("mail.host", "smtp.qq.com"); //发邮件的服务器地址,这里设置为本地
        props.setProperty("mail.smtp.auth", "true");// 指定验证为true
        props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.setProperty("mail.smtp.socketFactory.fallback", "false");
        props.setProperty("mail.smtp.port", "465");
        props.setProperty("mail.smtp.socketFactory.port", "465");

        // 创建验证器
        Authenticator auth = new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(senderEmail, sslPWd);
            }//发邮件的账号的验证
        };

        //        连接成功的标识
        Session session = Session.getInstance(props, auth);

        // 2.创建一个Message,它相当于是邮件内容
        Message message = new MimeMessage(session);

        message.setFrom(new InternetAddress(senderEmail)); // 设置发送者

        message.setRecipient(RecipientType.TO, new InternetAddress(email)); // 设置发送方式与接收者

        message.setSubject(subject); //设置邮件主题
        // message.setText("这是一封激活邮件,请<a href='#'>点击</a>");

        message.setContent(emailMsg, "text/html;charset=utf-8");

        // 3.创建 Transport用于将邮件发送

        Transport.send(message);
    }
}

运行

import Utils.MailUtils;

import javax.mail.MessagingException;

public class SendEmailDemo {
    public static void main(String[] args) throws MessagingException {
        MailUtils.sendMail("2269841094@qq.com", "小明是小鸡", "小明打不过小鸡","939902332@qq.com","vuuofnyftjvjbfdf");
    }
}

运行结果

案例

发送生日祝福的案例

步骤分析

  1. 编写ServletContext监听器
  2. 重写contextInitialized方法
  3. 编写模拟MySQL数据表,包含uname,uid,uemail,ubirthday,插入一个正确的user,以及一个干扰项
  4. 设置定时器,当服务器启动开始运行,进行查询数据库,模糊查询当天生日的用户集合,将集合返回给监听器,监听器执行任务,周期为1天

编写sql语句

# 创建数据库
CREATE DATABASE listener CHARACTER SET 'utf8';
USE listener;
# 创建表
CREATE TABLE user(
  uid INT PRIMARY KEY AUTO_INCREMENT,
  uusername VARCHAR(50),
  upassword VARCHAR(50),
  email VARCHAR(50),
  birthday VARCHAR(50)
)CHARACTER SET 'utf8';
# 插入数据
INSERT INTO user (uusername, upassword, email, birthday)VALUES (
    '小马哥',
  'feng',
  '2269841094@qq.com',
  '1995-04-23'
),(
    '小明',
  'xiaoming',
  '2760180314@qq.com',
  '1995-04-24'
),(
    '小花',
  'xiaohua',
  '2499433540@qq.com',
  '1995-04-30'
);

JavaBean对象

package com.company.domain;


public class User {
    /*
     *
     *   uid INT PRIMARY KEY AUTO_INCREMENT,
     *      uusername VARCHAR(50),
     *      upassword VARCHAR(50),
     *      email VARCHAR(50),
     *      birthday VARCHAR(50)
     * */


    private String uusername;
    private String upassword;
    private String email;
    private String birthday;
    private int uid;

    public String getUusername() {
        return uusername;
    }

    public void setUusername(String uusername) {
        this.uusername = uusername;
    }

    public String getUpassword() {
        return upassword;
    }

    public void setUpassword(String upassword) {
        this.upassword = upassword;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }
}

Email Utils工具

package Utils;

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 {

    public static void sendMail(String email, String subject, String emailMsg,String senderEmail,String sslPWd)
            throws AddressException, MessagingException {

        // 1.创建一个程序与邮件服务器会话对象 Session
        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", "SMTP"); //发邮件协议
        props.setProperty("mail.host", "smtp.qq.com"); //发邮件的服务器地址,这里设置为本地
        props.setProperty("mail.smtp.auth", "true");// 指定验证为true
        props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.setProperty("mail.smtp.socketFactory.fallback", "false");
        props.setProperty("mail.smtp.port", "465");
        props.setProperty("mail.smtp.socketFactory.port", "465");

        // 创建验证器
        Authenticator auth = new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(senderEmail, sslPWd);
            }//发邮件的账号的验证
        };

        //        连接成功的标识
        Session session = Session.getInstance(props, auth);

        // 2.创建一个Message,它相当于是邮件内容
        Message message = new MimeMessage(session);

        message.setFrom(new InternetAddress(senderEmail)); // 设置发送者

        message.setRecipient(RecipientType.TO, new InternetAddress(email)); // 设置发送方式与接收者

        message.setSubject(subject); //设置邮件主题
        // message.setText("这是一封激活邮件,请<a href='#'>点击</a>");

        message.setContent(emailMsg, "text/html;charset=utf-8");

        // 3.创建 Transport用于将邮件发送

        Transport.send(message);
    }
}

Dao与数据库交互

package com.company.dao;

import Utils.DbUTils;
import com.company.domain.User;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.List;

public class SendBIrthdayBlessingListenerDao {
    public List<User> getBirthdayPeoson(String format) throws SQLException {
        QueryRunner queryRunner = new QueryRunner(DbUTils.get_connection_pool());
        String sql = "SELECT * FROM user WHERE birthday LIKE ?";
        return queryRunner.query(sql, new BeanListHandler<>(User.class), "%" + format);
    }
}

ServletContextListener监听器

package birthday;

import Utils.MailUtils;
import com.company.dao.SendBIrthdayBlessingListenerDao;
import com.company.domain.User;
import javax.mail.MessagingException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

@WebListener()
public class SendBIrthdayBlessingListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

        //        设置定时器
        Timer timer = new Timer();

        timer.schedule(new TimerTask() {
            @Override
            public void run() {

                //                1.从数据库获取符合模糊查询的数据
                List<User> users = null;
                try {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd");
                    String format = dateFormat.format(new Date());
                    users = new SendBIrthdayBlessingListenerDao().getBirthdayPeoson(format);
                } catch (SQLException e) {
                    e.printStackTrace();
                }

                System.out.println("发送邮件");
                //                2.遍历集合,对用户发送邮件
                if (users!= null){
                    for (User user:users){
                        try {
                            MailUtils.sendMail(user.getEmail(),"生日快乐!","生日快乐啊 ","939902332@qq.com","ozrmgjeevcwfbeej");
                        } catch (MessagingException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }, new Date(), 1000*60*60*24);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

结果

从服务器启动开始,一天周期进行发送邮件任务,以当天时间向数据库进行模糊查询,生日为当天的发送邮件给对方。