2019独角兽企业重金招聘Python工程师标准>>>

目录:

1.概述

2.JedisAdapter

3.EventModel

4.EventHandler

5.LikeHandler

6.EventProducer

7.EventConsumer

1.概述

在一个网站中,一个业务发生的同时,还有一些后续业务需要发生。

比如点赞,除了完成点赞功能外,还有一系列,比如提醒被点赞的用户等等,为了能够实现这些操作并且不拖慢单纯点赞功能的实现,我们将这些使用异步队列实现。

处理流程如下图:

Biz为业务部门,理解为点赞的实现,也就是在实现点赞的同时通过EventProducer发送一个事件;

这个事件进入队列等待,队列另一头,有一个EventConsumer,不断消费事件;

EventConsumer下面有很多EventHandler,只要EventHandler发现自己需要处理的事件类型,就会进行相应的操作。

优点:①后续业务的实现,不会拖慢主业务。②如果后续业务的服务器挂掉,只要重启,继续从优先队列消费事件即可。

2.JedisAdapter

在jedisAdapter中添加如下方法

public void setObject(String key, Object obj) {//将一个对象转换为一个jsoon串存入set中set(key, JSON.toJSONString(obj));
}public <T> T getObject(String key, Class<T> clazz) {//从set中取出json串,并转换为相应objectString value = get(key);if (value != null) {return JSON.parseObject(value, clazz);}return null;
}

3.EventModel

即发送的队列的事件模型,只有一些基本属性和get、set方法。

其中一些set的return 设置为this,是因为方便连续set多个属性。

package com.nowcoder.async;import java.awt.*;
import java.util.HashMap;
import java.util.Map;/*** Created by nowcoder on 2016/7/14.*/
public class EventModel {private EventType type;private int actorId;private int entityId;private int entityType;private int entityOwnerId;private Map<String, String> exts = new HashMap<>();public Map<String, String> getExts() {return exts;}public EventModel() {}public EventModel(EventType type) {this.type = type;}public String getExt(String name) {return exts.get(name);}public EventModel setExt(String name, String value) {exts.put(name, value);return this;}public EventType getType() {return type;}public EventModel setType(EventType type) {this.type = type;return this;}public int getActorId() {return actorId;}public EventModel setActorId(int actorId) {this.actorId = actorId;return this;}public int getEntityId() {return entityId;}public EventModel setEntityId(int entityId) {this.entityId = entityId;return this;}public int getEntityType() {return entityType;}public EventModel setEntityType(int entityType) {this.entityType = entityType;return this;}public int getEntityOwnerId() {return entityOwnerId;}public EventModel setEntityOwnerId(int entityOwnerId) {this.entityOwnerId = entityOwnerId;return this;}
}

EventType

package com.nowcoder.async;/*** Created by nowcoder on 2016/7/14.*/
public enum EventType {//枚举类LIKE(0),COMMENT(1),LOGIN(2),MAIL(3);private int value;EventType(int value) {this.value = value;}public int getValue() {return value;}
}

4.EventHandler

设计为一个接口,handler都实现此接口。

package com.nowcoder.async;import java.util.List;/*** Created by nowcoder on 2016/7/14.*/
public interface EventHandler {void doHandle(EventModel model);//处理此事件List<EventType> getSupportEventTypes();//添加监视的事件类型
}

5.LikeHandler

实现EventHandler接口。

package com.nowcoder.async.handler;import com.nowcoder.async.EventHandler;
import com.nowcoder.async.EventModel;
import com.nowcoder.async.EventType;
import com.nowcoder.model.Message;
import com.nowcoder.model.User;
import com.nowcoder.service.MessageService;
import com.nowcoder.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.Arrays;
import java.util.Date;
import java.util.List;/*** Created by nowcoder on 2016/7/14.*/
@Component
public class LikeHandler implements EventHandler {@AutowiredMessageService messageService;@AutowiredUserService userService;@Overridepublic void doHandle(EventModel model) {Message message = new Message();User user = userService.getUser(model.getActorId());message.setToId(model.getEntityOwnerId());message.setContent("用户" + user.getName() +" 赞了你的资讯,http://127.0.0.1:8080/news/"+ String.valueOf(model.getEntityId()));// SYSTEM ACCOUNTmessage.setFromId(3);message.setCreatedDate(new Date());messageService.addMessage(message);}@Overridepublic List<EventType> getSupportEventTypes() {//只关注“like”类型的事件return Arrays.asList(EventType.LIKE);}
}

6.EventProducer

负责将事件添加到队列中。

package com.nowcoder.async;import com.alibaba.fastjson.JSONObject;
import com.nowcoder.util.JedisAdapter;
import com.nowcoder.util.RedisKeyUtil;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.ExceptionHandler;/*** Created by nowcoder on 2016/7/14.*/
@Service
public class EventProducer {@AutowiredJedisAdapter jedisAdapter;public boolean fireEvent(EventModel eventModel) {try {String json = JSONObject.toJSONString(eventModel);//生成valueString key = RedisKeyUtil.getEventQueueKey();//生成keyjedisAdapter.lpush(key, json);//将事件添加到队列中return true;} catch (Exception e) {return false;}}
}

7.EventConsumer

负责从队列中消费事件。

package com.nowcoder.async;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.nowcoder.async.handler.LoginExceptionHandler;
import com.nowcoder.util.JedisAdapter;
import com.nowcoder.util.RedisKeyUtil;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** Created by nowcoder on 2016/7/14.*/
@Service
public class EventConsumer implements InitializingBean, ApplicationContextAware {//InitializingBean  通过实现此接口的afterPropertiesSet()方法记录哪些Event需要哪些handler来处理
//ApplicationContextAware  通过实现此接口的setApplicationContext方法获取上下文private static final Logger logger = LoggerFactory.getLogger(EventConsumer.class);//用来存储一个事件类型对应的所有的eventhandler,下次有该事件产生时,即可直接调用对应的listprivate Map<EventType, List<EventHandler>> config = new HashMap<>();private ApplicationContext applicationContext;@Autowiredprivate JedisAdapter jedisAdapter;@Overridepublic void afterPropertiesSet() throws Exception {//记录哪些Event需要哪些handler来处理//找出上下文中所有实现了EventHandler接口的类,存入beansMap<String, EventHandler> beans = applicationContext.getBeansOfType(EventHandler.class);if (beans != null) {//遍历所有的handler,将他们存入他们所监听的eventType对应的list中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() {@Overridepublic void run() {// 从队列一直消费while (true) {String key = RedisKeyUtil.getEventQueueKey();List<String> messages = jedisAdapter.brpop(0, key);//从redis的队列中取出事件,并存入list中// 第一个元素是队列名字,跳过for (String message : messages) {if (message.equals(key)) {continue;}EventModel eventModel = JSON.parseObject(message, EventModel.class);// 找到这个事件的处理handler列表if (!config.containsKey(eventModel.getType())) {logger.error("不能识别的事件");continue;}for (EventHandler handler : config.get(eventModel.getType())) {//处理他的所有的handlerhandler.doHandle(eventModel);}}}}});thread.start();}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
}

转载于:https://my.oschina.net/u/3786691/blog/1799784

Web项目(四)————异步队列的实现相关推荐

  1. apache2.4打开laravel项目_Laravel异步队列全攻略

    最近项目需求,研究了laravel的异步队列.官方文档虽然很是详细,但也有些晦涩难懂,在此记录下步骤,供大家参考. 1.修改/config/queue.php文件 <?phpreturn [/* ...

  2. IntelliJ IDEA 14.x 创建工作空间与多个Java Web项目

    以往的Eclipse.NetBeans等开发工具不同,IDEA的Project相当与Eclipse的Workspace,而Module相当于Project. 下边就给出Eclipse与IDEA的概念的 ...

  3. IDEA创建mybatis框架web项目

    IDEA创建mybatis框架web项目 一.idea新建项目 新建的时候选择java Enterprise ,选择jdk,maven仓库等.点击next 二.选择Web Profile,点击next ...

  4. 移动web app开发必备 - 异步队列 Deferred

    背景 移动web app开发,异步代码是时常的事,比如有常见的异步操作: Ajax(XMLHttpRequest) Image Tag,Script Tag,iframe(原理类似) setTimeo ...

  5. spring boot web项目_SpringBoot2.x入门到项目实战课程系列(第四章)

    项目源码:https://github.com/wenMN1994/SpringBoot 第4章 Spring Boot 日志配置 在市场上存在非常多的日志框架: Spring Boot 采用了 sl ...

  6. spring学习(四) ———— 整合web项目(SSH)

    清楚了spring的IOC 和 AOP,最后一篇就来整合SSH框架把,记录下来,以后应该会用的到. --WH 一.web项目中如何使用spring? 当tomcat启动时,就应该加载spring的配置 ...

  7. Docker基本概念与实践(四)-部署简单web项目(tomcat+war+mysql)

    Docker简单部署web项目(tomcat+war包+mysql) 先简单测试单独运行tomcat项目 #启用tomcat8镜像命名为webapp,将容器的8080端口映射到主机的8080端口 do ...

  8. Jenkins系列之——第四章 Jenkins编译一个Web项目并远程发布到Tomcat

    上一章讲了如何编译我们第一个项目 但是有时候我们不仅仅只是编译更多的是需要发布 在微服务普及之前我们最常用的就无非就是通过tomcat运行war格式的项目了,本章将介绍如何配置一个传统的Java we ...

  9. Spring Boot 学习[四] web项目实战训练(增删改查,分页,排序)

    Spring boot非常适合Web应用程序开发.您可以轻松创建自包含的HTTP应用.web服务器采用嵌入式Tomcat,或者Jetty等. 几点说明: Spring boot开发web项目,通常打成 ...

最新文章

  1. wikioi 1083 Cantor表
  2. BDD 与DSL 入门
  3. ARC和MRC 兼容的单例模式
  4. Xcode打包上传时,最后一步出现An error occurred uploading to the iTunes Store.的解决方法...
  5. @程序员,这些编程陷阱你中招了吗?
  6. .NET简谈自定义事务资源管理器
  7. VMware Mac 全屏问题
  8. python+opencv打开摄像头、拍摄指定次数的照片_python+openCV调用摄像头拍摄和处理图片的实现...
  9. 51单片机redefinition_lcd12864程序在keil中出现好多重新定义,尝试了很多办法都改不了,求助大家了...
  10. 计算器软件测试方法和技术,人工如何测试计算器
  11. 离散数学及其应用(第七版黑书)笔记
  12. python文本查重_GitHub - LiuYinCarl/check_homework: 文本查重工具
  13. 三角形的几何公式大全_初中数学几何公式、定理梳理大全,老师都收藏了
  14. linux vi恢复文件怎么打开文件,Linux上vi编辑文件非正常退出后文件恢复
  15. 计算机键盘没有fn,键盘Fn键失灵怎么解决?键盘Fn键失灵的修复方法
  16. Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分
  17. CORTEX-A系列处理器
  18. Arduino 寄存器(ADC)
  19. 哪些著名软件是用C、C++编写的?
  20. 郑州轻工业大学软件学院计算机网络期末复习

热门文章

  1. python 按位运算符_Python按位运算符
  2. TestNG参数– DataProvider和XML
  3. primefaces教程_Primefaces日历组件示例教程
  4. c++枚举和c语言枚举_C语言枚举初学者指南
  5. 如何使用InetAddress在Java中获取IP地址
  6. 我是做Java的,刚入职了,月薪20k,面试题还是很管用的
  7. OpenCV(三) 图像的读取和显示
  8. Linux(centos7)共享文件
  9. QTP自动化测试从零基础到精通进阶(脚本测试、VBS语法、描述性编程、测试框架)...
  10. [SCOI2005][BZOJ 1084]最大子矩阵