本指南将引导您完成使用 JMS 代理发布和订阅消息的过程。
您将构建什么
您将构建一个应用程序,该应用程序使用 Spring 发布单个消息,并使用托管 Bean 的注释方法订阅它。JmsTemplate@JmsListener
你需要什么
- 约15分钟
- 最喜欢的文本编辑器或 IDE
- JDK 1.8或以后
- 格拉德尔 4+或梅文 3.2+
- 您也可以将代码直接导入到 IDE 中:
- 弹簧工具套件 (STS)
- 智能理念
- VSCode
如何完成本指南
像大多数春天一样入门指南,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。无论哪种方式,您最终都会得到工作代码。
要从头开始,请继续[划痕].
要跳过基础知识,请执行以下操作:
- 下载并解压缩本指南的源存储库,或使用吉特:git clone https://github.com/spring-guides/gs-messaging-jms.git
- 光盘成gs-messaging-jms/initial
- 跳转到从 Spring 初始化开始.
完成后,您可以根据 中的代码检查结果。gs-messaging-jms/complete
从 Spring 初始化开始
你可以使用这个预初始化项目,然后单击生成以下载 ZIP 文件。此项目配置为适合本教程中的示例。
手动初始化项目:
如果您的 IDE 集成了 Spring Initializr,则可以从 IDE 完成此过程。
您也可以从 Github 分叉项目,然后在 IDE 或其他编辑器中打开它。
创建消息接收器
Spring 提供了将消息发布到任何 POJO(普通旧 Java 对象)的方法。
本指南描述如何通过 JMS 消息代理发送消息。首先,请创建包含电子邮件详细信息的简单 POJO。请注意,我们不会发送电子邮件。我们将详细信息从一个地方发送到另一个地方,以便在消息中发送什么。
src/main/java/hello/Email.java
package hello;public class Email { private String to; private String body; public Email() { } public Email(String to, String body) { this.to = to; this.body = body; } public String getTo() { return to; } public void setTo(String to) { this.to = to; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } @Override public String toString() { return String.format("Email{to=%s, body=%s}", getTo(), getBody()); }}这个 POJO 非常简单,包含两个字段(to 和 body),以及假定的 getter 和 setter 集合。
从这里,您可以定义消息接收器:
src/main/java/hello/Receiver.java
package hello;import org.springframework.jms.annotation.JmsListener;import org.springframework.stereotype.Component;@Componentpublic class Receiver { @JmsListener(destination = "mailbox", containerFactory = "myFactory") public void receiveMessage(Email email) { System.out.println("Received <" + email + ">"); }}Receiver也称为消息驱动的 POJO。如代码所示,无需实现任何特定接口或使方法具有任何特定名称。此外,该方法可能具有灵活的签名.特别要注意的是,此类没有导入 JMS API。
注释定义此方法应侦听的名称以及对用于创建基础消息侦听器容器的引用。严格来说,最后一个属性不是必需的,除非你需要自定义容器的构建方式,因为 Spring Boot 会在必要时注册默认工厂。JmsListenerDestinationJmsListenerContainerFactory
这参考文档更详细地介绍了这一点。
使用 Spring 发送和接收 JMS 消息
Next, wire up a sender and a receiver.
src/main/java/hello/Application.java
package hello;import jakarta.jms.ConnectionFactory;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.jms.annotation.EnableJms;import org.springframework.jms.config.DefaultJmsListenerContainerFactory;import org.springframework.jms.config.JmsListenerContainerFactory;import org.springframework.jms.core.JmsTemplate;import org.springframework.jms.support.converter.MappingJackson2MessageConverter;import org.springframework.jms.support.converter.MessageConverter;import org.springframework.jms.support.converter.MessageType;@SpringBootApplication@EnableJmspublic class Application { @Bean public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); // This provides all boot's default to this factory, including the message converter configurer.configure(factory, connectionFactory); // You could still override some of Boot's default if necessary. return factory; } @Bean // Serialize message content to json using TextMessage public MessageConverter jacksonJmsMessageConverter() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); converter.setTargetType(MessageType.TEXT); converter.setTypeIdPropertyName("_type"); return converter; } public static void main(String[] args) { // Launch the application ConfigurableApplicationContext context = SpringApplication.run(Application.class, args); JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); // Send a message with a POJO - the template reuse the message converter System.out.println("Sending an email message."); jmsTemplate.convertAndSend("mailbox", new Email("info@example.com", "Hello")); }}@SpringBootApplication是一个方便的注释,它添加了以下所有内容:
- @Configuration:将类标记为应用程序上下文的 Bean 定义源。
- @EnableAutoConfiguration:告诉 Spring 引导根据类路径设置、其他 bean 和各种属性设置开始添加 bean。例如,如果 在类路径上,则此注释会将应用程序标记为 Web 应用程序并激活关键行为,例如设置 .spring-webmvcDispatcherServlet
- @ComponentScan:告诉 Spring 在包中查找其他组件、配置和服务,让它找到控制器。hello
该方法使用 Spring Boot 的方法启动应用程序。您是否注意到没有一行 XML?也没有文件。此 Web 应用程序是 100% 纯 Java,您无需处理配置任何管道或基础结构。main()SpringApplication.run()web.xml
@EnableJms触发对使用 注释的方法的发现,在幕后创建消息侦听器容器。@JmsListener
为了清楚起见,我们还定义了一个在接收器注释中引用的 bean。因为我们使用 Spring Boot 提供的基础设施,所以它与 Spring Boot 默认创建的基础设施相同。myFactoryJmsListenerDefaultJmsListenerContainerFactoryConfigurerJmsMessageListenerContainer
默认值只能转换基本类型(如、、)、,而我们的不是故意的。我们希望使用 Jackson 并将内容序列化为 JSON 以文本格式(即作为 )。Spring 引导会检测到 的存在,并将其与默认值和由 创建的任何 相关联。MessageConverterStringMapSerializableEmailSerializableTextMessageMessageConverterJmsTemplateJmsListenerContainerFactoryDefaultJmsListenerContainerFactoryConfigurer
JmsTemplate使向 JMS 目标发送消息变得简单。在 runner 方法中,启动后,您可以使用 发送 POJO。由于我们的自定义已自动关联到它,因此仅在 a 中生成 JSON 文档。mainjmsTemplateEmailMessageConverterTextMessage
您看不到定义的两个 bean 是 和 。这些是由Spring Boot自动创建的。在这种情况下,ActiveMQ 代理以嵌入式方式运行。JmsTemplateConnectionFactory
默认情况下,Spring 引导会创建一个配置为JmsTemplate传输到队列通过设置为 .配置方式也相同。若要重写,请通过 Boot 的属性设置(在内部或通过设置环境变量)进行设置。然后确保接收容器具有相同的设置。pubSubDomainfalseJmsMessageListenerContainerspring.jms.isPubSubDomain=trueapplication.properties
Spring 可以直接通过它的方法接收消息,但这只能同步工作,这意味着它会阻塞。因此,我们建议您使用侦听器容器(例如基于缓存的连接工厂),以便可以异步使用消息并具有最大的连接效率。JmsTemplatereceiveDefaultMessageListenerContainer
构建可执行的 JAR
您可以使用 Gradle 或 Maven 从命令行运行应用程序。您还可以构建一个包含所有必需依赖项、类和资源的可执行 JAR 文件并运行该文件。通过构建可执行 jar,可以轻松地在整个开发生命周期中跨不同环境等将服务作为应用程序进行交付、版本控制和部署。
如果使用 Gradle,则可以使用 .或者,您可以使用 JAR 文件生成 JAR 文件,然后运行该文件,如下所示:./gradlew bootRun./gradlew build
java -jar build/libs/gs-messaging-jms-0.1.0.jar如果使用 Maven,则可以使用 运行应用程序。或者,您可以使用 JAR 文件生成 JAR 文件,然后运行该文件,如下所示:./mvnw spring-boot:run./mvnw clean package
java -jar target/gs-messaging-jms-0.1.0.jar此处描述的步骤将创建一个可运行的 JAR。你也可以构建经典 WAR 文件.
当它运行时,隐藏在所有日志记录中,您应该看到以下消息:
Sending an email message.Received <Email{to=info@example.com, body=Hello}>总结
祝贺!您已经开发了基于 JMS 的消息的发布者和使用者。