1.启动activemq服务端,并查看服务是否启动:
2.引入activemq依赖,配置消息生产者activemq信息:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>javax.jms-api</artifactId>
</dependency>
# 消息生产者配置信息
spring:
activemq:
broker-url: tcp://localhost:61616
user: admin
password: admin
in-memory: true
pool:
enabled: false
## 队列名称(查看activemq时队列名称会是这个),供生产者读取
messages:
queue: mail_queue
3.建立注册邮件消息生产者
package com.id0304.mq.producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import javax.jms.Destination;
import java.util.HashMap;
import java.util.Map;
//往消息服务推送邮件信息,消息队列生产者
@Service("registerMailboxProducer")
public class RegisterMailboxProducer {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
public void send(Destination destination, String json){
jmsMessagingTemplate.convertAndSend(destination,json);
}
}
4.调用生产者创建队列:
package com.id0304.manage.impl;
import com.alibaba.fastjson.JSONObject;
import com.id0304.constants.DBTableName;
import com.id0304.constants.MQInterfaceType;
import com.id0304.dao.UserDao;
import com.id0304.entity.UserEntity;
import com.id0304.manage.UserServiceManage;
import com.id0304.mq.producer.RegisterMailboxProducer;
import com.id0304.utils.DateUtils;
import com.id0304.utils.Md5Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.jms.Destination;
@Service
@Slf4j
public class UserServiceManageImpl implements UserServiceManage {
@Autowired
private UserDao userDao;
@Autowired
private RegisterMailboxProducer registerMailboxProducer;
//读取配置文件的队列名
@Value("${messages.queue}")
private String MESSAGES_QUEUE;
//注册服务
@Override
public void regist(UserEntity userEntity) {
userEntity.setCreated(DateUtils.getTimestamp());
userEntity.setUpdated(DateUtils.getTimestamp());
String password = userEntity.getPassword();
String phone = userEntity.getPhone();
userEntity.setPassword(MD5PasswordSalt(phone,password));
userDao.save(userEntity, DBTableName.TABLE_MB_USER);
//创建名为MESSAGES_QUEUE属性值的队列
Destination destination = new ActiveMQQueue(MESSAGES_QUEUE);
//组装报文格式得到一个json字符串,自定义报文方法mailMessage在下面
String mailMessage = mailMessage(userEntity.getEmail(),userEntity.getUsername());
//输出日志
log.info("###regist() 注册发送邮件报文mailMessage:{}",mailMessage);
//向ActiveMQ推送消息(指明消息目的名称和消息内容)
registerMailboxProducer.send(destination,mailMessage);
}
//组装自定义报文,根据实际情况自定义
/**
* 这里注意,我们是将一个json字符串存进了队列里作为自定义的消息队列报文,格式如下:
* "root" : {
* "header" : {
* //接口类型也是自定义的,这里定义了一个发送邮件的接口类型sms_mail,供消费者识别:
* "interfaceType" : "sms_mail"
* },
* "content" : {
* //消息体内容,即要传什么数据到队列里,这里传了email地址和用户名
* email : "",
* username : ""
* }
* }
* @param email
* @param username
* @return
*/
@Override
public String mailMessage(String email,String username){
JSONObject root = new JSONObject();
JSONObject header = new JSONObject();
header.put("interfaceType",MQInterfaceType.SMS_MAIL);
JSONObject content = new JSONObject();
content.put("mail",email);
content.put("username",username);
root.put("header",header);
root.put("content",content);
return root.toString();
}
}
5.调用这个接口,消息就会被推送到ActiveMQ:
这里队列有1个消息,消费者数为0,入队的有1个,出队数目为0:
6.接下来,我们来创建一个消费者来对这个消息进行消费:
由于消息服务也是一个较大的服务,所以单独提取出来作为一个工程,建立消息服务:
1) 配置消费者,注册该服务进eureka,集成邮件发送:
server:
port: 8763
context-path: /message
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: message
activemq:
broker-url: tcp://localhost:61616
user: admin
password: admin
in-memory: true
pool:
enabled: false
mail:
username: xxxx@qq.com
password: xxxx
host: smtp.qq.com
# qq邮箱要求ssl安全连接,这里需要开启ssl
properties:
mail.smtp.ssl.enable=true
2) 首先建立消费者适配器接口MessageAdapter,提高扩展性:
package com.id0304.adapter;
import com.alibaba.fastjson.JSONObject;
//所有消息都会交给他进行转发
//此后若要增加不同类型的消费者(短信,公众号推送等),可以进行拓展
public interface MessageAdapter {
//接受消息
public void distribute(JSONObject jsonObject);
}
3) 建立消费者服务SMSMailboxService继承MessageAdapter接口:
关于邮箱发送任务,详见我的另一篇博客:https://mp.csdn.net/mdeditor/90322248#
package com.id0304.service;
import com.alibaba.fastjson.JSONObject;
import com.id0304.adapter.MessageAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class SMSMailboxService implements MessageAdapter {
//集成发送邮件
@Autowired
private JavaMailSender mailSender; //自动注入bean
//这里需要传入一个消息体(包含mail和username)json对象content,完成邮箱发送服务,真正发送邮件的服务
@Override
public void distribute(JSONObject jsonObject) {
String username = jsonObject.getString("username"); //获取用户名
String mail = jsonObject.getString("mail"); //获取邮箱
log.info("###消费者收到消息...mail:{}",mail,username); //日志
//发送邮件
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("xxxx@qq.com");
message.setTo(mail);
message.setSubject("欢迎!!");
message.setText("欢迎注册!使用邮件任务...");
log.info("###发送短信邮箱:{}",mail);
mailSender.send(message);
}
}
4) 接下来创建接受并消费服务的方法ConsumerDistribute:
package com.id0304.mq.distribute;
import com.alibaba.fastjson.JSONObject;
import com.id0304.adapter.MessageAdapter;
import com.id0304.constants.MQInterfaceType;
import com.id0304.service.SMSMailboxService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
//消费消息mq 从队列获取最新消息
@Slf4j
@Component
public class ConsumerDistribute {
@Autowired
private SMSMailboxService smsMailboxService;
//监听消息队列,这里注意队列名要对上,方法参数是刚刚我们存进去的json字符串
@JmsListener(destination = "mail_queue")
public void distribute(String json){
log.info("###消息服务###收到消息,消息内容json:{}",json);
if(StringUtils.isEmpty(json)){ //判空
return;
}
//将json字符串转化为json对象
JSONObject jsonObject = new JSONObject().parseObject(json);
//获取json对象里的头信息(我们自定义的json报文格式)
JSONObject header = jsonObject.getJSONObject("header");
//获取json对象的接口信息
String interfaceType = header.getString("interfaceType");
//创建适配器,以下会根据消息类型判断使用哪个实现类,会实现实现该接口的distribute方法
MessageAdapter messageAdapter = null;
//判断接口类型(这里只写了一个邮箱,公众号推送等可以自行补充)
switch (interfaceType){
//根据消息类型是SMS_MAIL对应的属性值发送邮件
case MQInterfaceType.SMS_MAIL:
messageAdapter = smsMailboxService; //确定调用邮件发送实现类
break;
//...
default:
break;
}
//获得消息体内容(mail和username)
JSONObject content = jsonObject.getJSONObject("content");
//调用适配器的distribute方法,传入这个消息体对象
messageAdapter.distribute(content);
}
}
7.接下来,一旦开启了这个服务,就会一直监听消息队列,一旦有消息对应的消费者,消息就会有序地被消费,自动运行 @JmsListener(destination = “”)下对应的方法:
消息消费者加了1,出队的消息也加了1
邮件也被发送出去了: