一 新建Project
1 控制台程序
2 Net core版本 : >= 2.1
二 引用Nuget包
Agebull.ZeroNet.Core
三 编码
Program.cs:
using Agebull.Common.Ioc;
using Agebull.ZeroNet.Core;
using Agebull.ZeroNet.ZeroApi;
namespace ApiTest
{
partial class Program
{
static void Main(string[] args)
{
ZeroApplication.CheckOption();
ZeroApplication.Discove(typeof(AutoRegister).Assembly);
ZeroApplication.Initialize();
ZeroApplication.RunAwaite();
}
}
}
代码说明:
1 ZeroApplication.CheckOption();
必须是第一句,它会处理你的所有配置文件
2 ZeroApplication.Discove(typeof(AutoRegister).Assembly);
这句的目的是自动发现对应程序集中的 ZeroObject对象(如ApiStation\SubStation\PubStation) ,如果存在API站点,将处理以下几件事:
- 生成动态程序集,注入到API调用链中
- 分析你的接口与对应注释,生成帮助文件.
- ZeroApplication.Initialize();
初始化发现的ZeroObject对象,以保证能正常运行
3 ZeroApplication.RunAwaite();
运行站点,并在接收到系统中止信号时正确关闭站点
流程描述如下:
- 1 与ZeroCenter握手 , 如果失败,则跳过2-3步,直接执行第4步
- 2 获取所有站点配置
- 3 启动每一个站点
3.1 检查是否存在对应站点配置文件,在配置文件不存在时
3.1.1 如果是ApiStation,会执行自动安装后继续运行(注意会分配一组端口地址)
3.1.2 如果是其它,则不继续运行站点
3.2 运行站点进入网络侦听
3.3 处理请求 - 4 运行SystemMonitor,用于接收系统消息
4.1 接收站点状态事件
4.2 接收站点启动,暂停,继续,关闭,卸载事件,并进行本地同步处理
启动:对应站点单独执行步骤3
4.3 接收ZeroCenter 关闭与启动事件,并进行本地同步处理 - 5 ZeroCenter 关闭时将中止所有站点
- 6 ZeroCenter 启动时将执行2-3步
ApiControl
using Agebull.ZeroNet.ZeroApi;
using Gboxt.Common.DataModel;
using System.ComponentModel;
namespace ApiTest
{
/// <summary>
/// 登录服务
/// </summary>
[Station("Login")]
public class LoginStation : ZeroApiController
{
/// <summary>
/// 登录
/// </summary>
/// <param name="user">用户信息</param>
/// <returns>登录状态</returns>
[Route("api/login"), Category("登录")]
[ApiAccessOptionFilter(ApiAccessOption.Anymouse | ApiAccessOption.Public)]
public ApiResult Login(LoginArg user)
{
return new ApiResult
{
Success = true,
Status = new ApiStatsResult
{
ErrorCode = 0,
ClientMessage = $"Wecome {user.MobilePhone}!"
}
};
}
}
}
与WebApi基本兼容
1 继承于ZeroApiController
2 Station特性
- 如果此Controler的站点名称不同于配置文件中的名称,可在此独立命名.
- 如无此特性,将合并到配置文件对应的StationName的站点(我们称为全局站点).
- 限制,如果用全局站点,每一个Controler中的方法名称不能相同
3 api定义
- 必须为实例方法(非static)
- public (当前未限制,但不保证未来会进行限制,所以请遵行此原则)
- Route特性 : 与WebApi相同,即暴露的Api名称,必须存在
- Category 特性 : 用于在生成文档时进行分类
- ApiAccessOptionFilter特性 : 配置此API的访问权限,组合有效
名称 | 说明 | 令牌校验 |
---|---|---|
None | 不可访问 | |
Public | 公开访问 | |
Internal | 内部访问 | |
ArgumentCanNil | 参数可以为null | |
Anymouse | 游客可访问 | DeviceId |
Customer | 登录客户可访问 | AccessToken |
Employe | 内部员工可访问 | AccessToken |
Business | 商家用户可访问 | AccessToken |
User1-8 | 扩展用户性质可访问 | AccessToken |
4 Api 参数
using Agebull.ZeroNet.ZeroApi;
using Gboxt.Common.DataModel;
using System.Text.RegularExpressions;
namespace ApiTest
{
/// <summary>
/// 登录参数
/// </summary>
public class LoginArg : IApiArgument
{
/// <summary>
/// 手机号
/// </summary>
/// <value>11位手机号,不能为空</value>
/// <example>15618965007</example>
[DataRule(CanNull = false, Max = 11, Min = 11, Regex = "1[3-9]\\d{9,9}")]
public string MobilePhone { get; set; }
/// <summary>
/// 密码
/// </summary>
/// <value>6-16位特殊字符\字母\数字组成,特殊字符\字母\数字都需要一或多个,不能为空</value>
/// <example>pwd#123</example>
[DataRule(CanNull = false, Max = 6, Min = 16, Regex = "[\\da-zA-Z~!@#$%^&*]{6,16}")]
public string UserPassword { get; set; }
/// <summary>
/// 验证码
/// </summary>
/// <value>6位字母或数字,不能为空</value>
/// <example>123ABC</example>
[DataRule(CanNull = false, Max = 6, Min = 6, Regex = "[a-zA-Z\\d]{6,6}")]
public string VerificationCode { get; set; }
/// <summary>
/// 校验
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
bool IApiArgument.Validate(out string message)
{
message = null;
return true;
}
}
}
- 只允许一个参数且继承于IApiArgument
- IApiArgument.Validate :
如果有参数的校验,应在此处实现,此方法早于进入API时处理,并在校验不通过的情况直接返回错误
返回参数校验错误时,不会进入API处理方法,Debug时要特别注意
当只有一个参数时,可使用Argument类
- Argument : 非泛型版本,Value为string类型参数
- Argument<> : 泛型版本,Value可为各种值类型参数
注释与Api文档的关系
- summary : 对应字段的名称
- remarks : 对应字段的说明
- example : 对应字段的示例内容
- value : 对应参数或返回值的字段规则文字说明
- DataRule特性 : 对应字段的数据规则详细说明(注意 这与校验无关.只是为了文档)
5 Api返回值
继承于IApiResult
namespace Gboxt.Common.DataModel
{
/// <summary>
/// 表示API返回数据
/// </summary>
public interface IApiResultData
{
}
/// <summary>
/// API状态返回(一般在出错时发生)
/// </summary>
public interface IApiStatusResult
{
/// <summary>
/// 错误码(系统定义)
/// </summary>
[JsonProperty("code")]
int ErrorCode { get; set; }
/// <summary>
/// 对应HTTP错误码(参考)
/// </summary>
[JsonProperty("http")]
string HttpCode { get; set; }
/// <summary>
/// 客户端信息
/// </summary>
[JsonProperty("msg")]
string ClientMessage { get; set; }
/// <summary>
/// 内部信息
/// </summary>
string InnerMessage { get; set; }
}
/// <summary>
/// API返回基类
/// </summary>
public interface IApiResult
{
/// <summary>
/// 成功或失败标记
/// </summary>
[JsonProperty("success")]
bool Success { get; set; }
/// <summary>
/// API执行状态(为空表示状态正常)
/// </summary>
[JsonProperty("status")]
IApiStatusResult Status { get; set; }
}
/// <summary>
/// API返回基类
/// </summary>
public interface IApiResult<out TData> : IApiResult
where TData : IApiResultData
{
/// <summary>
/// 返回值
/// </summary>
[JsonProperty("data")]
TData ResultData { get; }
}
}
特殊说明:
- 为保持不同语言之间的风格独立,Json序列化使用的Name与CSharp是不相同的,调试时需要特别注意
- 以上接口,均有相应的各种实现,可直接使用,无需再造车轮
- ApiResult : 仅返回状态而无数据时使用
- ApiValueResult : 非泛型类,返回值为string类型
- ApiValueResult : 泛型类,返回值为任何对象
- ApiArrayResult : 泛型类,返回值为对象数组
- ApiPageResult : 泛型类,返回值为分页数据
四 编译执行
如配置正确,可直接运行,并可通过HttpGateway访问
五 部署
与NetCore的发布部署相同
六 联调
可直接连接测试环境而与前端开发机调试
ZeroCenter地址配置为测试环境相同即可,配置详见后续章节说明