摘要:本文以一个非常简单的业务场景为例,即系统给用户发送通知邮件,来讲一讲如何构建简单的消息通信。实现生产者和消费者在这里生产者负责生成包含邮件收件人和内容等信息的消息并存入队列,而消费者则负责从这些信息中国生成邮件并发送出去。
前言
对于WEB系统,向用户发送邮件、短信、站内信等几乎是必备的基础功能,但这些任务相对于所见即所得的立即响应式的请求对实时性的要求并不高,同时任务处理的量还很大。在复杂多系统的情形下,还要考虑多个子系统的通信问题。无论是从实际业务需求还是从软件工程的设计角度出发,消息通信都有必要成为一个独立的模块。本文以一个非常简单的业务场景为例,即系统给用户发送通知邮件,来讲一讲如何构建简单的消息通信。
引入JMS在上一次的博客中我们讲述了消息队列,消息队列是消息通信系统的重要组成部分。J2EE为运行在jvm虚拟机上的程序间的通信早就制定了一套标准,也就是我们提到的JMS标准。但JMS并不涉及到具体实现,我们在本文中采用应用最为广泛的ActiveMQ为例。
首先我们需要在pom.xml中引入相关依赖。
配置JMS和ActiveMQorg.springframework spring-jms ${spring.version} org.apache.activemq activemq-core 5.7.0
然后我们要在ApplicationContext.xml文件中作出相关配置。
JMS简单应用配置
对于上文我们将一一解释:
ConnectionFactory:用于产生到JMS服务器的链接
targetConnectionFactory:真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供,在这里是ActiveMQ
JmsTemplate:实现消息发送的工具,由Spring提供
Destination:用来表示目的地的接口在ActiveMQ中实现了两种类型的Destination,一个是点对点的ActiveMQQueue,另一个就是支持订阅/发布模式的ActiveMQTopic。,没有任何方法定义,只是用来做一个标识而已。
实现生产者和消费者在这里生产者负责生成包含邮件收件人和内容等信息的消息并存入队列,而消费者则负责从这些信息中国生成邮件并发送出去。
生产者代码
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最简便的封装convertAndSend()发送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; } }
消费者代码
public class NotifyMessageListener implements MessageListener { private static Logger logger = LoggerFactory.getLogger(NotifyMessageListener.class); @Autowired(required = false) private MailService simpleMailService; /** * MessageListener回调函数. */ @Override public void onMessage(Message message) { try { MapMessage mapMessage = (MapMessage) message; // 打印消息详情 logger.info("UserName:{}, Email:{}", mapMessage.getString("userName"), mapMessage.getString("email")); // 发送邮件 if (simpleMailService != null) { simpleMailService.sendNotificationMail(mapMessage.getString("userName")); } } catch (Exception e) { logger.error("处理消息时发生异常.", 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; /**邮件内容**/ 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; /** * 发送纯文本的用户修改通知邮件. */ public void sendNotificationMail(String userName) { SimpleMailMessage msg = new SimpleMailMessage(); msg.setFrom("suemi94@qq.com"); msg.setTo("suemi994@gmail.com"); msg.setSubject("用户修改通知"); // 将用户名与当期日期格式化到邮件内容的字符串模板 String content = String.format(textTemplate, userName, new Date()); msg.setText(content); try { mailSender.send(msg); if (logger.isInfoEnabled()) { logger.info("纯文本邮件已发送至{}", StringUtils.join(msg.getTo(), ",")); } } catch (Exception e) { logger.error("发送邮件失败", e); } } /** * 同步发送邮件 * * @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");//发件人 helper.setTo(InternetAddress.parse(email.getAddress()));//收件人 helper.setReplyTo("suemi94@qq.com");//回复到 helper.setSubject(email.getSubject());//邮件主题 helper.setText(email.getContent(), true);//true表示设定html格式 mailSender.send(mime); } /** * Spring的MailSender. */ public void setMailSender(JavaMailSender mailSender) { this.mailSender = mailSender; } /** * 邮件内容的字符串模板. */ public void setTextTemplate(String textTemplate) { this.textTemplate = textTemplate; } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/64640.html
摘要:对于与而言,则可以看做是消息传递技术的一种衍生或封装。在生产者通知消费者时,传递的往往是消息或事件,而非生产者自身。通过消息路由,我们可以配置路由规则指定消息传递的路径,以及指定具体的消费者消费对应的生产者。采用和来进行远程对象的通讯。 消息模式 归根结底,企业应用系统就是对数据的处理,而对于一个拥有多个子系统的企业应用系统而言,它的基础支撑无疑就是对消息的处理。与对象不同,消息本质上...
摘要:微软的虽然引入了事件机制,可以在队列收到消息时触发事件,通知订阅者。由微软作为主要贡献者的,则对以及做了进一层包装,并能够很好地实现这一模式。 在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在Java领域中有很多可实现远程通讯的技术,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,这些名词之间到底是些什么关系呢,它们背后到底是基...
摘要:微软的虽然引入了事件机制,可以在队列收到消息时触发事件,通知订阅者。由微软作为主要贡献者的,则对以及做了进一层包装,并能够很好地实现这一模式。 在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在Java领域中有很多可实现远程通讯的技术,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,这些名词之间到底是些什么关系呢,它们背后到底是基...
摘要:而中的消息中间件则是在常见的消息中间件类型无疑是不错的选择。是在之间传递的消息的对象。基本功能是用于和面向消息的中间件相互通信的应用程序接口。支持两种消息发送和接收模型。一种称为模型,即采用点对点的方式发送消息。 消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。而Ja...
阅读 1536·2023-04-25 18:56
阅读 1483·2021-09-29 09:34
阅读 1708·2021-09-22 15:51
阅读 3482·2021-09-14 18:03
阅读 1159·2021-07-23 17:54
阅读 2017·2019-08-29 18:38
阅读 2899·2019-08-29 12:38
阅读 609·2019-08-26 13:41