X-Admin&ABP框架开发-消息通知

  业务型网站使用过程当中,消息通知是一个不可或缺的功能,采用站内通知、短信通知、邮件通知、微信通知等等各类方式都有,ABP框架对这部分工做已经封装的很好了,站在巨人的肩膀上,一览全貌,带来的就是心情舒畅。java

   ABP官网地址:https://aspnetboilerplate.com/git

 

1、明确概念及设计

  一次完整的消息发送/接收过程当中,会存在几个必要的点,也正如同现实生活中的场景,有人发送,有人接收,发送的消息自己也有类型。后端

  

一、消息类型定义浏览器

   在ABP中已经提供了消息类型定义的相关类,可是须要咱们去实现,在领域层新建一个Notifications文件夹并添加一个定义经常使用消息类型名称的静态类如AppNotificationNames(名称可随意),在其中开始定义消息类型名称。微信

/// <summary>
/// 设置应用程序中经常使用通知惟一的名称常量
/// </summary>
public static class AppNotificationNames
{
    #region 新的任务
    public const string NewTask = "App.NewTask";
    #endregion

    #region 简单消息
    public const string SimpleMessage = "App.SimpleMessage";
    #endregion
}

   其次,开始消息类型定义,新建一个NotificationProvider的类,完成消息类型定义,管理消息类型时,能够针对消息设置权限,这样方便不一样的角色拥有不一样的消息通知。app

/// <summary>
/// 消息类型定义
/// </summary>
public class AppNotificationProvider : NotificationProvider
{
    /// <summary>
    /// 设置消息类型
    /// </summary>
    /// <param name="context"></param>
    public override void SetNotifications(INotificationDefinitionContext context)
    {
        #region 任务提醒
        context.Manager.Add(
            new NotificationDefinition(
                AppNotificationNames.NewTask,
                displayName: L("NewTask"),
                permissionDependency: new SimplePermissionDependency(PermissionNames.Pages_TaskManage)
            )
        );
        #endregion
    }

    private static ILocalizableString L(string name)
    {
        return new LocalizableString(name, SurroundConsts.LocalizationSourceName);
    }
}

   最后在领域层的Module.PreInitialize()中完成加入。框架

//通知定义
Configuration.Notifications.Providers.Add<AppNotificationProvider>();

 

二、消息订阅方式async

  对于消息订阅环节,是存在两种情形的,第一种,发送方发出的消息,能够指定全部订阅了的人员接收,好比,只有拥有任务管理权限的人才会接收到新的任务下发的通知;第二种就是指定到具体人员接收,好比文件上传完毕的消息通知是通知到负责文件上传的人。ide

   

   消息订阅的管理,在ABP框架中已经封装好了,咱们能够经过构造函数注入直接使用,经过获取系统内的提早定义的全部消息类型,咱们能够在界面上完成订阅工做,为当前用户订阅在他角色权限内的消息通知及无权限限制的消息通知等。函数

private readonly INotificationDefinitionManager _notificationDefinitionManager;
private readonly INotificationSubscriptionManager _notificationSubscriptionManager;

public NotificationAppService(
    INotificationDefinitionManager notificationDefinitionManager,
    INotificationSubscriptionManager notificationSubscriptionManager)
{
    _notificationDefinitionManager = notificationDefinitionManager;
    _notificationSubscriptionManager = notificationSubscriptionManager;
}

 

三、消息发布方式

  

  消息发布时,能够是嵌入在其它操做中,好比制定完成一个新的任务后,发送消息给相关人员,或是在文件上传完毕后,发送给文件上传人员,也能够是定时任务中,指定时间点发送消息,对于这部分来说,在领域层创建一个消息通知的类,来负责处理消息通知,而具体实现消息通知的过程ABP框架中已经实现了,如同消息订阅同样,只须要在构造函数中注入便可,其次定义具体的消息发送方法,使得具体操做结束后调用具体的消息发送来发送消息。

/// <summary>
/// 消息通知发布实例
/// </summary>
public class AppNotifier : DomainService, IAppNotifier
{
    #region 初始化
    private readonly INotificationPublisher _notificationPublisher;

    public AppNotifier(INotificationPublisher notificationPublisher)
    {
        _notificationPublisher = notificationPublisher;
    }
    #endregion

    #region 消息发送
    public async Task SendMessageAsync(UserIdentifier user, string message, NotificationSeverity severity = NotificationSeverity.Info)
    {
        await _notificationPublisher.PublishAsync(
            AppNotificationNames.SimpleMessage,
            new MessageNotificationData(message),
            severity: severity,
            userIds: new[] { user }
        );
    }
    #endregion

    #region 任务提醒
    public async Task NewTaskAsync(string message, NotificationSeverity severity = NotificationSeverity.Info)
    {
        await PublishMessage(AppNotificationNames.NewTask, message);
    }
    #endregion

    #region 辅助方法
    private async Task PublishMessage(string appNotificationName, string message)
    {
        await _notificationPublisher.PublishAsync(appNotificationName, new MessageNotificationData(message));
    }
    #endregion
}

 

2、完成用户订阅消息

   在MVC层,在用户控制器中完成对消息通知设置,消息自己是独立的,只应有了用户才活跃起来,所以把消息的设定挂钩在用户身上,应该算是合理的,并同时完成页面的设计。

/// <summary>
/// 通知设置
/// </summary>
/// <returns></returns>
public async Task<ActionResult> NotificationSetting()
{
    var notificationSettings = await _notificationAppService.GetNotificationSettings();
    return View(notificationSettings);
}

/// <summary>
/// 更新通知订阅
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<JsonResult> UpdateNotificationSetting([FromBody]UpdateNotificationSettingsInput input)
{
    await _notificationAppService.UpdateNotificationSettings(input);
    return Json(new ResponseParamViewModel("通知设置已更新"));
}

   页面设计只须要对提早在领域层中定义好的消息类型展现出来便可,用户自主勾选哪些想要接收的消息提示。

  

 

3、发布消息通知用户

  在指定操做完毕,能够调用消息服务来推送消息到目标接收人员,此处,更改了原先数据字典建立处的代码,当建立数据字典成功后,给与一个消息提示来模拟发布消息通知用户的过程。

var existedDataDictionary = await _dataDictionaryRepository.GetAll().Where(d => d.TypeName == input.DataDictionary.TypeName).FirstOrDefaultAsync();

if (existedDataDictionary != null)
{
    throw new UserFriendlyException(L("该字典类型已存在,没法添加"));
}

var dataDictionary = ObjectMapper.Map<DataDictionary>(input.DataDictionary);
await _dataDictionaryRepository.InsertAsync(dataDictionary);

//模拟测试消息通知
await _appNotifier.NewTaskAsync("字典类型已完成添加,能够开始使用了");

   该消息触发的前提是,须要订阅该消息,否则有人发,无人收,老是很难为情。所以提早在通知设置中开启类型为“新的任务”的开关。

  

  对于消息发送到了浏览器中呈现,这个过程采用了SignalR,ABP框架也完成了先后端的消息通知,所以能够直接使用便可。

 

  至此,站内消息通知的设计完毕,对于业务需求中可能面对的更为丰富的功能就得花更多时间来完成了。 

  代码地址:https://gitee.com/530521314/Partner.Surround.git

 

2019-07-27,望技术有成后能回来看见本身的脚步
相关文章
相关标签/搜索