• 首页
  • 粮食
  • 蔬菜
  • 果品
  • 水产
  • 酒水
  • 饮料
  • 茶叶
  • 畜禽
  • 食用油
  • 资讯
logo
  • 首页>
  • 水产 >
  • 正文

[Volo.Abp升级笔记]使用旧版Api规则替换RESTful Api以兼容老程序

2023-03-29 11:28:05 来源:博客园

@


(资料图片仅供参考)

目录原理分析开始改造更换基类型重写接口替换默认规则在微服务架构中的问题Volo.Abp 配置应用层自动生成Controller,增删查改服务(CrudAppService)将会以RESTful Api的方式生成对应的接口(官方文档),这与旧版本的Abp区别很大。RESTful固然好,虽然项目里新的Api会逐步使用RESTful Api代替旧的,但在前后端分离的项目中已经定好的接口,往往需要兼容之前的方式。原理分析

旧版行为

应用层继承于AsyncCrudAppService的类,在Web层调用CreateControllersForAppServices后,Abp框架将以默认的规则实现Controller,具体的规则如下:

Get: 如果方法名称以GetList,GetAll或Get开头.Put: 如果方法名称以Put或Update开头.Delete: 如果方法名称以Delete或Remove开头.Post: 如果方法名称以Create,Add,Insert或Post开头.Patch: 如果方法名称以Patch开头.其他情况, Post 为 默认方式.自动删除"Async"后缀.

例子:

新版行为:将会以RESTful Api的方式生成对应的接口,具体规则如下

服务方法名称HTTP MethodRoute
GetAsync(Guid id)GET/api/app/book/
GetListAsync()GET/api/app/book
CreateAsync(CreateBookDto input)POST/api/app/book
UpdateAsync(Guid id, UpdateBookDto input)PUT/api/app/book/
DeleteAsync(Guid id)DELETE/api/app/book/
GetEditorsAsync(Guid id)GET/api/app/book/{id}/editors
CreateEditorAsync(Guid id, BookEditorCreateDto input)POST/api/app/book/{id}/editor

例子

开始改造更换基类型

为了兼容旧版Abp,先来还原增删查改服务(CrudAppService)的方法签名。注意到

Volo.Abp 中 UpdateAsync方法签名已与旧版不同旧版中的GetAllAsync方法,被GetListAsync所取代。

新建一个CrudAppServiceBase类继承 CrudAppService。并重写UpdateAsync和GetListAsync方法。

为了还原旧版的接口,将用private new关键字覆盖掉 UpdateAsync,GetListAsync方法,并重新实现更改和查询列表的功能

public abstract class CrudAppServiceBase    : CrudAppService    where TEntity : class, IEntity        where TGetOutputDto : IEntityDtowhere TGetListOutputDto : IEntityDto{    protected CrudAppServiceBase(IRepository repository): base(repository)    {    }    private new Task UpdateAsync(TKey id, TUpdateInput input)    {        return base.UpdateAsync(id, input);    }    private new Task> GetListAsync(TGetListInput input)    {        return base.GetListAsync(input);    }    public virtual async Task UpdateAsync(TUpdateInput input)    {        await CheckUpdatePolicyAsync();        var entity = await GetEntityByIdAsync((input as IEntityDto).Id);        MapToEntity(input, entity);        await Repository.UpdateAsync(entity, autoSave: true);        return await MapToGetOutputDtoAsync(entity);    }    public virtual Task> GetAllAsync(TGetListInput input)    {        return this.GetListAsync(input);    }   }

基于扩展性考虑,我们可以像官方实现一样做好类型复用

public abstract class CrudAppServiceBase    : CrudAppServiceBase    where TEntity : class, IEntity    where TEntityDto : IEntityDto{    protected CrudAppServiceBase(IRepository repository)        : base(repository)    {    }}public abstract class CrudAppServiceBase    : CrudAppServiceBase    where TEntity : class, IEntity    where TEntityDto : IEntityDto{    protected CrudAppServiceBase(IRepository repository)        : base(repository)    {    }}public abstract class CrudAppServiceBase    : CrudAppServiceBase    where TEntity : class, IEntity    where TEntityDto : IEntityDto{    protected CrudAppServiceBase(IRepository repository)        : base(repository)    {    }}public abstract class CrudAppServiceBase: CrudAppServiceBasewhere TEntity : class, IEntitywhere TEntityDto : IEntityDto{    protected CrudAppServiceBase(IRepository repository)        : base(repository)    {    }    protected override Task MapToGetListOutputDtoAsync(TEntity entity)    {        return MapToGetOutputDtoAsync(entity);    }    protected override TEntityDto MapToGetListOutputDto(TEntity entity)    {        return MapToGetOutputDto(entity);    }}
重写接口

重写增删查改服务接口

public interface IBaseCrudAppService    {        Task GetAsync(TKey id);        Task> GetAllAsync(TGetListInput input);        Task CreateAsync(TCreateInput input);        Task UpdateAsync(TUpdateInput input);        Task DeleteAsync(TKey id);    }

基于扩展性考虑,我们可以像官方实现一样做好类型复用

public interface IBaseCrudAppService    : IBaseCrudAppService{}public interface IBaseCrudAppService    : IBaseCrudAppService{}public interface IBaseCrudAppService    : IBaseCrudAppService{}public interface IBaseCrudAppService    : IBaseCrudAppService{}

将应用服务接口IReservationAppService继承于IBaseCrudAppService和IApplicationService

public interface IReservationAppService: IBaseCrudAppService, IApplicationService{    //除增删查改业务的其他业务}

创建应用服务类ReservationAppService,此时应用服务派生自CrudAppServiceBase,应用服务应该会完全实现接口

public class ReservationAppService : CrudAppServiceBase, IReservationAppService{    ...}
替换默认规则

Abp封装了Controller自动生成规则,利用了Asp.Net MVC的约定接口IApplicationModelConvention,这一特性,所谓规则即Convention,AbpServiceConvention是此接口的实现类,在此类中约定了如何将应用层程序集增删查改服务(CrudAppService)中的成员方法,按上述规则生成Controller。

规则的具体代码封装在ConventionalRouteBuilder里

既然是默认规则方式,我们就重写一个自定义的Convention来代替它默认的那个。假设有领域Workflow,在Web层中新建WorkflowServiceConvention,把原AbpServiceConvention类中的所有内容复制到这个类中

public class WorkflowServiceConvention : IAbpServiceConvention, ITransientDependency{}

将不需要用到的对象删掉

// 删除 protected IConventionalRouteBuilder ConventionalRouteBuilder { get; } 

重写CreateAbpServiceAttributeRouteModel

protected virtual AttributeRouteModel CreateAbpServiceAttributeRouteModel(string rootPath, string controllerName, ActionModel action, string httpMethod, [CanBeNull] ConventionalControllerSetting configuration){    return new AttributeRouteModel(        new RouteAttribute(                $"api/services/{rootPath}/{controllerName}/{action.ActionName}"        )    );}

在Web层的Module文件WorkflowHostModule中,添加WorkflowApplicationModule

Configure(options =>{    options        .ConventionalControllers        .Create(typeof(WorkflowApplicationModule).Assembly);});

用WorkflowServiceConvention替换原始的AbpServiceConvention实现。

Configure(options =>{    options.Conventions.RemoveAt(0);    options.Conventions.Add(convention.Value);});
在微服务架构中的问题

Asp.Net MVC在微服务的网关层中无法通过仅引用应用层方法的接口,生成Controller,即便改写 ControllerFeatureProvider, 还是需要引用实现类,这些实现类在应用层中。但网关仅仅依赖定义层,若要拿到实现类,将改变微服务架构的依赖关系。

在官方的微服务实例中,也没有用Controller的自动生成,在这个issue中作者也给出了解答https://github.com/abpframework/abp/issues/1731

因此如果想达到目的,只能用重写controller基类的方式了,这个方式好处在于简单好用,可读性和可维护性高,缺陷就是每写一个应用层类,需要写一个对应的Controller类,但在项目不多用CV大法还是可以接受的。

新建WorkflowController并继承于AbpControllerBase,并创建增删查改(Curd)的终结点路由,通过调用ITAppService的方法,实现各业务功能

public abstract class WorkflowController    : AbpControllerBasewhere ITAppService : IBaseCrudAppService        where TGetOutputDto : IEntityDtowhere TGetListOutputDto : IEntityDto{    protected WorkflowController()    {        LocalizationResource = typeof(WorkflowResource);    }    private readonly ITAppService _recipeAppService;    public WorkflowController(ITAppService recipeAppService)    {        _recipeAppService = recipeAppService;    }    [HttpPost]    [Route("Create")]    public async Task CreateAsync(TCreateInput input)    {        return await _recipeAppService.CreateAsync(input);    }    [HttpDelete]    [Route("Delete")]    public async Task DeleteAsync(TKey id)    {        await _recipeAppService.DeleteAsync(id);    }    [HttpGet]    [Route("GetAll")]    public async Task> GetAllAsync(TGetListInput input)    {        return await _recipeAppService.GetAllAsync(input);    }    [HttpGet]    [Route("Get")]    public async Task GetAsync(TKey id)    {        return await _recipeAppService.GetAsync(id);    }    [HttpPut]    [Route("Update")]    public async Task UpdateAsync(TUpdateInput input)    {        return await _recipeAppService.UpdateAsync(input);    }}

基于扩展性考虑,我们可以做好类型复用

public abstract class WorkflowController      : WorkflowController      where ITAppService : IBaseCrudAppService      where TEntityDto : IEntityDto{    protected WorkflowController(ITAppService appService)        : base(appService)    {    }}public abstract class WorkflowController    : WorkflowController    where ITAppService : IBaseCrudAppService    where TEntityDto : IEntityDto{    protected WorkflowController(ITAppService appService)        : base(appService)    {    }}public abstract class WorkflowController : WorkflowController where ITAppService : IBaseCrudAppService where TEntityDto : IEntityDto{    protected WorkflowController(ITAppService appService)        : base(appService)    {    }}public abstract class WorkflowController: WorkflowControllerwhere ITAppService : IBaseCrudAppServicewhere TEntityDto : IEntityDto{    protected WorkflowController(ITAppService appService)        : base(appService)    {    }}

创建实际的Controller,定义Area名称和Controller路由“api/Workflow/reservation”

此时Controller派生自WorkflowController,应用服务应该会完全实现接口

[Area(WorkflowRemoteServiceConsts.ModuleName)][RemoteService(Name = WorkflowRemoteServiceConsts.RemoteServiceName)][Route("api/Workflow/reservation")]public class ReservationController : WorkflowController, IReservationAppService{    private readonly IReservationAppService _reservationAppService;    public ReservationController(IReservationAppService reservationAppService):base(reservationAppService)    {        _reservationAppService = reservationAppService;    }}

运行程序,我们将得到一个旧版的接口

每次为新的应用服务类创建Controller,只需要新建一个派生自WorkflowController类的Controller,并指定一个应用服务类对象。就完成了,不需要自己写一大堆的控制器方法。

关键词:

    为您推荐

  • [Volo.Abp升级笔记]使用旧版Api规则替换RESTful Api以兼容老程序

    水产2023-03-29
  • 文学的功能_关于文学的功能简介 环球新要闻

    水产2023-03-29
  • 破解县域电商货源不优难题-观热点

    水产2023-03-29
  • 当前观点:3月29日生意社醋酸丁酯基准价为7337.50元/吨

    水产2023-03-29
  • 焦点热议:英方禁止政府人员使用TikTok 驻英大使表态

    水产2023-03-29
  • 国家智慧教育读书平台正式上线

    水产2023-03-29
  • 广州市检察院数字检察工作办公室揭牌成立 每日速递

    水产2023-03-29
  • 崔永熙32分祝铭震19+10 广州5人上双力克福建斩获三连胜 焦点速读

    水产2023-03-28
  • 海得控制:拟购买行芝达75%股权 3月29日复牌

    水产2023-03-28
  • 【寻味中华】虫与叶的“邂逅” 台湾东方美人茶香两岸

    水产2023-03-28
  • 天天热文:动物园白狐胖成“煤气罐” 官方回应:这是为御寒 夏天会变瘦

    水产2023-03-28
  • 每日报道:露笑科技(002617.SZ):拟斥2亿元-3亿元回购公司股份

    水产2023-03-28
  • 同济医院动物实验新发现:一种免疫治疗方法有望用于晚期肝癌治疗

    水产2023-03-28
  • 天天即时:赛隆药业:赛隆聚智拟减持公司不超1%股份

    水产2023-03-28
  • 与辩证法相对立的是什么_与辩证法相对立的思维形态是

    水产2023-03-28
  • 太空垃圾光污染严重 天空正在飞速变化_头条

    水产2023-03-28
  • 博腾股份业绩增三倍 大客户“依赖症”严重 66%收入来自第一大客户 环球新动态

    水产2023-03-28
  • 环球热资讯!2023年2月大宗商品-石脑油价格分析:价格为8221.5元/吨,同比下降9.74%

    水产2023-03-28
  • 数字经济和AI背后共有的数据生态机遇 世界新消息

    水产2023-03-28
  • 天天亮点!郗鉴渣男_时太尉郗鉴使门生翻译

    水产2023-03-28

果品

  • 吃一颗杨梅等于吃10条虫子? 专家提醒:这些说法对不对?
  • 北京2022年冬奥会、冬残奥会奖牌“同心”正式发布
  • 冬奥故事会丨一图了解冬奥会历届奖牌
  • 同心筑梦向未来——写在北京冬奥会开幕倒计时100天之际
  • 外交部:美国针对亚裔仇恨犯罪数字令人痛心

蔬菜

  • 说好“一梯一户”却成了“两梯两户”,买方能否解除合同?
  • 更高水平开放合作助力中国东盟经贸发展迎新机遇
  • 9被告人犯侵犯著作权罪被判刑罚
  • 玉渊谭天丨中美再通话,“建设性”很重要
  • 环球时报社评:中美经贸需要建设性对话
  • 俄媒:莫斯科扩大新冠感染新疗法试点范围
  • 冰雪之约 中国之邀 | 追赶的勇气
  • 中国第20批赴黎维和建筑工兵分队完成“VA-2”道路排水系统修缮任务
  • 中国常驻联合国代表团举办恢复联合国合法席位50周年图片展
  • 美专家认为三大原因导致美国供应链危机

Copyright   2015-2022 大西洋食品网 版权所有  备案号:沪ICP备2020036824号-2   联系邮箱: 562 66 29@qq.com