异步队列的实现。
如下图所示
这里的异步实现,采用redis作为单向的任务队列,将事件通过序列存入redis队列,通过反序列化将其发送给事件消费者。
事件消费者,通过一个EventHandler接口,来处理不同的事件。
public interface EventHandler{
//用来处理事件
doHandle(EventModel model);
//返回可以处理的事件的类型
List<EventType>getsupportedTypes();
}
事件分发器通过向jedisqueue lpush事件,consumer 从jedisqueue中brpop被序列化的事件,并反序列交给从applicationContext中获取的Eventhandler的实现类去实现点赞,或者评论。
public enum EventType{
LIKE(0);
COMMENT(1);
LOGIN(3);
MAIL(3);
private int value;
EventType(int value){this.val=value;}
public int getValue(){return value;}
}
public calss EeventModel{
private EvrntTypr tpe
private int actorId;//事件触发者
privtae entityId;//触发对象 评论的id
private int entityType;//评论的类型 实体的类型和id
private int entityOwnerId;//接收事件
private Map<String ,String> exts=new Hashmap<String,String>();
//get 和set函数
}
@Service
//事件的入口,统一发事件
Blpop Brpop
public class EventProducer{
@Autowired
JedisAdapter jedisAdapter;
//将事件放入队列
public boolean firEvent(EventModel eventmodel){
try{
String json =JSONOBJECT.toJSONString(eventModel);//将事件对象序列化存放在redis中
String key=ReidsKeyutil.getEventQueueKey();
JedisAdapter.lpush(key,json);//事件推入队列
return true;
}catche(Exception e){
return false;
}
}
}
public interface EventHandler{
//用来处理事件
doHandle(EventModel model);//处理事件
//返回可以处理的事件的类型
List<EventType>getsupportedTypes();//注册自己 表名对哪些事件关注
}
@Service
class EventConsumer implements InitilizinfBean
, ApplicationContextAware
{//进行初始化 通过Spring的上下文
//分发事件
private Map<EventType,List<Evenethandler>> config=new hashMapp<>();
private ApplicationContext applicationContext;
@Override
public void aferpropertiesSet() throws Exception{
Map<String, EventHandler> beans = applicationContext.getBeansOfType(EventHandler.class);
if (beans != null) {
for (Map.Entry<String, EventHandler> entry : beans.entrySet()) {
List<EventType> eventTypes = entry.getValue().getSupportEventTypes();
for (EventType type : eventTypes) {
if (!config.containsKey(type)) {
config.put(type, new ArrayList<EventHandler>());
}
config.get(type).add(entry.getValue());
}
}
}
//使用线程一直去取队列
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
String key = RedisKeyUtil.getEventQueueKey();
List<String> events = jedisAdapter.brpop(0, key);//从尾部取
for (String message : events) {
if (message.equals(key)) {
continue;
}
EventModel eventModel = JSON.parseObject(message, EventModel.class);
if (!config.containsKey(eventModel.getType())) {
logger.error("不能识别的事件");
continue;
}
for (EventHandler handler : config.get(eventModel.getType())) {
handler.doHandle(eventModel);
}
}
}
}
});
thread.start();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
知识渊博的小可爱