1. 程式人生 > >Springboot mini - Solon詳解(六)- Solon的校驗框架使用、定製與擴充套件

Springboot mini - Solon詳解(六)- Solon的校驗框架使用、定製與擴充套件

> Springboot min -Solon 詳解系列文章: > [Springboot mini - Solon詳解(一)- 快速入門](https://www.cnblogs.com/noear/p/14115763.html) > [Springboot mini - Solon詳解(二)- Solon的核心](https://www.cnblogs.com/noear/p/14115817.html) > [Springboot mini - Solon詳解(三)- Solon的web開發](https://www.cnblogs.com/noear/p/14115846.html) > [Springboot mini - Solon詳解(四)- Solon的事務傳播機制](https://www.cnblogs.com/noear/p/14119759.html) > [Springboot mini - Solon詳解(五)- Solon擴充套件機制之Solon Plugin](https://www.cnblogs.com/noear/p/14125526.html) 在業務的實現過程中,尤其是對外介面開發,我們需要對請求進行大量的驗證並返回錯誤狀態碼和描述。lombok 框架有很多很讚的註解,但是人家是throw一個異常,這與有些需求不一定能匹配。 該文將介紹Spring min -Solon的擴充套件驗證框架:`solon.extend.validation` 的使用和擴充套件( `org.noear:solon-web` 已包含)。效果如下: ```java @Valid @Controller public class UserController { @NoRepeatSubmit //重複提交驗證 @Whitelist //白名單驗證 @NotNull({"name", "mobile", "icon", "code"}) //非NULL驗證 @Numeric({"code"}) @Mapping("/user/add") public void addUser(String name, @Pattern("^http") String icon, int code, @Pattern("^13\\d{9}$") String mobile){ //... } } ``` 相較於 Spring 的 Validator 是爭對 Bean,Solon 則是爭對 Context(即http引數)。這點區別非常大,Solon 的設計是在 Action 執行之前對 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 | 控制器 或 動作 | 校驗本次請求在白名單範圍內 | | | | | Valid | 控制器 或 動作 | 為控制器 或 動作啟用驗證能力 | 可作用在 [動作 或 引數] 上的註解,加在動作上時可支援多個引數的校驗。 ### 一、定製使用 solon.extend.validation 通過 ValidatorManager,提供了一組定製和擴充套件介面。 #### 1、@NoRepeatSubmit 改為分散式鎖 NoRepeatSubmit 預設使用了本地延時鎖。如果是分散式環境,需要定製為分散式鎖: ```java 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()); ``` 或者 完全重寫 NoRepeatSubmitValidator,並進行重新註冊 #### 2、@Whitelist 實現驗證 框架層面沒辦法為 Whitelist 提供一個名單庫,所以需要通過一個介面實現完成對接。 ```java public class WhitelistCheckerNew implements WhitelistChecker { @Override public boolean check(Whitelist anno, Context ctx) { String ip = IPUtils.getIP(ctx); return WaterClient.Whitelist.existsOfServerIp(ip); } } ValidatorManager.setWhitelistChecker(new WhitelistCheckerNew()); ``` 或者 完全重寫 WhitelistValidator,並進行重新註冊 #### 3、改造校驗輸出 solon.extend.validation 預設輸出 http 400 狀態 + json;嘗試改改去掉 http 400 狀態。 ```java @Configuration public class Config { @Bean //Solon 的 @Bean 也支援空函式,為其它提執行申明 public void adapter() { ValidatorManager.global().onFailure((ctx, ano, rst, message) -> { ctx.setHandled(true); if (Utils.isEmpty(message)) { message = new StringBuilder(100) .append("@") .append(ano.annotationType().getSimpleName()) .append(" verification failed") .toString(); } ctx.output(message); return true; }); } } ``` ### 二、添一個擴充套件註解 #### 1、先定義個校驗註解 @Date 偷懶一下,直接把自帶的扔出來了。只要看著能自己搞就行了:-P ```java @Target({ElementType.PARAMETER}) //只讓它作用到引數,不管作用在哪,最終都是對Context的校驗 @Retention(RetentionPolicy.RUNTIME) public @interface Date { @Note("日期表示式, 預設為:ISO格式") //用Note註解,是為了用時還能看到這個註釋 String value() default ""; String message() default ""; } ``` #### 2、新增 @Date 的校驗器實現類 ```java public class DateValidator implements V