Solon详解系列文章:

Solon详解(一)- 快速入门

Solon详解(二)- Solon的核心

Solon详解(三)- Solon的web开发

Solon详解(四)- Solon的事务传播机制

Solon详解(五)- Solon扩展机制之Solon Plugin

Solon详解(六)- Solon的校验扩展框架使用与扩展

在业务的实现过程中,尤其是对外接口开发,我们需要对请求进行大量的验证并返回错误状态码和描述。lombok 框架有很多很赞的注解,但是人家是throw一个异常,这与有些需求不一定能匹配。

该文将介绍Solon的扩展验证框架:solon.extend.validation 的使用和扩展。效果如下:


@XValid
@XController
public class UserController extends VerifyController{
@RepeatSubmit //重复提交验证
@Whitelist //IP白名单验证
@NotNull({"name", "mobile", "icon", "code"}) //非NULL验证
@Numeric({"code"})
@XMapping("/user/add")
public void addUser(String name, @Pattern("^http") String icon, int code, @Pattern("^13\\d{9}$") String mobile){
//...
}
}

相较于 Spring 的 Validator 是争对 Bean,Solon 则是争对 XContext(即http参数)。这点区别非常大,Solon 是在 XAction 执行之前对 http 参数进行校验。

注解 作用范围 说明
Date 参数 校验注解的参数值为日期格式
DecimalMax(value) 参数 校验注解的参数值小于等于@ DecimalMax指定的value值
DecimalMin(value) 参数 校验注解的参数值大于等于@ DecimalMin指定的value值
Email 参数 校验注解的参数值为电子邮箱格式
Length(min, max) 参数 校验注解的参数值长度在min和max区间内
Max(value) 参数 校验注解的参数值小于等于@Max指定的value值
Min(value) 参数 校验注解的参数值大于等于@Min指定的value值
NoRepeatSubmit 控制器 或 动作 校验本次请求没有重复
NotBlank 动作 或 参数 校验注解的参数值不是空白
NotEmpty 动作 或 参数 校验注解的参数值不是空
NotNull 动作 或 参数 校验注解的参数值不是null
NotZero 动作 或 参数 校验注解的参数值不是0
Null 动作 或 参数 校验注解的参数值是null
Numeric 动作 或 参数 校验注解的参数值为数字格式
Pattern(value) 参数 校验注解的参数值与指定的正则表达式匹配
Whitelist 控制器 或 动作 校验本次请求在白名单范围内
XValid 控制器 或 动作 为控制器 或 动作启用验证能力

可作用在 [动作 或 参数] 上的注解,加在动作上时可支持多个参数的校验。

一、定制使用

solon.extend.validation 通过 ValidatorManager,提供了一组定制和扩展接口。

1、@NoRepeatSubmit 改为分布式锁

NoRepeatSubmit 默认使用了本地延时锁。如果是分布式环境,需要定制为分布式锁:

public class NoRepeatLockNew implements NoRepeatLock {
@Override
public boolean tryLock(String key, int seconds) {
//使用分布式锁
//
return LockUtils.tryLock(XWaterAdapter.global().service_name(), key, seconds);
}
} ValidatorManager.setNoRepeatLock(new NoRepeatLockNew());

2、@Whitelist 实现验证

框架层面没办法为 Whitelist 提供一个名单库,所以需要通过一个接口实现完成对接。

public class WhitelistCheckerNew implements WhitelistChecker {
@Override
public boolean check(Whitelist anno, XContext ctx) {
String ip = IPUtils.getIP(ctx); return WaterClient.Whitelist.existsOfServerIp(ip);
}
} ValidatorManager.setWhitelistChecker(new WhitelistCheckerNew());

3、改造校验输出

solon.extend.validation 默认输出 http 400 状态 + json;尝试改改去掉 http 400 状态。

@XConfiguration
public class Config {
@XBean //Solon 的 @XBean 也支持空函数,为其它提运行申明
public void adapter() {
ValidatorManager.globalSet(new ValidatorManager((ctx, ano, rst, message) -> {
ctx.setHandled(true); if (XUtil.isEmpty(message)) {
message = new StringBuilder(100)
.append("@")
.append(ano.annotationType().getSimpleName())
.append(" verification failed")
.toString();
} ctx.output(message); return true;
}));
}
}

二、添一个扩展注解

1、先定义个校验注解 @Date

偷懒一下,直接把自带的扔出来了。只要看着能自己搞就行了:-P

@Target({ElementType.PARAMETER})   //只让它作用到参数,不管作用在哪,最终都是对XContext的校验
@Retention(RetentionPolicy.RUNTIME)
public @interface Date {
@XNote("日期表达式, 默认为:ISO格式") //用XNote注解,是为了用时还能看到这个注释
String value() default ""; String message() default "";
}

2、添加 @Date 的校验器实现类

public class DateValidator implements Validator<Date> {
public static final DateValidator instance = new DateValidator(); @Override
public String message(Date anno) {
return anno.message();
} @Override
public XResult validate(XContext ctx, Date anno, String name, StringBuilder tmp) {
String val = ctx.param(name);
if (val == null || tryParse(anno, val) == false) {
tmp.append(',').append(name);
} if (tmp.length() > 1) {
return XResult.failure(tmp.substring(1));
} else {
return XResult.succeed();
}
} private boolean tryParse(Date anno, String val) {
try {
if (XUtil.isEmpty(anno.value())) {
DateTimeFormatter.ISO_LOCAL_DATE_TIME.parse(val);
} else {
DateTimeFormatter.ofPattern(anno.value()).parse(val);
} return true;
} catch (Exception ex) {
return false;
}
}
}

3、注册到校验管理器

@XConfiguration
public class Config {
@XBean
public void adapter() {
ValidatorManager.global().register(Date.class, DateValidator.instance);
}
}

4、使用一下

@XValid
@XController
public class UserController extends VerifyController{
@XMapping("/user/add")
public void addUser(String name, @Date("yyyy-MM-dd") String birthday){
//...
}
}

Solon详解(六)- Solon的校验扩展框架使用与扩展的更多相关文章

  1. Springboot mini - Solon详解(六)- Solon的校验框架使用、定制与扩展

    Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...

  2. Springboot mini - Solon详解(五)- Solon扩展机制之Solon Plugin

    Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...

  3. Solon详解(二)- Solon的核心

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  4. Solon详解(三)- Solon的web开发

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  5. Solon详解(七)- Solon Ioc 的注解对比Spring及JSR330

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  6. Solon详解(八)- Solon的缓存框架使用和定制

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  7. Solon详解(九)- 渲染控制之定制统一的接口输出

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  8. Solon详解(十)- 怎么用 Solon 开发基于 undertow jsp tld 的项目?

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

  9. Solon详解(11)- Mybatis 与 Solon 相亲相爱

    Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...

随机推荐

  1. 解放双手!用 Python 控制你的鼠标和键盘

    在工作中难免遇到需要在电脑上做一些重复的点击或者提交表单等操作,如果能通过 Python 预先写好相关的操作指令,让它帮你操作,然后你自己去刷网页打游戏,岂不是很爽?] 很多人学习python,不知道 ...

  2. SpringBoot整合Shiro自定义Redis存储

    Shiro Shiro 主要分为 安全认证 和 接口授权 两个部分,其中的核心组件为 Subject. SecurityManager. Realms,公共部分 Shiro 都已经为我们封装好了,我们 ...

  3. 连通图算法详解之① :Tarjan 和 Kosaraju 算法

    相关阅读: 双连通分量 ,割点和桥 简介 在阅读下列内容之前,请务必了解 图论相关概念 中的基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly ...

  4. jQuery 购物车案例

    h1 { text-align: center; } .cart { width: 1200px; height: 600px; margin: 0 auto; border: 1px solid # ...

  5. Java—io流之打印流、 commons-IO

    打印流 打印流根据流的分类: 字节打印流  PrintStream 字符打印流  PrintWriter /* * 需求:把指定的数据,写入到printFile.txt文件中 * * 分析: * 1, ...

  6. 2020-06-20:一句话总结ZK?

    福哥答案2020-06-20: 这道题价值不大,但是面试题里有这道题. 分布式协调服务,注册服务和发现,树形结构,监听机制,过半机制. ZooKeeper是源代码开放的分布式协调服务,由雅虎公司创建, ...

  7. C#LeetCode刷题-栈

    栈篇 # 题名 刷题 通过率 难度 20 有效的括号 C#LeetCode刷题之#20-有效的括号(Valid Parentheses) 33.0% 简单 42 接雨水   35.6% 困难 71 简 ...

  8. vue的使用规范之v-if 与 v-for 一起使用

    当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级,这意味着 v-if 将分别重复运行于每个 v-for 循环中 所以,不推荐v-if和v-for同时使用 使用推荐方 ...

  9. 解决"$ is not defined" 亲自体验

    引入jquery <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>

  10. 题解 UVA10457

    题目大意:另s = 路径上的最大边权减最小边权,求u到v上的一条路径,使其s最小,输出这个s. 很容易想到枚举最小边然后跑最小瓶颈路. so,如何跑最小瓶颈路? 利用Kruskal,因为树上两点路径唯 ...