CAP

  • CAP docs看到更多详细资料。
  • CAP 视频教程,学习如何在项目中集成CAP。
  • GitHub源码:https://github.com/dotnetcore/cap
  • 示例代码:https://github.com/dotnetcore/CAP/tree/master/samples

    过滤器

    在过去,CAP 通过对第三方 AOP 组件提供支持来做到这一点,但了这种方式存在一些缺点,例如无法方便的在代理类中进行构造函数注入以及方法需要设定为 virtual 另外还有拦截器生命周期控制等问题。
    CAP引入了对订阅者过滤器的支持,以使在某些场景(如事务处理,日志记录等)中变得容易。

    自定义过滤器

    创建一个过滤器类,并继承 SubscribeFilter 抽象类。 ```csharp public class MyCapFilter: SubscribeFilter { public override void OnSubscribeExecuting(ExecutingContext context) {

    1. // 订阅方法执行前

    }

    public override void OnSubscribeExecuted(ExecutedContext context) {

    1. // 订阅方法执行后

    }

    public override void OnSubscribeException(ExceptionContext context) {

    1. // 订阅方法执行异常

    } }

  1. 在一些场景中,如果想终止订阅者方法执行,可以在 OnSubscribeExecuting 中抛出异常,并且在 OnSubscribeException 中选择忽略该异常。<br />通过在 ExceptionContext 中设置 context.ExceptionHandled = true 来忽略异常。
  2. ```csharp
  3. public override void OnSubscribeException(ExceptionContext context)
  4. {
  5. context.ExceptionHandled = true;
  6. }
  1. services.AddCap(opt =>
  2. {
  3. // ***
  4. }.AddSubscribeFilter<MyCapFilter>();

过滤器示例

创建一个CAP.Filter.Demo项目,使用CAP之消息的项目代码,

  1. Install-Package DotNetCore.CAP
  2. Install-Package DotNetCore.CAP.InMemoryStorage
  3. Install-Package Savorboard.CAP.InMemoryMessageQueue

创建一个过滤器类,并继承 SubscribeFilter 抽象类。

  1. using DotNetCore.CAP.Filter;
  2. namespace CAP.Filter.Demo.Filter;
  3. public class MyCapFilter : SubscribeFilter
  4. {
  5. public override void OnSubscribeExecuting(ExecutingContext context)
  6. {
  7. // 订阅方法执行前
  8. Console.WriteLine("订阅方法执行前");
  9. }
  10. public override void OnSubscribeExecuted(ExecutedContext context)
  11. {
  12. // 订阅方法执行后
  13. Console.WriteLine("订阅方法执行后");
  14. }
  15. public override void OnSubscribeException(ExceptionContext context)
  16. {
  17. // 订阅方法执行异常
  18. Console.WriteLine("订阅方法执行异常");
  19. //忽略异常
  20. //context.ExceptionHandled = true;
  21. }
  22. }
  1. builder.Services.AddCap(config =>
  2. {
  3. config.UseInMemoryMessageQueue(); //配置一个消息队列
  4. config.UseInMemoryStorage(); //配置一个事件存储
  5. }).AddSubscribeFilter<MyCapFilter>();//配置过滤器

公共部分

  1. using Microsoft.AspNetCore.Mvc;
  2. namespace CAP.Filter.Demo.Controllers;
  3. /// <summary>
  4. /// 基础控制器
  5. /// </summary>
  6. [Route("api/[area]/[controller]/[action]")]
  7. [ApiController]
  8. public abstract class BaseController : ControllerBase
  9. {
  10. }
  1. using Microsoft.AspNetCore.Mvc;
  2. namespace CAP.Filter.Demo.Controllers.Order;
  3. /// <summary>
  4. /// 域控制器
  5. /// </summary>
  6. [Area("Order")]
  7. public abstract class AreaController : BaseController
  8. {
  9. }

发布消息

新建立一个PublishController

  1. using DotNetCore.CAP;
  2. using Microsoft.AspNetCore.Mvc;
  3. using System.Text.Json;
  4. namespace CAP.Filter.Demo.Controllers.Order;
  5. /// <summary>
  6. /// 发送消息
  7. /// </summary>
  8. public class PublishController : AreaController
  9. {
  10. ICapPublisher _capBus;
  11. public PublishController(ICapPublisher capBus)
  12. {
  13. _capBus = capBus;
  14. }
  15. /// <summary>
  16. /// 订单处理示例
  17. /// </summary>
  18. /// <returns></returns>
  19. [HttpGet]
  20. public IActionResult PublisherMessage()
  21. {
  22. Console.WriteLine("订单处理示例");
  23. //商品数量扣除调用模拟的ConsumerController的place.order.qty.deducted
  24. _capBus.Publish("place.order.qty.deducted",
  25. contentObj: new { OrderId = 1234, ProductId = 23255, Qty = 1 },
  26. //当商品数量成功扣除时将状态标记为 succeeded ,否则为 failed
  27. callbackName: "place.order.mark.status");
  28. return Ok();
  29. }
  30. /// <summary>
  31. /// 当商品数量成功扣除时将状态标记为 succeeded ,否则为 failed
  32. /// </summary>
  33. /// <param name="param"></param>
  34. [NonAction]//表示控制器方法不是动作方法
  35. [CapSubscribe("place.order.mark.status")]
  36. public void MarkOrderStatus(JsonElement param)
  37. {
  38. var orderId = param.GetProperty("OrderId").GetInt32();
  39. var isSuccess = param.GetProperty("IsSuccess").GetBoolean();
  40. if (isSuccess)
  41. {
  42. // mark order status to succeeded
  43. }
  44. else
  45. {
  46. // mark order status to failed
  47. }
  48. }
  49. }

处理消息

新建立一个ConsumerController

  1. using DotNetCore.CAP;
  2. using Microsoft.AspNetCore.Mvc;
  3. using System.Text.Json;
  4. namespace CAP.Filter.Demo.Controllers.Order;
  5. /// <summary>
  6. /// 处理消息
  7. /// </summary>
  8. [ApiController]
  9. public class ConsumerController : ControllerBase
  10. {
  11. /// <summary>
  12. /// 订阅方法-商品数量扣除处理
  13. /// </summary>
  14. /// <param name="param"></param>
  15. /// <returns></returns>
  16. [NonAction]//表示控制器方法不是动作方法
  17. [CapSubscribe("place.order.qty.deducted")]
  18. public object DeductProductQty(JsonElement param)
  19. {
  20. Console.WriteLine("商品数量扣除处理被调用");
  21. var orderId = param.GetProperty("OrderId").GetInt32();
  22. var productId = param.GetProperty("ProductId").GetInt32();
  23. var qty = param.GetProperty("Qty").GetInt32();
  24. //business logic
  25. return new { OrderId = orderId, IsSuccess = true };
  26. }
  27. }

目录结构

1663586499838.png

测试

http://localhost:5017/api/Order/Publish/PublisherMessage
1663586516965.png
1663586544898.png