最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Dubbo注解方式數(shù)據(jù)校驗支持詳解

 更新時間:2026年02月06日 15:10:49   作者:玩名堂_  
這篇文章主要介紹了JavaBeanValidation規(guī)范的三個主要版本JSR303、JSR349和JSR380,以及它們在SpringMVC中的應(yīng)用,文章還介紹了如何進行嵌套校驗和自定義校驗,并以DubboRPC參數(shù)校驗為例,展示了如何在RPC框架中使用BeanValidation進行參數(shù)校驗

數(shù)據(jù)校驗

簡介:

作為一個Java開發(fā)者我們或多或少在Spring MVC使用場景中接觸過數(shù)據(jù)校驗(Bean Validation)。Bean Validation技術(shù)隸屬于Java EE規(guī)范,期間有多個JSR(Java Specification Requests)支持,目前共有三次相關(guān)JSR標準發(fā)布:

  • JSR303 最早(2009)
  • JSR349
  • JSR380

JSR303

JSR303提出很早(2009年),它為 基于注解的 JavaBean驗證定義元數(shù)據(jù)模型和API。JSR-303主要是對JavaBean進行驗證,如方法級別(方法參數(shù)/返回值)、依賴注入等的驗證是沒有指定的。

作為開山之作,它規(guī)定了Java數(shù)據(jù)校驗的模型和API,這就是Java Bean Validation 1.0版本。

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.0.0.GA</version>
</dependency>

該版本提供了13個現(xiàn)在常見的校驗注解:

注解支持類型含義null值是否校驗
@AssertFalsebool元素必須是false
@AssertTruebool元素必須是true
@DecimalMaxNumber的子類型(浮點數(shù)除外)以及String元素必須是一個數(shù)字,且值必須<=最大值
@DecimalMin同上元素必須是一個數(shù)字,且值必須>=最小值
@Max同上同上
@Min同上同上
@Digits同上元素構(gòu)成是否合法(整數(shù)部分和小數(shù)部分)
@Future時間類型(包括JSR310)元素必須為一個將來(不包含相等)的日期(比較精確到毫秒)
@Past同上元素必須為一個過去(不包含相等)的日期(比較精確到毫秒)
@NotNullany元素不能為null
@Nullany元素必須為null
@PatternString元素需符合指定的正則表達式
@SizeString/Collection/Map/Array元素大小需在指定范圍中

它的官方參考實現(xiàn)如下:

JSR349

該規(guī)范2013年完成伴隨java EE 7一起發(fā)布,就是我們比較熟悉的Bean Validation1.1。

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>

相較于1.0版本,它主要的改進/優(yōu)化有如下幾點:

  1. 標準化了Java平臺的約束定義、描述、和驗證
  2. 支持方法級驗證(入?yún)⒒蚍祷刂档尿炞C)
  3. Bean驗證組件的依賴注入
  4. 與上下文和DI依賴注入集成
  5. 使用EL表達式的錯誤消息插值,讓錯誤消息動態(tài)化起來(強依賴于ElManager)
  6. 跨參數(shù)驗證。比如密碼和驗證密碼必須相同

注解個數(shù)上,相較于1.0版本并沒新增~

它的官方參考實現(xiàn)如下:

注:當你導入了hibernate-validator后,無需再顯示導入javax.validation

JSR380

當下主流版本,也就是Java Bean Validation 2.0,它完成于2017年8月,在2019年8月發(fā)布,屬于Java EE 8的一部分。它的官方參考實現(xiàn)只有唯一的Hibernate validator了:

此版本具有很重要的現(xiàn)實意義,主要有以下變化:

支持通過注解泛型類型來驗證容器內(nèi)的元素,如:List<@Positive Integer> positiveNumbers,即容器內(nèi)元素須為正數(shù)

  • 1. 更靈活的集合類型級聯(lián)驗證;例如,現(xiàn)在可以驗證映射的鍵和值,如:Map<@Valid CustomerType, @Valid Customer> customersByType
  • 2. 支持java.util.Optional類型,并且支持通過插入額外的值提取器來支持自定義容器類型

讓@Past/@Future注解支持注解在JSR310時間上

新增內(nèi)建的注解類型(共9個):@Email, @NotEmpty, @NotBlank, @Positive, @PositiveOrZero, @Negative, @NegativeOrZero, @PastOrPresent和@FutureOrPresent

所有內(nèi)置的約束現(xiàn)在都支持重復(fù)標記

JDK最低版本要求:JDK 8

新增注解

注解支持類型含義null值是否校驗
@EmailString元素必須是電子郵箱地址
@NotEmpty容器類型集合的Size必須大于0
@NotBlankString字符串必須包含至少一個非空白的字符
@PositivePositive元素必須必須為正數(shù)(不包括0)
@PositiveOrZero同上同上(包括0)
@Negative同上元素必須必須為負數(shù)(不包括0)
@NegativeOrZero同上同上(包括0)
@PastOrPresent時間類型在@Past基礎(chǔ)上包括相等
@FutureOrPresent時間類型在@Futrue基礎(chǔ)上包括相等

從1.1版本起就需要El管理器支持用于錯誤消息動態(tài)插值,因此需要自己額外導入EL的實現(xiàn)。EL也屬于Java EE標準技術(shù),可認為是一種表達式語言工具,它并不僅僅是只能用于Web,可以用于任意地方(類比Spring的SpEL)

這是EL技術(shù)規(guī)范的API:

<dependency>
    <groupId>javax.el</groupId>
    <artifactId>javax.el-api</artifactId>
    <version>3.0.0</version>
</dependency>

Expression Language 3.0表達式語言規(guī)范于2013-4-29發(fā)布,Tomcat 8、Jetty 9、GlasshFish 4都已經(jīng)支持實現(xiàn)了EL 3.0,如果你是web環(huán)境,就不用自己手動導入了

簡單來說以上JSR提供了一套Bean校驗規(guī)范的API,維護在包javax.validation.constraints下。該規(guī)范使用屬性或者方法參數(shù)或者類上的一套簡潔易用的注解來做參數(shù)校驗。開發(fā)者在開發(fā)過程中,僅需在需要校驗的地方加上形如@NotNull, @NotEmpty , @Email的注解,就可以將參數(shù)校驗的重任委托給一些第三方校驗框架來處理。

Spring MVC中,只需要使用@Valid注解標注在方法參數(shù)商,Spring MVC即可對參數(shù)對象進行校驗,校驗結(jié)果會放在BindingResult對象中。除了@Valid 還有 @Validated注解支持參數(shù)的分組校驗。它們的區(qū)別:

  • @Valid:沒有分組的功能。
  • @Valid:可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(字段)上
  • @Validated:提供了一個分組功能,可以在入?yún)Ⅱ炞C時,根據(jù)不同的分組采用不同的驗證機制
  • @Validated:可以用在類型、方法和方法參數(shù)上。但是不能用在成員屬性(字段)上

兩者是否能用于成員屬性(字段)上直接影響能否提供嵌套驗證的功能

嵌套驗證

看下圖:

比如我們現(xiàn)在有個實體叫做Item:

public class Item {

    @NotNull(message = "id不能為空")
    @Min(value = 1, message = "id必須為正整數(shù)")
    private Long id;

    @NotNull(message = "props不能為空")
    @Size(min = 1, message = "至少要有一個屬性")
    private List<Prop> props;
}

Item帶有很多屬性,屬性里面有:pid、vid、pidName和vidName,如下所示:

public class Prop {

    @NotNull(message = "pid不能為空")
    @Min(value = 1, message = "pid必須為正整數(shù)")
    private Long pid;

    @NotNull(message = "vid不能為空")
    @Min(value = 1, message = "vid必須為正整數(shù)")
    private Long vid;

    @NotBlank(message = "pidName不能為空")
    private String pidName;

    @NotBlank(message = "vidName不能為空")
    private String vidName;
}

屬性這個實體也有自己的驗證機制,比如pid和vid不能為空,pidName和vidName不能為空等。

正常情況,Spring Validation框架只會對Item的id和props做非空和數(shù)量驗證,不會對props字段里的Prop實體進行字段驗證。 

如何進行嵌套校驗?

為了能夠進行嵌套驗證,必須手動在Item實體的props字段上明確指出這個字段里面的實體也要進行驗證。由于@Validated不能用在成員屬性(字段)上,但是@Valid能加在成員屬性(字段)上,而且@Valid類注解上也說明了它支持嵌套驗證功能,那么我們能夠推斷出:@Valid加在方法參數(shù)時并不能夠自動進行嵌套驗證,而是用在需要嵌套驗證類的相應(yīng)字段上,來配合方法參數(shù)上@Validated@Valid來進行嵌套驗證。

修改Item類如下所示:

public class Item {

    @NotNull(message = "id不能為空")
    @Min(value = 1, message = "id必須為正整數(shù)")
    private Long id;

    @Valid // 嵌套驗證必須用@Valid
    @NotNull(message = "props不能為空")
    @Size(min = 1, message = "props至少要有一個自定義屬性")
    private List<Prop> props;
}

除了上面常見的@NotNull、@Min@NotBlank@Size等校驗注解我們還可以自定義校驗注解~

類級別驗證(多字段聯(lián)合驗證)

約束也可以放在類級別上(也就說注解標注在類上)。在這種情況下,驗證的主體不是單個屬性,而是整個對象。如果驗證依賴于對象的幾個屬性之間的相關(guān)性,那么類級別約束就能搞定。

這個需求場景在平時開發(fā)中也非常常見,比如此處我舉個簡單場景案例:修改用戶名密碼,需要輸入兩遍新密碼:newPass,newPassAgain,要求newPass.equals(newPassAgain)

如果用事務(wù)腳本來實現(xiàn)這個驗證規(guī)則,那么你的代碼里肯定穿插著類似這樣的代碼:

if (!this.newPass.equals(this.newPassAgain)){
    throw new RuntimeException("...");
}

雖然這么做也能達到校驗的效果,但很明顯這不夠優(yōu)雅。

但是基于Hibernate-Validator內(nèi)置的@ScriptAssert,可以很容易的處理這種case:

@ScriptAssert(lang = "javascript", alias = "_", script = "_.newPass.equals(_.newPassAgain)",message = "兩個密碼不相等")
public class SecContent implements Serializable {

    @NotNull(message = "age 不能為空",groups = {TestGroup.class})
    private Integer age;

    @NotBlank
    private String newPass;
    @NotBlank
    private String newPassAgain;
    ...
}

@ScriptAssert支持寫腳本來完成驗證邏輯,這里使用的是javascript(缺省情況下的唯一選擇,也是默認選擇)

@ScriptAssert是內(nèi)置就提供的,因此使用起來非常的方便和通用。但缺點也是因為過于通用,因此語義上不夠明顯,需要閱讀腳本才知。推薦少量(非重復(fù)使用)、邏輯較為簡單時使用,更為輕巧

自定義校驗

舉例說明自定義注解的實現(xiàn):需要一個自定義注解來校驗入?yún)ame不能和已存在name重名

1.自定義注解

@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueConstraintValidator.class)
public @interface UniqueConstraint {

    //下面三個屬性是必須有的屬性

    String message();

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

2.新建一個UniqueConstraintValidator類來驗證注解

//自定義校驗注解 的 校驗邏輯
//不需要加注解@Component,因為實現(xiàn)了ConstraintValidator接口自動會注冊為spring bean
public class UniqueConstraintValidator implements ConstraintValidator<UniqueConstraint,Object> {

    @Autowired
    private UserService userService;

    @Override
    public void initialize(UniqueConstraint uniqueConstraint) {
        System.out.println("my validator init");
    }

    //Object為校驗的字段類型
    //返回true則校驗成功
    //o為校驗字段的值,constraintValidatorContext為校驗注解里的屬性值
    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        String username = (String) o;
        TbUser user = userService.findByUsername(username);
        return user==null?true:false;
    }
}
  • UniqueConstraintValidator類必須實現(xiàn)ConstraintValidator接口initialize方法以及驗證方法isValid
  • 具體的校驗邏輯在isValid方法中做校驗

使用的時候在需要的字段上標記該注解即可:

Dubbo RPC參數(shù)校驗

那么Dubbo作為國產(chǎn)優(yōu)秀的開源RPC框架,支持注解方式校驗參數(shù)么?答案當然是支持的~

ValidationFilter

ValidationFilter通過在實際方法調(diào)用之前,根據(jù)調(diào)用者url配置的validation屬性值找到正確的{Validator}實例來調(diào)用驗證。

關(guān)于ValidationFilter是如何被調(diào)用的是dubbo spi的內(nèi)容這里就不提了,但是要想其生效需要在consumer或者provider端配置一下:

consumer:

   @DubboReference(validation = "true")
    private DemoService demoService;

provider:

@DubboService(validation = "true")
public class DemoServiceImpl implements DemoService {

注:如果在消費端開啟參數(shù)校驗,不通過就不會向服務(wù)端發(fā)起rpc調(diào)用,但是要自己處理校驗異常ConstraintViolationException

Validator校驗器

默認ValidationFilter使用的校驗器看下圖

JValidation實現(xiàn)代碼還是比較少的

/**
 * Creates a new instance of {@link Validator} using input argument url.
 * @see AbstractValidation
 * @see Validator
 */
public class JValidation extends AbstractValidation {

    /**
     * Return new instance of {@link JValidator}
     * @param url Valid URL instance
     * @return Instance of JValidator
     */
    @Override
    protected Validator createValidator(URL url) {
        return new JValidator(url);
    }

}

可以看到實際干活的是org.apache.dubbo.validation.support.jvalidation.JValidator

在其validate方法中可以看到有一個@MethodValidated注解

點開查看它的注釋

大意上能明白這注解是標記在方法上支持分組校驗的!

簡單示例:

消費方代碼:

@Component("demoServiceComponent")
public class DemoServiceComponent implements DemoService {
    
    @DubboReference(validation = "true")
    private DemoService demoService;

    @Override
    public String sayHello(String name) {
        return demoService.sayHello(name);
    }

    @Override
    public String sayGoodBye(Content content) {
        return demoService.sayGoodBye(content);
    }

    @Override
    public CompletableFuture<String> sayHelloAsync(String name) {
        return null;
    }
}

dubbo client interface:

public interface DemoService {

    String sayHello(String name);

    @MethodValidated({TestGroup.class})
    String sayGoodBye(Content content);

    default CompletableFuture<String> sayHelloAsync(String name) {
        return CompletableFuture.completedFuture(sayHello(name));
    }

}

方法入?yún)ontent:

public class Content implements Serializable {

    @NotNull(message = "name不能為空",groups = {TestGroup.class})
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

注:沒有設(shè)置groups的校驗注解也會進行校驗,作為默認分組。最后捕獲下拋出的ConstraintViolationException以結(jié)構(gòu)化的json格式返回給調(diào)用方"校驗錯誤信息"

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。 

相關(guān)文章

  • feign客戶端HTTP狀態(tài)碼為204時?響應(yīng)體被忽略的問題

    feign客戶端HTTP狀態(tài)碼為204時?響應(yīng)體被忽略的問題

    這篇文章主要介紹了feign客戶端HTTP狀態(tài)碼為204時?響應(yīng)體被忽略的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • java中怎樣表示圓周率

    java中怎樣表示圓周率

    這篇文章主要介紹了java中怎樣表示圓周率問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • java開發(fā)線上事故理解RocketMQ異步精髓

    java開發(fā)線上事故理解RocketMQ異步精髓

    這篇文章主要介紹了java開發(fā)線上事故理解RocketMQ異步精髓
    2022-07-07
  • JAVA 格式化JSON數(shù)據(jù)并保存到j(luò)son文件中的實例

    JAVA 格式化JSON數(shù)據(jù)并保存到j(luò)son文件中的實例

    這篇文章主要介紹了JAVA 格式化JSON數(shù)據(jù)并保存到j(luò)son文件中的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • 使用res:bean屬性復(fù)制避免null值覆蓋版本

    使用res:bean屬性復(fù)制避免null值覆蓋版本

    這篇文章主要介紹了使用res:bean屬性復(fù)制避免null值覆蓋版本的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java單例模式分析

    Java單例模式分析

    這篇文章主要給大家介紹了關(guān)于Java單例模式,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2021-09-09
  • 解決spring cloud zuul與nginx的域名轉(zhuǎn)發(fā)問題

    解決spring cloud zuul與nginx的域名轉(zhuǎn)發(fā)問題

    這篇文章主要介紹了spring cloud zuul與nginx的域名轉(zhuǎn)發(fā)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java詳細講解分析雙指針法的使用

    Java詳細講解分析雙指針法的使用

    嚴格的來說,雙指針只能說是是算法中的一種技巧。雙指針指的是在遍歷對象的過程中,不是普通的使用單個指針進行訪問,而是使用兩個相同方向(快慢指針)或者相反方向(對撞指針)的指針進行掃描,從而達到相應(yīng)的目的
    2022-04-04
  • Springboot整合Shiro的代碼實例

    Springboot整合Shiro的代碼實例

    這篇文章主要介紹了Springboot整合Shiro的代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • java?http請求獲取圖片并返回文件流給前端的方法步驟

    java?http請求獲取圖片并返回文件流給前端的方法步驟

    作為一名Java后端開發(fā)者,掌握如何從后端返回文件流至前端是基本技能之一,這篇文章主要介紹了java?http請求獲取圖片并返回文件流給前端的方法步驟,需要的朋友可以參考下
    2024-09-09

最新評論

呼和浩特市| 江门市| 施秉县| 宁强县| 三江| 天镇县| 察雅县| 龙井市| 临邑县| 阿克陶县| 白银市| 元江| 麻栗坡县| 庄河市| 葫芦岛市| 博野县| 云浮市| 宜城市| 措勤县| 长岛县| 龙陵县| 乡宁县| 博罗县| 大田县| 龙州县| 古交市| 天台县| 苍山县| 赤峰市| 昭苏县| 綦江县| 灵璧县| 苏尼特右旗| 钟祥市| 高青县| 怀宁县| 定日县| 九龙县| 昭通市| 收藏| 蒲城县|