代码
学习的过程中,网上很多案例代码不全,只截取片段。下面是本次demo的完整代码,按照说明更改后,能正常运行。本次demo对应的模块是rabbitmqcommon, rabbitmqconsumer, rabbitmqproducer.共三个模块。
https://github.com/MrDujing/SpringDemo
运行环境
后台使用阿里云服务器,centos8系统,在此安装了rabbitmq服务端。
前台win8.1系统,分别开发三个模块:公用配置、生产者、消费者,使用的direct route.
开发使用IDEA+Maven,测试借助了Postman工具。
rabbitmq服务端安装
当时网上也查了不少,此处建议严格安装官网说明,使用yum安装,一次性安装成功,免得麻烦。
打开后,选择“Install Using PackageCloud Yum Repository”环节
上述有两个办法,一个是使用curl脚本一次性搞定,但其实搞不定;建议采用第二个办法,手动按照操作一个个来,肯定没问题。
提醒:如果采用脚本自动配置repo的办法,设置的repo名,与后面指令的名称不一致,建议留意下。
服务端安装后,需要做下述几步操作:
1 设置远程登陆用户名
2 建立virtual-host,demo中建立的名称为demohost
3 建立队列,demo中建立的队列为queueone
rabbitmq工程建立
采用分模块方法,rabbitmqcommon提供常规配置,rabbitmqconsumer取队列,只是简单的打印,rabbitmqproducer生产信息,借助spring mvc的post生产。
跨模块引用其他模块功能,如rabbitmqproducer模块引用rabbitmqcommon模块,需要在rabbitmqproducer/pom.xml里引入对rabbitmqcommon的依赖,同时rabbitmqproducer的启动点@SpringBootApplication需要指名扫描范围 ,不然无法成功扫描装配,如下图。
@SpringBootApplication(scanBasePackages = "bob.spring")
public class RabbitmqproducerApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitmqproducerApplication.class, args);
}
}
rabbitmqcommon模块
主要类为RabbitmqConfig
@PropertySource("classpath:config.properties")
@Component
public class RabbitmqConfig {
@Autowired
private Environment env;
public String getRabbitmqServerUrl() {
return env.getProperty("RABBITMQ_SERVER_URL");
}
public int getRabbitmqServerPort() {
return Integer.parseInt(env.getProperty("RABBITMQ_SERVER_PORT"));
}
public String getDemoQueueName() {
return env.getProperty("DEMO_QUEUE_NAME");
}
public String getDemoExchangeName() {
return env.getProperty("DEMO_EXCHANGE_NAME");
}
public String getDemoRoutingKey() {return env.getProperty("DEMO_ROUTING_KEY");}
public String getRabbitmqServerName() {return env.getProperty("RABBITMQ_SERVER_NAME");}
public String getRabbitmqServerPassWORD() {return env.getProperty("RABBITMQ_SERVER_PASSWORD");}
}
注意,将公共配置写在了config.properties里,而不是application.properties。因为跨模块引用的话,其他模块如RabbitmqProducer依赖RabbitmqCommon,调用RabbitmqCommon,读取的properties是RabbitmqProducer/application.properties,而不是RabbitmqCommon/application.properties。
所以将公共配置写在config.properties,并且使用@PropertySource限定配置文件路径。
rabbitmqproducer模块
重点是队列、交换机的绑定,其设置需要与服务端相应队列、交换机的设置一致,冲突的话,无法成功运行。
DirectRabbitmqConfig
@Configuration
public class DirectRabbitmqConfig {
@Resource
private RabbitmqConfig rabbitmqConfig;
@Bean
public Queue getDemoDirectQueue() {
return new Queue(rabbitmqConfig.getDemoQueueName(), false, false, false);
}
@Bean
public DirectExchange getDemoExchange() {
return new DirectExchange(rabbitmqConfig.getDemoExchangeName(),true, false);
}
@Bean
public Binding bindingDirect() {
return BindingBuilder
.bind(getDemoDirectQueue())
.to(getDemoExchange())
.with(rabbitmqConfig.getDemoRoutingKey());
}
}
MsgService提供消息的生产
@Service
public class MsgService implements RabbitMQService{
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Resource
private RabbitTemplate rabbitTemplate;
@Resource
private RabbitmqConfig rabbitmqConfig;
@Override
public String sendMsg(String msg) {
String msgId = UUID.randomUUID().toString().replace("-", "").substring(0, 32);
String sendTime = sdf.format(new Date());
Map<String, Object> map = new HashMap<>();
map.put("msgId", msgId);
map.put("sendTime", sendTime);
map.put("msg", msg);
rabbitTemplate.convertAndSend(rabbitmqConfig.getDemoExchangeName(), rabbitmqConfig.getDemoRoutingKey(), map);
return sdf.toString() + ": succeed send";
}
}
RabbitMQControler借助spring mvc触发消息发送,测试的时候,下载postman,借助该工具测试即可。
@RestController
@RequestMapping("/rabbitmq")
public class RabbitMQController {
@Resource
private RabbitMQService rabbitMQService;
@PostMapping("/sendMsg")
public String sendMsg(@RequestParam(name = "msg") String msg){
return rabbitMQService.sendMsg(msg);
}
}
rabbitmqconsumer模块
RabbitConsumerConfig,监听器配置
@Configuration
public class RabbitConsumerConfig {
@Resource
private RabbitmqConfig rabbitmqConfig;
@Bean
public Queue getDemoQueue() {
return new Queue(rabbitmqConfig.getDemoQueueName(), false, false, false);
}
@Bean
ConnectionFactory connectionFactory(@Value("${spring.rabbitmq.port}") int port,
@Value("${spring.rabbitmq.host}") String host,
@Value("${spring.rabbitmq.username}") String userName,
@Value("${spring.rabbitmq.password}") String password,
@Value("${spring.rabbitmq.virtual-host}") String vhost) {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setHost(host);
connectionFactory.setVirtualHost(vhost);
connectionFactory.setPort(port);
connectionFactory.setUsername(userName);
connectionFactory.setPassword(password);
return connectionFactory;
}
@Bean
public SimpleMessageListenerContainer msgContainer(DemoListenerService listenerProcess, ConnectionFactory connectionFactory) throws AmqpException {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames(rabbitmqConfig.getDemoQueueName());
container.setExposeListenerChannel(true);
container.setMessageListener(listenerProcess);//监听处理类
return container;
}
}
DemoListenerService处理接收到的信息
@Service
public class DemoListenerService implements ChannelAwareMessageListener {
@Override
public void onMessage(Message message, Channel channel){
byte[] body = message.getBody();
System.out.println("Receive msg: " + new String(body));
}
}
总结
git clone代码,工程配置齐全,改动下述信息
1 queue exchange virtualhost名字,需要与服务端对应
2 服务端地址 端口
3 用户名 密码
当时建立demo,主要是想把整个流程走通,便于理解,错误之处,望指出。