如何在spring boot中实现jms队列

Mar*_*iou 8 jms spring-jms spring-boot

我使用初始化程序创建了一个Spring Boot项目,我正在尝试创建我的第一条消息,但我不知道从哪里开始.我熟悉使用JEE的相同过程,所以我想我需要创建一个工厂,一个发件人和一个消费者.

有人可以帮我吗?

Ale*_*NIS 14

最好的起点是项目入门指南

一般来说,你的方法是正确的,但他就是骨架的样子.

第一个spring-boot为你提供了一个完美的配置文件结构,如果你使用像Netbeans这样的智能设备,那么通过添加spring-boot插件,你也可以在属性文件中自动完成.由于Spring对每个代理的作用有点不同,在我的例子中我将使用ActiveMQ

通过在构建路径上安装ActiveMQ,Spring Boot将自动设置ActiveMQ代理.我们需要设置一些属性,使其成为内存代理,而不需要连接池.我们可以通过为Spring Boot设置两个属性来实现.

spring.activemq.in-memory=true
spring.activemq.pooled=false
jms.bookmgrqueue.name=book-mgr-queue #queue name
Run Code Online (Sandbox Code Playgroud)

其他经纪人也可以进行类似的配置.

首先,您从Spring应用程序的设置开始.您应该放置@EnableJms注释以启用Jms支持,然后设置新队列.

@EnableJms
@Configuration
public class JmsConfiguration {

    @Autowired
    private BeanFactory springContextBeanFactory;

    @Bean
    public DefaultJmsListenerContainerFactory containerFactory(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setDestinationResolver(new BeanFactoryDestinationResolver(springContextBeanFactory));
        factory.setConcurrency("3-10");
        return factory;
    }

    @Bean
    public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) throws JMSException {
        return new JmsTemplate(connectionFactory);
    }

}
Run Code Online (Sandbox Code Playgroud)

收听队列消息

监听器组件(BookMgrQueueListener.java)使用@JmsListener带有选择器的Spring 注释来读取具有给定Operation头的消息.

@Component
public class BookMgrQueueListener implements Loggable{

    private final BookService bookService;

    @Autowired
    public BookMgrQueueListener(BookService bookService) {
        this.bookService = bookService;
    }

    @JmsListener(containerFactory = "containerFactory",
                 destination = "bookMgrQueueDestination",
                 selector = "Operation = 'Create'")
    public void processCreateBookMessage(BookDTO book) throws JMSException{
        bookService.createNew(book);
    }

    @JmsListener(containerFactory = "containerFactory",
                 destination = "bookMgrQueueDestination",
                 selector = "Operation = 'Update'")
    public void processUpdateBookMessage(BookDTO book) throws JMSException{
        bookService.update(book.getIsbn(), book);
    }

    @JmsListener(containerFactory = "containerFactory",
                 destination = "bookMgrQueueDestination",
                 selector = "Operation = 'Delete'")
    public void processDeleteBookMessage(BookDTO book) throws JMSException{
        bookService.delete(book.getIsbn());
    }

}
Run Code Online (Sandbox Code Playgroud)

用于测试的活动MQ

为了测试配置,我们在新配置文件ActiveMqConfiguration.java中设置activeMq代理.

@Configuration
public class ActiveMqConfiguration {

    public static final String ADDRESS = "vm://localhost";

    private BrokerService broker;

    @Bean(name="bookMgrQueueDestination")
    public Destination bookMgrQueueDestination(@Value("${jms.bookmgrqueue.name}") String bookMgrQueueName)
            throws JMSException {
        return new ActiveMQQueue(bookMgrQueueName);
    }

    @PostConstruct
    public void startActiveMQ() throws Exception {
        broker = new BrokerService();
        // configure the broker
        broker.setBrokerName("activemq-broker");
        broker.setDataDirectory("target");
        broker.addConnector(ADDRESS);
        broker.setUseJmx(false);
        broker.setUseShutdownHook(false);
        broker.start();
    }

    @PreDestroy
    public void stopActiveMQ() throws Exception {
        broker.stop();
    }

    @Bean
    public ConnectionFactory connectionFactory() {
        return new ActiveMQConnectionFactory(ADDRESS + "?broker.persistent=false");
    }
}
Run Code Online (Sandbox Code Playgroud)

我们在测试用例中设置了一个完整的应用程序上下文,但我们正在将侦听器中的BookService引用替换为MockedBookService,我们将使用它来验证是否执行了正确的调用.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
@WebAppConfiguration
public class BookMgrQueueListenerIntegrationTest {

    @Autowired(required = false)
    private JmsTemplate jmsTemplate;

    @Autowired
    private BookMgrQueueListener bookMgrQueueListener;


    @Autowired(required = false)
    @Qualifier("bookMgrQueueDestination")
    private Destination bookMgrQueueDestination;

    @Mock
    private BookService mockBookService;

    @Captor
    private ArgumentCaptor<BookDTO> bookArgumentCaptor;

    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
        ReflectionTestUtils.setField(bookMgrQueueListener, "bookService", mockBookService);
    }

    /* ... tests */
}
Run Code Online (Sandbox Code Playgroud)

最后,我们为所有操作添加测试,并验证是否使用正确的操作和参数调用了服务层.

/* ... */
public class BookMgrQueueListenerIntegrationTest {
    /* ... */
    @Test
    public void testSendCreateBookMessage(){
        BookDTO book =  new BookDTO("isbn", "title", "author");
        jmsTemplate.convertAndSend(bookMgrQueueDestination, book, Message -> {
            return OperationHeader.CREATE.applyToMessage(Message);
        });
        // verify
        verify(mockBookService).createNew(bookArgumentCaptor.capture());
        assertEquals(book.getIsbn(), bookArgumentCaptor.getValue().getIsbn());
        assertEquals(book.getTitle(), bookArgumentCaptor.getValue().getTitle());
        assertEquals(book.getAuthor(), bookArgumentCaptor.getValue().getAuthor());
    }

    @Test
    public void testSendUpdateBookMessage(){
        BookDTO book =  new BookDTO("isbn", "title", "author");
        jmsTemplate.convertAndSend(bookMgrQueueDestination, book, Message -> {
            return OperationHeader.UPDATE.applyToMessage(Message);
        });
        // verify
        verify(mockBookService).update(eq(book.getIsbn()), bookArgumentCaptor.capture());
        assertEquals(book.getIsbn(), bookArgumentCaptor.getValue().getIsbn());
        assertEquals(book.getTitle(),bookArgumentCaptor.getValue().getTitle());
        assertEquals(book.getAuthor(),bookArgumentCaptor.getValue().getAuthor());
    }

    @Test
    public void testSendDeleteBookMessage(){
        BookDTO book =  new BookDTO("isbn", "title", "author");
        jmsTemplate.convertAndSend(bookMgrQueueDestination, book, Message -> {
            return OperationHeader.DELETE.applyToMessage(Message);
        });
        // verify
        verify(mockBookService).delete(book.getIsbn());
    }
Run Code Online (Sandbox Code Playgroud)

我们很高兴去!

引用将JMS队列集成到Spring应用程序中

  • 非常感谢!这非常有帮助! (3认同)
  • 很好的答案和参考。只是警告那些想要使用jmslistener批注的方法在Bean上使用Mockito.spy():间谍阻止了它实际在队列上侦听。 (2认同)