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

该文将基于Solon的一些扩展基础,简单的实现一套定制的业务验证机制。效果如下:


@XController
public class UserController extends VerifyController{
@RepeatSubmit //重复提交验证
@Whitelist //IP白名单验证
@NotNull({"name", "mobile", "icon", "code"}) //非NULL验证
public void addUser(UserModel user){
//...
}
}

一、定制开始

1、先定义一组验证注解

@Inherited
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotNull {
String[] value();
} @Inherited
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Whitelist {
} //... 更多略

2、然后,定义一个验证用的拦截器

//
//Solon里的所有拦截器,也都是 XHandler
//
public class VerifyInterceptor implements XHandler {
@Override
public void handle(XContext ctx) throws Throwable {
//获取上下文中的XAction
//
XAction action = ctx.attr("action");
if (action != null) {
handle0(ctx, action);
}
} protected void handle0(XContext ctx, XAction action) throws Throwable {
//这里的顺序,要与业务的期望顺序匹配 //白名单
checkWhitelist(ctx, action); //不能为Null
checkNotNull(ctx, action); //...更多略
} protected void checkWhitelist(XContext ctx, XAction action) throws Throwable{
if(ctx.getHandled()){
return;
} Whitelist anno = action.method().getAnnotation(Whitelist.class);
if (anno != null) {
String ip = IpUtils.getIP(ctx);
if (WhitelistApi.existsOfServerIp(ip) == false) {
ctx.setHandled(true);
ctx.render(UapiCodes.CODE_16);
}
}
} protected void checkNotNull(XContext ctx, XAction action) throws Throwable{
if(ctx.getHandled()){
return;
} NotNull anno = action.method().getAnnotation(NotNull.class);
if (anno != null) {
checkParamsIsOk(ctx, false, anno.value());
}
}
}

3、再是,定义一个支持验证的控制器基类

//
// 创建一个有验证拦截器的基类;@XBefore 注解是可继承的...
//
@XBefore({VerifyInterceptor.class})
public class VerifyController { }

完工了

二、附:关于 XContext 的部分扩展属性

Solon 的上下文对象:XContext,有一组可扩展属性的接口:attr(), attrSet(), attrMap()。用于记录处理过程中的数据或对象。

以下是框架在运行过程中已记录的扩展属性:

扩展属性 说明
ctx.attr("controller") 获取当前控制器
ctx.attr("action") 获取当前活动
ctx.result 获取当前活动的执行结果,可用于统一的业务日志记录
ctx.attr("error") 获取当前错误
ctx.attr("output") 获取当前序列化输出,可用于统一的业务日志记录

Solon详解(六)- 定制业务级别的验证注解的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. Springboot mini - Solon详解(四)- Solon的事务传播机制

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

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

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

随机推荐

  1. 中缀转逆波兰表达式 c++ 队列,栈

    记得早在几十天以前,xty 学长曾让我学这个.一直推到了现在哈 咕咕咕(能鸽善鹉orz) 抱歉,学妹我来还愿了! 中缀表达式比较适合人类的计算,但是后缀表达式更适合机器计算(毕竟没有那么多运算符优先级 ...

  2. 线程_gevent自动切换CPU协程

    import gevent def f(n): for i in range(n): print (gevent.getcurrent(), i) # gevent.getcurrent() 获取当前 ...

  3. P2489 [SDOI2011]迷宫探险 概率dp

    LINK:迷宫探险 题目中要求在最优的策略下的最大概率 而并非期望概率. 一个坑点 题目中虽然没有明说 但是 探险者是知道地图的模样和每个陷阱的概率的. 所以才有最优策略一说. 最优策略尽管不知道可以 ...

  4. Linux下利用docker搭建elasticsearch(单节点)

    1. 拉取镜像 #elasticsearch 6.x和7.x版本有很多不一样需要确认 docker pull docker.elastic.co/elasticsearch/elasticsearch ...

  5. [转]HashMap 和 currentHashMap 总结

    作者:浅蓝色的麻吉 https://www.jianshu.com/p/a7767e6ff2a2 1. 什么是哈希表 在讨论哈希表之前,我们先大概了解下其他数据结构在新增,查找等基础操作执行性能 1. ...

  6. SpringBoot中使用AOP打印接口日志的方法(转载)

    前言 AOP 是 Aspect Oriented Program (面向切面)的编程的缩写.他是和面向对象编程相对的一个概念.在面向对象的编程中,我们倾向于采用封装.继承.多态等概念,将一个个的功能在 ...

  7. jquery 事件对象笔记

    jQuery元素操作 设置或获取元素固有属性   获取               prop(属性名)    修改               prop(属性名,值) 获取自定义属性          ...

  8. 【av68676164(p31-p32)】Windows和Linux同步机制

    4.6.1 Windows同步机制 临界区(CRITICAL_SECTION) 在进程内使用,保证仅一个线程可以申请到该对象 临界区内是临界资源的访问 相关的API函数 初始化临界区 WINBASEA ...

  9. Go之Gorm简介及使用案例

    简介 ORM Object-Relationl Mapping, 它的作用是映射数据库和对象之间的关系,方便我们在实现数据库操作的时候不用去写复杂的sql语句,把对数据库的操作上升到对于对象的操作 G ...

  10. 用前端姿势玩docker【五】快速构建中类Unix系统与Windows系统的差异化处理

    目录 用前端姿势玩docker[一]Docker通俗理解常用功能汇总与操作埋坑 用前端姿势玩docker[二]dockerfile定制镜像初体验 用前端姿势玩docker[三]基于nvm的前端环境构建 ...