@

假设有一个按照官方sample搭建的微服务项目,并安装好了abp-cli。

需要创建一个名为GDMK.CAH.Common的模块,并在模块中创建标签管理功能

因为大部分的代码是自动生成的,此示例仅描述需要手动更改的内容。我们以创建一个全新的最小化的微服务模块为例,需要做以下几步:

创建模块

用abp-cli创建一个新的模块

在项目根目录下执行以下命令:

abp new GDMK.CAH.Common --template module --no-ui --ui='none' -d='ef' --output-folder .\modules\GDMK.CAH.Common --local-framework-ref --abp-path ..\..\..\..\abp\

--template module: 模块/服务模板

--no-ui: 不创建前端项目

-d: 指定数据库提供程序为ef.

--output-folder: 指定输出目录

--local-framework-ref: 使用本地abp框架

你可以自由设定模板选项,详情请参考abp-cli文档

我们只需要保留应用层,领域层,数据库,Api访问层以及各抽象层。将这些项目放在模块目录下,即当前位置(.\modules\GDMK.CAH.Common)

Common.Host项目作为微服务单独放置在服务目录中(一般为microservices)

看起来模块的目录结构如下

领域层

领域层中我们创建一个Tag实体、领域层服务和模型

Tag实体

public class Tag : AuditedEntity<long>, IMultiTenant
{
...
}

Tag领域层服务

public class TagManager<T> : DomainService
{
...
}

页面结构看起来像这样

应用层

在应用层抽象层中创建ITagAppService接口,以及各Dto类。

ITagAppService接口继承ICurdAppService,实现标签管理的增删改查功能

public interface ITagAppService : ICurdAppService<TagDto, TagDto, long, GetAllTagInput, GetAllTagInput, CreateTagInput, CreateTagInput>, IApplicationService
{
...
}

页面结构看起来像这样

应用层中创建标签管理的应用层服务TagAppService

TagAppService继承CurdAppServiceBase,实现ITagAppService接口

public class TagAppService : CurdAppServiceBase<Tag, TagDto, TagDto, long, GetAllTagInput, GetAllTagInput, CreateTagInput, CreateTagInput>, ITagAppService
{
...
}

配置AutoMapper

在CommonApplicationAutoMapperProfile中添加Tag的映射配置

public class CommonApplicationAutoMapperProfile : Profile
{
public CommonApplicationAutoMapperProfile()
{
/* You can configure your AutoMapper mapping configuration here.
* Alternatively, you can split your mapping configurations
* into multiple profile classes for a better organization. */
CreateMap<Tag.Tag, TagDto>(); CreateMap<TagDto, Tag.Tag>().Ignore(c => c.TenantId);
CreateMap<CreateTagInput, Tag.Tag>().IgnoreAuditedObjectProperties()
.Ignore(c => c.TenantId); }
}

数据库和仓储

在CommonDbContext中添加Tag的DbSet

public class CommonDbContext : AbpDbContext<CommonDbContext>, ICommonDbContext
{
/* Add DbSet for each Aggregate Root here. Example:
* public DbSet<Question> Questions { get; set; }
*/
public DbSet<Tag.Tag> Tag { get; set; } ...
}

在CommonDbContextModelCreatingExtensions中添加对Tag实体的配置

ConfigureByConvention会根据DataAnnotationAttributes为实体配置一些默认的属性,如Id为主键,Name为索引等,详情请参考Abp文档EF文档

public static class CommonDbContextModelCreatingExtensions
{
public static void ConfigureCommon(
this ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder)); builder.Entity<Tag.Tag>(b =>
{
b.ToTable(CommonDbProperties.DbTablePrefix + nameof(Tag.Tag), CommonDbProperties.DbSchema); b.ConfigureByConvention(); }); ...
}
}

在CommonEntityFrameworkCoreModule的ConfigureServices方法中,为Tag添加默认仓储

public class CommonEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<CommonDbContext>(options =>
{
/* Add custom repositories here. Example:
* options.AddRepository<Question, EfCoreQuestionRepository>();
*/
options.AddDefaultRepositories(includeAllEntities: true); }); }
}

控制器

添加控制器,配置路由

[Area(CommonRemoteServiceConsts.ModuleName)]
[RemoteService(Name = CommonRemoteServiceConsts.RemoteServiceName)]
[Route("api/Common/tag")]
public class TagController : CommonController<ITagAppService, TagDto, TagDto, long, GetAllTagInput, GetAllTagInput, CreateTagInput, CreateTagInput>, ITagAppService
{
private readonly ITagAppService _tagAppService; public TagController(ITagAppService tagAppService) : base(tagAppService)
{
_tagAppService = tagAppService;
} }

配置微服务

在服务目录中打开Common.Host项目,将CommonHttpApi,CommonApplication以及CommonEntityFrameworkCore模块添加到项目引用,并建立Abp模块的依赖关系

    [DependsOn(
typeof(AbpAutofacModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpEntityFrameworkCoreSqlServerModule), typeof(CommonHttpApiModule),
typeof(CommonApplicationModule),
typeof(CommonEntityFrameworkCoreModule),
...
)]
public class CommonServiceHostModule : AbpModule

在launchSettings.json中指定端口号,此端口号不要跟其他服务的端口号冲突

"profiles": {
"CommonService.Host": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:44363",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
...
}

准备一些种子数据

public static List<Tag> tags = new List<Tag>()
{
new Tag() { Title = "医术高明" },
new Tag() { Title = "救死扶伤" },
new Tag() { Title = "心地仁慈" },
new Tag() { Title = "百治百效" },
new Tag() { Title = "白衣天使" },
new Tag() { Title = "手到病除" },
new Tag() { Title = "妙手回春" },
};

在CommonServiceDataSeeder创建种子数据

public class CommonServiceDataSeeder : IDataSeedContributor, ITransientDependency
{
private readonly IRepository<Tag.Tag, long> _tagRepository; public CommonServiceDataSeeder(
IRepository<Tag.Tag, long> tagRepository)
{
_tagRepository = tagRepository; } [UnitOfWork]
public virtual async Task SeedAsync(DataSeedContext context)
{
await _tagRepository.InsertManyAsync(StaticMember.tags);
} }

创建迁移

将Common.Host设置为启动项目,打开程序包管理器控制台选择Common.Host默认项目。

执行Add-Migration init命令和Update-Database命令

测试微服务

启动Common.Host,打开浏览器,输入http://localhost:44363/swagger/index.html

微服务注册

添加资源配置

AuthServerDataSeeder中添加identityServer4资源配置

添加Scopes

private async Task CreateApiScopesAsync()
{
...
await CreateApiScopeAsync("CommonService");
}

添加Resource

private async Task CreateApiResourcesAsync()
{
...
await CreateApiResourceAsync("CommonService", commonApiUserClaims); }

添加Client

private async Task CreateClientsAsync()
{
...
await CreateClientAsync(
"common-service-client",
commonScopes.Union(new[] { "InternalGateway", "IdentityService" }),
new[] { "client_credentials" },
commonSecret
);
}

配置网关

在内外网关的appsettings.json中添加Ocelot对微服务的路由转发

 {
"DownstreamPathTemplate": "/api/common/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44363
}
],
"UpstreamPathTemplate": "/api/common/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
}

网关中添加对CommonHttpApi项目的引用,并配置Abp模块依赖

namespace BackendAdminAppGateway.Host
{
[DependsOn(
...
typeof(CommonHttpApiModule)
)]
public class BackendAdminAppGatewayHostModule : AbpModule ...

选择启动项目,将Common.Host微服务设置为启动

到此完成了新模块的配置工作

运行项目

可以通过网关访问Tag接口了

Volo.Abp升级小记(二)创建全新微服务模块的更多相关文章

  1. SpringCloud系列二:Restful 基础架构(搭建项目环境、创建 Dept 微服务、客户端调用微服务)

    1.概念:Restful 基础架构 2.具体内容 对于 Rest 基础架构实现处理是 SpringCloud 核心所在,其基本操作形式在 SpringBoot 之中已经有了明确的讲解,那么本次为 了清 ...

  2. ABP VNext从单体切换到微服务

    注:此处的微服务只考虑服务部分,不考虑内外层网关.认证等. ABP VNext从单体切换到微服务,提供了相当大的便利性,对于各模块内部不要做任何调整,仅需要调整承载体即可. ABP can help ...

  3. JHipster生成微服务架构的应用栈(二)- 认证微服务示例

    本系列文章演示如何用JHipster生成一个微服务架构风格的应用栈. 环境需求:安装好JHipster开发环境的CentOS 7.4(参考这里) 应用栈名称:appstack 认证微服务: uaa 业 ...

  4. maven 聚合工程 用spring boot 搭建 spring cloud 微服务 模块式开发项目

    项目的简单介绍: 项目采用maven聚合工程 用spring boot 搭建 spring cloud的微服务 模块式开发 项目的截图: 搭建开始: 能上图 我少打字 1.首先搭建maven的聚合工程 ...

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

    @ 目录 原理分析 开始改造 更换基类型 重写接口 替换默认规则 在微服务架构中的问题 Volo.Abp 配置应用层自动生成Controller,增删查改服务(CrudAppService)将会以RE ...

  6. Docker(二):微服务教程

    Docker 是一个容器工具,提供虚拟环境.很多人认为,它改变了我们对软件的认识. 站在 Docker 的角度,软件就是容器的组合:业务逻辑容器.数据库容器.储存容器.队列容器......,Docke ...

  7. 持续提升程序员幸福指数——使用abp vnext设计一款面向微服务的单体架构

    可能你会面临这样一种情况,在架构设计之前,你对业务不甚了解,需求给到的也模棱两可,这个时候你既无法明确到底是要使用单体架构还是使用微服务架构,如果使用单体,后续业务扩展可能带来大量修改,如果使用微服务 ...

  8. 微服务理论之二:面向微服务架构与传统架构、SOA对比,以及云化对比

    一.Monolith 网上对Microservice进行介绍的文章常常以Monolith作为开头,我也不会例外.原因是,知道了Monolith的不便之后才能更容易地理解Microservice架构模式 ...

  9. 二、springcloud微服务测试环境搭建

    版本说明: springcloud:Greenwich.SR3 springboot:2.1.8 1.构建步骤 1.1.microservicecloud整体父工程Project 新建父工程micro ...

  10. SpringCloud学习笔记(二):微服务概述、微服务和微服务架构、微服务优缺点、微服务技术栈有哪些、SpringCloud是什么

    从技术维度理解: 微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底 地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事, 从技术角度看就是一种小而独立的处理过程,类 ...

随机推荐

  1. Hugging News #0324: 🤖️ 黑客松结果揭晓、一键部署谷歌最新大语言模型、Gradio 新版发布,更新超多!

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...

  2. golang 中的 cronjob

    引言 最近做了一个需求,是定时任务相关的.以前定时任务都是通过 linux crontab 去实现的,现在服务上云(k8s)了,尝试了 k8s 的 CronJob,由于公司提供的是界面化工具,使用.查 ...

  3. JAVA基础——常用类(一)

     首先认识到--String是不可以变性(final) String:字符串,使用一对""引起来表示.      * 1.String声明为final的,不可被继承      * ...

  4. 二进制安装Kubernetes(k8s) v1.24.2 IPv4/IPv6双栈

    二进制安装Kubernetes(k8s) v1.24.2 IPv4/IPv6双栈 Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes二进制安装 强烈建议在Github ...

  5. list列表和tuple、条件判断、循环、dict和set、调用函数、定义函数

    1.list列表是有序的可变的列表,可以进通过append()方法末尾添加,通过pop删除末尾以及根据索引pop(i)来删除指定索引对应的元素 通过给指定的列表元素赋值更改元素值,通过列表的索引查看元 ...

  6. 【Java Se】JDBC

    启停服务 net start mysql net stop mysql 登录 mysql -u -p 访问指定IP的mysql mysql -u root -P 3306 -h localhost - ...

  7. 基于Java实现数据脱敏

    用法 Jdk版本 大于等于1.8 maven依赖 <dependency> <groupId>red.zyc</groupId> <artifactId> ...

  8. JS执行机制--同步与异步

    单线程JavaScript语言具有单线程的特点,同一个时间只能做一件事情.这是因为JavaScript脚本语言是为了处理页面中用户的交互,以及操作DOM而诞生的.如果对某个DOM元素进行添加和删除,不 ...

  9. Spring源码系列:核心概念解析

    前言 本文旨在为读者解析Spring源码中的关键类,以便读者在深入阅读源码时,能够了解关键类的作用和用途.在阅读Spring源码时,经常会遇到一些不熟悉的概念,了解关键类的作用可以帮助读者更好地理解这 ...

  10. 使用RAMMap+PoolMon分析Windows内存异常使用问题

    由于技术能力有限,文章仅能进行简要分析和说明,如有不对的地方,请指正,谢谢. 1 RAMMap和PoolMon工具简介 RAMMap和PoolMon都是微软Sysinternals的工具,前者可以从使 ...