不少項目, 都不是一個系統就作完了. 而是好多個系統, 相互協做來完成功能. 那, 系統與系統之間, 不可能徹底獨立吧?html
如: 在學校所用的管理系統中, 有學生系統, 資產系統, 宿舍系統等等. 當學期結束以後, 是否須要對已經結束的期次進行歸檔操做. 假如歸檔功能在學生系統中, 那點擊歸檔以後, 學生是否是還要關心宿舍那邊是否已結束, 學生所領資產是否全都歸還? spring
顯然, 這並非一個好的方式, 系統之間的耦合性作的太強了, 很不利於系統擴展, 並且, 一步操做, 可能要等好久好久, 才能完成. 用戶可願意等?apache
既然同步歸檔不可能了, 那是否有辦法實現異步歸檔? 異步歸檔怎麼實現呢?centos
咱們其實能夠經過消息隊列來實現異步歸檔. 學生這邊點擊歸檔後, 發個消息到隊列中, 其餘系統自行去讀取, 而後完成各自系統應該完成的工做.瀏覽器
下載地址: http://activemq.apache.org/download.htmlspringboot
安裝過程比較簡單, 在centos中, 解壓出來, 就算是安裝好了app
運行方法: 異步
運行起來後, 能夠經過 ip:8161 來查看是否成功. tcp
點擊紅框中的連接, 會出現登陸彈框, 帳號密碼默認都是admin.spring-boot
一. 目錄結構
producer : 消息生產者
consumer-a : 消息消費者
consumer-b : 消息消費者
pom文件:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency>
若是使用pool的話, 就須要在pom中加入如下依賴:
<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-pool</artifactId> <version>5.14.5</version> </dependency>
二. producer
1. 目錄結構
2. yml文件:
server: port: 8080 context-path: /pro spring: activemq: user: admin password: admin broker-url: tcp://192.168.153.129:61616 pool: enabled: true max-connections: 10 queueName: publish.queue topicName: publish.topic
這裏我開啓了鏈接池, 默認是不開的.
這裏要注意端口, 不是以前的8161.
2. 配置文件 ActiveMQConfig
/** * @author: elvin */ @Configuration public class ActiveMQConfig { @Value("${queueName}") private String queueName; @Value("${topicName}") private String topicName; @Value("${spring.activemq.user}") private String usrName; @Value("${spring.activemq.password}") private String password; @Value("${spring.activemq.broker-url}") private String brokerUrl; @Bean public Queue queue(){ return new ActiveMQQueue(queueName); } @Bean public Topic topic(){ return new ActiveMQTopic(topicName); } @Bean public ActiveMQConnectionFactory connectionFactory() { return new ActiveMQConnectionFactory(usrName, password, brokerUrl); } @Bean public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ActiveMQConnectionFactory connectionFactory){ DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory(); bean.setConnectionFactory(connectionFactory); return bean; } @Bean public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ActiveMQConnectionFactory connectionFactory){ DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
//設置爲發佈訂閱方式, 默認狀況下使用的生產消費者方式 bean.setPubSubDomain(true); bean.setConnectionFactory(connectionFactory); return bean; } }
這裏原本不須要配置這麼多的, 可是在consumer中也會用到, 因此就暫時弄一份同樣的, 拷貝一下完事.
3. PublishController
/** * @author: elvin */ @RestController @RequestMapping("/publish") public class PublishController { @Autowired private JmsMessagingTemplate jms; @Autowired private Queue queue; @Autowired private Topic topic; @RequestMapping("/queue") public String queue(){ for (int i = 0; i < 10 ; i++){ jms.convertAndSend(queue, "queue"+i); } return "queue 發送成功"; } @JmsListener(destination = "out.queue") public void consumerMsg(String msg){ System.out.println(msg); } @RequestMapping("/topic") public String topic(){ for (int i = 0; i < 10 ; i++){ jms.convertAndSend(topic, "topic"+i); } return "topic 發送成功"; } }
三. consumer
1. 目錄結構
a,b是同樣的, 只是顯示的信息不一樣.
2. 配置文件
yml配置文件是同樣的, 只是修改了端口和context-path.
ActiveMQConfig文件內容是同樣的.
3. listener
/** * @author: elvin */ @Component public class QueueListener { @JmsListener(destination = "publish.queue", containerFactory = "jmsListenerContainerQueue") @SendTo("out.queue") public String receive(String text){ System.out.println("QueueListener: consumer-a 收到一條信息: " + text); return "consumer-a received : " + text; } }
SendTo 會將此方法返回的數據, 寫入到 queue : out.queue 中去.
/** * @author: elvin */ @Component public class TopicListener { @JmsListener(destination = "publish.topic", containerFactory = "jmsListenerContainerTopic") public void receive(String text){ System.out.println("TopicListener: consumer-a 收到一條信息: " + text); } }
這裏經過傳入不一樣的factory, 來實現發送不一樣類型的信息.
四. 測試
1. queue測試
瀏覽器中訪問: http://localhost:8080/pro/publish/queue
而後看一下, 控制檯, 那些用戶接收到了信息.
從上兩幅圖看的出來, a, b並不能同時接收數據. 這是queue的方式, 點對點.
那我想點對面, 怎麼辦?
2. topic測試
瀏覽器訪問頁面: http://localhost:8080/pro/publish/topic
a用戶徹底接收到信息了. 再看看b用戶
沒毛病, 也都接收到數據了.
topic默認狀況下, 是不會保存數據的, 也就是說, consumer是接收不到以前未接收到的信息.
而queue倒是能夠的.
可是, topic並非不能實現那個功能, 只要配置一下, 仍是能夠的.