提交.Net6版本
This commit is contained in:
1074
Yi.Framework.Net6/Yi.Framework.Core/CacheClientDB.cs
Normal file
1074
Yi.Framework.Net6/Yi.Framework.Core/CacheClientDB.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
using Consul;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Common.IOCOptions;
|
||||
|
||||
namespace Yi.Framework.Core.ConsulExtend
|
||||
{
|
||||
public abstract class AbstractConsulDispatcher
|
||||
{
|
||||
protected ConsulClientOption _ConsulClientOption = null;
|
||||
protected KeyValuePair<string, AgentService>[] _CurrentAgentServiceDictionary = null;
|
||||
|
||||
public AbstractConsulDispatcher(IOptionsMonitor<ConsulClientOption> consulClientOption)
|
||||
{
|
||||
this._ConsulClientOption = consulClientOption.CurrentValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 负载均衡获取地址
|
||||
/// </summary>
|
||||
/// <param name="mappingUrl">Consul映射后的地址</param>
|
||||
/// <returns></returns>
|
||||
public string GetAddress(string mappingUrl)
|
||||
{
|
||||
Uri uri = new Uri(mappingUrl);
|
||||
string serviceName = uri.Host;
|
||||
string addressPort = this.ChooseAddress(serviceName);
|
||||
return $"{uri.Scheme}://{addressPort}{uri.PathAndQuery}";
|
||||
}
|
||||
|
||||
protected virtual string ChooseAddress(string serviceName)
|
||||
{
|
||||
ConsulClient client = new ConsulClient(c =>
|
||||
{
|
||||
c.Address = new Uri($"http://{this._ConsulClientOption.IP}:{this._ConsulClientOption.Port}/");
|
||||
c.Datacenter = this._ConsulClientOption.Datacenter;
|
||||
});
|
||||
AgentService agentService = null;
|
||||
//var response = client.Agent.Services().Result.Response;
|
||||
////foreach (var item in response)
|
||||
////{
|
||||
//// Console.WriteLine("***************************************");
|
||||
//// Console.WriteLine(item.Key);
|
||||
//// var service = item.Value;
|
||||
//// Console.WriteLine($"{service.Address}--{service.Port}--{service.Service}");
|
||||
//// Console.WriteLine("***************************************");
|
||||
////}
|
||||
|
||||
//this._CurrentAgentServiceDictionary = response.Where(s => s.Value.Service.Equals(serviceName, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
|
||||
//升级consul实例获取
|
||||
var entrys = client.Health.Service(serviceName).Result.Response;
|
||||
List<KeyValuePair<string, AgentService>> serviceList = new List<KeyValuePair<string, AgentService>>();
|
||||
for (int i = 0; i < entrys.Length; i++)
|
||||
{
|
||||
serviceList.Add(new KeyValuePair<string, AgentService>(i.ToString(), entrys[i].Service));
|
||||
}
|
||||
this._CurrentAgentServiceDictionary = serviceList.ToArray();
|
||||
|
||||
int index = this.GetIndex();
|
||||
agentService = this._CurrentAgentServiceDictionary[index].Value;
|
||||
|
||||
return $"{agentService.Address}:{agentService.Port}";
|
||||
}
|
||||
|
||||
protected abstract int GetIndex();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Consul;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Yi.Framework.Common.IOCOptions;
|
||||
|
||||
namespace Yi.Framework.Core.ConsulExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// 平均
|
||||
/// </summary>
|
||||
public class AverageDispatcher : AbstractConsulDispatcher
|
||||
{
|
||||
#region Identity
|
||||
private static int _iTotalCount = 0;
|
||||
private static int iTotalCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _iTotalCount;
|
||||
}
|
||||
set
|
||||
{
|
||||
_iTotalCount = value >= Int32.MaxValue ? 0 : value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public AverageDispatcher(IOptionsMonitor<ConsulClientOption> consulClientOption) : base(consulClientOption)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 平均
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override int GetIndex()
|
||||
{
|
||||
return new Random(iTotalCount++).Next(0, base._CurrentAgentServiceDictionary.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Consul;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Yi.Framework.Common.IOCOptions;
|
||||
|
||||
namespace Yi.Framework.Core.ConsulExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// 轮询
|
||||
/// </summary>
|
||||
public class PollingDispatcher : AbstractConsulDispatcher
|
||||
{
|
||||
#region Identity
|
||||
private static int _iTotalCount = 0;
|
||||
private static int iTotalCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _iTotalCount;
|
||||
}
|
||||
set
|
||||
{
|
||||
_iTotalCount = value >= Int32.MaxValue ? 0 : value;
|
||||
}
|
||||
}
|
||||
|
||||
public PollingDispatcher(IOptionsMonitor<ConsulClientOption> consulClientOption) : base(consulClientOption)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 轮询
|
||||
/// </summary>
|
||||
/// <param name="serviceCount"></param>
|
||||
/// <returns></returns>
|
||||
protected override int GetIndex()
|
||||
{
|
||||
return iTotalCount++ % base._CurrentAgentServiceDictionary.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Consul;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Yi.Framework.Common.IOCOptions;
|
||||
|
||||
namespace Yi.Framework.Core.ConsulExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// 权重
|
||||
/// </summary>
|
||||
public class WeightDispatcher : AbstractConsulDispatcher
|
||||
{
|
||||
#region Identity
|
||||
private static int _iTotalCount = 0;
|
||||
private static int iTotalCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _iTotalCount;
|
||||
}
|
||||
set
|
||||
{
|
||||
_iTotalCount = value >= Int32.MaxValue ? 0 : value;
|
||||
}
|
||||
}
|
||||
public WeightDispatcher(IOptionsMonitor<ConsulClientOption> consulClientOption) : base(consulClientOption)
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override string ChooseAddress(string serviceName)
|
||||
{
|
||||
ConsulClient client = new ConsulClient(c =>
|
||||
{
|
||||
c.Address = new Uri($"http://{base._ConsulClientOption.IP}:{base._ConsulClientOption.Port}/");
|
||||
c.Datacenter = base._ConsulClientOption.Datacenter;
|
||||
});
|
||||
AgentService agentService = null;
|
||||
var response = client.Agent.Services().Result.Response;
|
||||
|
||||
this._CurrentAgentServiceDictionary = response.Where(s => s.Value.Service.Equals(serviceName, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
|
||||
|
||||
var serviceDictionaryNew = new List<AgentService>();
|
||||
foreach (var service in base._CurrentAgentServiceDictionary)
|
||||
{
|
||||
serviceDictionaryNew.AddRange(Enumerable.Repeat(service.Value, int.TryParse(service.Value.Tags?[0], out int iWeight) ? 1 : iWeight));
|
||||
}
|
||||
int index = new Random(DateTime.Now.Millisecond).Next(0, int.MaxValue) % serviceDictionaryNew.Count;
|
||||
agentService = serviceDictionaryNew[index];
|
||||
|
||||
return $"{agentService.Address}:{agentService.Port}";
|
||||
}
|
||||
/// <summary>
|
||||
/// 不需要了
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override int GetIndex()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Yi.Framework.Net6/Yi.Framework.Core/ElasticSearchInvoker.cs
Normal file
53
Yi.Framework.Net6/Yi.Framework.Core/ElasticSearchInvoker.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Nest;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Common.IOCOptions;
|
||||
|
||||
namespace Yi.Framework.Core
|
||||
{
|
||||
public class ElasticSearchInvoker
|
||||
{
|
||||
private readonly ElasticSearchOptions _elasticSearchOptions;
|
||||
|
||||
public ElasticSearchInvoker(IOptionsMonitor<ElasticSearchOptions> optionsMonitor)
|
||||
{
|
||||
_elasticSearchOptions = optionsMonitor.CurrentValue;
|
||||
var settings = new ConnectionSettings(new Uri(_elasticSearchOptions.Url)).DefaultIndex(this._elasticSearchOptions.IndexName);
|
||||
Client = new ElasticClient(settings);
|
||||
}
|
||||
private ElasticClient Client;
|
||||
public ElasticClient GetElasticClient()
|
||||
{
|
||||
return Client;
|
||||
}
|
||||
public void Send<T>(List<T> model) where T : class
|
||||
{
|
||||
Client.IndexMany(model);
|
||||
}
|
||||
|
||||
public void InsertOrUpdata<T>(T model) where T : class
|
||||
{
|
||||
Client.IndexDocument(model);
|
||||
}
|
||||
|
||||
public bool Delete<T>(string id) where T : class
|
||||
{
|
||||
|
||||
var response = Client.Delete<T>(id);
|
||||
return response.IsValid;
|
||||
}
|
||||
public bool DropIndex(string indexName)
|
||||
{
|
||||
return Client.Indices.Delete(Indices.Parse(indexName)).IsValid;
|
||||
}
|
||||
public void CreateIndex(string indexName)
|
||||
{
|
||||
var settings = new ConnectionSettings(new Uri(_elasticSearchOptions.Url)).DefaultIndex(indexName);
|
||||
this.Client = new ElasticClient(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
63
Yi.Framework.Net6/Yi.Framework.Core/MakeJwt.cs
Normal file
63
Yi.Framework.Net6/Yi.Framework.Core/MakeJwt.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using Microsoft.IdentityModel.JsonWebTokens;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Common.Const;
|
||||
using Yi.Framework.Model.Models;
|
||||
using JwtRegisteredClaimNames = Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames;
|
||||
|
||||
namespace Yi.Framework.Core
|
||||
{
|
||||
|
||||
public class jwtUser
|
||||
{
|
||||
public user user { get; set; }
|
||||
public List<menu> menuIds { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class MakeJwt
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// user需关联所有roles,还有一个menuIds
|
||||
/// </summary>
|
||||
/// <param name="_user"></param>
|
||||
/// <returns></returns>
|
||||
public static string app(jwtUser _user)
|
||||
{
|
||||
//通过查询权限,把所有权限加入进令牌中
|
||||
List<Claim> claims = new List<Claim>();
|
||||
claims.Add(new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"));
|
||||
claims.Add(new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddMinutes(30)).ToUnixTimeSeconds()}"));
|
||||
claims.Add(new Claim(ClaimTypes.Name, _user.user.username));
|
||||
claims.Add(new Claim(ClaimTypes.Sid, _user.user.id.ToString()));
|
||||
foreach (var k in _user?.menuIds)
|
||||
{
|
||||
claims.Add(new Claim("menuIds",k.id.ToString()));
|
||||
}
|
||||
foreach (var k in _user.user.roles)
|
||||
{
|
||||
claims.Add(new Claim(ClaimTypes.Role, k.role_name));
|
||||
}
|
||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtConst.SecurityKey));
|
||||
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||
|
||||
var token = new JwtSecurityToken(
|
||||
issuer: JwtConst.Domain,
|
||||
audience: JwtConst.Domain,
|
||||
claims: claims,
|
||||
expires: DateTime.Now.AddMinutes(30),
|
||||
signingCredentials: creds);
|
||||
var tokenData = new JwtSecurityTokenHandler().WriteToken(token);
|
||||
|
||||
return tokenData;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yi.Framework.Core.Quartz
|
||||
{
|
||||
public class MyQuartzFactory : IJobFactory
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public MyQuartzFactory(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
|
||||
{
|
||||
return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
|
||||
}
|
||||
|
||||
public void ReturnJob(IJob job)
|
||||
{
|
||||
var disposable = job as IDisposable;
|
||||
disposable?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
150
Yi.Framework.Net6/Yi.Framework.Core/Quartz/QuartzInvoker.cs
Normal file
150
Yi.Framework.Net6/Yi.Framework.Core/Quartz/QuartzInvoker.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Quartz;
|
||||
using Quartz.Impl.Matchers;
|
||||
using Quartz.Spi;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Common.Helper;
|
||||
using Yi.Framework.Job;
|
||||
|
||||
namespace Yi.Framework.Core
|
||||
{
|
||||
public class QuartzInvoker
|
||||
{
|
||||
private readonly ISchedulerFactory _schedulerFactory;
|
||||
private IScheduler _scheduler;
|
||||
private ILogger<QuartzInvoker> _logger;
|
||||
private IJobFactory _jobFactory;
|
||||
public QuartzInvoker(ISchedulerFactory schedulerFactory, ILogger<QuartzInvoker> logger, IJobFactory jobFactory)
|
||||
{
|
||||
_schedulerFactory = schedulerFactory;
|
||||
_logger = logger;
|
||||
_jobFactory = jobFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始任务
|
||||
/// </summary>
|
||||
/// <param name="cron"></param>
|
||||
/// <param name="jobKey"></param>
|
||||
/// <param name="jobClass"></param>
|
||||
/// <param name="second"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public async Task start(string cron, JobKey jobKey, string jobClass, long second = 0, IDictionary<string, object> data = null)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
data = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
var myClass = AssemblyHelper.GetClass("Yi.Framework.Job", jobClass).FirstOrDefault();
|
||||
|
||||
_scheduler = await _schedulerFactory.GetScheduler();
|
||||
_scheduler.JobFactory = _jobFactory;
|
||||
//开启调度器
|
||||
await _scheduler.Start();
|
||||
//创建一个触发器
|
||||
var trigger = TriggerBuilder.Create()
|
||||
.StartAt(DateTimeOffset.Now.AddSeconds(second))
|
||||
.WithCronSchedule(cron)
|
||||
.Build();
|
||||
//创建任务
|
||||
var jobDetail = JobBuilder.Create(myClass)
|
||||
.UsingJobData(new JobDataMap(data))
|
||||
.WithIdentity(jobKey.Name, jobKey.Group)
|
||||
.Build();
|
||||
//将触发器和任务器绑定到调度器中
|
||||
await _scheduler.ScheduleJob(jobDetail, trigger);
|
||||
|
||||
_logger.LogWarning($"开始任务:{jobKey.Name},组别:{jobKey.Group}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暂停任务
|
||||
/// </summary>
|
||||
/// <param name="jobKey"></param>
|
||||
/// <returns></returns>
|
||||
public async Task Stop(JobKey jobKey)
|
||||
{
|
||||
var _scheduler = await _schedulerFactory.GetScheduler();
|
||||
//LogUtil.Debug($"暂停任务{jobKey.Group},{jobKey.Name}");
|
||||
await _scheduler.PauseJob(jobKey);
|
||||
_logger.LogWarning($"暂停任务:{jobKey.Name},组别:{jobKey.Group}");
|
||||
}
|
||||
|
||||
|
||||
public async Task Delete(JobKey jobKey)
|
||||
{
|
||||
var _scheduler = await _schedulerFactory.GetScheduler();
|
||||
//LogUtil.Debug($"暂停任务{jobKey.Group},{jobKey.Name}");
|
||||
await _scheduler.DeleteJob(jobKey);
|
||||
_logger.LogWarning($"删除任务:{jobKey.Name},组别:{jobKey.Group}");
|
||||
}
|
||||
|
||||
public async Task Resume(JobKey jobKey)
|
||||
{
|
||||
var _scheduler = await _schedulerFactory.GetScheduler();
|
||||
//LogUtil.Debug($"恢复任务{jobKey.Group},{jobKey.Name}");
|
||||
await _scheduler.ResumeJob(jobKey);
|
||||
_logger.LogWarning($"恢复任务:{jobKey.Name},组别:{jobKey.Group}");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 得到可运行的job列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<string> getJobClassList()
|
||||
{
|
||||
var myClassList = AssemblyHelper.GetClass("Yi.Framework.Job");
|
||||
List<string> data = new List<string>();
|
||||
myClassList.ForEach(k => data.Add(k.Name));
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 得到现在正在运行的任务列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<JobKey>> getRunJobList()
|
||||
{
|
||||
_scheduler = await _schedulerFactory.GetScheduler();
|
||||
var groups = await _scheduler.GetJobGroupNames();
|
||||
var data = new List<JobKey>();
|
||||
foreach (var groupName in groups)
|
||||
{
|
||||
foreach (var jobKey in await _scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(groupName)))
|
||||
{
|
||||
string jobName = jobKey.Name;
|
||||
string jobGroup = jobKey.Group;
|
||||
data.Add(jobKey);
|
||||
var triggers = await _scheduler.GetTriggersOfJob(jobKey);
|
||||
foreach (ITrigger trigger in triggers)
|
||||
{
|
||||
///下一次的执行时间
|
||||
var utcTime =trigger.GetNextFireTimeUtc();
|
||||
string str = utcTime.ToString();
|
||||
//TimeZone.CurrentTimeZone.ToLocalTime(Convert.ToDateTime(str));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class JobKeyModel
|
||||
{
|
||||
public JobKey jobKey { get; set; }
|
||||
public DateTime? nextTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
257
Yi.Framework.Net6/Yi.Framework.Core/RabbitMQInvoker.cs
Normal file
257
Yi.Framework.Net6/Yi.Framework.Core/RabbitMQInvoker.cs
Normal file
@@ -0,0 +1,257 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using RabbitMQ.Client;
|
||||
using RabbitMQ.Client.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Common.IOCOptions;
|
||||
|
||||
namespace Yi.Framework.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 一个Exchange----多个Queue-----弄个缓存映射关系,初始化+支持全新绑定
|
||||
/// 全局单例使用
|
||||
///
|
||||
/// 关系应该是直接配置到RabbitMQ了---程序只是向某个位置写入即可
|
||||
///
|
||||
///
|
||||
/// 全量更新--耗时---阻塞实时更新---换不同的exchange?
|
||||
/// </summary>
|
||||
public class RabbitMQInvoker
|
||||
{
|
||||
#region Identity
|
||||
private readonly RabbitMQOptions _rabbitMQOptions;
|
||||
private readonly string _HostName = null;
|
||||
private readonly string _UserName = null;
|
||||
private readonly string _Password = null;
|
||||
private readonly int _Port = 0;
|
||||
public RabbitMQInvoker(IOptionsMonitor<RabbitMQOptions> optionsMonitor) : this(optionsMonitor.CurrentValue.HostName, optionsMonitor.CurrentValue.UserName, optionsMonitor.CurrentValue.Password,optionsMonitor.CurrentValue.Port)
|
||||
{
|
||||
this._rabbitMQOptions = optionsMonitor.CurrentValue;
|
||||
}
|
||||
|
||||
public RabbitMQInvoker(string hostName, string userName = "cc", string password = "cc",int port= 5672)
|
||||
{
|
||||
this._HostName = hostName;
|
||||
this._UserName = userName;
|
||||
this._Password = password;
|
||||
this._Port = port;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
private static object RabbitMQInvoker_BindQueueLock = new object();
|
||||
private static Dictionary<string, bool> RabbitMQInvoker_ExchangeQueue = new Dictionary<string, bool>();
|
||||
private void InitBindQueue(RabbitMQConsumerModel rabbitMQConsumerModel)
|
||||
{
|
||||
if (!RabbitMQInvoker_ExchangeQueue.ContainsKey($"InitBindQueue_{rabbitMQConsumerModel.ExchangeName}_{rabbitMQConsumerModel.QueueName}"))
|
||||
{
|
||||
lock (RabbitMQInvoker_BindQueueLock)
|
||||
{
|
||||
if (!RabbitMQInvoker_ExchangeQueue.ContainsKey($"InitBindQueue_{rabbitMQConsumerModel.ExchangeName}_{rabbitMQConsumerModel.QueueName}"))
|
||||
{
|
||||
this.InitConnection();
|
||||
using (IModel channel = _CurrentConnection.CreateModel())
|
||||
{
|
||||
channel.ExchangeDeclare(exchange: rabbitMQConsumerModel.ExchangeName, type: ExchangeType.Fanout, durable: true, autoDelete: false, arguments: null);
|
||||
channel.QueueDeclare(queue: rabbitMQConsumerModel.QueueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
|
||||
channel.QueueBind(queue: rabbitMQConsumerModel.QueueName, exchange: rabbitMQConsumerModel.ExchangeName, routingKey: string.Empty, arguments: null);
|
||||
}
|
||||
RabbitMQInvoker_ExchangeQueue[$"InitBindQueue_{rabbitMQConsumerModel.ExchangeName}_{rabbitMQConsumerModel.QueueName}"] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 必须先声明exchange--检查+初始化
|
||||
/// </summary>
|
||||
/// <param name="rabbitMQConsumerModel"></param>
|
||||
private void InitExchange(string exchangeName)
|
||||
{
|
||||
if (!RabbitMQInvoker_ExchangeQueue.ContainsKey($"InitExchange_{exchangeName}"))//没用api确认
|
||||
{
|
||||
lock (RabbitMQInvoker_BindQueueLock)
|
||||
{
|
||||
if (!RabbitMQInvoker_ExchangeQueue.ContainsKey($"InitExchange_{exchangeName}"))
|
||||
{
|
||||
this.InitConnection();
|
||||
using (IModel channel = _CurrentConnection.CreateModel())
|
||||
{
|
||||
channel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Fanout, durable: true, autoDelete: false, arguments: null);
|
||||
}
|
||||
RabbitMQInvoker_ExchangeQueue[$"InitExchange_{exchangeName}"] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//public void UnBindQueue(string exchangeName, string queueName)
|
||||
//{
|
||||
//}
|
||||
|
||||
private static object RabbitMQInvoker_InitLock = new object();
|
||||
private static IConnection _CurrentConnection = null;//链接做成单例重用--channel是新的
|
||||
private void InitConnection()
|
||||
{
|
||||
//https://blog.csdn.net/weixin_30646315/article/details/99101279
|
||||
if (_CurrentConnection == null || !_CurrentConnection.IsOpen)
|
||||
{
|
||||
lock (RabbitMQInvoker_InitLock)
|
||||
{
|
||||
if (_CurrentConnection == null || !_CurrentConnection.IsOpen)
|
||||
{
|
||||
var factory = new ConnectionFactory()
|
||||
{
|
||||
HostName = this._HostName,
|
||||
Password = this._Password,
|
||||
UserName = this._UserName,
|
||||
Port=this._Port
|
||||
|
||||
};
|
||||
_CurrentConnection = factory.CreateConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 只管exchange---
|
||||
/// 4种路由类型?
|
||||
///
|
||||
/// Send前完成交换机初始化
|
||||
/// </summary>
|
||||
/// <param name="exchangeName"></param>
|
||||
/// <param name="message">建议Json格式</param>
|
||||
public void Send(RabbitMQConsumerModel rabbitMQConsumerModel, string message)
|
||||
{
|
||||
this.InitExchange(rabbitMQConsumerModel.ExchangeName);
|
||||
this.InitBindQueue(rabbitMQConsumerModel);
|
||||
if (_CurrentConnection == null || !_CurrentConnection.IsOpen)
|
||||
{
|
||||
this.InitConnection();
|
||||
}
|
||||
using (var channel = _CurrentConnection.CreateModel())//开辟新的信道通信
|
||||
{
|
||||
try
|
||||
{
|
||||
channel.TxSelect();//开启Tx事务---RabbitMQ协议级的事务-----强事务
|
||||
|
||||
var body = Encoding.UTF8.GetBytes(message);
|
||||
channel.BasicPublish(exchange: rabbitMQConsumerModel.ExchangeName,
|
||||
routingKey: string.Empty,
|
||||
basicProperties: null,
|
||||
body: body);
|
||||
channel.TxCommit();//提交
|
||||
Console.WriteLine($" [x] Sent {body.Length}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
Console.WriteLine($"【{message}】发送到Broker失败!{ex.Message}");
|
||||
channel.TxRollback(); //事务回滚--前面的所有操作就全部作废了。。。。
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 固定无消费队列名字---转移到目标队列---定好时间
|
||||
/// </summary>
|
||||
/// <param name="targetExchangeName"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="delaySecond"></param>
|
||||
public void SendDelay(string targetExchangeName, string message, int delaySecond)
|
||||
{
|
||||
this.InitExchange(targetExchangeName);
|
||||
|
||||
if (_CurrentConnection == null || !_CurrentConnection.IsOpen)
|
||||
{
|
||||
this.InitConnection();
|
||||
}
|
||||
using (var channel = _CurrentConnection.CreateModel())//开辟新的信道通信
|
||||
{
|
||||
try
|
||||
{
|
||||
string delayExchangeName = "ZhaoxiMSA_DelayExchange";
|
||||
|
||||
//普通交换器
|
||||
channel.ExchangeDeclare(delayExchangeName, "fanout", true, false, null);
|
||||
//参数设置
|
||||
Dictionary<string, object> args = new Dictionary<string, object>();
|
||||
args.Add("x-message-ttl", delaySecond * 1000);//TTL 毫秒
|
||||
args.Add("x-dead-letter-exchange", targetExchangeName);//DLX
|
||||
args.Add("x-dead-letter-routing-key", "routingkey");//routingKey
|
||||
channel.QueueDeclare("ZhaoxiMSA_DelayQueue", true, false, false, args);
|
||||
channel.QueueBind(queue: "ZhaoxiMSA_DelayQueue",
|
||||
exchange: delayExchangeName,
|
||||
routingKey: string.Empty,
|
||||
arguments: null);
|
||||
|
||||
////DLX--- //死信队列绑定
|
||||
//channel.ExchangeDeclare("ZhaoxiMSA_exchange_dlx", "fanout", true, false, null);
|
||||
//channel.QueueDeclare("ZhaoxiMSA_queue_dlx", true, false, false, null);
|
||||
//channel.QueueBind("ZhaoxiMSA_queue_dlx", "ZhaoxiMSA_exchange_dlx", "routingkey", null);
|
||||
|
||||
|
||||
channel.TxSelect();//开启Tx事务---RabbitMQ协议级的事务-----强事务
|
||||
var properties = channel.CreateBasicProperties();
|
||||
|
||||
var body = Encoding.UTF8.GetBytes(message);
|
||||
channel.BasicPublish(exchange: delayExchangeName,
|
||||
routingKey: string.Empty,
|
||||
basicProperties: properties,
|
||||
body: body);
|
||||
channel.TxCommit();//提交
|
||||
Console.WriteLine($" [x] Sent {body.Length}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
Console.WriteLine($"【{message}】发送到Broker失败!{ex.Message}");
|
||||
channel.TxRollback(); //事务回滚--前面的所有操作就全部作废了。。。。
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Receive
|
||||
/// <summary>
|
||||
/// 注册处理动作
|
||||
/// </summary>
|
||||
/// <param name="rabbitMQConsumerMode"></param>
|
||||
/// <param name="func"></param>
|
||||
public void RegistReciveAction(RabbitMQConsumerModel rabbitMQConsumerMode, Func<string, bool> func)
|
||||
{
|
||||
this.InitBindQueue(rabbitMQConsumerMode);
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
using (var channel = _CurrentConnection.CreateModel())
|
||||
{
|
||||
var consumer = new EventingBasicConsumer(channel);
|
||||
channel.BasicQos(0, 0, true);
|
||||
consumer.Received += (sender, ea) =>
|
||||
{
|
||||
string str = Encoding.UTF8.GetString(ea.Body.ToArray());
|
||||
if (func(str))
|
||||
{
|
||||
channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);//确认已消费
|
||||
}
|
||||
else
|
||||
{
|
||||
//channel.BasicReject(deliveryTag: ea.DeliveryTag, requeue: true);//放回队列--重新包装信息,放入其他队列
|
||||
}
|
||||
};
|
||||
channel.BasicConsume(queue: rabbitMQConsumerMode.QueueName,
|
||||
autoAck: false,//不ACK
|
||||
consumer: consumer);
|
||||
Console.WriteLine($" Register Consumer To {rabbitMQConsumerMode.ExchangeName}-{rabbitMQConsumerMode.QueueName}");
|
||||
Console.ReadLine();
|
||||
Console.WriteLine($" After Register Consumer To {rabbitMQConsumerMode.ExchangeName}-{rabbitMQConsumerMode.QueueName}");
|
||||
}
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
46
Yi.Framework.Net6/Yi.Framework.Core/SMS/AliyunSMSInvoker.cs
Normal file
46
Yi.Framework.Net6/Yi.Framework.Core/SMS/AliyunSMSInvoker.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Common.IOCOptions;
|
||||
|
||||
namespace Yi.Framework.Core.SMS
|
||||
{
|
||||
public class AliyunSMSInvoker
|
||||
{
|
||||
private IOptionsMonitor<SMSOptions> _sMSOptions;
|
||||
public AliyunSMSInvoker(IOptionsMonitor<SMSOptions> sMSOptions)
|
||||
{
|
||||
_sMSOptions = sMSOptions;
|
||||
}
|
||||
private static AlibabaCloud.SDK.Dysmsapi20170525.Client CreateClient(string accessKeyId, string accessKeySecret)
|
||||
{
|
||||
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config
|
||||
{
|
||||
// 您的AccessKey ID
|
||||
AccessKeyId = accessKeyId,
|
||||
// 您的AccessKey Secret
|
||||
AccessKeySecret = accessKeySecret,
|
||||
};
|
||||
// 访问的域名
|
||||
config.Endpoint = "dysmsapi.aliyuncs.com";
|
||||
return new AlibabaCloud.SDK.Dysmsapi20170525.Client(config);
|
||||
}
|
||||
|
||||
public void SendCode(string code,string phone)
|
||||
{
|
||||
AlibabaCloud.SDK.Dysmsapi20170525.Client client = CreateClient(_sMSOptions.CurrentValue.ID, _sMSOptions.CurrentValue.Secret);
|
||||
AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest sendSmsRequest = new AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest
|
||||
{
|
||||
PhoneNumbers = phone,
|
||||
SignName = _sMSOptions.CurrentValue.Sign,
|
||||
TemplateCode = _sMSOptions.CurrentValue.Template,
|
||||
TemplateParam = "{\"code\":\""+ code + "\"}",
|
||||
};
|
||||
// 复制代码运行请自行打印 API 的返回值
|
||||
client.SendSms(sendSmsRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
108
Yi.Framework.Net6/Yi.Framework.Core/TreeMenuBuild.cs
Normal file
108
Yi.Framework.Net6/Yi.Framework.Core/TreeMenuBuild.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Yi.Framework.Model.Models;
|
||||
|
||||
namespace Yi.Framework.Core
|
||||
{
|
||||
public static class TreeMenuBuild
|
||||
{
|
||||
/// <summary>
|
||||
/// 过滤所有已经删除的菜单
|
||||
/// </summary>
|
||||
/// <param name="menu_data"></param>
|
||||
/// <returns></returns>
|
||||
public static menu Normal(menu menu_data)
|
||||
{
|
||||
for (int i = menu_data.children.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
if (menu_data.children[i].is_delete == (short)Common.Enum.DelFlagEnum.Deleted)
|
||||
{
|
||||
menu_data.children.Remove(menu_data.children[i]);
|
||||
}
|
||||
else if (menu_data.children[i] != null)
|
||||
{
|
||||
Normal(menu_data.children[i]);
|
||||
}
|
||||
}
|
||||
return menu_data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static menu ShowFormat(menu menu_data, List<int> allMenuIds)
|
||||
{
|
||||
return Format(Show(menu_data, allMenuIds));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 过滤用户不展示及已删除及未拥有的菜单
|
||||
/// </summary>
|
||||
/// <param name="menu_data"></param>
|
||||
/// <param name="allMenuIds"></param>
|
||||
/// <returns></returns>
|
||||
private static menu Show(menu menu_data, List<int> allMenuIds)
|
||||
{
|
||||
for (int i = menu_data.children.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
if (!allMenuIds.Contains(menu_data.children[i].id) || menu_data.children[i].is_delete == (short)Common.Enum.DelFlagEnum.Deleted || menu_data.children[i].is_show == (short)Common.Enum.ShowFlagEnum.NoShow)
|
||||
{
|
||||
menu_data.children.Remove(menu_data.children[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Show(menu_data.children[i], allMenuIds);
|
||||
}
|
||||
}
|
||||
return menu_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为了匹配前端格式,通常和show方法一起
|
||||
/// </summary>
|
||||
/// <param name="menu_data"></param>
|
||||
/// <returns></returns>
|
||||
private static menu Format(menu menu_data)
|
||||
{
|
||||
for (int i = menu_data.children.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
if (menu_data.children[i].icon == null)
|
||||
{
|
||||
menu_data.children[i].icon = "mdi-view-dashboard";
|
||||
}
|
||||
if (menu_data.children != null || menu_data.children.Count() != 0)
|
||||
{
|
||||
Format(menu_data.children[i]);
|
||||
}
|
||||
}
|
||||
if (menu_data.children.Count() == 0)
|
||||
{
|
||||
menu_data.children = null;
|
||||
}
|
||||
|
||||
return menu_data;
|
||||
}
|
||||
|
||||
public static menu Sort(menu menu_data)
|
||||
{
|
||||
if (menu_data.children != null)
|
||||
{
|
||||
for (int i = menu_data.children.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
menu_data.children = menu_data.children.AsEnumerable().OrderByDescending(u => u.sort).ToList();
|
||||
|
||||
if (menu_data.children != null || menu_data.children.Count() != 0)
|
||||
{
|
||||
Sort(menu_data.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return menu_data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
43
Yi.Framework.Net6/Yi.Framework.Core/Yi.Framework.Core.csproj
Normal file
43
Yi.Framework.Net6/Yi.Framework.Core/Yi.Framework.Core.csproj
Normal file
@@ -0,0 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="2.0.8" />
|
||||
<PackageReference Include="Consul" Version="1.6.10.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
|
||||
<PackageReference Include="NEST" Version="7.16.0" />
|
||||
<PackageReference Include="RabbitMQ.Client" Version="6.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Framework.Common\Yi.Framework.Common.csproj" />
|
||||
<ProjectReference Include="..\Yi.Framework.Model\Yi.Framework.Model.csproj" />
|
||||
<ProjectReference Include="..\Yi.Framework.Task\Yi.Framework.Job.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Bcl.AsyncInterfaces">
|
||||
<HintPath>Library\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ServiceStack.Common">
|
||||
<HintPath>Library\ServiceStack.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ServiceStack.Interfaces">
|
||||
<HintPath>Library\ServiceStack.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ServiceStack.Redis">
|
||||
<HintPath>Library\ServiceStack.Redis.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ServiceStack.Text">
|
||||
<HintPath>Library\ServiceStack.Text.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user