标签:msmq 队列 reposity rabbitmq redis
最近vs2017神器正式版发布让人很是激动,vs2017支持了很多语言的开发,从前端-后端-底层的支持,堪称是工具中的神器;netcore我喜爱的架构之一也得到了大力的宣传,应群友的邀请将在队列工厂(msmq,redis,rabbitmq)一些列文章过后,继续增加.netcore方面的文章,只为.netcore发展更好贡献一份微弱的力量;本章内容分享的是队列(msmq,redis,rabbitmq)封装的队列工厂之MSMQ希望大家能够喜欢,也希望各位多多"扫码支持"和"推荐"谢谢!
创建队列工厂QueueReposity<T>
. 队列公共操作接口IQueue
. 配置文件操作类ConfClass<T>
. 非安全单例创建队列实例
Win7和Server2008安装MSMQ支持
MSMQ测试用例(服务端+客户端)
下面一步一个脚印的来分享:
创建队列工厂QueueReposity<T>
首先,因为这里需要统一封装几个常用的队列方式的用法,因此采用了简单工厂模式,所以有了QueueReposity<T>;
. 队列公共操作接口IQueue
工厂模式的特性创建实例,因为这里封装的都是队列,故而能提取出统一的规则来,因此定义了如下接口(这里没有考虑一些队列兼容的异步方法请忽略):
/// <summary>
/// 队列公共操作
/// </summary>
public interface IQueue : IDisposable
{
/// <summary>
/// 创建队列
/// </summary>
void Create();
/// <summary>
/// 总数
/// </summary>
/// <returns></returns>
int Total();
/// <summary>
/// 读取一个队列
/// </summary>
/// <returns></returns>
Message Read();
///// <summary>
///// 读取多个队列
///// </summary>
///// <returns></returns>
//List<Message> ReadAll();
/// <summary>
/// 写入队列
/// </summary>
/// <returns></returns>
bool Write(string content, string name = "");
}. 配置文件操作类ConfClass<T>
因为每个队列的都有自己的配置信息,因此封装了统一管理的配置文件读取类ConfClass<T>,来读取配置在同一个xml文件中的配置信息,如下封装了自定义配置文件的属性和读取方法:
#region 文件操作类
/// <summary>
/// 配置文件操作类
/// </summary>
/// <typeparam name="T"></typeparam>
public class ConfClass<T> where T : class,new()
{
public ConfClass() {
var apiNodeName = this.GetType().Name;
Reader(apiNodeName);
}
#region 单例模式
public static readonly object Singleton_Lock = new object();
/// <summary>
/// 单例对象
/// </summary>
private static T t = default(T);
/// <summary>
/// 通过方法获取单例
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static T GetInstance(T t)
{
t = t ?? new T();
return t;
}
/// <summary>
/// 通过属性获取单例(在继承的时候使用)
/// </summary>
public static T Current
{
get
{
t = t ?? new T();
return t;
}
}
#endregion
#region 配置文件操作
#region 配置文件属性
/// <summary>
/// 配置文件地址
/// </summary>
//public string ConfPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Conf", "ShenNiuApi.xml");
public string ConfPath = @"C:\Conf\ShenNiuApi.xml";
/// <summary>
/// 配置文件父节点名称
/// </summary>
public string ConfParentNodeName = "ShenNiuApi";
/// <summary>
/// 配置文件内容
/// </summary>
public string ConfContent { get; set; }
/// <summary>
/// 配置文件文档doc对象
/// </summary>
public XmlDocument doc { get; set; }
/// <summary>
/// 账号
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string UserPwd { get; set; }
/// <summary>
/// 接口地址
/// </summary>
public string ApiUrl { get; set; }
/// <summary>
/// 秘钥
/// </summary>
public string ApiKey { get; set; }
#endregion
public ConfClass(string ConfPath, string ConfParentNodeName="")
{
this.ConfPath = string.IsNullOrWhiteSpace(ConfPath) ? this.ConfPath : ConfPath;
this.ConfParentNodeName = string.IsNullOrWhiteSpace(ConfParentNodeName) ? this.ConfParentNodeName : ConfParentNodeName;
var apiNodeName = this.GetType().Name;
Reader(apiNodeName);
}
/// <summary>
/// 读取配置信息
/// </summary>
/// <param name="apiNodeName"></param>
public void Reader(string apiNodeName)
{
try
{
if (string.IsNullOrWhiteSpace(ConfPath) || string.IsNullOrWhiteSpace(ConfParentNodeName))
{
throw new Exception("配置文件地址或者配置文件父节点名称不能为空");
}
if (!File.Exists(ConfPath)) { return; }
//获取配置文件信息
using (StreamReader reader = new StreamReader(ConfPath))
{
this.ConfContent = reader.ReadToEndAsync().Result;
}
if (string.IsNullOrWhiteSpace(this.ConfContent)) { return; }
//加入doc中
this.doc = new XmlDocument();
this.doc.LoadXml(this.ConfContent);
//解析
var parentNode = string.Format("{0}/{1}", this.ConfParentNodeName, apiNodeName);
var apiNode = this.doc.SelectSingleNode(parentNode);
if (apiNode == null) { throw new Exception("未能找到" + parentNode + "节点"); }
this.UserName = apiNode.SelectSingleNode("UserName").InnerText;
this.UserPwd = apiNode.SelectSingleNode("UserPwd").InnerText;
this.ApiUrl = apiNode.SelectSingleNode("ApiUrl").InnerText;
this.ApiKey = apiNode.SelectSingleNode("ApiKey").InnerText;
}
catch (Exception ex)
{
throw new Exception("加载配置文件" + this.ConfPath + "异常:" + ex.Message);
}
}
#endregion
}
#endregion这个配置文件的类主要运用在队列实例继承上,只要继承了默认就会读取响应的配置节点信息;配置xml文件默认存储的地址: C:\Conf\ShenNiuApi.xml ,最大父节点名称默认:ShenNiuApi,格式如下所示:
<ShenNiuApi> <QMsmq> <UserName></UserName> <UserPwd></UserPwd> <ApiUrl>.\Private$\MyMsmq</ApiUrl> <ApiKey></ApiKey> </QMsmq> </ShenNiuApi>
. 非安全单例创建队列实例
由于工厂都是专门用来提供实例的存在,创建实例的模式也有很多这种,这里我选择的是非安全单例创建队列实例,所有在ConfClass类中默认加入了单例模式:
#region 单例模式
public static readonly object Singleton_Lock = new object();
/// <summary>
/// 单例对象
/// </summary>
private static T t = default(T);
/// <summary>
/// 通过方法获取单例
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static T GetInstance(T t)
{
t = t ?? new T();
return t;
}
/// <summary>
/// 通过属性获取单例(在继承的时候使用)
/// </summary>
public static T Current
{
get
{
t = t ?? new T();
return t;
}
}
#endregion因此这里所说的工厂模式通过泛型传递类型,再创建实例的具体代码只有这么点,简短精炼:
/// <summary>
/// 队列工厂
/// </summary>
public class QueueReposity<T> where T : class,IQueue, new()
{
public static IQueue Current
{
get
{
return PublicClass.ConfClass<T>.Current;
}
}
}Win7和Server2008安装MSMQ支持
上面分享的是队列工厂的结构,到这里就要开始我们的第一个MSMQ队列的安装和封装分享了;首先来看Win7测试环境上怎么安装MSMQ的支持:开始菜单-》控制面板-》程序和功能:

-》打开或关闭Windows功能-》勾选如图所示队列安装组件:

-》确定等待安装完成;到此win7安装msmq就完成了,因为msmq是系统默认的所以安装起来很方便,当然server2008也差不多,按照如下操作安装(这里我使用租的阿里云Server2008R2服务器为例):开始-》控制面板-》程序(下面的打开或关闭Window功能)->功能-》添加功能-》消息队列:

在server上安装的步骤基本没啥变化,是不是很简单;安装完成后这样你的电脑或服务器就支持msmq了,此刻的你是不是很兴奋,觉得又能学到新东西了呵呵;
MSMQ测试用例(服务端+客户端)
首先,这里我用控制台程序做测试用例,我分为客户端和服务端,用服务端通过分装的插入队列方法插入数据,然后通过客户端读取队列信息,先来上个图撑撑场面吧:

这里我创建了MSMQ的分装类 public class QMsmq : PublicClass.ConfClass<QMsmq>, IQueue 实现了队列接口IQueue和继承配置文件类ConfClass<QMsmq>,此时具体的方法体如下:
public class QMsmq : PublicClass.ConfClass<QMsmq>, IQueue
{
private MessageQueue _msmq = null;
public void Create()
{
if (string.IsNullOrWhiteSpace(this.ApiUrl)) { throw new Exception("创建队列需要指定队列:地址"); }
_msmq = MessageQueue.Exists(this.ApiUrl) ?
new MessageQueue(this.ApiUrl) :
_msmq ?? MessageQueue.Create(this.ApiUrl);
//设置数据格式
_msmq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
}
public int Total()
{
if (_msmq == null) { throw new Exception("请先创建队列"); }
return _msmq.GetAllMessages().Length;
}
public Message Read()
{
try
{
if (_msmq == null) { throw new Exception("请先创建队列"); }
//60s超时
return _msmq.Receive(TimeSpan.FromSeconds(60));
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
//public List<Message> ReadAll()
//{
// try
// {
// if (_msmq == null) { throw new Exception("请先创建队列"); }
// var messages = _msmq.GetAllMessages();
// return messages.ToList();
// }
// catch (Exception ex)
// {
// throw new Exception(ex.Message);
// }
//}
public bool Write(string content, string name = "")
{
try
{
if (_msmq == null) { throw new Exception("请先创建队列"); }
if (string.IsNullOrWhiteSpace(content)) { throw new Exception("填充内容不能为空"); }
var message = new Message();
message.Body = content;
message.Label = name;
_msmq.Send(message);
return true;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public void Dispose()
{
if (_msmq != null)
{
_msmq.Close();
_msmq.Dispose();
_msmq = null;
}
}
}到这里我们的MSMQ简单封装代码已经完成了,咋们再来通过控制台调用下这个队列客户端代码:
class Program
{
static void Main(string[] args)
{
Client();
}
/// <summary>
/// 客户端
/// </summary>
private static void Client()
{
//实例化QMsmq对象
var msmq = QueueReposity<QMsmq>.Current;
try
{
Console.WriteLine("创建:msmq");
msmq.Create();
while (true)
{
try
{
var result = msmq.Read();
Console.WriteLine(string.Format("接受第{0}个:{1}", result.Label, result.Body));
}
catch (Exception ex)
{ Console.WriteLine("异常信息:" + ex.Message); }
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
Console.WriteLine("释放。");
msmq.Dispose();
}
}
}这里能够看出客户端代码中使用MSMQ步骤主要有:QueueReposity<QMsmq>.Current工厂创建自定义队列实例-》Create()创建-》Read()读取-》Dispose()释放mq,流程还算清晰吧;如下服务端代码:
class Program
{
static void Main(string[] args)
{
Server();
}
/// <summary>
/// 服务端
/// </summary>
private static void Server()
{
//实例化QMsmq对象
var msmq = QueueReposity<QMsmq>.Current;
try
{
Console.WriteLine("创建:msmq");
msmq.Create();
var num = 0;
do
{
Console.WriteLine("输入循环数量(数字,0表示结束):");
var readStr = Console.ReadLine();
num = string.IsNullOrWhiteSpace(readStr) ? 0 : Convert.ToInt32(readStr);
Console.WriteLine("插入数据:");
for (int i = 0; i < num; i++)
{
var str = "我的编号是:" + i;
msmq.Write(str, i.ToString());
Console.WriteLine(str);
}
} while (num > 0);
}
catch (Exception ex)
{
}
finally
{
Console.WriteLine("释放。");
msmq.Dispose();
}
Console.ReadLine();
}
}服务端的步骤几乎和客户端差不多,区别在于一个读取一个写入,服务端步骤:QueueReposity<QMsmq>.Current工厂创建自定义队列实例-》Create()创建-》Write()写入-》Dispose()释放mq;以上对MSMQ的代码分享和环境搭建讲解,希望能给您带来好的帮助,谢谢阅读;
本文出自 “神牛步行3博客” 博客,请务必保留此出处http://shenniu003.blog.51cto.com/3316359/1923484
标签:msmq 队列 reposity rabbitmq redis
原文地址:http://shenniu003.blog.51cto.com/3316359/1923484