RabbitMQ的简单封装
一般在工作中,都是直接使用已经封装好的mq的程序集进行功能开发。所以很多时候都没有去了解rabbitmq到底是如何封装(实现使用的)。所以心血来潮,简单记录下自己对rabbitmq的简单封装
整体的思路是:约定消息体均继承值Command,消息业务类均继承于Handler,并且业务实体均实现Handle方法。消息发布者发送command;消费者接收到消息时通过反射,触发对应的消费业务。
一,定义消息实体相关
1 /// <summary>
2 /// command消息接口
3 /// </summary>
4 public interface ICommand
5 {
6 }
7 /// <summary>
8 /// 消息基类
9 /// </summary>
10 public class Command : ICommand
11 {
12 public Command() {
13 Id = Guid.NewGuid();
14 Time = DateTime.UtcNow;
15 }
16 /// <summary>
17 /// Id
18 /// </summary>
19 public Guid Id { get; set; }
20 /// <summary>
21 /// 消息时间
22 /// </summary>
23 public DateTime Time { get; set; }
24 }
实际的消息体
1 /// <summary>
2 /// 类别变更command
3 /// </summary>
4 public class CategoryChangedCommand : Command
5 {
6 /// <summary>
7 /// 类别Id
8 /// </summary>
9 public Guid CategoryId { get; set; }
10 /// <summary>
11 /// Sku id
12 /// </summary>
13 public Guid SkuId { get; set; }
14 }
二、定义消息处理类
1 /// <summary>
2 /// 消息处理接口
3 /// </summary>
4 /// <typeparam name="T"></typeparam>
5 public interface IHandler<T> where T : Command
6 {
7 /// <summary>
8 /// 处理消息
9 /// </summary>
10 /// <param name="t"></param>
11 void Handle(T t);
12 }
13 /// <summary>
14 /// 消息处理基类
15 /// </summary>
16 /// <typeparam name="T"></typeparam>
17 public abstract class Handler<T> : IHandler<T> where T : Command
18 {
19 public abstract void Handle(T t);
20
21 }
实现处理类
/// <summary>
/// 类别变更处理类
/// </summary>
public class CategoryChangeHandler : Handler<CategoryChangedCommand>
{
public override void Handle(CategoryChangedCommand t)
{
Console.WriteLine("sku 类别变化,修改对应listing的类别");
}
}
三、通过反射,定义mq消费者(重,以下代码只是实现简单的direct方式的消费,仅作参考辅助理解)
消费者一般随着程序启动建立,所以一般都是在startup.cs中进行初始化启动监听消费。
1、初始化消费类别字典,字典的约定为command与对应的Handler作为一对。(如果是支持fanout,则可以设置成,一个command类别对应多个Handler)
private void InitHandler()
{
Assembly assembly = Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, "SimpleNetCore.RabbitmqCommon.dll"));
var types = assembly.GetTypes().Where(p => p.IsClass && !p.IsAbstract && p.GetInterfaces().Any(x => x.Name == "IHandler`1"));
foreach (var type in types)
{
var handleMethod = type.GetMethod("Handle");
if (handleMethod != null)
{
var parameter = handleMethod.GetParameters()[0];
var parameterType = parameter.ParameterType;
_DicHandlerType.Add(parameterType, type);
}
}
}
2、创建消费者
1 var factory = new ConnectionFactory()
2 {
3 HostName = mqConfig.Host,
4 VirtualHost = mqConfig.VirtualHost,
5 UserName = mqConfig.UserName,
6 Password = mqConfig.Password
7 };
8 foreach (var item in _DicHandlerType)
9 {
10 var connection = factory.CreateConnection();
11
12
13 var channel = connection.CreateModel();
14 channel.QueueDeclare(item.Key.FullName, true, false, false, null);
15 channel.ExchangeDeclare(item.Key.FullName, ExchangeType.Direct, true, false, null);
16 ///定义事件消费者
17 EventingBasicConsumer consumer = new EventingBasicConsumer(channel);
18 consumer.Received += Consumer_Received; ;
19 //消费
20 channel.BasicConsume(item.Key.FullName, false, consumer);
21 //此处不关闭connection,channel,保持开启持续消费
22
23
24 }
3、消费事件方法,通过反射调用真正的业务类进行业务处理
1 private void Consumer_Received(object sender, BasicDeliverEventArgs e)
2 {
3 var message = Encoding.UTF8.GetString(e.Body.ToArray());
4 #region 业务处理
5 Console.WriteLine(message);
6 #endregion
7
8 EventingBasicConsumer consumer = sender as EventingBasicConsumer;
9 string exchangeName = e.Exchange;
10 var typeItem = _DicHandlerType.FirstOrDefault(p => p.Key.FullName == exchangeName);
11 if (typeItem.Key != null)
12 {
13 var t = JsonHelper.DeserialType(message, typeItem.Key);
14 var obj = Activator.CreateInstance(typeItem.Value);
15 var method = typeItem.Value.GetMethod("Handle");
16 method.Invoke(obj, new object[] { t });
17 }
18 string routeKey = e.RoutingKey;
19 //设置已经被消费
20 consumer.Model.BasicAck(e.DeliveryTag, false);
21
22 }
四、定义MQ消息生产者(重)
1 /// <summary>
2 /// 消息发布者接口
3 /// </summary>
4 public interface IBusFactory
5 {
6 /// <summary>
7 /// 发送command--针对的是direct方式
8 /// </summary>
9 /// <typeparam name="T"></typeparam>
10 /// <param name="command"></param>
11 void SendCommand<T>(T command) where T : ICommand;
12 }
13 /// <summary>
14 /// 消息发布者
15 /// </summary>
16 public class BusFactory : IBusFactory
17 {
18 private RabbitmqConfig _config;
19 private ConnectionFactory _factory;
20 public BusFactory(IOptions<RabbitmqConfig> config)
21 {
22 this._config = config.Value;
23 this._factory = new ConnectionFactory()
24 {
25 HostName = _config.Host,
26 VirtualHost = _config.VirtualHost,
27 UserName = _config.UserName,
28 Password = _config.Password,
29 };
30 }
31 public void SendCommand<T>(T command) where T : ICommand
32 {
33 string queueName = command.GetType().FullName;
34 string exchangeName = command.GetType().FullName;
35 string routeKey = command.GetType().FullName;
36 using (var connection = _factory.CreateConnection())
37 {
38 using (var channel = connection.CreateModel())
39 {
40 //定义交换机
41 channel.ExchangeDeclare(exchangeName, ExchangeType.Direct, true, false, null);
42 //定义队列
43 channel.QueueDeclare(queueName, true, false, false, null);
44 //绑定
45 channel.QueueBind(queueName, exchangeName, routeKey, null);
46 string message = JsonHelper.Serial(command);
47 byte[] data = Encoding.UTF8.GetBytes(message);
48 //发送消息
49 channel.BasicPublish(exchangeName, routeKey, null, data);
50 }
51 }
52 }
53 }
附 mq配置类
1 /// <summary>
2 /// rabbitmq 配置类
3 /// </summary>
4 public class RabbitmqConfig
5 {
6 /// <summary>
7 /// 主机地址
8 /// </summary>
9 public string Host { get; set; }
10 /// <summary>
11 /// 用户名称
12 /// </summary>
13 public string UserName { get; set; }
14 /// <summary>
15 /// 密码
16 /// </summary>
17 public string Password { get; set; }
18 /// <summary>
19 /// 虚拟主机名称
20 /// </summary>
21 public string VirtualHost { get; set; }
22 }
1 /// <summary>
2 /// rabbitmq 配置类
3 /// </summary>
4 public class RabbitmqConfig
5 {
6 /// <summary>
7 /// 主机地址
8 /// </summary>
9 public string Host { get; set; }
10 /// <summary>
11 /// 用户名称
12 /// </summary>
13 public string UserName { get; set; }
14 /// <summary>
15 /// 密码
16 /// </summary>
17 public string Password { get; set; }
18 /// <summary>
19 /// 虚拟主机名称
20 /// </summary>
21 public string VirtualHost { get; set; }
22 }
对应配置文件
1 "RabbitmqConfig": {
2 "Host":"127.0.0.1",
3 "UserName": "qingy",
4 "Password": "r3295",
5 "VirtualHost": "vTest"
6 }
----
以上就是非常简单的封装实现。仅作为参考!
RabbitMQ的简单封装的更多相关文章
- .Net Core应用RabbitMQ,及简单封装
首先,还是万分感谢大家能够抽空来阅读我的文章,万分感谢.今天我带来的是.Net Core中应用RabbitMQ,和简单封装.因为昨天的文章里说了今天要写,所以今天一定要写出来.小编翻阅了很多资料,想要 ...
- 关于RabbitMQ的简单理解
说明:想要理解RabbitMQ,需要先理解MQ是什么?能做什么?然后根据基础知识去理解RabbitMQ是什么.提供了什么功能. 一.MQ的简单理解 1. 什么是MQ? 消息队列(Message Que ...
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
- FMDB简单封装和使用
工具:火狐浏览器+SQLite Manager插件 ; Xcode; FMDB库; 效果: 项目地址: https://github.com/sven713/PackFMDB 主要参考这两篇博客: 1 ...
- Android--Retrofit+RxJava的简单封装(三)
1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...
- okhttp3 get post 简单封装
最近打算在新项目中使用 okhttp3, 简单封装了一下异步 get post 因为 CallBack 也是在子线程中执行,所以用到了 Handler public class MyOkHttpCli ...
- python网页请求urllib2模块简单封装代码
这篇文章主要分享一个python网页请求模块urllib2模块的简单封装代码. 原文转自:http://www.jbxue.com/article/16585.html 对python网页请求模块ur ...
- 对pymysql的简单封装
#coding=utf-8 #!/usr/bin/python import pymysql class MYSQL: """ 对pymysql的简单封装 "& ...
- iOS开发——UI篇OC篇&UITableView简单封装
UITableView简单封装 UITableView时iOS开发中使用最多也是最重的一个UI空间,其实在App Store里面的%80以上的应用都用到了这个控件,所以就给大家介绍一下,前面的文章中也 ...
随机推荐
- 如何安装eclipse
1.打开浏览器输入网址:http://www.eclipse.org 进入官方 2.(目前我使用windows操作系统),下拉界面选择"windows"后的"64-bit ...
- java安全编码指南之:方法编写指南
目录 简介 不要在构造函数中调用可以被重写的方法 不要在clone()方法中调用可重写的方法 重写equals()方法 hashCode和equals compareTo方法的实现 简介 java程序 ...
- 054 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 01 数组概述
054 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 01 数组概述 本文知识点:数组概述 为什么要学习数组? 实际问题: 比如我们要对学生的成绩进行排序,一个班级 ...
- OpenCV中threshold函数的使用
转自:https://blog.csdn.net/u012566751/article/details/77046445 一篇很好的介绍threshold文章: 图像的二值化就是将图像上的像素点的灰度 ...
- CSG:清华大学提出通过分化类特定卷积核来训练可解释的卷积网络 | ECCV 2020 Oral
论文提出类特定控制门CSG来引导网络学习类特定的卷积核,并且加入正则化方法来稀疏化CSG矩阵,进一步保证类特定.从实验结果来看,CSG的稀疏性能够引导卷积核与类别的强关联,在卷积核层面产生高度类相关的 ...
- dirsearch下载与简单实用
下载 下载地址 我的电脑是Windows,而且我也有python3.6的环境,所以我是直接clone到本地就能使用了. 命令的提示在上面的下载地址里就有,这里给个最简单的命令(脚本小子专属,我 ...
- git-代码分支管理
1. git代码分支管理 DEV SIT UAT PET PRE PRD PROD常见环境英文缩写含义 英文缩写 英文 中文 DEV development 开发 SIT System Int ...
- eclipse 配置opencv
1 准备 eclipse 2017 JDK1.8 opencv 4.40 2 配置 新建java工程 添加jar包 选择opencv-xxx.jar包 加入原生库 选择原生库位置 确认即可,测试 新建 ...
- 爬虫学习之-scrapy交互式命令 scrapy查看页面
scrapy shell https:///www.baidu.com 会启动爬虫请求网页 view(response) 会在浏览器打开请求到的临时文件 response.xpath("/ ...
- 教你怎么写jQuery的插件
jQuery(以下简称JQ)是一个功能强大而又小巧的JS框架,现在很多网站都在使用JQ,本站也不例外.本文教大家如何写一个属于你自己的JQ插件. 本JQ插件例子是在你网站的文章结尾处添加你的版权. J ...