摘要:本文以一個(gè)非常簡(jiǎn)單的業(yè)務(wù)場(chǎng)景為例,即系統(tǒng)給用戶發(fā)送通知郵件,來講一講如何構(gòu)建簡(jiǎn)單的消息通信。實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者在這里生產(chǎn)者負(fù)責(zé)生成包含郵件收件人和內(nèi)容等信息的消息并存入隊(duì)列,而消費(fèi)者則負(fù)責(zé)從這些信息中國(guó)生成郵件并發(fā)送出去。
前言
對(duì)于WEB系統(tǒng),向用戶發(fā)送郵件、短信、站內(nèi)信等幾乎是必備的基礎(chǔ)功能,但這些任務(wù)相對(duì)于所見即所得的立即響應(yīng)式的請(qǐng)求對(duì)實(shí)時(shí)性的要求并不高,同時(shí)任務(wù)處理的量還很大。在復(fù)雜多系統(tǒng)的情形下,還要考慮多個(gè)子系統(tǒng)的通信問題。無論是從實(shí)際業(yè)務(wù)需求還是從軟件工程的設(shè)計(jì)角度出發(fā),消息通信都有必要成為一個(gè)獨(dú)立的模塊。本文以一個(gè)非常簡(jiǎn)單的業(yè)務(wù)場(chǎng)景為例,即系統(tǒng)給用戶發(fā)送通知郵件,來講一講如何構(gòu)建簡(jiǎn)單的消息通信。
引入JMS在上一次的博客中我們講述了消息隊(duì)列,消息隊(duì)列是消息通信系統(tǒng)的重要組成部分。J2EE為運(yùn)行在jvm虛擬機(jī)上的程序間的通信早就制定了一套標(biāo)準(zhǔn),也就是我們提到的JMS標(biāo)準(zhǔn)。但JMS并不涉及到具體實(shí)現(xiàn),我們?cè)诒疚闹胁捎脩?yīng)用最為廣泛的ActiveMQ為例。
首先我們需要在pom.xml中引入相關(guān)依賴。
配置JMS和ActiveMQorg.springframework spring-jms ${spring.version} org.apache.activemq activemq-core 5.7.0
然后我們要在ApplicationContext.xml文件中作出相關(guān)配置。
JMS簡(jiǎn)單應(yīng)用配置
對(duì)于上文我們將一一解釋:
ConnectionFactory:用于產(chǎn)生到JMS服務(wù)器的鏈接
targetConnectionFactory:真正可以產(chǎn)生Connection的ConnectionFactory,由對(duì)應(yīng)的 JMS服務(wù)廠商提供,在這里是ActiveMQ
JmsTemplate:實(shí)現(xiàn)消息發(fā)送的工具,由Spring提供
Destination:用來表示目的地的接口在ActiveMQ中實(shí)現(xiàn)了兩種類型的Destination,一個(gè)是點(diǎn)對(duì)點(diǎn)的ActiveMQQueue,另一個(gè)就是支持訂閱/發(fā)布模式的ActiveMQTopic。,沒有任何方法定義,只是用來做一個(gè)標(biāo)識(shí)而已。
實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者在這里生產(chǎn)者負(fù)責(zé)生成包含郵件收件人和內(nèi)容等信息的消息并存入隊(duì)列,而消費(fèi)者則負(fù)責(zé)從這些信息中國(guó)生成郵件并發(fā)送出去。
生產(chǎn)者代碼
public class NotifyMessageProducer { private JmsTemplate jmsTemplate; private Destination notifyQueue; private Destination notifyTopic; public void sendQueue(final User user) { sendMessage(user, notifyQueue); } public void sendTopic(final User user) { sendMessage(user, notifyTopic); } /** * 使用jmsTemplate最簡(jiǎn)便的封裝convertAndSend()發(fā)送Map類型的消息. */ private void sendMessage(User user, Destination destination) { Map map = new HashMap(); map.put("userName", user.getName()); map.put("email", user.getEmail()); jmsTemplate.convertAndSend(destination, map); } public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void setNotifyQueue(Destination notifyQueue) { this.notifyQueue = notifyQueue; } public void setNotifyTopic(Destination nodifyTopic) { this.notifyTopic = nodifyTopic; } }
消費(fèi)者代碼
public class NotifyMessageListener implements MessageListener { private static Logger logger = LoggerFactory.getLogger(NotifyMessageListener.class); @Autowired(required = false) private MailService simpleMailService; /** * MessageListener回調(diào)函數(shù). */ @Override public void onMessage(Message message) { try { MapMessage mapMessage = (MapMessage) message; // 打印消息詳情 logger.info("UserName:{}, Email:{}", mapMessage.getString("userName"), mapMessage.getString("email")); // 發(fā)送郵件 if (simpleMailService != null) { simpleMailService.sendNotificationMail(mapMessage.getString("userName")); } } catch (Exception e) { logger.error("處理消息時(shí)發(fā)生異常.", e); } } }
郵件模型
public class ApplicationEmail implements Serializable { public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getCc() { return cc; } public void setCc(String cc) { this.cc = cc; } 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; } /**收件人**/ private String address; /**抄送給**/ private String cc; /**郵件主題**/ private String subject; /**郵件內(nèi)容**/ private String content; /**附件**/ //private MultipartFile[] attachment = new MultipartFile[0]; }
郵件幫助類(此處采用了java mail依賴包)
public class MailService { private static Logger logger = LoggerFactory.getLogger(MailService.class); private JavaMailSender mailSender; private String textTemplate; /** * 發(fā)送純文本的用戶修改通知郵件. */ public void sendNotificationMail(String userName) { SimpleMailMessage msg = new SimpleMailMessage(); msg.setFrom("suemi94@qq.com"); msg.setTo("suemi994@gmail.com"); msg.setSubject("用戶修改通知"); // 將用戶名與當(dāng)期日期格式化到郵件內(nèi)容的字符串模板 String content = String.format(textTemplate, userName, new Date()); msg.setText(content); try { mailSender.send(msg); if (logger.isInfoEnabled()) { logger.info("純文本郵件已發(fā)送至{}", StringUtils.join(msg.getTo(), ",")); } } catch (Exception e) { logger.error("發(fā)送郵件失敗", e); } } /** * 同步發(fā)送郵件 * * @param email * @throws MessagingException * @throws IOException */ public void sendMailBySynchronizationMode(ApplicationEmail email) throws MessagingException, IOException { Session session=Session.getDefaultInstance(new Properties()); MimeMessage mime= new MimeMessage(session); MimeMessageHelper helper = new MimeMessageHelper(mime, true, "utf-8"); helper.setFrom("suemi94@qq.com");//發(fā)件人 helper.setTo(InternetAddress.parse(email.getAddress()));//收件人 helper.setReplyTo("suemi94@qq.com");//回復(fù)到 helper.setSubject(email.getSubject());//郵件主題 helper.setText(email.getContent(), true);//true表示設(shè)定html格式 mailSender.send(mime); } /** * Spring的MailSender. */ public void setMailSender(JavaMailSender mailSender) { this.mailSender = mailSender; } /** * 郵件內(nèi)容的字符串模板. */ public void setTextTemplate(String textTemplate) { this.textTemplate = textTemplate; } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/64640.html
摘要:對(duì)于與而言,則可以看做是消息傳遞技術(shù)的一種衍生或封裝。在生產(chǎn)者通知消費(fèi)者時(shí),傳遞的往往是消息或事件,而非生產(chǎn)者自身。通過消息路由,我們可以配置路由規(guī)則指定消息傳遞的路徑,以及指定具體的消費(fèi)者消費(fèi)對(duì)應(yīng)的生產(chǎn)者。采用和來進(jìn)行遠(yuǎn)程對(duì)象的通訊。 消息模式 歸根結(jié)底,企業(yè)應(yīng)用系統(tǒng)就是對(duì)數(shù)據(jù)的處理,而對(duì)于一個(gè)擁有多個(gè)子系統(tǒng)的企業(yè)應(yīng)用系統(tǒng)而言,它的基礎(chǔ)支撐無疑就是對(duì)消息的處理。與對(duì)象不同,消息本質(zhì)上...
摘要:微軟的雖然引入了事件機(jī)制,可以在隊(duì)列收到消息時(shí)觸發(fā)事件,通知訂閱者。由微軟作為主要貢獻(xiàn)者的,則對(duì)以及做了進(jìn)一層包裝,并能夠很好地實(shí)現(xiàn)這一模式。 在分布式服務(wù)框架中,一個(gè)最基礎(chǔ)的問題就是遠(yuǎn)程服務(wù)是怎么通訊的,在Java領(lǐng)域中有很多可實(shí)現(xiàn)遠(yuǎn)程通訊的技術(shù),例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關(guān)系呢,它們背后到底是基...
摘要:微軟的雖然引入了事件機(jī)制,可以在隊(duì)列收到消息時(shí)觸發(fā)事件,通知訂閱者。由微軟作為主要貢獻(xiàn)者的,則對(duì)以及做了進(jìn)一層包裝,并能夠很好地實(shí)現(xiàn)這一模式。 在分布式服務(wù)框架中,一個(gè)最基礎(chǔ)的問題就是遠(yuǎn)程服務(wù)是怎么通訊的,在Java領(lǐng)域中有很多可實(shí)現(xiàn)遠(yuǎn)程通訊的技術(shù),例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關(guān)系呢,它們背后到底是基...
摘要:而中的消息中間件則是在常見的消息中間件類型無疑是不錯(cuò)的選擇。是在之間傳遞的消息的對(duì)象。基本功能是用于和面向消息的中間件相互通信的應(yīng)用程序接口。支持兩種消息發(fā)送和接收模型。一種稱為模型,即采用點(diǎn)對(duì)點(diǎn)的方式發(fā)送消息。 消息中間件利用高效可靠的消息傳遞機(jī)制進(jìn)行平臺(tái)無關(guān)的數(shù)據(jù)交流,并基于數(shù)據(jù)通信來進(jìn)行分布式系統(tǒng)的集成。通過提供消息傳遞和消息排隊(duì)模型,它可以在分布式環(huán)境下擴(kuò)展進(jìn)程間的通信。而Ja...
閱讀 1537·2023-04-25 18:56
閱讀 1484·2021-09-29 09:34
閱讀 1710·2021-09-22 15:51
閱讀 3483·2021-09-14 18:03
閱讀 1160·2021-07-23 17:54
閱讀 2018·2019-08-29 18:38
閱讀 2900·2019-08-29 12:38
閱讀 610·2019-08-26 13:41