自定义事件分发,执行耗时操作服务

关于SpringMVC里面,进行自定义事件,分发处理耗时操作服务的示例解析

事件处理在spring的应用程序上下文(ApplicationContext )里面,是通过ApplicationEvent和ApplicationListener 实现的,spring本身的一些事件有ContextRefreshedEvent,ContextStartedEvent,ContextStoppedEvent, etc. 同时spring可以允许我们自定义事件,并进行事件的捕获及处理( 这种机制可以让我们做一些耗时操作的服务,或者消息服务之类的等),下面本人通过发送邮件服务对这个spring特性进行示例应用下。

1 . 首先自定义我们的邮件发送事件实体

package com.hisoka.applicationEvent;

import org.springframework.context.ApplicationEvent;

import com.hisoka.POJO.Email;


/**
 * EmailMonitorEvent.java
 * 
 * @author: Hinsteny
 * @date: 2015年11月25日
 * @copyright: 2015 All rights reserved.
 * 
 */
public class EmailMonitorEvent extends ApplicationEvent {

    /**
     * serialVersionUID
     * long
     */
    private static final long serialVersionUID = 7197120866146492975L;

    private final String sendAddress;
    private final Email email;

    public EmailMonitorEvent(Object source, String sendAddress, Email email) {
        super(source);
        this.sendAddress = sendAddress;
        this.email = email;
    }

    public String getSendAddress() {
        return sendAddress;
    }

    public Email getEmail() {
        return email;
    }

}

2 . 这里实现ApplicationEventPublisherAware,然后就可以触发并发布一个自定义事件

package com.hisoka.applicationEvent;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;

import com.hisoka.POJO.Email;
import com.hisoka.support.email.MailSender;


/**
 * EmailService.java
 * 
 * @author: Hinsteny
 * @date: 2015年11月25日
 * @copyright: 2015 All rights reserved.
 * 
 */
@Component
public class EmailService implements ApplicationEventPublisherAware {

    private Logger logger = LoggerFactory.getLogger(EmailService.class);

    @Autowired
    MailSender mailSender;//发送邮件的工具类

    private ApplicationEventPublisher publisher;


    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    public void sendEmail(String toAddress, String title, String content) {
        Email email = new Email();
        email.setTitle(title);
        email.setContent(content);
        email.setToAddress(toAddress);
        EmailMonitorEvent event = new EmailMonitorEvent(this, mailSender.getMailUser(), email);
        logger.debug("publish send email Event!");
        publisher.publishEvent(event);

        // other service

    }

}

3 . 然后实现ApplicationListener接口,即接收我们的自定义事件及处理事件

package com.hisoka.applicationEvent;

import java.io.IOException;

import javax.annotation.Resource;
import javax.mail.MessagingException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * EmailListNotifier.java
 * 
 * @author: Hinsteny
 * @date: 2015年11月25日
 * @copyright: 2015 All rights reserved.
 * 
 */
@Component
public class EmailListNotifier implements ApplicationListener<EmailMonitorEvent> {

    private Logger logger = LoggerFactory.getLogger(EmailListNotifier.class);

    @Resource
    private EmailJob emailJob;//发送邮件的服务类

    @Override
    public void onApplicationEvent(EmailMonitorEvent event) {
        try {
            logger.debug("Just do send email service!");
            emailJob.send(event.getEmail());
        } catch (MessagingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4 . 发送邮件的服务类代码

package com.hisoka.applicationEvent;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.mail.MessagingException;

import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.StringTemplateResourceLoader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import com.hisoka.POJO.Email;
import com.hisoka.support.email.MailSender;
import com.hisoka.utils.Strings;

/**
 * @author: Hinsteny
 * @date: 2015年11月25日
 * @copyright: 2015 All rights reserved.
 */
@Component
public class EmailJob {

    private static final String url = "email.tmpl";

    @Resource
    private MailSender mailSender;

    public void send(Email email) throws MessagingException, IOException {

        //邮件模板
        String emailTemplate = Strings.getContentFromInputStream(new ClassPathResource(url).getInputStream(),"utf-8");

        Map<String,Object> data = new HashMap<>();
        data.put("totalRegister", 15);

        StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader();
        Configuration cfg = Configuration.defaultConfiguration();
        GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
        Template t = gt.getTemplate(emailTemplate);
        t.binding(data);
        mailSender.send(email.getToAddress(), email.getTitle(), t.render());
    }

}

5 . 最后就是进行邮件发送的工具类

package com.hisoka.support.email;

import java.util.Date;
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.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.springframework.stereotype.Component;

import com.hisoka.support.config.Config;



/**
 * MailSender.java
 * 
 * @author: Hinsteny
 * @date: 2015年11月25日
 * @copyright: 2015 All rights reserved.
 * 
 */
@Component
public class MailSender {

    @Config("mail.user")
    private String mailUser;

    @Config("mail.password")
    private String mailPassword;

    @Config("mail.host")
    private String mailHost;

    public String getMailUser() {
        return mailUser;
    }

    public void setMailUser(String mailUser) {
        this.mailUser = mailUser;
    }

    public String getMailPassword() {
        return mailPassword;
    }

    public void setMailPassword(String mailPassword) {
        this.mailPassword = mailPassword;
    }

    public String getMailHost() {
        return mailHost;
    }

    public void setMailHost(String mailHost) {
        this.mailHost = mailHost;
    }


    /**
     * 邮件发送
     * 
     * @param receiver 接收邮箱
     * @param subject 主题
     * @param content 内容
     * @throws MessagingException
     */
    public void send(String receiver, String subject, String content) throws MessagingException {
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.host", mailHost);
        props.put("mail.debug", "true");

        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(mailUser, mailPassword);
            }
        });

        MimeMessage msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(mailUser));
        String[] arr = receiver.split(",|,");
        InternetAddress[] address = new InternetAddress[arr.length];
        for (int i = 0; i < arr.length; i++) {
            address[i] = new InternetAddress(arr[i]);
        }
        msg.addRecipients(Message.RecipientType.TO, address);
        msg.setSubject(subject);
        msg.setSentDate(new Date());
        msg.setContent(content, "text/html;charset=utf-8");
        Transport.send(msg);
    }

}

上面我们在实际应用中,一般请求一个服务 (譬如上面EmailService的sendEmail方法),假如我们的发送邮件是一个耗时的操作 (查一些邮件内容需要的数据,做数据库记录等),这里我们要是等到所有事情做完并发完邮件,那客户端等待的时间就比较长了 (或者说客户体验不好,哈哈),并且客户端不需要发送邮件服务返回什么数据,那我们在这里可以先给客户端返回,把真正的邮件发送服务安排到一个事件处理里面 (这里一般还可以用多线程的方式去处理),这样很明显对客户端的响应就快速,友好多了嘛

关于spring的自定义事件分发处理的介绍就到这了,后面再学习更多的spring特性,哈哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值