Springboot集成activeMQ接收发送对象报错问题及解决方法
activeMQ接收发送对象报错问题及解决方法
报错信息:
org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.test.openapi.workshop.service.listeners.QueueConsumerListener.readEmptyContainerActiveQueue(java.lang.Object) throws javax.jms.JMSException' threw exception; nested exception is javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: Forbidden class com.test.openapi.repository.model.dto.EmptyContainerGateOutDTO! This class is not trusted to be serialized as ObjectMessage payload. Please take a look at http://activemq.apache.org/objectmessage.html for more information on how to configure trusted classes.
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:122)
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:77)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674)
at org.springframework.jms.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:645)
at org.springframework.jms.listener.SimpleMessageListenerContainer.processMessage(SimpleMessageListenerContainer.java:345)
at org.springframework.jms.listener.SimpleMessageListenerContainer.lambda$createListenerConsumer$2(SimpleMessageListenerContainer.java:322)
at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1404)
at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131)
at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202)
at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:133)
at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:48)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
代码:
@Configuration
public class ActiveMqBeanConfig {
@Value("${spring.activemq.broker-url}")
private String brokerUrl;
@Value("${spring.activemq.user}")
private String username;
@Value("${spring.activemq.password}")
private String password;
@Value("${spring.activemq.queue-name-empty}")
private String emptyQueue;
@Value("${spring.activemq.queue-name-full}")
private String fullQueue;
@Value("${spring.activemq.topic-name}")
private String topic;
public Queue emptyQueue() {
return new ActiveMQQueue(emptyQueue);
}
public Queue fullQueue() {
return new ActiveMQQueue(fullQueue);
}
public Topic topic() {
return new ActiveMQTopic(topic);
}
@Bean
public ConnectionFactory connectionFactory() {
return new ActiveMQConnectionFactory(username, password, brokerUrl);
}
@Bean
public JmsMessagingTemplate jmsMessageTemplate() {
return new JmsMessagingTemplate(connectionFactory());
}
/**
* 在Queue模式中,对消息的监听需要对containerFactory进行配置
*
* @param connectionFactory
* @return
*/
@Bean("queueListener")
public JmsListenerContainerFactory<?> queueJmsListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(false);
return factory;
}
/**
* 在Topic模式中,对消息的监听需要对containerFactory进行配置
*
* @param connectionFactory
* @return
*/
@Bean("topicListener")
public JmsListenerContainerFactory<?> topicJmsListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(true);
return factory;
}
}
发送:
@RestController
@RequestMapping(value = "/testApi")
@Api(tags = "(测试对外接口)- TestApi endpoints")
@Slf4j
public class TestApiEndpoint {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private ActiveMqBeanConfig activeMqBeanConfig;
@GetMapping(value = "/testApi", produces = MediaType.TEXT_PLAIN_VALUE)
@ApiOperation(value = "测试api", notes = "测试api")
@MixmicroResponseBody(direct = true)
public String testApi() throws JMSException {
EmptyContainerGateOutDTO emptyContainerGateOutDTO = new EmptyContainerGateOutDTO();
emptyContainerGateOutDTO.setEirId("test");
log.info("[==] {}", emptyContainerGateOutDTO);
this.sendMessage(activeMqBeanConfig.emptyQueue(), emptyContainerGateOutDTO);
return "success";
}
/**
* 发送消息,destination是发送到的队列,message是待发送的消息
*
* @param destination
* @param obj
*/
public void sendMessage(Destination destination, Object obj) throws JMSException {
ActiveMQObjectMessage activeMQObjectMessage = new ActiveMQObjectMessage();
activeMQObjectMessage.setObject((Serializable) obj);
jmsMessagingTemplate.convertAndSend(destination, activeMQObjectMessage);
}
}
监听:
@JmsListener(destination = "${spring.activemq.queue-name-empty}", containerFactory = "queueListener")
public void readEmptyContainerActiveQueue(Object message) throws JMSException {
ActiveMQObjectMessage activeMQObjectMessage = (ActiveMQObjectMessage)message;
EmptyContainerGateOutDTO emptyContainerGateOutDTO = (EmptyContainerGateOutDTO)activeMQObjectMessage.getObject();
System.out.println("queue接受到:" + emptyContainerGateOutDTO);
}
然后看了下官方文档 大致意思就是为了安全官方给出了,设置了白名单的功能
方法一:在客户端设置下 按照官方文档来就好了,由于这个MQ不是我自己在用,这个方法就不试了
方法二:
①某些包设置白名单
//白名单的包名
activeMQObjectMessage.setTrustedPackages(new ArrayList(Arrays.asList("class com.test.openapi.repository.model.dto".split(","))));
②信任全部
activeMQObjectMessage.setTrustAllPackages(true); //需要设置信任哪些包 //设置这样表示信任所有
两种都可以解决ActiveMQ发送接收对象的报错问题