发送邮件及消息中间件

邮件发送过程

协议:规定了数据传输的格式。

工具类

/**
 *
 * @param to            : 邮件接收者
 * @param subject       :主题
 * @param content       :邮件正文
 * @throws Exception
 */
public static void sendMsg(String to ,String subject ,String content) throws Exception{
   //1.发送邮件设置
   Properties props = new Properties();
   props.setProperty("mail.smtp.host", "smtp.sina.com");  //设置主机地址   smtp.qq.com    smtp.sina.com
   props.setProperty("mail.smtp.auth", "true");//认证

   //2.产生一个用于邮件发送的Session对象
   Session session = Session.getInstance(props);

   //3.产生一个邮件的消息对象
   MimeMessage message = new MimeMessage(session);

   //4.设置消息的发送者
   Address fromAddr = new InternetAddress("004@sina.com");
   message.setFrom(fromAddr);

   //5.设置消息的接收者
   Address toAddr = new InternetAddress(to);
   //TO 直接发送  CC抄送    BCC密送
   message.setRecipient(MimeMessage.RecipientType.TO, toAddr);

   //6.设置主题
   message.setSubject(subject);
   //7.设置正文
   message.setText(content);

   //8.准备发送,得到火箭
   Transport transport = session.getTransport("smtp");
   //9.设置火箭的发射目标
   transport.connect("smtp.sina.com", "004@sina.com", "loveyou");
   //10.发送
   transport.sendMessage(message, message.getAllRecipients());

   //11.关闭
   transport.close();
}

新增用户发送邮件

/**
 * 新增用户
 *      1.获取表单数据构造user对象
 *      2.添加对应的企业属性
 * 更新用户
 */
@RequestMapping(value = "/edit" , name = "编辑用户")
public String edit(User user) {
   user.setCompanyId(companyId);
   user.setCompanyName(companyName);
   //1.判断是否具有id属性
   if(UtilFuns.isEmpty(user.getId())) {
      String password = user.getPassword();
      //2.没有id,保存
      userService.save(user);
      //发送邮件
      try{
         MailUtil.sendMsg(user.getEmail(),"恭喜申请成功","尊敬的xxx用户您好:欢迎加入xxxxx,您的登录账号为:"+
               user.getEmail()+",登录密码为:"+password);//接收者,主体,正文
      }catch (Exception e) {
         e.printStackTrace();
      }
   }else{
      //3.具有id,更新
      userService.update(user);
   }
   return "redirect:/system/user/list.do";
}

消息中间件

概述

消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,
它可以在分布式环境下扩展进程间的通信。消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,
实现高性能,高可用,可伸缩和最终一致性架构。 对于消息中间件,常见的角色大致也就有 Producer(生产者)、Consumer(消费者)。

常见消息中间件

常见的消息中间件产品:
(1 )ActiveMQ
ActiveMQ 是 Apache 出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持 JMS1.1 和J2EE 1.4 规范的 JMS Provider 实现。
(2)RabbitMQ
AMQP 协议的领导实现,支持多种场景。淘宝的 MySQL 集群内部有使用它进行通讯,OpenStack 开源云平台的通信组件,最先在金融行业得到运用。
(3)ZeroMQ
史上最快的消息队列系统
(4)Kafka
Apache 下的一个子项目 。特点:高吞吐,在一台普通的服务器上既可以达到 10W/s 的吞吐速率;完全的分布式系统。适合处理海量数据。

消息的两种模式

ActiveMQ

软件安装

绿色版解压即可

spring整合ActiveMQ

消息生产者

引入坐标

<properties>
    <spring.version>5.0.2.RELEASE</spring.version>
</properties>

<dependencies>
    <!-- Spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-all</artifactId>
        <version>5.11.2</version>
    </dependency>
    <dependency>
        <groupId>javax.jms</groupId>
        <artifactId>javax.jms-api</artifactId>
        <version>2.0.1</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd">

<context:component-scan base-package="cn.jia"></context:component-scan>

<!--
spring和activeMq整合:通过整合JmsTemplate对象进行消息发送
-->
<!--1.连接工厂-->
<bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://127.0.0.1:61616"></property>
</bean>
<!--2.spring管理连接工厂-->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="activeMQConnectionFactory"></property>
</bean>
<!--3.指定目的地址:queue或者topic-->
<bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
<!--value:表示在activeMQ中创建的列表名称-->
<constructor-arg value="test-spring-queue"></constructor-arg>
</bean>
<!--4.通过连接工厂创建jmstemplate-->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>

<!--3.指定目的地址:queue或者topic-->
<bean id="topic" class="org.apache.activemq.command.ActiveMQTopic">
<!--value:表示在activeMQ中创建的列表名称-->
<constructor-arg value="test-spring-topic"></constructor-arg>
</bean>
</beans>

消息提供者java代码

@Component
public class ActivemqProducer {

    @Autowired
    private Destination queue; //注入queue

    @Autowired
    private Destination topic; //注入topic

    @Autowired
    private JmsTemplate jmsTemplate; //注入工具类

    public void sendQueue(final String msg){
        //参数1:表示消息要传递到哪个队列中   参数2:消息创建器对象
        jmsTemplate.send(queue, new MessageCreator() {
            //session:消息对象
            public Message createMessage(Session session) throws JMSException {
                //创建一个字符串类型消息
                TextMessage textMessage = session.createTextMessage(msg);
                return textMessage;
            }
        });
    }

    public void sendTopic(final String msg){
        //参数1:表示消息要传递到哪个队列中   参数2:消息创建器对象
        jmsTemplate.send(topic, new MessageCreator() {
            //session:消息对象
            public Message createMessage(Session session) throws JMSException {
                //创建一个字符串类型消息
                TextMessage textMessage = session.createTextMessage(msg);
                return textMessage;
            }
        });
    }
}

测试

// @RunWith(SpringJUnit4ClassRunner.class)
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:applicationContext-jms.xml")
public class TestActiveMq {


    @Autowired
    private ActivemqProducer activemqProducer;

    @Test
    //测试queue
    public void test1(){
        activemqProducer.sendQueue("hello123");
    }

    @Test
    //测试topic
    public void test2(){
        activemqProducer.sendTopic("hello tom");
    }
}

消息消费者

配置文件

 <context:component-scan base-package="cn.jia"></context:component-scan>

    <!--
        spring和activeMq整合:通过整合JmsTemplate对象进行消息发送
    -->
    <!--1.连接工厂-->
    <bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://127.0.0.1:61616"></property>
    </bean>
    <!--2.spring管理连接工厂-->
    <bean id="connectionFactory"  class="org.springframework.jms.connection.CachingConnectionFactory">
        <property name="targetConnectionFactory" ref="activeMQConnectionFactory"></property>
    </bean>

    <!--告知消费者业务类,去哪个队列中获取消息-->
    <!--配置监听器管理器
       配置的都是基于queue类型的消息监听    -->
    <jms:listener-container destination-type="queue" connection-factory="connectionFactory">
        <jms:listener destination="test-spring-queue" ref="activeMqConsumer"/>
    </jms:listener-container>

    <!--告知消费者业务类,去哪个队列中获取消息-->
    <!--配置监听器管理器
       配置的都是基于topic类型的消息监听    -->
    <jms:listener-container destination-type="topic" connection-factory="connectionFactory">
        <jms:listener destination="test-spring-topic" ref="activeMqTopicConsumer"/>
    </jms:listener-container>

</beans>

web.xml配置监听器

   <!-- 监听器监听其他的spring配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext-jms.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

测试

@Component
public class ActiveMqConsumer implements MessageListener{


    public void onMessage(Message message) {
        //把消息类型转换成字符串类型消息
        TextMessage textMessage = (TextMessage) message;
        try {
            //输出消息
            System.out.println("Queue: "+textMessage.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}
@Component
public class ActiveMqTopicConsumer implements MessageListener {

    public void onMessage(Message message) {
        //把消息类型转换成字符串类型消息
        TextMessage textMessage = (TextMessage) message;
        try {
            //输出消息
            System.out.println("Topic: "+textMessage.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

改造邮件发送

引入坐标

  <!--activeMq-->
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
            <version>${activemq.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.jms</groupId>
            <artifactId>javax.jms-api</artifactId>
            <version>2.0.1</version>
        </dependency>

      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jms</artifactId>
      <version>${spring.version}</version>
      </dependency>

编写配置

哪个发邮件在哪编写配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:amq="http://activemq.apache.org/schema/core"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/jms
        http://www.springframework.org/schema/jms/spring-jms.xsd
        http://activemq.apache.org/schema/core
        http://activemq.apache.org/schema/core/activemq-core.xsd">

   <!-- <context:component-scan base-package="cn.jia"></context:component-scan>-->

    <!--
        spring和activeMq整合:通过整合JmsTemplate对象进行消息发送
    -->
    <!--1.连接工厂-->
    <bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://127.0.0.1:61616"></property>
    </bean>
    <!--2.spring管理连接工厂-->
    <bean id="connectionFactory"  class="org.springframework.jms.connection.CachingConnectionFactory">
        <property name="targetConnectionFactory" ref="activeMQConnectionFactory"></property>
    </bean>
    <!--3.指定目的地址:queue或者topic-->
    <bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
        <!--value:表示在activeMQ中创建的列表名称-->
        <constructor-arg value="email-queue"></constructor-arg>
    </bean>
    <!--4.通过连接工厂创建jmstemplate-->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory"></property>
    </bean>

</beans>

service实现类

 @Autowired
    private Destination queue; //点对点消息模型

    @Autowired
    private JmsTemplate jmsTemplate;

    public void save(User user) {
        String pwd = user.getPassword();
        //1、保存用户
        user.setId(UUID.randomUUID().toString());
        user.setPassword(Encrypt.md5(user.getPassword(),user.getEmail()));
        userDao.save(user);

        //2、给用户发送邮件
        jmsTemplate.send(queue, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                MapMessage mapMessage = session.createMapMessage();
                mapMessage.setStringProperty("to",user.getEmail());
                mapMessage.setStringProperty("subject","xxx邮件");
                mapMessage.setStringProperty("content","欢迎您加入xxx有限公司!您的账号为:"+user.getEmail()+",初始密码是:"+pwd);
                return mapMessage;
            }
        });

    /*try {
    MailUtil.sendMsg(user.getEmail(),"xxx邮件","欢迎您加入xxx有限公司!您的账号为:"+user.getEmail()+",初始密码是:"+pwd);
    } catch (Exception e) {
    e.printStackTrace();
     }*/

新建消费者模块

引入坐标(父工程已有)

依赖common里的发送邮件的工具类

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:amq="http://activemq.apache.org/schema/core"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/jms
        http://www.springframework.org/schema/jms/spring-jms.xsd
        http://activemq.apache.org/schema/core
        http://activemq.apache.org/schema/core/activemq-core.xsd">

    <context:component-scan base-package="cn.jia"></context:component-scan>

    <!--
        spring和activeMq整合:通过整合JmsTemplate对象进行消息发送
    -->
    <!--1.连接工厂-->
    <bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://127.0.0.1:61616"></property>
    </bean>
    <!--2.spring管理连接工厂-->
    <bean id="connectionFactory"  class="org.springframework.jms.connection.CachingConnectionFactory">
        <property name="targetConnectionFactory" ref="activeMQConnectionFactory"></property>
    </bean>

    <!--告知消费者业务类,去哪个队列中获取消息-->
    <!--配置监听器管理器
       配置的都是基于queue类型的消息监听    -->
    <jms:listener-container destination-type="queue" connection-factory="connectionFactory">
        <jms:listener destination="email-queue" ref="emailListener"/>
    </jms:listener-container>



</beans>

web.xml配置监听器

    <!-- 监听器监听其他的spring配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext-jms.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

emailListener

@Component
public class EmailListener implements MessageListener{
    //参数:队列中的消息对象
    public void onMessage(Message message) {
        try {
            //1、获取消息数据
            MapMessage mapMessage = (MapMessage) message;
            String to = mapMessage.getStringProperty("to");
            String subject = mapMessage.getStringProperty("subject");
            String content = mapMessage.getStringProperty("content");
            //2、发送邮件
            MailUtil.sendMsg(to,subject,content);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

 

posted @ 2019-07-20 14:25  MonstersU  阅读(777)  评论(0编辑  收藏  举报