简易的定时发送生日邮件功能(Listener+定时器+使用java发送邮件)

实现功能主要技术点:

Listener(监听器)

使用Java发送邮件(JavaMail的使用)

代码示例

创建web工程,写一个监听器监听ServletContext对象的创建(创建时机:启动服务器,部署该工程),ServletContext对象创建时,开启定时器查询数据库用户表中当天过生日的用户,使用封装的MailUtils工具类,给用户发送生日邮件。
在这里插入图片描述

  • BirthdayMailListener
/*
   ServletContextListener
   作用:监听ServletContext对象的创建与销毁
   扩展:
   servletcontext创建:启动服务器的时候
   servletContext销毁:关闭服务器. 从服务器移除项目
 */
@WebListener()
public class BirthdayMailListener implements ServletContextListener {
    /**
     * 监听ServletContext对象的创建
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("启动服务器,创建ServletContext执行");

        //实例化定时器对象
        Timer timer = new Timer();

        //得到定时器第一次执行的时间,如已过第一次执行的时间,则启动定时器时定时器任务就会执行一次
        String firstTimeStr="2020-02-22 10:00:00";
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date firstTime=null;
        try {
            firstTime = simpleDateFormat.parse(firstTimeStr);
            System.out.println("BirthdayMailListener firstTime"+firstTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        /*给定时器对象指派任务。
        参数说明:
		task:TimerTask接口,定时器任务对象,需要创建一个匿名内部类,把要执行的代码写在run方法里
		firstTime:第一次执行的时间,类型是Date
		period:任务执行的周期间隔,单位毫秒 。
         */
        timer.schedule(new TimerTask() {
            @Override
            public void run() {

                //调用业务逻辑层,得到今天过生日的用户
                UserService userService = new UserService();
                List<User> userList =userService.getBirthdayUsers();
                System.out.println("BirthdayMailListener userList"+userList);

                for (User user :userList) {
                    try {
                        MailUtils.sendMail(user.getEmail(),"生日邮件","祝您生日快乐!!!");
                        System.out.println("今天是"+user.getUsername()+"的生日,已给他/她发送了生日邮件");
                    } catch (MessagingException e) {
                        e.printStackTrace();
                    }
                }
            }
        },firstTime,24*60*60*1000);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}
  • UserService
public class UserService {
    public List<User> getBirthdayUsers() {
        List<User> birthdayUsers = null;
        try {
            //通过指定格式的SimpleDateFormat格式化Date对象,得到 月-日 (如:02-24)
            SimpleDateFormat simpleDateFormat=new SimpleDateFormat("MM-dd");
            String today = simpleDateFormat.format(new Date());
            System.out.println(today);

            //调用数据访问层,查询今天过生日的用户
            UserDao userDao=new UserDao();
            birthdayUsers = userDao.getBirthdayUsers(today);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return birthdayUsers;
    }
}
  • UserDao
public class UserDao {
    public List<User> getBirthdayUsers(String today) throws SQLException {

        QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());

        /*Mysql数据类型-日期和时间类型- DATE类型
        DATE类型用于仅需要日期值时。日期格式为 'YYYY-MM-DD',其中 YYYY 表示年,MM 表示月,DD 表示日。
        在业务逻辑层得到的today="02-24"
        */
        //使用LIKE的模糊查询
        String sql="select * from t_user where birthday like ?";
        //①要封装,则User类的属性名要与数据库的字段名相同。②百分号%是 MySQL中常用的一种通配符,在过滤条件中,百分号可以表示任何字符串。
        List<User> userList = queryRunner.query(sql, new BeanListHandler<User>(User.class), "%" + today);
        return userList;
    }

}

数据库中的部分用户表:

  • User
public class User {
    private String username;
    private Integer password;
    private String email;
    private Date birthday;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getPassword() {
        return password;
    }

    public void setPassword(Integer password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + username + '\'' +
                ", password=" + password +
                ", email='" + email + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

  • JDBCUtils
public class JDBCUtils {
    //使用Druid数据库连接池技术获取数据库连接
    private static DataSource createDataSource;
    static{
        try {
            Properties pros = new Properties();
//            InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            pros.load(is);
            createDataSource = DruidDataSourceFactory.createDataSource(pros);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection() throws SQLException {
        return createDataSource.getConnection();
    }

    public static DataSource getDataSource() throws SQLException {
        return createDataSource;
    }

    //使用dbutils.jar中提供的DbUtils工具类,实现资源的关闭
    public static void closeResource(Connection conn, Statement ps, ResultSet rs){
        DbUtils.closeQuietly(conn);
        DbUtils.closeQuietly(ps);
        DbUtils.closeQuietly(rs);
    }

    public static void closeResource(Connection conn){
        DbUtils.closeQuietly(conn);
    }

    public static void closeResource(Connection conn,ResultSet rs){
        DbUtils.closeQuietly(conn);
        DbUtils.closeQuietly(rs);
    }
}
  • MailUtils
/**
 * 发送邮件工具类
 */
public final class MailUtils {
	private MailUtils(){}
	/**
	 * 发送邮件
	 * @param email 收件人的邮箱地址
	 * @param subject 邮件主题
	 * @param 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.qq.com");//邮件发送服务器的地址(如QQ邮箱的发件服务器地址SMTP服务器: smtp.qq.com)
		props.setProperty("mail.smtp.auth", "true");//指定验证为true

		// 创建验证器
		Authenticator auth = new Authenticator() {
			public PasswordAuthentication getPasswordAuthentication() {
				//发件人的用户名(不带后缀的,如QQ邮箱的@qq.com不用写)和授权码(这里一般不使用密码,为避免密码泄露,用授权码代替密码登录第三方邮件客户端)
				//授权码:用于登录第三方邮件客户端的专用密码。  第三方邮件客户端:如这个java程序。
				return new PasswordAuthentication("QQ邮箱地址不带@qq.com", "开启POP3/SMTP服务得到的授权码");
			}
		};

		Session session = Session.getInstance(props, auth);

		
		// 2.[创建一封邮件]创建一个Message,它相当于是邮件内容
		Message message = new MimeMessage(session);
		message.setFrom(new InternetAddress("创建验证器时你用的用户名@qq.com")); // 设置发送者的邮箱地址
		message.setRecipient(RecipientType.TO, new InternetAddress(email)); // 设置发送方式与接收者
		message.setSubject(subject);//邮件主题
		message.setContent(emailMsg, "text/html;charset=utf-8");//设置邮件的内容

		// 3.[发送邮件]创建 Transport用于将邮件发送
		Transport.send(message);
	}
}

部署工程后,因已过第一次执行的时间,部署工程后就会启动定时器执行定时器任务一次,给当天生日用户发送生日邮件:
在这里插入图片描述

发布了48 篇原创文章 · 获赞 18 · 访问量 2943

猜你喜欢

转载自blog.csdn.net/qq_45615417/article/details/104476600