1. ホーム
  2. ジャワ

Validatedアノテーションの説明、Grouped Validation、Nested Validation、@Validと@Validatedの違い、Spring Boot @Validated

2022-03-01 03:05:04

テクノロジースタック

スプリングブート2.3.3.RELEASE

ハイバーネートバリデーター

プロジェクトのソースコードは、この記事の最後に添付されています。

ディレクトリ

簡単な説明

プロジェクトの依存関係

グローバル例外処理クラス

ベースパラメータチェックサム

エンティティクラス

制御クラス

テスト

ネストしたパラメータの検証

エンティティクラス

制御クラス

テスト

グループ化されたパラメータの検証

インターフェースクラス

エンティティクラス

制御クラス

テスト

 Validと@Validatedの違いについて


簡単な説明

Validationは、転送されたパラメータのデータを検証し続けるためのアノテーションのセットで、Validationを設定することで簡単に行うことができます。

クラス、メソッド、パラメータに作用する @Validated

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
    Class<? >[] value() default {};
}

エラーステータスコード

返されるレスポンスコードは、400 bad requestを推奨します。

すべてのパラメータコメントの意味

プロジェクトの依存関係

Mavenの依存関係の座標です。

注:デモプロジェクトでは、すべてのエンティティクラスはパッケージのエンティティに、コントロールレイヤーはパッケージのコントローラに含まれています。

グローバル例外処理クラス

注意:例外処理を行わない場合、@Validatedアノテーションに対するデフォルトの例外メッセージは以下のようになります(例)。

2020-09-05 21:48:38.106 WARN 9796 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind. MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String com.example.validateddemo.controller. DemoController.validatedDemo1(com.example.validateddemo.entity.dto.UseDto): [Field error in object 'useDto' on field 'username': rejected value [null]; codes [NotBlank.useDto.username,NotBlank.username,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework. context.support.DefaultMessageSourceResolvable: codes [useDto.username,username]; arguments []; default message [username]]; default message [username cannot be empty!] ]

 そこで、パラメータのチェックサムが失敗したときにスローされる例外を処理するグローバルな例外処理クラスをここで作成し、ログの出力と一緒に処理するようにしました。

package com.example.validateddemo.handler;

import com.example.validateddemo.base.Result;
import com.example.validateddemo.enums.ResultEnum;
import com.example.validateddemo.utils.ResultUtil;
import lombok.extern.slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind;
import org.springframework.web.bind.annotation;
import org.springframework.web.bind.annotation;
import org.springframework.web.bind.annotation;
import org.springframework.web.bind.annotation.ResponseStatus;
import java.util.List;

List; /**
 * @author He Changjie on 2020/9/5
 */
@Slf4j
@ControllerAdvice
public class ValidatedExceptionHandler {

    /**
     * Handle @Validated parameter validation failure exceptions
     * @param exception exception class
     * @return response
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result exceptionHandler(MethodArgumentNotValidException exception){
        BindingResult result = exception.getBindingResult();
        StringBuilder stringBuilder = new StringBuilder();
        if (result.hasErrors()) {
            List<ObjectErrors> errors = result.getAllErrors();
            if (errors ! = null) {
                errors.forEach(p -> {
                    FieldError fieldError = (FieldError) p;
                    log.warn("Bad Request Parameters: dto entity [{}],field [{}],message [{}]",fieldError.getObjectName(), fieldError.getField(), fieldError.getDefaultMessage());
                    stringBuilder.append(fieldError.getDefaultMessage());
                });
            }
        }
        return ResultUtil.validatedException(stringBuilder.toString());
    }
}


ベースパラメーターチェックサム

エンティティクラス

package com.example.validateddemo.entity.dto;

import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;

import javax.validation.constraints.*;

/**
 * User entity
 * Data transfer object
 * @author He Changjie on 2020/9/5
 */
@Data
public class User1Dto {
    /**
     * User name
     */
    @NotBlank(message = "User name cannot be empty! ")
    private String username;
    /**
     * Gender
     */
    @NotBlank(message = "Gender cannot be empty! ")
    private String gender;
    /**
     * Age
     */
    @Min(value = 1, message = "Age is wrong! ")
    @Max(value = 120, message = "Age is wrong! ")
    private int age

制御クラス

package com.example.validateddemo.controller;

import com.example.validateddemo.entity.dto.Use1Dto;
import org.springframework.validation.annotation.Validated;
importieren org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
importieren org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;

/**
 * @Autor He Changjie am 2020/9/5
 */
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {

    @PostMapping("/insert")
    public String validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){
        System.out.println(use1Dto);
        return "success";
    }
}


テスト

1. パラメータ・キャリブレーションに合格

2. パラメータのチェックサムに失敗しました。

ネストしたパラメータの検証

検証する必要があるエンティティ内のオブジェクトのセットや他のオブジェクトを検証する

エンティティクラス

package com.example.validateddemo.entity.dto;

import lombok.Data;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import javax.util.List; import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * 队伍实体
 * 数据传输对象
 * @Autor He Changjie am 2020/9/5
 */
@Daten
public class Team1Dto {
    /**
     * 队伍名称
     */
    @NotBlank(message = "队伍名称不能为空!")
    private String name;
    /**
     * 队伍人员
     */
    @NotNull(message = "队伍人员不能为空!")
    @Gültig
    private List<User1Dto> userList;

    /**
     * 队伍负责人
     */
    @NotNull(message = "队伍负责人不能为空!")
    @Gültig
    private User1Dto user;
}


制御クラス

package com.example.validateddemo.controller;

import com.example.validateddemo.base.Result;
import com.example.validateddemo.entity.dto.Team1Dto;
importieren com.example.validateddemo.entity.dto.Use1Dto;
importieren com.example.validateddemo.utils.ResultUtil;
import org.springframework.validation.annotation.Validated;
importieren org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
importieren org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;

/**
 * @Autor He Changjie am 2020/9/5
 */
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {

    @PostMapping("/insert")
    public Result validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){
        return ResultUtil.success(use1Dto);
    }

    @PostMapping("/insert2")
    public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){
        return ResultUtil.success(team1Dto);
    }
}


テスト

1. パラメータのバリデーションに合格した。

2. パラメータバリデーションが通らない。

グループ化されたパラメータ検証

異なる検証ルールをグループ化し、使用時に異なる検証ルールを指定することができる

インターフェースクラス

package com.example.validateddemo.interfaces;

/**
 * 校验分组1
 * @author He Changjie am 2020/9/5
 */
public interface Gruppe1 {
}


package com.example.validateddemo.interfaces;

/**
 * 校验分组2
 * @author He Changjie am 2020/9/5
 */
öffentliche Schnittstelle Group2 {
}


エンティティクラス

package com.example.validateddemo.entity.dto;

import com.example.validateddemo.interfaces.Group1;
import com.example.validateddemo.interfaces.Group2;
import lombok.Data;

import javax.validation.constraints.*;

/**
 * @author He Changjie am 2020/9/5
 */
@Data
public class User2Dto {
    /**
     * 用户名
     */
    @NotBlank(message = "用户名不能为空!", groups = {Group1.class})
    private String username;
    /**
     * 性别.
     */
    @NotBlank(message = "性别不能为空!")
    private String gender;
    /**
     * 年龄
     */
    @Min(value = 1, message = "年龄有误!", groups = {Group1.class})
    @Max(Wert = 120, Nachricht = "年龄有误!", Gruppen = {Group2.class})
    private int age;
    /**
     * 地址.
     */
    @NotBlank(message = "地址不能为空!")
    private String-Adresse;
    /**
     * 邮箱
     */
    @Email(message = "邮箱有误!", groups = {Group2.class})
    private String email;
    /**
     * 手机号码
     */
    @Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$",message = "手机号码有误!", groups = {Group2.class})
    private String mobile;
}



制御クラス

package com.example.validateddemo.controller;

import com.example.validateddemo.base.Result;
import com.example.validateddemo.entity.dto.Team1Dto;
import com.example.validateddemo.entity.dto.User1Dto;
import com.example.validateddemo.entity.dto.User2Dto;
import com.example.validateddemo.interfaces.Group1;
import com.example.validateddemo.interfaces.Group2;
import com.example.validateddemo.utils.ResultUtil;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation;
import org.springframework.web.bind.annotation;
import org.springframework.web.bind.annotation;

/**RequestMapping; import org.springframework.web.bind.annotation.
 * @author He Changjie on 2020/9/5
 */
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {

    @PostMapping("/insert")
    public Result validatedDemo1(@Validated @RequestBody User1Dto user1Dto){
        return ResultUtil.success(user1Dto);
    }

    @PostMapping("/insert2")
    public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){
        return ResultUtil.success(team1Dto);
    }

    @PostMapping("/insert3")
    public Result validatedDemo3(@Validated @RequestBody User2Dto user2Dto){
        return ResultUtil.success(user2Dto);
    }

    @PostMapping("/insert4")
    public Result validatedDemo4(@Validated(Group1.class) @RequestBody User2Dto user2Dto){
        return ResultUtil.success(user2Dto);
    }

    @PostMapping("/insert5")
    public Result validatedDemo5(@Validated(Group2.class) @RequestBody User2Dto user2Dto){
        return ResultUtil.success(user2Dto);
    }
}


テスト

1. グループ化されていないチェックサムが通過する。

2. グループ化されていないパラメータのチェックサムが通らない。


3. グループ1パラメータがチェックアウトされる

4. グループ 1 パラメータのチェックサムが通らない

5. グループ化された2つのパラメータチェックが通過

6. グループ化 2 パラメータのチェックサムが通らない

7. デフォルトのグループ化を使用すると、パラメータのチェックサムは通過します。

注:以下のように調整した後、コントロールレイヤー/insert3インターフェイスをテストしてください。

@PostMapping("/insert3")
    public Result validatedDemo3(@Validated(Default.class) @RequestBody User2Dto user2Dto){
        return ResultUtil.success(user2Dto);
    }

Default.classはValidated依存関係に含まれるインターフェースクラスであり、カスタムインターフェースクラスではありません。

8. デフォルトのグループ化を使用すると、パラメータのチェックサムが通らない。

説明 ポイント7と同じ操作

 Validと@Validatedの違いについて

ソースコードによる解析。

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Valid {
}

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
    Class<? >[] value() default {};
}

@Valid です。グループ化されていません。

有効:メソッド、コンストラクタ、メソッドパラメータ、メンバプロパティ(フィールド)に使用できる。

Validated: グループ化機能を提供し、受信した検証時に異なる検証メカニズムを異なるグループに適用することができます。

Validated: 型、メソッド、メソッド・パラメータに使用できます。ただし、メンバープロパティ(フィールド)には使用できない。

メンバープロパティ(フィールド)で両方を使用できることは、ネストされたバリデーションを提供する能力に直接影響します。

コードクラウドのアドレスです。 https://gitee.com/jie_harris/validateddemo.git

手作業での編集は難しいので、出典を明記してください。

ありがとうございます。