读书人

EJB系统施用JMS异步发送邮件

发布时间: 2012-12-24 10:43:14 作者: rapoo

EJB系统使用JMS异步发送邮件

EJB中有三种Bean,EntityBean,SessionBean,MessageBean,其中MessageBean就是用来发送消息的。
服务器:JBoss 4.2

EJB中支持两种类型的消息,一种是Topic,一种是Queue。
Topic:基于发布/订阅的方式,允许有多个接受者,消息生产者将消息发送到主题上,接受者必须先订阅该主题。
Queue:点对点的方式,只能被一个接受者接受一次,消息生产者把消息发送到队列中,不需订阅。

要在JBoss中使用JMS,需要配置一些文件
1.%JBOSS_HOME%\server\default\deploy 下mail-service.xml,该文件用于配置发送email的一些参数(例子中使用gmail服务器)

<?xml version="1.0" encoding="UTF-8"?><server>  <mbean code="org.jboss.mail.MailService"         name="jboss:service=Mail">    <attribute name="JNDIName">java:/Mail</attribute>    <attribute name="User">zoucailong</attribute>    <attribute name="Password">******</attribute>    <attribute name="Configuration">      <!-- A test configuration -->      <configuration>        <!-- Change to your mail server prototocol -->        <property name="mail.store.protocol" value="pop3"/>        <property name="mail.transport.protocol" value="smtp"/>        <!-- Change to the user who will receive mail  -->        <property name="mail.user" value="zoucailong"/>        <!-- Change to the mail server  -->        <property name="mail.pop3.host" value="pop3.gmail.com"/>        <!-- Change to the SMTP gateway server -->        <property name="mail.smtp.host" value="smtp.gmail.com"/><property name="mail.smtp.socketFactory.class" value="javax.net.ssl.SSLSocketFactory"/><property name="mail.smtp.socketFactory.fallback" value="false"/><property name="mail.smtp.auth" value="true"/>                <!-- The mail server port -->        <property name="mail.smtp.port" value="465"/>                <!-- Change to the address mail will be from  -->        <property name="mail.from" value="zoucailong@gmail.com"/>        <!-- Enable debugging output from the javamail classes -->        <property name="mail.debug" value="false"/>      </configuration>    </attribute>    <depends>jboss:service=Naming</depends>  </mbean></server>

如果邮件发送不成功,可以把"mail.debug"的值改为true调试。

2.%JBOSS_HOME%\server\default\deploy\jms 下jbossmq-destinations-service.xml,该文件用于配置Topic和Queue

<mbean code="org.jboss.mq.server.jmx.Topic" name="jboss.mq.destination:service=Topic,name=testTopic">    <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>    <depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>    <attribute name="SecurityConf">      <security>        <role name="guest" read="true" write="true"/>        <role name="publisher" read="true" write="true" create="false"/>        <role name="durpublisher" read="true" write="true" create="true"/>      </security>    </attribute>  </mbean>   <mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=fmQueue">    <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>    <depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>    <attribute name="MessageCounterHistoryDayLimit">-1</attribute>    <attribute name="SecurityConf">      <security>        <role name="guest" read="true" write="true"/>        <role name="publisher" read="true" write="true" create="false"/>        <role name="noacc" read="false" write="false" create="false"/>      </security>    </attribute>  </mbean>

启动JBoss,可以在控制台看到自己配置的Topic或Queue的名字。

?

定义一个实体,用来封装发送邮件所需要的参数,包括接收人邮件地址、主题、内容、附件地址等。

import java.io.Serializable;import java.util.Date;public class EmailEntity implements Serializable {    private static final long serialVersionUID = 3436776941158302904L;    private String from;     private String to;      private String subject;       private String content;    private String multiPartFile;    private Date sendDate;        public EmailEntity() {            }    public EmailEntity(String to, String subject, String content, String multiPartFile) {        this.to = to;        this.subject = subject;        this.content = content;        this.multiPartFile = multiPartFile;    }    public String getFrom() {        return from;    }    public void setFrom(String from) {        this.from = from;    }    public String getTo() {        return to;    }    public void setTo(String to) {        this.to = to;    }    public String getSubject() {        return subject;    }    public void setSubject(String subject) {        this.subject = subject;    }    public String getContent() {        return content;    }    public void setContent(String content) {        this.content = content;    }    public String getMultiPartFile() {        return multiPartFile;    }    public void setMultiPartFile(String multiPartFile) {        this.multiPartFile = multiPartFile;    }    public Date getSendDate() {        return sendDate;    }    public void setSendDate(Date sendDate) {        this.sendDate = sendDate;    }}

?

?

写一个Message Producer,一个普通的Java类,在这个类中使用到JMS的API

import java.util.Properties;import javax.jms.JMSException;import javax.jms.MessageProducer;import javax.jms.ObjectMessage;import javax.jms.Queue;import javax.jms.QueueConnection;import javax.jms.QueueConnectionFactory;import javax.jms.QueueSession;import javax.jms.Session;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import org.apache.log4j.Logger;public class MsgProducerService {        private static Logger logger = Logger.getLogger(MsgProducerService.class);        private static InitialContext context;    private static Queue queue;    private static QueueConnectionFactory connectionFactory;        private static InitialContext getInitialContext() throws NamingException {        if(context == null) {            Properties env = new Properties();            env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");            env.setProperty(Context.PROVIDER_URL, "localhost");            context = new InitialContext(env);        }        return context;    }        static {           try {            connectionFactory = (QueueConnectionFactory) getInitialContext().lookup("ConnectionFactory");            queue = (Queue) getInitialContext().lookup("queue/fmQueue");        } catch (NamingException e) {            e.printStackTrace();        }    }        public static void sendMail(EmailEntity emailEntity) {                QueueConnection connection = null;        QueueSession session = null;        MessageProducer producer;                try {            connection = connectionFactory.createQueueConnection();            session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);            producer = session.createProducer(queue);            ObjectMessage msg = session.createObjectMessage();            msg.setObject(emailEntity);            producer.send(msg);        } catch (JMSException e) {            logger.error("Send email error:"+e);            e.printStackTrace();        } finally {            try {                if(session != null)                    session.close();                if(connection != null)                    connection.close();            } catch (JMSException e) {                    e.printStackTrace();            }        }    }}

以上代码中,ObjectMessage根据你的消息类型而定,有
StreamMessage:一种主体中包含Java基本值流的消息。其填充和读取均按顺序进行。
MapMessage:一种主体中包含一组名-值对的消息。(没有定义条目顺序)
TextMessage:一种主体中包含Java字符串的消息(例如:XML消息)
ObjectMessage:一种主体中包含序列化Java对象的消息。
BytesMessage:一种主体中包含连续字节流的消息。

?

下面定义一个消息接受者,该类实现MessageListener接口,自动监听消息的状态,当有消息到达时,就会触发onMessage方法

import java.io.File;import java.util.Date;import javax.activation.DataHandler;import javax.activation.FileDataSource;import javax.ejb.ActivationConfigProperty;import javax.ejb.MessageDriven;import javax.jms.MessageListener;import javax.jms.ObjectMessage;import javax.mail.Message;import javax.mail.Multipart;import javax.mail.Session;import javax.mail.Transport;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;import javax.naming.Context;import javax.naming.InitialContext;//指定destination的类型和名字,以下用的是Queue,用到上面的配置文件中定义的fmQueue@MessageDriven(activationConfig ={        @ActivationConfigProperty(propertyName = "destinationType",                propertyValue = "javax.jms.Queue"),        @ActivationConfigProperty(propertyName = "destination",                propertyValue = "queue/fmQueue")})public class EmailBean implements MessageListener {    @Override    public void onMessage(javax.jms.Message msg) {        try {            if(msg != null && msg instanceof ObjectMessage) {                ObjectMessage objMsg = (ObjectMessage)msg;                EmailEntity emailEntity = (EmailEntity) objMsg.getObject();                sendMail(emailEntity);            }        } catch (Exception e) {            e.printStackTrace();        }    }            //发送邮件的方法    private void sendMail(EmailEntity emailEntity) throws Exception {        if(emailEntity == null)            return;                Context context = new InitialContext();        Session session = (Session) context.lookup("java:/Mail");        MimeMessage msg = new MimeMessage(session);        msg.setFrom();                if(emailEntity.getTo() != null && emailEntity.getTo().trim().length() > 0) {            String[] toArr = emailEntity.getTo().split(",");            if(toArr.length > 0) {                InternetAddress[] addressArr = new InternetAddress[toArr.length];                for(int i = 0; i < toArr.length; i++) {                    addressArr[i] = new InternetAddress(toArr[i]);                }                msg.addRecipients(Message.RecipientType.TO, addressArr);            }        }        if(emailEntity.getSubject() != null)            msg.setSubject(emailEntity.getSubject(), "UTF-8");                if(emailEntity.getMultiPartFile() != null) {            File file = new File(emailEntity.getMultiPartFile());            if(file.exists()) {//添加附件                Multipart multipart = new MimeMultipart();                MimeBodyPart bodyPart = new MimeBodyPart();                FileDataSource fds = new FileDataSource(emailEntity.getMultiPartFile());                bodyPart.setDataHandler(new DataHandler(fds));                bodyPart.setFileName(fds.getName());                multipart.addBodyPart(bodyPart);                                if(emailEntity.getContent() != null) {                    MimeBodyPart bodyPartText = new MimeBodyPart();                    bodyPartText.setText(emailEntity.getContent(), "UTF-8");                    multipart.addBodyPart(bodyPartText);                }                msg.setContent(multipart);            } else                return;        }                msg.setSentDate(new Date());        msg.saveChanges();        Transport.send(msg, msg.getRecipients(Message.RecipientType.TO));    }}

这样就可以实现邮件的异步发送了。

读书人网 >编程

热点推荐