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

SpringBoot參數校驗,消除if else方式

 更新時間:2026年04月12日 11:00:02   作者:別團等shy哥發(fā)育  
文章介紹了使用JSR303和Spring Boot中的spring-boot-starter-validation進行數據驗證的方法,包括注解使用、分組驗證、嵌套對象校驗、快速失敗配置以及自定義校驗規(guī)則等內容

1、參數校驗簡介

在實際工作中,得到數據得到的第一步就是校驗數據的正確性,如果存在錄入上的問題,一般會通過注解校驗,發(fā)現錯誤后返回給用戶,但是對于一些邏輯上的錯誤,比如 購買金額 = 購買數量 × 單價 購買金額=購買數量\times 單價 購買金額=購買數量×單價,這樣的規(guī)則就很難使用注解方式驗證了,此時可以使用Spring提供的驗證器(Validator)規(guī)則去驗證。

由于Validator框架通過硬編碼完成數據校驗,在實際開發(fā)中會顯得比較麻煩,因此現在開發(fā)更加推薦使用JSR 303完成服務端的數據校驗。

Spring3開始支持JSR 303驗證框架,JSR 303是Java為Bean數據合法性校驗所提供的標準框架。

JSR 303支持XML風格的和注解風格的驗證,通過在Bean屬性上標注類似于@NotNull、@Max等的標準注解指定校驗規(guī)則,并通過標準的驗證接口對Bean進行驗證。

訪問http://jcp.org/en/jsr/detail?id=303可以查看詳細內容并下載JSR 303 Bean Validation。JSR 303 不需要編寫驗證器,它定義了一套可標注在成員變量、屬性方法上的校驗注解,如下表所示:

約束說明
@Null被注解的元素必須為Null
@NotNull被注解的元素必須部位Null
@AssertTrue被注解的元素必須為true
@AssertFalse被注解的元素必須為false
@Min(value)被注解的元素必須是一個數字,其值必須大于等于最小值
@Max(value)被注解的元素必須是一個數字,其值必須小于等于最大值
@DecimalMin(value)被注解的元素必須是一個數字,其值必須大于等于最小值
@DecimalMax(value)被注解的元素必須是一個數字,其值必須小于等于最大值
@Size(max,min)被注解的元素的大小必須在指定的范圍內
@Digits(integer,fraction)被注解的元素必須是一個數字,其值必須在可接受范圍內
@Past被注解的元素必須是一個過去的日期
@Future被注解的元素必須是一個將來的日期
@Pattern(value)被直接的元素必須符合指定的正則表達式

Hibernate Validator是JSR 303的一個參考實現,除了支持所有標準的校驗注解之外,還擴展了如下表所示的注解。

約束說明
@NotBlank檢查被注解的元素是不是Null,以及被去掉前后空格的長度是否大于0
@Email被注解的元素必須是電子郵件格式
@URL被注解的元素必須是合法的URL地址
@length被注解的字符串的字符串的大小必須在指定的范圍內
@NotEmpty校驗集合元素或數組元素或者字符串是否非空。通常作用于集合字段或數組字段,此時需要集合或者數字的元素個數大于0。也可以作用于字符串,此時校驗字符串不能為null或空串(可以是一個空格)。
@Range被注解的元素必須在合適的范圍內

2、實戰(zhàn)

spring-boot-starter-validation是Spring Boot 框架中的一個模塊,它構建在Hibernate Validator的基礎之上,并提供了對Bean Validation的集成支持。它可以通過SpringBoot的自動配置機制輕松集成到Spring應用程序中。使用 spring-boot-starter-validation,你可以在SpringBoot應用程序中使用 Hibernate Validator的功能,而不需要顯式地配置Hibernate Validator。

因此,Hibernate Validator是一個獨立的驗證框架,而 spring-boot-starter-validation 則是一個為 Spring Boot應用程序提供集成 Hibernate Validator 的模塊。

在這里搭建一個簡單的SpringBoot項目,并引入如下依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2.1 全局異常處理

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
    //參數校驗異常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Result error(MethodArgumentNotValidException e){
        log.warn(e.getMessage());
        return Result.fail()
                .code(ResultCodeEnum.ARGUMENT_VALID_ERROR.getCode())
                .message(e.getBindingResult().getFieldError().getDefaultMessage());
    }
    //參數校驗異常
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public Result error(BindException e){
        log.warn(e.getMessage());
        StringBuilder sb = new StringBuilder();
        for (ObjectError error : e.getBindingResult().getAllErrors()) {
            sb.append(error.getDefaultMessage());
        }
        return Result.fail()
                .code(ResultCodeEnum.ARGUMENT_VALID_ERROR.getCode())
                .message(sb.toString());
    }
    //參數校驗異常
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public Result error(ConstraintViolationException e){
        log.warn(e.getMessage());
        StringBuilder sb = new StringBuilder();
        for (ConstraintViolation<?> violation : e.getConstraintViolations()) {
            sb.append(violation.getMessage());
        }
        return Result.fail()
                .code(ResultCodeEnum.ARGUMENT_VALID_ERROR.getCode())
                .message(sb.toString());
    }
    //全局異常
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result error(Exception e){
        log.warn(e.getMessage());
        return Result.fail().message("執(zhí)行了全局異常處理");
    }
}

2.2 快速開始

2.2.1 實體類

@Data
public class UserCreateVo {
    @NotBlank(message = "用戶名不能為空")
    private String userName;

    @NotBlank(message = "姓名不能為空")
    private String name;

    @Size(min=11,max=11,message = "手機號長度不符合要求")
    private String phone;

    @NotNull(message = "性別不能為空")
    private Integer sex;
}
@Data
public class UserUpdateVo {

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

    @NotBlank(message = "用戶名不能為空")
    private String userName;

    @NotBlank(message = "姓名不能為空")
    private String name;

    @Size(min=11,max=11,message = "手機號長度不符合要求")
    private String phone;

    @NotNull(message = "性別不能為空")
    private Integer sex;
}

2.2.1 定義請求接口

@Validated
@RestController
public class UserController {

    @PostMapping("create")
    public Result createUser(@Validated @RequestBody UserCreateVo userCreateVo){
        return Result.ok("參數校驗成功");
    }

    @PostMapping("update")
    public Result updateUser(@Validated @RequestBody UserUpdateVo userUpdateVo){
        return Result.ok("參數校驗成功");
    }
}

2.2.2 測試

新增接口測試:

這里故意不寫用戶名

更新接口測試:

2.3 路徑傳參校驗

有時候我們是通過@Pathvariable注解實現參數傳遞的,這個時候校驗如下:

@GetMapping("getUserById/{id}")
public Result getUserById(@PathVariable @Size(min=2,max=5,message = "id長度不符合要求") String id){
    return Result.ok("參數校驗成功");
}

可以看到,校驗規(guī)則是生效的。

2.4 分組校驗

我們前邊寫了兩個Vo類:UserCreateVoUserUpdateVo。如果每個請求都要定制Vo類的話,那我們還不如直接用if else梭哈呢。

比如我們新增的時候一般不需要id,但是修改的時候需要傳入id。

2.4.1 定義分組校驗接口

//分組校驗
public class UserGroup {
    public interface CreateGroup extends Default {
    }
    public interface UpdateGroup extends Default {
    }
}

2.4.2 統(tǒng)一Vo校驗類

@Data
public class UserVo {

    @NotBlank(message = "id不能為空",groups = UserGroup.UpdateGroup.class)
    private String id;

    @NotBlank(message = "用戶名不能為空",groups = 
            {UserGroup.CreateGroup.class,UserGroup.UpdateGroup.class})
    private String userName;

    @NotBlank(message = "姓名不能為空",groups = 
            {UserGroup.CreateGroup.class,UserGroup.UpdateGroup.class})
    private String name;

    @Size(min=11,max=11,message = "手機號長度不符合要求",groups = 
            {UserGroup.CreateGroup.class,UserGroup.UpdateGroup.class})
    private String phone;

    @NotNull(message = "性別不能為空",groups = 
            {UserGroup.CreateGroup.class,UserGroup.UpdateGroup.class})
    private Integer sex;
}

2.4.3 修改接口

參數上邊添加@Validated接口,并指定分組名稱,并統(tǒng)一使用UserVo類接收參數。

@Validated
@RequestMapping("/user")
@RestController
public class UserController {

    @PostMapping("create")
    public Result createUser(@Validated(UserGroup.CreateGroup.class) @RequestBody UserVo userVo){
        return Result.ok("參數校驗成功");
    }

    @PutMapping("update")
    public Result updateUser(@Validated(UserGroup.UpdateGroup.class) @RequestBody UserVo userVo){
        return Result.ok("參數校驗成功");
    }

    @GetMapping("getUserById/{id}")
    public Result getUserById(@PathVariable @Size(min=2,max=5,message = "id長度不符合要求") String id){
        return Result.ok("參數校驗成功");
    }

}

2.4.4 測試

新增接口:

修改接口:

2.5 嵌套對象校驗

存在嵌套對象校驗的時候,使用@Valid注解解決。

2.5.1 添加一個角色實體

@Data
public class Role {
    @NotBlank(message = "角色名稱不能為空")
    private String roleName;
}

2.5.2 修改VO類

在User類中引入角色實體,并加入@Valid注解。

@Data
public class UserVo {

    @NotBlank(message = "id不能為空",groups = UserGroup.UpdateGroup.class)
    private String id;

    @NotBlank(message = "用戶名不能為空",groups =
            {UserGroup.CreateGroup.class,UserGroup.UpdateGroup.class})
    private String userName;

    @NotBlank(message = "姓名不能為空",groups =
            {UserGroup.CreateGroup.class,UserGroup.UpdateGroup.class})
    private String name;

    @Size(min=11,max=11,message = "手機號長度不符合要求",groups =
            {UserGroup.CreateGroup.class,UserGroup.UpdateGroup.class})
    private String phone;

    @NotNull(message = "性別不能為空",groups =
            {UserGroup.CreateGroup.class,UserGroup.UpdateGroup.class})
    private Integer sex;

    @Valid
    @NotNull(message = "角色信息不能為空")
    private Role role;
}

2.5.3 測試

測試新增接口,故意不傳角色信息:

測試修改接口,故意不傳角色信息:

2.6 快速失敗配置

默認validation的校驗規(guī)則默認會檢查所有屬性的校驗規(guī)則,在每一條規(guī)則都校驗完成后才拋出異常,這樣子難免效率會很低,我們希望在發(fā)現錯誤后就不再向后檢查,可以通過“快速失敗”配置解決,參考代碼如下:

/**
 * 參數校驗相關配置
 */
@Configuration
public class ValidConfig {
    /**
     * 快速返回校驗器
     * @return
     */
    @Bean
    public Validator validator(){
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                //快速失敗模式
                .failFast(true)
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }

    /**
     * 設置快速校驗,返回方法校驗處理器
     * 使用MethodValidationPostProcessor注入后,會啟動自定義校驗器
     * @return
     */
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor(){
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
    }
}

2.7 自定義校驗規(guī)則

有時候框架自帶的校驗無法滿足我們業(yè)務的需求,這個時候可以根據自己的需求定制校驗規(guī)則。

這里我們自定義一個手機號校驗的注解,僅作示例使用,因為官方已經提供了手機號的校驗注解。

2.7.1 定義注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Constraint(validatedBy = PhoneValidator.class)
public @interface PhoneValid {
    String message() default "請?zhí)顚懻_的手機號";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

@Constraint注解是Hibernate Validator的注解,用于實現自定義校驗規(guī)則,通過validatedBy參數指定進行參數校驗的實現類。

2.7.2 校驗實現類

實現ConstraintValidator接口。

ConstraintValidator<A extends Annotation, T>中,第一個參數為注解,即Annotation,第二個參數是泛型。

public class PhoneValidator implements ConstraintValidator<PhoneValid,Object> {
    /**
     * 11位手機號的正則表達式,以13、14、15、17、18頭
     * ^:匹配字符串的開頭
     * 13\d:匹配以13開頭的手機號碼
     * 14[579]:匹配以145、147、149開頭的手機號
     * 15[^4\D]:匹配以15開頭且第3位數字不為4的手機號碼
     * 17[^49\D]:匹配以17開頭且第3位數字部位4或9的手機號碼
     * 18\d :匹配以18開頭的手機號碼
     * \d{8}:匹配手機號碼的后8位,即剩余的8個數字
     * $:匹配字符串的結尾
     */
    public static final String REGEX_PHONE="^(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}$";


    //初始化注解
    @Override
    public void initialize(PhoneValid constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
    }

    //校驗參數,true表示校驗通過,false表示校驗失敗
    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        String phone = String.valueOf(o);
        if(phone.length()!=11){
            return false;
        }
        //正則校驗
        return phone.matches(REGEX_PHONE);
    }
}

2.7.3 在實體中添加自定義注解

2.7.4 測試自定義校驗規(guī)則

先使用一個正確的手機號測試,校驗成功。

再用一個錯誤的手機號測試,校驗失敗。

就介紹到這里,其實參數校驗的用法很多,這里只是介紹下常用的功能。

總結

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

相關文章

  • Java高效實現復制PPT(PowerPoint)幻燈片

    Java高效實現復制PPT(PowerPoint)幻燈片

    在日常的開發(fā)工作中,我們經常會遇到需要對Office文檔進行編程處理的需求,本文將為您揭示如何利用強大的 Spire.Presentation for Java進行PPT復制,有需要的小伙伴可以了解下
    2025-09-09
  • JUC之Semaphore源碼分析

    JUC之Semaphore源碼分析

    這篇文章主要為大家詳細分析了JUC之Semaphore源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Springboot集成SpringBatch批處理組件

    Springboot集成SpringBatch批處理組件

    這篇文章主要介紹了Springboot集成SpringBatch批處理組件,用于處理大規(guī)模數據作業(yè),提供ItemReader/Processor/Writer核心組件,支持任務持久化與H2數據庫配置,具有一定的參考價值,感興趣的可以了解一下
    2025-06-06
  • Java分布式鎖理論(redis、zookeeper))案例詳解

    Java分布式鎖理論(redis、zookeeper))案例詳解

    zookeeper有個節(jié)點路徑的概念,節(jié)點路徑不能重復,保證了唯一性,這篇文章給大家介紹Java分布式鎖理論(redis、zookeeper)?案例詳解,感興趣的朋友跟隨小編一起看看吧
    2024-01-01
  • Java使用EasyExcel進行單元格合并的問題詳解

    Java使用EasyExcel進行單元格合并的問題詳解

    項目中需要導出并合并指定的單元格,下面這篇文章主要給大家介紹了關于java評論、回復功能設計與實現的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-06-06
  • 封裝jndi操作ldap服務器的工具類

    封裝jndi操作ldap服務器的工具類

    這篇文章主要介紹了封裝JNDI操作LDAP服務器的工具類,使用者只需要會使用List,Map 數據結構,大家參考使用吧
    2014-01-01
  • Spring Boot集成Kafka最佳實踐與詳細代碼

    Spring Boot集成Kafka最佳實踐與詳細代碼

    Spring Boot作為Java領域的流行框架,提供了與Kafka的無縫集成,本文將詳細介紹如何在Spring Boot項目中優(yōu)雅地集成Kafka,并通過最佳實踐和代碼示例詳細講解,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • Spring中的Context你真的懂了嗎

    Spring中的Context你真的懂了嗎

    這篇文章主要給大家介紹了關于Spring中Context的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-08-08
  • 詳解Java中的日期類

    詳解Java中的日期類

    這篇文章主要介紹了Java中的日期類的相關資料,幫助大家更好的利用Java處理時間,感興趣的朋友可以了解下
    2020-10-10
  • MyBatis中關于resultType和resultMap的區(qū)別介紹

    MyBatis中關于resultType和resultMap的區(qū)別介紹

    MyBatis中在查詢進行select映射的時候,返回類型可以用resultType,也可以用resultMap,那么MyBatis中關于resultType和resultMap的區(qū)別是什么呢?下面小編通過本文給大家解答下
    2016-09-09

最新評論

惠安县| 运城市| 赤城县| 同德县| 荔浦县| 彭水| 鄱阳县| 东港市| 广昌县| 拜泉县| 青神县| 宜春市| 清原| 冷水江市| 灯塔市| 青浦区| 绥芬河市| 诸城市| 奉节县| 呈贡县| 泗水县| 瑞丽市| 星座| 阿合奇县| 镇江市| 尖扎县| 青川县| 商水县| 绥中县| 台北县| 深圳市| 二连浩特市| 仁怀市| 沂源县| 江都市| 灵璧县| 定西市| 福清市| 昂仁县| 龙游县| 二手房|