ActiveMQ
简介
ActiveMQ是Apache出品的,非常流行的消息中间件,可以说要掌握消息中间件,需要从ActiveMQ开始,要掌握更加强大的RocketMQ,也需要ActiveMQ的基础。
什么是消息中间件:
消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。
目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ。
安装使用
去官方网站官方网站:http://activemq.apache.org/ 下载相应的版本,解压安装简单方便。
在linux系统下,要将端口开放
验证:
打开浏览器,使用admin用户名和密码访问http://IP:8161/,看到下图即可证明安装成功。
Spring Boot整合ActiveMQ
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
代码中引入了ActiveMQ的starter,和activemq-pool是方便使用连接池机制,可以在application.properties配置ActiveMQ。
配置application.properties
# ActiveMQ地址
spring.activemq.broker-url=tcp://192.168.1.105:61616
# 用户名和密码
spring.activemq.user=admin
spring.activemq.password=admin
# 是否使用发布订阅模式,默认是false
spring.jms.pub-sub-domain=true
# 默认目的地址
spring.jms.template.default-destination=myDestination
# 线程池配置
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=50
# 为MQ添加所有包信任
spring.activemq.packages.trust-all=true
配置JMS连接
JmsConfig.java
@Configuration
public class JmsConfig {
@Value(value = "${spring.activemq.broker-url}")
private String url ;
@Value(value = "${spring.jms.template.default-destination}")
private String defaultDestination;
@Bean
ConnectionFactory connectionFactory() {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(url);
//MQ要想支持序列化对象,需将setTrustAllPackages设置为true
factory.setTrustAllPackages(true);
return factory;
}
@Bean
JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
jmsTemplate.setPriority(999);
return jmsTemplate;
}
@Bean(value="jmsMessagingTemplate")
JmsMessagingTemplate jmsMessagingTemplate(JmsTemplate jmsTemplate) {
JmsMessagingTemplate messagingTemplate = new JmsMessagingTemplate(jmsTemplate);
return messagingTemplate;
}
// 在Queue模式中,对消息的监听需要对containerFactory进行配置
@Bean("queueListener")
public JmsListenerContainerFactory<?> queueJmsListenerContainerFactory(ConnectionFactory connectionFactory){
SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(false);
return factory;
}
}
定义MQ服务接口以及实现
ActivemqService .java
@Service
public interface ActivemqService {
public void sendMsg(String msg);
public void receiveMsg(String msg);
}
ActivemqServiceImpl .java
@Service
public class ActivemqServiceImpl implements ActivemqService {
@Autowired
private JmsTemplate jmsTemplate = null;
@Override
public void sendMsg(String msg) {
System.out.println("send message[" + msg + "]");
jmsTemplate.convertAndSend("myDestination",msg);
}
@Override
//使用注解监听发送过来的消息
@JmsListener(destination = "${spring.jms.template.default-destination}",containerFactory = "queueListener")
public void receiveMsg(String msg) {
System.out.println("收到消息:" + msg + "]");
}
}
上述例子发送的只是字符串消息,非常普通,且在真实项目中,发送对象往往是POJO,所以再定义一个POJO类User,来演示对象消息的收发:
User.java
public class User implements Serializable {
private static final long serialVersionUID = 8081834232494242383L;
private Long id;
private String username;
private String note = null;
public User(Long id, String username, String note) {
this.id = id;
this.username = username;
this.note = note;
}
//get set toString ....
}
ActivemqUserService .java
@Service
public interface ActivemqUserService {
public void sendUser(User user);
public void receiveUser(User user);
}
ActivemqUserServiceImpl .java
@Service
public class ActivemqUserServiceImpl implements ActivemqUserService {
@Autowired
private JmsTemplate jmsTemplate = null;
private static final String myDestination = "my-destination";
@Override
public void sendUser(User user) {
System.out.println("send user [" + user + "]");
jmsTemplate.convertAndSend(myDestination,user);
}
@Override
@JmsListener(destination = myDestination,containerFactory = "queueListener")
public void receiveUser(User user) {
System.out.println("received user [" + user + "]");
}
}
验证并测试
添加控制器,来实现服务请求。
ActivemqController.java
@RestController
@RequestMapping("/activemq")
public class ActivemqController {
@Autowired
private ActivemqService activemqService;
@Autowired
private ActivemqUserService activemqUserService;
@GetMapping("/msg")
@ResponseBody
public Map<String,Object> msg(String message){
activemqService.sendMsg(message);
return result(true,message);
}
@ResponseBody
@GetMapping("/user")
public Map<String,Object> sendUser(Long id,String username,String note){
User user = new User(id,username,note);
activemqUserService.sendUser(user);
return result(true,user);
}
private Map<String,Object> result(Boolean success,Object message){
Map<String,Object> result = new HashMap<>();
result.put("success",success);
result.put("message",message);
return result;
}
}
启动springboot项目,查看没有报错后,使用postman分别对msg和user接口进行请求访问,并查看日志信息:
2020-06-25 16:49:42.864 INFO 1544 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-06-25 16:49:42.867 INFO 1544 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 3 ms
send message[helloworld]
收到消息:helloworld]
send user [User{id=1, username='xiaowang', note='hello'}]
received user [User{id=1, username='xiaowang', note='hello'}]
打开MQ的页面,查看定义的两个destination ,页面中显示都有1个Consumer ,查看Consumer 信息。