创建一个消息队列的数据库维护表:
CREATE TABLE `consumer_local` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`topic` varchar(30) NOT NULL COMMENT '消费者所属的主题',
`consumer_id` varchar(50) NOT NULL COMMENT '消费者Consumer_id',
`access_key` varchar(60) NOT NULL COMMENT '阿里云身份验证',
`secre_key` varchar(300) NOT NULL COMMENT '阿里云身份验证,在阿里云服务器管理控制台创建',
`ons_address` varchar(300) NOT NULL COMMENT '设置的TCP接入域名',
`suspend_time_millis` varchar(10) NOT NULL COMMENT '顺序消息消费失败进行重试前的等待时间(毫秒)',
`max_reconsume_times` varchar(10) NOT NULL COMMENT '消息消费失败时的最大重试次数',
`sharding_key` varchar(30) NOT NULL COMMENT '顺序消息的区间',
`tag` varchar(30) NOT NULL COMMENT '处理消息的类型',
`investor` varchar(50) NOT NULL COMMENT '消费监控的类名',
`status` varchar(30) NOT NULL COMMENT '消费者的状态(stop,running,init)',
`state` int(1) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
然后再springboot的配置文件中添加配置的数据库Id:1
aliyun:
consumerId: 1
然后创建使用springboot配置的配置文件类:
package com.ryhui.properties;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.bean.OrderConsumerBean;
import com.aliyun.openservices.ons.api.bean.Subscription;
import com.aliyun.openservices.ons.api.order.ConsumeOrderContext;
import com.aliyun.openservices.ons.api.order.MessageOrderListener;
import com.aliyun.openservices.ons.api.order.OrderAction;
import com.ryhui.model.ConsumerLocal;
import com.ryhui.service.modelService.ConsumerLocalService;
import com.ryhui.utils.MessageListenerUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Created by 10351 on 2018/7/4.
*/
@Component
@ConfigurationProperties(prefix="aliyun")
@Slf4j
public class AliMQConfig {
@Autowired
private MessageListenerUtil messageListenerUtil;
@Autowired
private ConsumerLocalService consumerLocalService;
private String consumerId;
public String getConsumerId() {
return consumerId;
}
public void setConsumerId(String consumerId) {
this.consumerId = consumerId;
}
@Bean(initMethod = "start", destroyMethod = "shutdown")
public OrderConsumerBean getConsumer() {
ConsumerLocal consumerLocal = consumerLocalService.selectById(Long.valueOf(consumerId));
if(consumerLocal!=null&&consumerLocal.getStatus().equals("stop")){
OrderConsumerBean consumerBean = new OrderConsumerBean();
Properties properties = new Properties();
properties.put(PropertyKeyConst.ConsumerId, consumerLocal.getConsumerId());
// AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
properties.put(PropertyKeyConst.AccessKey, consumerLocal.getAccessKey());
// SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
properties.put(PropertyKeyConst.SecretKey, consumerLocal.getSecreKey());
//消息处理失败后多久重新发送消息
properties.put(PropertyKeyConst.SuspendTimeMillis, consumerLocal.getSuspendTimeMillis());
//重发的次数
properties.put(PropertyKeyConst.MaxReconsumeTimes, consumerLocal.getMaxReconsumeTimes());
//消费者的线程数
properties.put(PropertyKeyConst.ConsumeThreadNums,"1");
//消费者的介入地址
properties.put(PropertyKeyConst.ONSAddr, consumerLocal.getOnsAddress());
consumerBean.setProperties(properties);
Subscription subscription = new Subscription();
subscription.setTopic(consumerLocal.getTopic());
subscription.setExpression(consumerLocal.getTag());
Map map = new HashMap();
map.put(subscription, new MessageOrderListener(){
@Override
public OrderAction consume(Message message, ConsumeOrderContext consumeOrderContext) {
log.info("【{}】有消息进入,开始处理",message.getMsgID());
messageListenerUtil.sendMessage(message);
log.info("【{}】消息处理结束",message.getMsgID());
return OrderAction.Success;
}
});
consumerBean.setSubscriptionTable(map);
consumerLocal.setStatus("running");
consumerLocalService.update(consumerLocal);
return consumerBean;
}else{
return new OrderConsumerBean();
}
}
}
监听使用内部类格式,能够使用再配置文件中引入的spring管理类。spring管理类如下:
package com.ryhui.utils;
import com.aliyun.openservices.ons.api.Message;
import com.ryhui.model.ConsumerLocal;
import com.ryhui.model.ConsumerMessage;
import com.ryhui.service.modelService.ConsumerLocalService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* Created by 10351 on 2018/7/4.
*/
@Component
public class MessageListenerUtil {
@Resource
private ConsumerLocalService consumerLocalService;
public String sendMessage(Message message){
System.out.println(message.toString());
ConsumerLocal consumerLocal = consumerLocalService.selectByTopicAndTag(message.getTopic(),message.getTag());
if(consumerLocal!=null){
ConsumerMessage consumerMessage = consumerLocalService.selectByMessageUid(message.getMsgID());
if(consumerMessage==null){
consumerMessage = consumerLocalService.handlerMessage(message,consumerLocal.getId());
}
consumerLocalService.updateMessage(consumerMessage.getId(),"success");
}
System.out.println(message.toString()+"end");
return "hello";
}
}
项目启动后会自动开启消费者,如果需要多个消费者,就需要在数据库多配置一条数据,然后把配置的id写入到配置文件中。然后再配置类中引用。然后根据这个配置写一个消费者逻辑。模式同上。
内部类能使用spring的组件的原理:注意到 Inner 类可以访问 Outer 类的变量,即使是私有变量。那么,显然该内部类是与实例联系的,因为它可以访问实例的变量。对外层实例的显式引用为OuterClass.this。
里面有详细解释,如果有更专业的请回复。