2023年3月

作者:京东物流 纪卓志

目前我们在构建一个多租户多产品类网站,为了让用户更好的找到他们所需要的产品,我们需要构建站内搜索功能,并且它应该是实时更新的。本文将会讨论构建这一功能的核心基础设施,以及支持此搜索能力的技术栈。

问题的定义与决策

为了构建一个快速、实时的搜索引擎,我们必须做出某些设计决策。我们使用 MySQL 作为主数据库存储,因此有以下选择:



  1. 直接在 MySQL 数据库中查询用户在搜索框中输入的每个关键词,就像
    %#{word1}%#{word2}%...
    这样。

作者:京东科技 王亚森

前言

本文旨在从0到1的讲述一下我们团队在做系统可观测性过程中所沉淀下来的一整套解决方案,收效甚巨,不敢苟藏,当公之于众,共建吾辈光明之未来。

先讲一下我们从中得到的好处:

1,当我所负责系统宕机时我能第一时间得到通知

2,当我写的业务逻辑进入else或者catch时它会通知我

3,当我新做了一个产品功能上线后,我可以监控用户的访问情况

4,我不会再担心早上没到公司就收到同事的电话说昨晚上线的应用要回滚

5,发现新做的功能上线后有问题,可以第一时间在线将功能切换至老版本运行

6,不管有没有发生问题我都可以还原用户的操作轨迹查找问题

7,老板说我们好久没出生产事故了

下面内容比较干,建议请提前备好茶水,一起赏用更佳

一、介绍

何为系统可观测性?

可观测性是一种系统属性,如功能性或可测试性。通过收集和分析系统的运行状态以及系统所承载的业务状态,用一种可以让人理解的形式展示出来,以供我们对系统的运行情况做出合理的判断。

我们要观测什么?

通用部分:从硬件运维(cpu, meomery, disk)与 软件应用可访问性 与 应用性能几个方面进行监控。

业务部分:从页面正常初始化,业务可交互性,交互流程完整性 方面进行监控。

我们以集团内部现有的工具进行说明如何来做,而工具实现的技术手段不在本篇文章职责之内。

二、观测指标

系统指标

服务器运行状态

cpu 占用率

内存占用率,

硬盘 使用率

nginx 启停状态

应用指标

  1. 白屏, 因系统错误导致的白屏

  2. 资源加载错误

  3. 请求400,500

  4. 脚本错误,导致阻塞交互

  5. 首屏渲染时间

  6. 页面完全加载耗时

  7. 接口耗时

业务指标

以信贷产品为例,整个产品的黄金流程分为三部分:授信准入,借款融资,还款。

通用部分

业务异常 (999999)

掊口请求网络超时

接口请求错误

未知错误(未处理的异常码)

准入

跳转实名失败

补充信息提交失败 (从用户点击提交按钮开始,未到最终提交成功)

查询地址列表异常

获取合同列表失败

合同预览失败

准入开通结果页面未在60秒内正常跳转至首页

资质审核页面停留时长超过5分钟

融资

融资申请提交失败(接口返回正常,但未进入结果页面)

融资鉴权失败

还款

还款计划试算失败

还款失败

三、如何观测

以下所有的观测工具,皆以京东内部为准,以现有的工具,提供观测方案

系统指标观测方法

通过jdos 3.0 的智能监控系统 brolly 对系统的 cpu 占用率,内存占用率,硬盘使用率 进行监控告警

http://brolly.jdos.jd.com/app/

通过jen 对nginx状态,以及服务器状态进行监控告警

http://jen.jd.com/alarmConfig

应用相关指标观测方法

前端应用我们选择科技内部的 sgm 做为应用内场景上报工具,关于sgm的介绍与接入指引参考:
sgm接入指引

1,白屏告警

由于sgm中的白屏概念是指访问页面开始,到页面展示第一个字符或图片内容结果,中间用户感受到地白屏时间,如果因为发生系统错误导致无法展示内容而一直白屏,sgm采集到的白屏时间 为 0,所以sgm无法监测白屏故障。

由于白屏时,页面 #app 内容为空,此时页面已经完全加载,所以可能通过监听页面 load事件,判断#app内是否有内容来监控页面是否白白屏,再配上sgm自定义监控告警,从而达到可以有效监控白白屏故障。


window.addEventListener('load', () => {

 if(document.querySelector('#app').children.length < 1){
 
     
     window.__sgm__.custom({
 
         type: 'error',
 
         code: '系统白屏'
 
     })
 
  }
  
})

2,资源告警

详情见:
sgm接入指引

3, API 告警

详情见:
sgm接入指引

4, js error 告警

通过sgm-web 对页面中所有的脚本错误的关键字进行监控,常见的js错误类型为

SyntaxError 语法错误

TypeError 类型错误

ReferenceError 引用错误

RangeError 范围错误

URIError url解析错误

InternalError 内部错误

5,性能告警

详情见:
sgm接入指引

业务指标观测方法

自定义监控告警

自定义告警是监控业务指标的最佳手段,页面提交失败,函数进入catch逻辑,等都可以通过自定义监控进行告警设置。

下图例子中带Error的编码,代表进入catch逻辑,需要我们关注,可以通过设置调用量的阈值,来进行告警配置

详情见:
sgm接入指引

注意事项

a,埋点上报需包含的信息

userinfo 接口返回的用户信息,以确保可以拿到用户标识,查询相关日志或者用户轨迹

当前报错接口对应的出,入参

自定义上报埋点的上下文信息,以确认出现错误的场景

b, 其中页面路由跳转失败的场景可以通过定时器的方法进行上报,在页面销毁时清除定时器、

c,sgm上报用户标识逻辑

四、阈值优化

1,确定点位的有效性

通过本地模拟错误进行告警,以确保所有的点位可以正常上报

2,阈值设定的合理性验证

首先将所有阈值调整至最低,然后查看报警情况

如果有报警,分析报警信息的合理性,如果每次都是需要关注的生产问题,那么这里就需要设置为最低的阈值,如果是个例问题或者无须特殊关注的问题,那么把阈值逐渐调高,至合适的频率

3,Api监控

前端可以无需特殊关注,可以设置一个20%错误率批量报警数值即可

4,资源监控

以页面静态资源数为准,包含css, js, img 的总和为监控数值,其中 img 标签存在动态 src 时,页面在初次渲染会有一次当前页面url的资源错误上报,可通过 v-if 来避免误报

5,自定义监控

业务中的自定义错误上报 遵循第2条的原则进行逐渐优化

6,应用监控告警阈值配置原则:

由于 sgm 常规计算以 60秒错误数(),为一个周期,连续发生多少()周期 ,则触发告警规则,所以我们需要计算出应用的日均pv,以及对应指标产生的数量级,进行设置合理的阈值。

以 日均 pv 为 10000 的应用 为例,每60s pv 约等于7,每个pv 资源数约为
20
, 接口调用数量约为
3
,那么每秒总量是 140次资源请求,21个接口调用 。以
20%
错误率上报为标准,来设置对应的阈值。

以上数值可以根据业务线流量视情况而定。

五、报警信息触达

1,邮件(必选)

报警方式中选择邮件,另外在邮箱中配置报警邮件规则,由于报警邮件可能会有很多包括后端的报警,以及一些非紧急报警邮件,可以通过邮件标题来进行区分。

一般标题中会包含应用名,可以通过筛选应用名来过滤前端应用,另外可以根据标题中的[SGM-WEB]来过滤前端相关的报警信息。

H5_RESOURCE 资源错误标题关键字

H5_CUSTOM_CODE 自定义监控关键字

H5_JS_ERROR 脚本错误关键字

2,咚咚(必选)

咚咚 报警渠道会比邮件提醒更加及时,被看到的时效性会更高

3,外呼(可选)

时效性最高的报警方法,对于一些关键场景,批量错误,可以确定是生产问题类的场景需要增加外呼方式,及时触达信息

六、生产切量监控

可以使用自定义监控来配合系统的切量功能进行监控

假如我要上线一个新的重大功能,需要在生产环境通过切量的方式,逐渐替换老版本的功能,我们如何去监控上线后新老功能

我们需具备两个功能,一个是切量功能,一个是监控功能

切量是业务系统实现的一个功能,大概流程如下:

我们分别在新老版本的分支流程里通过自定义埋点来进行监控有多少用户走到了新流程,有多少老用户走到了老流程,

然后再通过sgm来查看两个流程的用户轨迹来判断用户是否在新流程中完成了全部操作,或者是用户卡在了哪一步,

以此来确定新上线的功能是否有问题,问题出在哪里

并且可以通过查看监控数据,来确定本次切量是否成功,是否需要及时回滚,或者修复上线,将影响范围缩小。

黎明前的暗夜下,巍巍昆仑侧广袤草原上,一道激光无声闪过,一辆黑马披星戴月疾驰向北。天边泛起朦朦金光,远处黑马的合金轮毂激射出金色炫光。

鸿蒙元服务(简称
元服务
)是华为提供的一种面向未来的服务形态,具有独立入口和免安装等特性,支持运行在1+8+N设备上。在万物互联时代,元服务酷似一匹黑马提供了更丰富的入口、更智能的分发、更高效的转化,助力开发者快速抢占流量入口。元服务开发完成后,需要完成签名、调试、打包、上架一系列的打磨,最终在广大用户前华丽展示。元服务的上架全流程如同黑马的四轮驱动般,以澎湃动力驱动黑马叱咤奔驰。

左前轮
-生成密钥库和证书请求文件

元服务开发完成后,在真机上调试前,必须要进行签名来确保元服务的完整性。HarmonyOS会通过数字证书和Profile文件来对元服务进行管控,只有签名过的元服务才允许安装到真机设备上进行调试。

签名过程中有两个关键文件:
密钥库文件

证书请求文件
。密钥库文件格式为.p12,用于数字签名和验证;证书请求文件格式为.csr,用于向AppGallery Connect(简称
AGC
)申请数字证书。可以使用DevEco Studio和命令行两种方式生成文件。

->>>
体验试驾请发动
左前轮

右前轮
-
签名调试

获取了密钥库和证书请求文件后,可以开始进行签名调试,华为为开发者提供了
自动签名

手动签名
两种调试方法。

  1. 自动签名
    就是开发者直接在开发工具DevEco Studio中打开项目,在线登录AGC自动生成并配置签名证书和Profile。
  2. 手动签名
    则需要开发者自行登录AGC网站通过证书请求文件(
    .csr
    )生成证书(.
    cer
    )和Profile文件(
    .p7b
    ),再将生成的文件手动配置到DevEco Studio工程中进行签名。

手动签名
的操作步骤相比
自动签名
的较多,推荐开发者优先使用
自动签名
进行调试。

->>>体验试驾请发动
右前轮

左后轮
-
元服务开放式测试

元服务开发完成后,如果想在服务中心查看实际的效果,或者担心没有经过用户体验直接全网发布,可能会因为元服务存在的一些问题影响用户使用。可以在正式全网发布前,通过发布开放式测试版本提前邀请部分友好用户进行体验,未邀请的用户搜索不到您的元服务,这样能很好的提前发现问题并进行改进。

开放式测试上架的操作和正式上架基本一样,只是增加了配置测试用户列表等操作。

元服务开放式测试是无需人工审核,提交审核后等待系统检测完就能自动上架。上架后AGC会给测试用户发送邀请链接,用户收到链接在手机登录华为帐号,打开服务中心,滑到最下方的“服务测试”栏目就可以看到发布的元服务。

->>>体验试驾请发动
左后轮

右后轮
-
元服务上架

元服务调试签名完成,即可按
创建->编译->发布
的流程在AGC网站上架。

1.
创建
项目和元服务

创建时注意
元服务包名
和DevEco Studio工程中的
bundleName
值保持一致。同时
“是否原子化服务”
务必选择为
“是”
,否则在上传元服务软件包时会报错。

2.
编译
元服务

此步主要是在AGC网站生成发布证书文件和发布Profile文件,然后在DevEco Studio工程中配置签名。正式上架时,必须使用发布证书和发布Profile文件进行签名。

3.
发布
元服务

此步主要是配置元服务上架的基本信息和上传软件包,待华为审核通过后,元服务发布成功,用户即可以在服务中心获取使用元服务。

->>>体验试驾请发动
右后轮

了解完元服务的上架全流程后,是不是对元服务信心满满。快来吧,与元服务黑马一起,一路向北,风驰电掣,跨越山海,奔向鸿蒙新时代。

欲了解更多更全技术文章,欢迎访问
https://developer.huawei.com/consumer/cn/forum/?ha_source=zzh

今天给大家推荐一个开源项目,基于.NetCore开发的、前后端分离、前端有Vue、Angular、MVC多个版本的快速开发框架。

项目简介

这是一个基于.NetCore开发的快速开发框架,项目采用模块化架构、最新的技术栈、项目高度封装了依赖注入、日志(Log4net、Nlog)、缓存(Redis)、身份认证、WebApi、权限授权、多数据库等模块,能让我们快速的应用于实际的项目,只需专注于业务开发。

前端项目有多个示例项目,包含Vue版本、Mvc 版本(Layui)、Angular版本,可以根据自己需求选择,也可以自行搭建。

技术架构

1、跨平台:这是基于.Net Core开发的系统,可以部署在Docker, Windows, Linux, Mac。

2、数据库支持:MySQL、Sqlserver、Oracle、PostgreSql、Sqlite。

3、技术栈:.Net6.0/.Net7.0  + AntDesign + Web API + swagger + Log4net/NLog + Redis + AutoMapper + MiniProfiler。

项目结构

图片

src文件夹为核心组件模块,samples文件夹为web、api、wpf示例、tests文件夹为单元测试模块。

系统功能

1、主页:用户统计、角色统计、模块统计、功能统计;

2、业务模块:根据业务需求,自定义添加模块;

3、身份认证:用户管理、角色管理、用户角色管理;

4、权限认证:模块管理、功能管理、数据实体管理、数据权限管理;

5、系统管理:操作审计、数据审计、系统设置、模块包。

部分功能截图

主页

图片

用户管理

图片

角色管理

图片

用户角色管理

图片

模块管理

图片

功能管理

图片

数据实体管理

图片

数据权限管理

图片

操作审计

图片

数据审计

图片

模块包

图片

项目地址

Github:
https://github.com/dotnetcore/osharp

Gitee:
https://gitee.com/i66soft/osharp

更多开源项目请查看

一个专注推荐优秀.Net开源项目的榜单

- End -

文章首发于公众号【编程乐趣】,欢迎大家关注。
图片

项目介绍

java 开发中,参数校验是非常常见的需求。但是 hibernate-validator 在使用过程中,依然会存在一些问题。

validator
在 hibernate-validator 等校验工具之上,做了一些改进,使其使用更加便捷优雅,进一步提升工作效率。

图片

变更日志

变更日志

特性

  • 支持 fluent-validation

  • 支持 jsr-303 注解

  • 支持 i18n

  • 支持用户自定义策略

  • 支持用户自定义注解

  • 支持针对属性的校验

  • 支持过程式编程与注解式编程

  • 支持指定校验生效的条件

创作目的

hibernate-validator 无法满足的场景

如今 java 最流行的 hibernate-validator 框架,但是有些场景是无法满足的。

比如:

  1. 验证新密码和确认密码是否相同。(同一对象下的不同属性之间关系)

  2. 当一个属性值满足某个条件时,才进行其他值的参数校验。

  3. 多个属性值,至少有一个不能为 null

其实,在
对于多个字段的关联关系处理时,hibernate-validator 就会比较弱

本项目结合原有的优点,进行这一点的功能强化。

validation-api 过于复杂

validation-api 提供了丰富的特性定义,也同时带来了一个问题。

实现起来,特别复杂。

然而我们实际使用中,常常不需要这么复杂的实现。

validator-api 提供了一套简化很多的 api,便于用户自行实现。

自定义缺乏灵活性

hibernate-validator 在使用中,自定义约束实现是基于注解的,针对单个属性校验不够灵活。

本项目中,
将属性校验约束和注解约束区分开,便于复用和拓展

过程式编程 vs 注解式编程

hibernate-validator 核心支持的是注解式编程,基于 bean 的校验。

一个问题是针对属性校验不灵活,有时候针对 bean 的校验,还是要自己写判断。

本项目支持 fluent-api 进行过程式编程,同时支持注解式编程。

尽可能兼顾灵活性与便利性。

快速开始

准备工作

JDK1.7+

Maven 3.X+

maven 引入

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>validator-core</artifactId>
    <version>0.4.0</version>
</dependency>

快速入门

定义对象

第一步,我们定义一个常见的 java bean 对象,可以指定内置的注解。

支持 jsr-303 注解和 hibernate-validator 的注解。

public class User {

    /**
     * 名称
     */
    @HasNotNull({"nickName"})
    private String name;

    /**
     * 昵称
     */
    private String nickName;

    /**
     * 原始密码
     */
    @AllEquals("password2")
    private String password;

    /**
     * 新密码
     */
    private String password2;

    /**
     * 性别
     */
    @Ranges({"boy", "girl"})
    private String sex;

    /**
     * 失败类型枚举
     */
    @EnumRanges(FailTypeEnum.class)
    private String failType;
    
    //getter & setter

}

ValidHelper 工具方法

ValidHelper 作为统一封装的工具类,提供了 java bean 校验常见的方法。

方法列表:

序号 方法 返回值 说明
1 failOver(Object object) IResult 全部验证后返回
2 failFast(Object object) IResult 快速验证后返回
3 failOverThrow(Object object) void 全部验证后返回-未通过抛出 ValidRuntimeException 异常
4 failFastThrow(Object object) void 快速验证后返回-未通过抛出 ValidRuntimeException 异常

使用起来很简单,我们以 failFast 为例:

// 对象定义
User user = new User();
user.sex("what").password("old").password2("new");

// 调用方法
IResult result = ValidHelper.failFast(user);

结果:

DefaultResult{pass=false, notPassList=[DefaultConstraintResult{pass=false, message='name: 值 <null> 不是预期值', value=null, constraint='HasNotNullConstraint', expectValue='', fieldName='name'}], allList=null}
  • IResult 方法说明

返回值实现默认为 DefaultResult,接口 IResult 属性如下:

public interface IResult {

    /**
     * 是否全部通过验证
     * @return 是否
     * @since 0.1.0
     */
    boolean pass();

    /**
     * 未通过的列表信息
     * @return 验证结果
     * @since 0.1.0
     */
    List<IConstraintResult> notPassList();

    /**
     * 所有的验证结果列表
     * @return 所有的验证结果
     * @since 0.1.0
     */
    List<IConstraintResult> allList();

    /**
     * 输出信息到控台
     * (1)主要是为了方便调整
     * (2)该功能其实可以做增强,比如输出到文件/数据库等等。
     * @return this
     * @since 0.0.6
     */
    IResult print();

    /**
     * 对于未通过的信息,
     * (1)未通过的界定。
     *  {@link IConstraintResult#pass()} 为 false
     *
     * (2)内容信息
     * 抛出运行时异常 {@link com.github.houbb.validator.api.exception.ValidRuntimeException},异常信息为 {@link IConstraintResult#message()} 消息
     * (3)内容限定
     *  为了避免异常内容过多,只抛出第一条即可。
     *  (4)改方法的增强空间
     *  4.1 可以指定什么情况下抛出异常
     *  4.2 抛出异常的信息和类别
     *
     * @return this
     * @since 0.0.6
     */
    IResult throwsEx();

}

注解说明

java bean 的校验,基于注解是比较方便的。和 hibernate-validator 使用类似,这里介绍下常见的注解。

内置约束注解

内置注解如下:

序号 注解 value() 说明
1 @AllEquals String[] 当前字段及其指定的字段 全部相等
2 @EnumRanges Class<? extends Enum> 当前字段必须在枚举值指定的范围内
3 @HasNotNull String[] 当前字段及其指定的字段 至少有一个不为 null
4 @Ranges String[] 当前字段必须在指定的范围内

JSR-303 + hibernate-validator 约束注解支持

序号 注解 说明
1 @AssertTrue 为 true 约束条件
2 @AssertFalse 为 false 约束条件
3 @Null 为 null 约束条件
4 @NotNull 不为 null 约束条件
5 @Past 是否在当前时间之前约束条件
6 @Future 是否在当前时间之后约束条件
7 @Pattern 正则表达式约束条件
8 @Size 在指定范围内的约束条件
9 @Digits 数字位数的约束条件
10 @DecimalMax 最大数字的约束条件
11 @DecimalMin 最小数字的约束条件
12 @Min 最小的约束条件
13 @Max 最大的约束条件
13 @NotBlank 不能为空格的约束条件
14 @NotEmpty 不能为空的约束条件
15 @Length 长度的约束条件
16 @CNPJ CNPJ 约束条件
17 @CPF CPF 约束条件
18 @URL URL 约束条件
18 @Email Email 约束条件
19 @UniqueElements 元素唯一约束条件
20 @Range 指定范围元素约束条件

条件注解

说明

有时候我们需要根据不同的参数,进行不同的限制条件。

比如新建时用户 id 不需要传入,但是修改时 id 必填。

如果是传统的 hibernate-validator 处理就会比较麻烦,此处引入条件注解。

内置注解

序号 注解 说明
1 @EqualsCondition 等于指定值的条件
2 @NotEqualsCondition 不等于指定值的条件
3 @AlwaysTrueCondition 永远生效的条件
4 @AlwaysFalseCondition 永远不生效的条件

使用

使用起来也不难,下面的效果如下:

  1. operType == 'create' 时,name 的校验才会生效。
  2. operType != 'create' 时,id 的校验才会生效。

其他使用方式保持不变。

public class ConditionUser {

    /**
     * 操作类型
     */
    @Ranges({"create", "edit"})
    private String operType;

    /**
     * 新建时,name 必填
     */
    @EqualsCondition(value = "create", fieldName = "operType")
    @Size(min = 3)
    @NotNull
    private String name;

    /**
     * 不是新建时, id 字段必填
     */
    @NotEqualsCondition(value = "create", fieldName = "operType")
    @Size(min = 16)
    private String id;
    
    //getter & setter
}

过程式接口

说明

日常开发中,我们都很喜欢使用注解对 java bean 进行校验。

但是这回导致我们定义的单个属性校验无法复用。

所以项目中的单个属性校验和注解是一一对应的,为了便于复用。

ValidHelper 方法

ValidHelper 作为统一封装的工具类,提供单个方法校验常见的方法。

和 java bean 类似,方法列表:

序号 方法 返回值 说明
1 failOver(Object object, IConstraint constraint) IResult 全部验证后返回
2 failFast(Object object, IConstraint constraint) IResult 快速验证后返回
3 failOverThrow(Object object, IConstraint constraint) void 全部验证后返回-未通过抛出 ValidRuntimeException 异常
4 failFastThrow(Object object, IConstraint constraint) void 快速验证后返回-未通过抛出 ValidRuntimeException 异常

使用例子

用法和 bean 的类似,只是入参多了第二个约束条件。

IResult result = ValidHelper.failFast("", Constraints.notEmptyConstraint());

IConstraint 对应关系

注解和常见的接口方法一一对应,所有的约束方法在
Constraints
工具类中。

序号 注解 说明 对应方法
1 @AssertTrue 为 true 约束条件 assertTrueConstraint
2 @AssertFalse 为 false 约束条件 assertFalseConstraint
3 @Null 为 null 约束条件 nullConstraint
4 @NotNull 不为 null 约束条件 notNullConstraint
5 @Past 是否在当前时间之前约束条件 pastConstraint
6 @Future 是否在当前时间之后约束条件 futureConstraint
7 @Pattern 正则表达式约束条件 patternConstraint
8 @Size 在指定范围内的约束条件 sizeConstraint
9 @Digits 数字位数的约束条件 digitsConstraint
10 @DecimalMax 最大数字的约束条件 decimalMaxConstraint
11 @DecimalMin 最小数字的约束条件 decimalMinConstraint
12 @Min 最小的约束条件 minConstraint
13 @Max 最大的约束条件 maxConstraint
13 @NotBlank 不能为空格的约束条件 notBlankConstraint
14 @NotEmpty 不能为空的约束条件 notEmptyConstraint
15 @Length 长度的约束条件 lengthConstraint
16 @CNPJ CNPJ 约束条件 cnpjConstraint
17 @CPF CPF 约束条件 cpfConstraint
18 @URL URL 约束条件 urlConstraint
18 @Email Email 约束条件 emailConstraint
19 @UniqueElements 元素唯一约束条件 uniqueElementsConstraint
20 @Range 指定范围元素约束条件 rangeConstraint
21 @AllEquals 当前字段及其指定的字段 全部相等 allEqualsConstraint
22 @EnumRanges 当前字段必须在枚举值指定的范围内 enumRangesConstraint
23 @HasNotNull 当前字段及其指定的字段 至少有一个不为 null hasNotNullConstraint
24 @Ranges 当前字段必须在指定的范围内 rangesConstraint

条件注解

注解和常见的接口方法一一对应,所有的约束方法在
Conditions
工具类中。

序号 注解 说明 对应方法
1 @EqualsCondition 等于指定值的条件 equalsCondition
2 @NotEqualsCondition 不等于指定值的条件 notEqualsCondition
3 @AlwaysTrueCondition 永远生效的条件 alwaysTrueCondition
4 @AlwaysFalseCondition 永远不生效的条件 alwaysFalseCondition

注解自定义

说明

内置的注解,自然无法满足所有的场景。

本项目中,约束和条件注解都是支持自定义的。

约束注解 @Constraint

所有系统的内置注解都可以作为学习的例子。

定义注解


@AllEquals
为例,核心的部分在
@Constraint(AtAllEqualsConstraint.class)

我们在 AtAllEqualsConstraint 中实现具体的约束逻辑。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(AtAllEqualsConstraint.class)
public @interface AllEquals {

    /**
     * 当前字段及其指定的字段 全部相等
     * 1. 字段类型及其他字段相同
     * @return 指定的字段列表
     */
    String[] value();

    /**
     * 提示消息
     * @return 错误提示
     */
    String message() default "";

    /**
     * 分组信息
     * @return 分组类
     * @since 0.1.2
     */
    Class[] group() default {};

}

实现逻辑

推荐直接继承
AbstractAnnotationConstraint<A>
,实现对应的逻辑即可。

public class AtAllEqualsConstraint extends AbstractAnnotationConstraint<AllEquals> {

    @Override
    protected IConstraint buildConstraint(AllEquals annotation) {
        return Constraints.allEqualsConstraint(annotation.value());
    }

}

条件注解 @Condition

所有系统的内置注解都可以作为学习的例子。

定义注解


@AlwaysTrueCondition
为例,核心的部分在
@Condition(AtAlwaysTrueCondition.class)

我们在 AtAlwaysTrueCondition 中实现具体的约束逻辑。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Condition(AtAlwaysTrueCondition.class)
public @interface AlwaysTrueCondition {
}

实现逻辑

推荐直接继承
AbstractAnnotationCondition<A>
,实现对应的逻辑即可。

public class AtAlwaysTrueCondition extends AbstractAnnotationCondition<AlwaysTrueCondition> {

    @Override
    protected ICondition buildCondition(AlwaysTrueCondition annotation) {
        return Conditions.alwaysTrueCondition();
    }

}

开源地址

为了便于大家学习使用,目前校验框架已开源。

欢迎大家 fork+star,鼓励一下老马~

validator