`
bh三少
  • 浏览: 100932 次
  • 性别: Icon_minigender_1
  • 来自: 北海
社区版块
存档分类
最新评论

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));
    }
}

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

分享到:
评论

相关推荐

    WSAD环境下JMS异步通信全攻略

     3.1 使用JMS QueueConnection对象  3.2 处理回退事件  3.3 关闭JMS对象  3.4 接收消息  3.5 消息驱动的Bean  3.6 消息持久化  3.7 消息选择器 四、JMS Pub/Sub编程 五、二阶段提交的事务 ...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    第二部分详细讲解了jsf ri、jta、jndi、rmi、jms、javamail、ejb 3的session bean、message driven bean、jpa、jax-ws 2、jaas等java ee知识,这部分知识以jsf+ejb 3+jpa整合开发为重点,通过使用netbeans ide工具...

    J2EE EJB规范文档

    JMS是Java的消息服务,JMS的客户端之间可以通过JMS服务进行异步的消息传输。JMS支持两种消息模型:Point-to-Point(P2P)和Publish/Subscribe(Pub/Sub),即点对点和发布订阅模型。

    javaee7-jms-websocket-example:集成 JMS 2.0、WebSockets 1.0、CDI 事件和 EJB 3 的 Java EE 7 应用程序示例

    此应用程序演示了一个使用 WebSockets 和 JMS 的全双工场景,具有功能齐全的服务器端异步推送,使用 CDI 事件和 EJB。 此处记录了详细信息和分步操作: : 怎么跑 下载并安装 JDK 8 和 GlassFish 4.1。 在 NetBeans...

    MDB 消息驱动Bean

    MDB是处理通过JMS传递的消息的异步消息消费者。虽然MDB负责处理消息,但是由运行MDB的EJB容器负责处理服务(事务、安全、资源、并发、消息确认,等等),使bean开发者把精力集中在处理消息的业务逻辑上。传统的JMS...

    jboss seam

    为轻量化的异步性集成了EJB Timer Service和Quartz,为工作流集成了jBPM,为业务规则集成了JBoss规则,为电子邮件集成了Meldware Mail,为完整的文本搜索集成了Hibernate Search和Lucene,为消息集成了JMS,以及为...

    Spring中文帮助文档

    2.4.4. 异步的JMS 2.4.5. JDBC 2.5. Web层 2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持...

    Spring API

    2.4.4. 异步的JMS 2.4.5. JDBC 2.5. Web层 2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持...

    从Java走向Java+EE+.rar

    15.3.2 编写发送邮件的实例 223 15.3.3 编写接收邮件的实例 235 15.4 小结 241 第16章 基于良好设计模式的Spring 243 16.1 Spring简介 243 16.2 实例——用Spring来打招呼 246 16.3 小结 248 第17章 ...

    JBPM4工作流应用开始指南.rar

    209 10.3 如何在活动中调用EJB方法 214 10.4 使用jms活动 215 10.4.1 模拟JMS服务 217 10.4.2 JMS文本消息 219 10.4.3 JMS Object消息 220 10.4.4 JMS Map消息 222 10.5 历史会话监听链 223 10.6 自定义Web任务表单 ...

    JAVA上百实例源码以及开源项目

    6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...

    Spring 2.0 开发参考手册

    2.4.3. 异步的JMS 2.4.4. JDBC 2.5. Web层 2.5.1. Spring MVC的表单标签库 2.5.2. Spring MVC合理的默认值 2.5.3. Portlet 框架 2.6. 其他特性 2.6.1. 动态语言支持 2.6.2. JMX 2.6.3. 任务规划 2.6.4. 对...

    JAVA上百实例源码以及开源项目源代码

    6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...

    java 面试题 总结

    Stateless Session Bean 虽然也是逻辑组件,但是他却不负责记录使用者状态,也就是说当使用者呼叫 Stateless Session Bean 的时候,EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method...

    超级有影响力霸气的Java面试题大全文档

    Stateless Session Bean 虽然也是逻辑组件,但是他却不负责记录使用者状态,也就是说当使用者呼叫 Stateless Session Bean 的时候,EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method...

    spring chm文档

    2.4.3. 异步的JMS 2.4.4. JDBC 2.5. Web层 2.5.1. Spring MVC的表单标签库 2.5.2. Spring MVC合理的默认值 2.5.3. Portlet 框架 2.6. 其他特性 2.6.1. 动态语言支持 2.6.2. JMX 2.6.3. 任务规划 2.6.4. 对...

    Spring-Reference_zh_CN(Spring中文参考手册)

    2.4.3. 异步的JMS 2.4.4. JDBC 2.5. Web层 2.5.1. Spring MVC的表单标签库 2.5.2. Spring MVC合理的默认值 2.5.3. Portlet 框架 2.6. 其他特性 2.6.1. 动态语言支持 2.6.2. JMX 2.6 .3. 任务规划 2.6.4. 对Java 5...

    Mule是一个企业服务总线(ESB)消息框架

    3.支持任何传输之上的异步,同步和请求响应事件处理机制. 4.支持Axis或者Glue的Web Service. 5.灵活的部署结构[Topologies]包括Client/Server, P2P, ESB 和Enterprise Service Network. 6.与Spring 框架集成:可...

Global site tag (gtag.js) - Google Analytics