一般在工作中,都是直接使用已经封装好的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. C# 中的延时的方法。

    转载:https://blog.csdn.net/caixiexin/article/details/5769121 System.Threading.Thread.Sleep(2000); 其中20 ...

  2. Solon详解(11)- Mybatis 与 Solon 相亲相爱

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  3. 史上最全Python快速入门教程,满满都是干货

    Python是面向对象,高级语言,解释,动态和多用途编程语言.Python易于学习,而且功能强大,功能多样的脚本语言使其对应用程序开发具有吸引力.Python的语法和动态类型具有其解释性质,使其成为许 ...

  4. fio硬盘测速windows+linux

    一.FIO工具简介 Fio工具的介绍网上有很多,都是可以通用的,这里就不做太多个人描述了,直接借鉴一下 fio是一种I / O工具,用于基准测试和压力/硬件验证.它支持19种不同类型的I / O引擎( ...

  5. devops-jenkins分布式构建

    1. devops-jenkins分布式构建 1) 点击系统管理 进入节点管理 2) 点击新建节点 3) 进行节点配置在node节点服务器配置,进行java的安装 [root@nginx-backup ...

  6. Azure Media Player Logo隐藏和 视频字幕样式

    <style type="text/css"> /**hide mediaplayer logo*/ .amp-default-skin .amp-content-ti ...

  7. Python+Appium自动化测试(4)-使用weditor进行元素定位

    一,weditor的安装与使用 首选需要在电脑上配置好Python环境 下载安装命令如下,加上镜像下载速度更快: pip install weditor -i https://pypi.tuna.ts ...

  8. (转载)跟Classic ARM 处理器说拜拜——Atmel SAMA5D3 Xplained开发板评测

    2014 年 4 月 10 日 时间: 下午 3:15 作者: 幸得安然 电子产业的蓬勃发展带来了史无前例的生活.生产大跃进,但是,人们在享受发展喜悦的同时又不得不面临现实现状的囧境--在以移动电子设 ...

  9. 多测师接口测试 --常见的接口面试题目002---高级讲师肖sir

      1.postman接口测试,它有一个功能可以设置参数化,你有用过吗 2.你测试过哪些接口 3.有做过接口测试吗?接口测试你们是怎么测的 4.多接口怎么测(postman里面有一个批量处理) 5.g ...

  10. SpringBoot+Activiti+bpmn.js+Vue.js+Elementui(OA系统审批流)

    引言:OA系统用到请假.加班.调休.离职,需要使用工作流进行流程审批 一:activiti流程设计器的选择(通过学习activiti工作流过程中,发现一款好的流程设计器将会更好的方便的设计好流程(主要 ...