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以上的应用都用到了这个控件,所以就给大家介绍一下,前面的文章中也 ...
随机推荐
- matlab中set设置图形属性
来源:https://ww2.mathworks.cn/help/matlab/ref/set.html?searchHighlight=set&s_tid=doc_srchtitle set ...
- MATLAB中exist函数的用法
exist:exist主要有两种形式,一个参数和两个参数的,作用都是用于确定某值是否存在:1. b = exist( a) 若 a 存在,则 b = 1: 否则 b = 0:2. b = e ...
- Tensorflow学习笔记No.3
使用tf.data加载数据 tf.data是tensorflow2.0中加入的数据加载模块,是一个非常便捷的处理数据的模块. 这里简单介绍一些tf.data的使用方法. 1.加载tensorflow中 ...
- 深入浅出学Java-HashMap
一.概要 HashMap在JDK1.8之前的实现方式 数组+链表,但是在JDK1.8后对HashMap进行了底层优化,改为了由 数组+链表+红黑树实现,主要的目的是提高查找效率. 如下图所示: JDK ...
- 【原创】Linux虚拟化KVM-Qemu分析(四)之CPU虚拟化(2)
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...
- H264裸码流I/P/B帧类型判别
花了两天时间做了个h264裸流nal类型和frame类型检测的工具,已上传至github,有需要的自行下载. 1.NAL类型检测 nal类型检测非常容易,对照下表即可容易判断类型. 较常用nal类型包 ...
- xshell选项卡不见了
最近使用xshell的时候发现建立多个选项卡的时候,因为没有选项卡,所以不能切换. 弄了好一会儿才弄出来 点击会话选项卡或者Ctrl + Shift + T可以调出来
- 在Windows7中打开照片,提示“Windows 照片查看器无法显示此图片,因为计算机上的可用内存可能不足。....”
在Windows7中打开照片,提示"Windows 照片查看器无法显示此图片,因为计算机上的可用内存可能不足.请关闭一些目前没有使用的程序或者释放部分硬盘空间(如果硬盘几乎已满),然后重试. ...
- MySQL数据库的完全备份与恢复
前言 在生产环境中,数据的安全性是至关重要的,任何数据的丢失都可能产生严重的后果,正确的数据库操作是实际环境下不可缺少的. 一.数据库备份的分类 1.1 从物理与逻辑的角度,备份的分类 物理备份:对数 ...
- git检出某文件的指定版本
比如当时文件所处的版本id是27e6266d86de3e6da6e1e7a8c43a8b51d6a87032 文件名是system/models/waimai/huodongdiscount.mdl. ...