一般在工作中,都是直接使用已经封装好的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的简单封装的更多相关文章

  1. .Net Core应用RabbitMQ,及简单封装

    首先,还是万分感谢大家能够抽空来阅读我的文章,万分感谢.今天我带来的是.Net Core中应用RabbitMQ,和简单封装.因为昨天的文章里说了今天要写,所以今天一定要写出来.小编翻阅了很多资料,想要 ...

  2. 关于RabbitMQ的简单理解

    说明:想要理解RabbitMQ,需要先理解MQ是什么?能做什么?然后根据基础知识去理解RabbitMQ是什么.提供了什么功能. 一.MQ的简单理解 1. 什么是MQ? 消息队列(Message Que ...

  3. Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池

    前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...

  4. FMDB简单封装和使用

    工具:火狐浏览器+SQLite Manager插件 ; Xcode; FMDB库; 效果: 项目地址: https://github.com/sven713/PackFMDB 主要参考这两篇博客: 1 ...

  5. Android--Retrofit+RxJava的简单封装(三)

    1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...

  6. okhttp3 get post 简单封装

    最近打算在新项目中使用 okhttp3, 简单封装了一下异步 get post 因为 CallBack 也是在子线程中执行,所以用到了 Handler public class MyOkHttpCli ...

  7. python网页请求urllib2模块简单封装代码

    这篇文章主要分享一个python网页请求模块urllib2模块的简单封装代码. 原文转自:http://www.jbxue.com/article/16585.html 对python网页请求模块ur ...

  8. 对pymysql的简单封装

    #coding=utf-8 #!/usr/bin/python import pymysql class MYSQL: """ 对pymysql的简单封装 "& ...

  9. iOS开发——UI篇OC篇&UITableView简单封装

    UITableView简单封装 UITableView时iOS开发中使用最多也是最重的一个UI空间,其实在App Store里面的%80以上的应用都用到了这个控件,所以就给大家介绍一下,前面的文章中也 ...

随机推荐

  1. Java (四)APACHE Commons IO 复制文件

    上一篇:Java (三)APACHE Commons IO 常规操作 例1:复制文件 1 import java.io.File; 2 import java.io.IOException; 3 4 ...

  2. CentOS 7安装docker和常用指令

    1.安装 yum -y install docker 2.启动 systemctl start docker // 启动 docker -v //查看版本号 systemctl stop docker ...

  3. CentOS7.7 系统下 virbr0 虚拟网卡的维护与管理

    在 CentOS 7 系统的安装过程中,如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的私网地址的 virbr0 网卡,这个是因为在虚拟化中有使用到 libvirtd 服务生 ...

  4. tmpwatch命令清除旧文件

    我们知道系统里面常常会有一些忘记删除的长时间不用而且确实没有用处的文件,如果不去处理,这些无用的文件会越来越多,浪费许多系统资源.在不知道文件名的情况下,很难去检查某一目录下到底是哪些文件长时间没有被 ...

  5. PHP的学习(提前学习了,业余爱好) (一)

    一个函数一个函数地堆 strstr()函数 在本地测试的时候,代码与显示如下 1.代码: <?php echo strstr("I love Shanghai!123",&q ...

  6. JS判断PC操作系统版本

    var version = navigator.userAgent; console.log(version); //"Mozilla/5.0 (Windows NT 10.0; WOW64 ...

  7. 多测师讲解_007 hashlib练习

    #Hash,译做"散列",也有直接音译为"哈希"的.把任意长度的输入,通过某种hash算法,变换成固定长度的输出,该输出就是散列值,也称摘要值.该算法就是哈希函 ...

  8. Martyr2项目实现——Number部分的问题求解 (1) Find Pi to Nth Digit

    Martyr2项目实现--Number部分的问题求解 (1) Find Pi to Nth Digit Find Pi to Nth Digit 问题描述: Find PI to the Nth Di ...

  9. Ubuntu安装zookeeper问题

    在Ubuntu系统安装zookeeper后,启动报错: root@host8:/usr/solrcould/service1/zookeeper-3.5.0-alpha# sh bin/zkServe ...

  10. Java中try()...catch()用法

    在stackoverflow偶尔看到的一个关于try()...catch()的用法,通常我们使用try...catch()捕获异常的,如果遇到类似IO流的处理,要在finally部分关闭IO流,当然这 ...