在实践Spring JMS的过程中,遇到如下问题:
使用的ActiveMQ的版本为: 5.15.9
详细的代码在github上:SpringJMSSpittr (服务端,发送消息),SpringJMSSpittrCustomer (客户端,消费消息)
说明: 在实践下面内容之前,要先安装一个流程的开源消息代理: ActiveMQ
如下是在macOS系统中启动和关闭activeMQ的命令:
// 启动activemq服务
cd ${apache-activemq}/bin/macosx
sudo ./activemq start
// 停止activemq服务
sudo ./activemq stop
一、Serializable class not available to broker
Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: Forbidden class com.hef.spittr.domain.Spitter
解决:
在客户端使用如下配置:
<amq:connectionFactory id="connectionFactory" brokerURL="tcp://localhost:61616" trustAllPackages="true"/>
二、使用convertAndSend 和 MappingJackson2MessageConverter
需要对MappingJackson2MessageConverter进行一些配置,否则会报错。
/**
* 配置消息转换器
* @return
*/
@Bean
public MappingJackson2MessageConverter messageConverter(){
MappingJackson2MessageConverter messageConverter =
new MappingJackson2MessageConverter();
messageConverter.setEncoding("UTF-8");
messageConverter.setTargetType(MessageType.TEXT);
Map<String, Class<?>> typMap = new HashMap<>();
typMap.put("spitter", Spitter.class);
messageConverter.setTypeIdMappings(typMap);
messageConverter.setTypeIdPropertyName("spitter");
return messageConverter;
}
三、 创建消息驱动的POJO
创建消息驱动的POJO的目的是:让消息接受者异步接收消息。
因此,只需要在消费者应用端进行创建和配置。
3.1 创建消息监听器
@Configuration
public class SpitterAlertAsychronizationHandlerImpl implements SpitterAlertAsychronizationHandler {
@Override
public void handleSpittleAlert(Spitter spitter) {
System.out.println("asychronization begin...");
System.out.println(spitter);
System.out.println("asychronization end...");
}
}
3.2 配置消息监听器
<!--第一步: 将处理器声明为bean-->
<bean id="spitterAlertAsychronizationHandler" class="com.hef.spittr.service.impl.SpitterAlertAsychronizationHandlerImpl"/>
<!--第二步: 将SpitterAlertAsychronizationHandlerImpl 转变为消息驱动的POJO-->
<jms:listener-container>
<jms:listener destination="spitter.alert.queue" ref="spitterAlertAsychronizationHandler" method="handleSpittleAlert"/>
</jms:listener-container>
3.3 测试异步消息
四、使用基于JMS的服务
4.1 在服务端应用程序中
4.1.1 定义服务接口
import com.hef.spittr.domain.Spitter;
public interface JMSRPCService {
Spitter findSpitterById(long id);
}
4.1.2 实现服务接口
import com.hef.spittr.domain.Spitter;
import com.hef.spittr.service.JMSRPCService;
import com.hef.spittr.service.SpitterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Date 2019-04-27
* @Author lifei
*/
@Component
public class JMSRPCServiceImpl implements JMSRPCService {
@Autowired
private SpitterService spitterService;
@Override
public Spitter findSpitterById(long id) {
System.out.println("id:" + id);
return spitterService.getSpitter(id);
}
}
4.1.3 装配导出器
import com.hef.spittr.service.JMSRPCService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.remoting.JmsInvokerServiceExporter;
/**
* @Date 2019-04-27
* @Author lifei
*/
@Configuration
public class JMSRPCServiceConfig {
/**
* 装配 导出器
* @param service
* @return
*/
@Bean
public JmsInvokerServiceExporter jmsInvokerServiceExporter(JMSRPCService service){
JmsInvokerServiceExporter jmsInvokerServiceExporter = new JmsInvokerServiceExporter();
jmsInvokerServiceExporter.setService(service);
jmsInvokerServiceExporter.setServiceInterface(JMSRPCService.class);
return jmsInvokerServiceExporter;
}
}
4.1.4 导出服务
<!-- 导出基于JMS的服务-->
<bean class="config.JMSRPCServiceConfig"/>
<jms:listener-container>
<jms:listener destination="spitter.rpc.queue" ref="jmsInvokerServiceExporter"/>
</jms:listener-container>
4.2 客户端应用程序
4.2.1 使用服务的配置
<!-- 练习第四部分: 使用基于JMS的服务-->
<bean id="jmsrpcService" class="org.springframework.jms.remoting.JmsInvokerProxyFactoryBean"
p:connectionFactory-ref="connectionFactory"
p:queueName="spitter.rpc.queue"
p:serviceInterface="com.hef.spittr.service.JMSRPCService"/>
4.3 测试JMS的RPC
4.3.1 启动服务端
/**
* @Date 2019-04-27
* @Author lifei
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RootConfig.class})
public class JMSRPCServiceTest {
@Autowired
private JMSRPCService jmsrpcService;
@Test
public void waritRPCInvokerTest(){
System.out.println("service begin:");
while (true){
try {
Thread.sleep(5000l);
System.out.println("welcome...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
4.3.2 启动服务端
/**
* @Date 2019-04-27
* @Author lifei
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RootConfig.class})
public class JMSRPCServiceTest {
@Autowired
private JMSRPCService jmsrpcService;
@Test
public void waritRPCInvokerTest(){
System.out.println("service begin:");
while (true){
try {
Thread.sleep(5000l);
System.out.println("welcome...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
服务端打印日志: