欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

javax.validation包里@NotNull等注解的使用方式

 更新時間:2024年01月04日 10:28:10   作者:pan_mlpan  
這篇文章主要介紹了javax.validation包里@NotNull等注解的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

在做項目的時候,對pojo和傳入的參數(shù)進行校驗,如果是代碼編寫,需要很多if來判斷

其實可根據(jù)一些校驗的注解來實現(xiàn)我們的參數(shù)校驗,主要介紹一下常用的 javax.validation 這個倉庫的使用,這里總結(jié)一下

1、導(dǎo)包

在項目的pom.xml 文件夾中導(dǎo)入包

 <!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>1.1.0.Final</version>
    </dependency>

這個驗證根據(jù)JSR 380規(guī)范,validation-api 依賴包含標(biāo)準(zhǔn)驗證注解

2、使用

這個包的注解主要有以下這么多,先簡單說明(以版本 號2.0.2為標(biāo)準(zhǔn))

下面再分別介紹

注解名稱驗證得類型描述
AssertFalseBoolean,boolean被注解的元素屬性值必須為false
AssertTrueBoolean,boolean被注解的元素屬性值必須為true
DecimalMaxBigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數(shù)字)子類型驗證注解的元素值小于等于指定的value值
DecimalMinBigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數(shù)字)子類型驗證注解的元素值大于等于指定的value值
DigitsBigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數(shù)字)子類型驗證注解的元素值的整數(shù)位數(shù)和小數(shù)位數(shù)上限
MaxBigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數(shù)字)子類型被注解的元素值的類型必須為數(shù)字,其值必須小于等于指定的最大值
MinBigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數(shù)字)子類型被注解的元素值的類型必須為數(shù)字,其值必須大于等于指定的最小值
EmailCharSequence子類型(如String)
Futurejava.util.Date,java.util.Calendar;Joda Time類庫的日期類型被注解的元素值得范圍必須為未來的一個時間
FutureOrPresentjava.util.Date,java.util.Calendar;Joda Time類庫的日期類型被注解的元素值得范圍必須為未來的一個時間或者現(xiàn)在得時間
Pastjava.util.Date,java.util.Calendar;Joda Time類庫的日期類型被注解的元素的值范圍必須為過去的一個時間
PastOrPresentjava.util.Date,java.util.Calendar;Joda Time類庫的日期類型被注解的元素的值范圍必須為過去或者現(xiàn)在的一個時間
Negative數(shù)值適用于數(shù)值并驗證它們是嚴(yán)格負數(shù),不包括0
NegativeOrZero數(shù)值適用于數(shù)值并驗證它們是嚴(yán)格負數(shù),包括0
NotBlankCharSequence子類型驗證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應(yīng)用于字符串且在比較時會去除字符串的首位空格
NotEmptyCharSequence子類型、Collection、Map、數(shù)組驗證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0)
NotNull任意類型被注解的元素屬性值必須非null
Null任意類型被注解的元素屬性值必須為null
PatternString,任何CharSequence的子類型被注解的元素值必須符合指定的正則表達式
Positive數(shù)值適用于數(shù)值并驗證它們是嚴(yán)格正數(shù),不包括0
PositiveOrZero數(shù)值適用于數(shù)值并驗證它們是嚴(yán)格正數(shù),包括0
SizeString, Collection, Map和數(shù)組屬性被注解的元素屬性值的大小必須在指定范圍內(nèi)

2.0 注解的介紹

// 表明注解可以使用在哪里
// 這里表示注解可以使用在 方法 屬性  注解  構(gòu)造方法  參數(shù)  type 
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
//描述保留注解的各種策略,它們與元注解(@Retention)一起指定注釋要保留多長時間
@Retention(RetentionPolicy.RUNTIME)
//表明這個注解是由 javadoc記錄的
@Documented
public @interface MyOwnAnnotation {
    
}

2.1 注解詳細屬性的介紹

查看上面所有注解的源碼,關(guān)于注解中的字段,主要分為以下兩種

2.1.1 不能自定義值的

以下面的這些注解為代表

  • AssertFalse AssertTrue
  • PositiveOrZero Positive Negative NegativeOrZero
  • NotNull Null NotEmpty NotBlank
  • FutureOrPresent Future PastOrPresent Past

@AssertFalse為例,該注解的詳細內(nèi)容(源碼)

@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
// 這個表明可以重復(fù)使用,
//例如在一個field使用這個注解
// 一般注解只能使用一次
//@Max(value = 11)
//Long num;
// 如果使用了這個@Repeatable標(biāo)注,那就可以使用兩次
//@Max(value = 11)
//@Max(value = 22)
//Long num;
@Repeatable(AssertFalse.List.class)
// 這個Constraint 指定驗證類,如果不自定義指定,實現(xiàn)其默認(rèn)的驗證類 ,如果指定
// @Constraint(validatedBy = { MyValidator.class })
@Constraint(validatedBy = {})
public @interface AssertFalse {
    // 校驗失敗的信息,可以自定義
    String message() default "{javax.validation.constraints.AssertFalse.message}";
    // 這里主要進行將validator進行分類,不同的類group中會執(zhí)行不同的validator操作
    Class<?>[] groups() default {};
	// 這個主要是指定bean,一般很少使用
    Class<? extends Payload>[] payload() default {};

    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        AssertFalse[] value();
    }
}

2.1.2 能自定義值的

其他的注解都是可以自定義一些值,作為校驗的參照值

@Max為例

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Max.List.class)
@Documented
@Constraint(validatedBy = {})
public @interface Max {
    // 校驗失敗的信息,可以自定義
    String message() default "{javax.validation.constraints.Max.message}";

    // 這里主要進行將validator進行分類,不同的類group中會執(zhí)行不同的validator操作
    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
	// 與上面不同的就是多了個value,這個需要自定義參數(shù)傳入的值與這個value值對比,也就是校驗的參考值
    long value();

    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        Max[] value();
    }
}

2.1.3 groups屬性的使用

這個屬性的作用就是舉個例子:例如我們在傳參的時候,加入我們創(chuàng)建一個用戶,那么我們再傳入的參數(shù)是不會包含用戶的id,而如果更新這個用戶,我們就需要傳入用戶id,那么根據(jù)多種校驗規(guī)則的時候,這個屬性就起作用了。

如果我們在一個屬性使用注解的時候,如果不指定groups的時候,其實默認(rèn)是在Default 組別中

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

等同于
import javax.validation.groups.Default;
@NotNull(message = "姓名不能為空" , groups = {Default.class})
private String name;  

那么根據(jù)這個情況,如果我們想自定義組別的時候,我們就可以分為以下幾個步驟:

  • 定義組別
  • 使用組別

(1)定義組別

還是這個例子:如果創(chuàng)建一個用戶,不用傳入用戶的id,如果更新這個用戶,我們就需要傳入用戶id

那么我們就定義兩個組別,創(chuàng)建用戶組別、更新用戶組別(其實就是兩個接口,里面不用有方法,但是要注意要繼承Default接口,理由下面會說

import javax.validation.groups.Default;

public interface CreateUser extends Default {
}

import javax.validation.groups.Default;

public interface UpdateUser extends Default{
}

(2)使用組別

1)首先在pojo中,我們需要使用組別,若屬性在不同的組別有不同的校驗方式,那么就特殊指定其需要校驗的規(guī)則,如果不指定,就還是默認(rèn)按照Default

這里需要注意:定義的組別最好要繼承Default接口,不然當(dāng)我們在指定規(guī)則的校驗時候,那么不標(biāo)注groups的屬性就不再校驗了,因為默認(rèn)按照Default

@Data
class User{
    	
    	@NotNull(message = "用戶id不能為空", groups = UpdateUser.class)
    	private Integer id;
   
        @NotNull(message = "姓名不能為空" ,groups = {CreateUser.class, UpdateUser.class})
        private String name;
    
        @NotNull(message = "性別不能為空")
        private String sex;
    
        @Max(value = 20 ,message = "最大長度為20")
        private String address;
    
        @Email(message = "不滿足郵箱格式")
        private String email;
    
        @AssertTrue(message = "字段為true才能通過")
        private boolean isAuth;
    
        @NotBlank(message = "手機號不能為空")
        @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手機號格式有誤")
        private String mobile;
    
        @Future(message = "時間在當(dāng)前時間之后才可以通過")
        private Date date;
}

2)在接口中使用特定的組別。

兩個接:

  • 創(chuàng)建user的時候,指定驗證的組別是CreateUser
  • 更新user的時候,指定驗證的組別是UpdateUser

(當(dāng)自定義的組別繼承了Default,這里指定驗證組別的,屬性會根據(jù)指定的groups來進行校驗,那么沒有指定groups的都會校驗,如果不繼承Default,那沒有自定義groups為這個組別的屬性就不生效了)

 /**
     * 走參數(shù)校驗注解的 groups 組合校驗
     *
     * @param user
     * @return
     */
@PostMapping("/users/update")
public ResponseDTO updateUser(@RequestBody @Validated(UpdateUser.class) User user) {
     userService.updateById(userDTO);
     return ResponseDTO.success();
}


 /**
     * 走參數(shù)校驗注解的 groups 組合校驗
     *
     * @param user
     * @return
     */
@PostMapping("/users/save")
public ResponseDTO saveUser(@RequestBody @Validated(CreateUser.class) User user) {
     userService.saveUser(userDTO);
     return ResponseDTO.success();
}

3、使用

3.1 第一種方式,pojo作為傳參的形式

  • Pojo 定義驗證規(guī)則以
  • pojo作為參數(shù)傳參

(1)User pojo類 定義校驗規(guī)則

@Data
class User{
   
        @NotNull(message = "姓名不能為空")
        private String name;
    
        @NotNull(message = "性別不能為空")
        private String sex;
    
        @Max(value = 20 ,message = "最大長度為20")
        private String address;
    
        @Email(message = "不滿足郵箱格式")
        private String email;
    
        @AssertTrue(message = "字段為true才能通過")
        private boolean isAuth;
    
        @NotBlank(message = "手機號不能為空")
        @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手機號格式有誤")
        private String mobile;
    
        @Future(message = "時間在當(dāng)前時間之后才可以通過")
        private Date date;
}

(2)讓校驗規(guī)則生效。在Controller類的時候,我們只需要利用 @Validated 注解來實現(xiàn)pojo的校驗

@RequestMapping("users")
public ResponseDTO saveUser( @RequestBody @Validated User user){
    
}

(3)捕捉驗證異常。如果參數(shù)校驗通過,那么就直接執(zhí)行接口方法,但是如果失敗了,我們?nèi)绾芜M行處理

MethodArgumentNotValidException是springBoot中進行綁定參數(shù)校驗時的異常,需要在springBoot中處理

其他需要處理 ConstraintViolationException異常進行處理

一般像異常捕捉的,可以自定義一個異常捕捉Handler,實現(xiàn)異常捕捉后的數(shù)據(jù)返回

import com.dto.ResponseDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;

@RestControllerAdvice
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private static int DUPLICATE_KEY_CODE = 1001;
    private static int PARAM_FAIL_CODE = 1002;
    private static int VALIDATION_CODE = 1003;

    /**
     * 處理自定義異常
     */
    @ExceptionHandler(BizException.class)
    public ResponseDTO handleRRException(BizException e) {
        logger.error(e.getMessage(), e);
        return new ResponseDTO(e.getCode(), e.getMessage());
    }

    /**
     * 方法參數(shù)校驗
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseDTO handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        logger.error(e.getMessage(), e);
        return new ResponseDTO(PARAM_FAIL_CODE, e.getBindingResult().getFieldError().getDefaultMessage());
    }

    /**
     * ValidationException
     */
    @ExceptionHandler(ValidationException.class)
    public ResponseDTO handleValidationException(ValidationException e) {
        logger.error(e.getMessage(), e);
        return new ResponseDTO(VALIDATION_CODE, e.getCause().getMessage());
    }

    /**
     * ConstraintViolationException
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseDTO handleConstraintViolationException(ConstraintViolationException e) {
        logger.error(e.getMessage(), e);
        return new ResponseDTO(PARAM_FAIL_CODE, e.getMessage());
    }
	/**
	* 路徑異常
	*/
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseDTO handlerNoFoundException(Exception e) {
        logger.error(e.getMessage(), e);
        return new ResponseDTO(404, "不好意思,路徑不存在,請檢查路徑是否正確");
    }
	/**
	* 所有其他異常捕捉
	*/
    @ExceptionHandler(Exception.class)
    public ResponseDTO handleException(Exception e) {
        logger.error(e.getMessage(), e);
        return new ResponseDTO(500, "不好意思,系統(tǒng)繁忙,請稍后再試");
    }
}

3.2 第二種方式,restful風(fēng)格

  • Controller 上加上@Validated
  • 參數(shù)上加注解
@RestController
@RequestMapping("user/")
@Validated
public class UserController{
    @RequestMapping("users)
    public ResponseDTO getUser(@RequestParam("userId") @NotNull(message = "用戶id不能為空") Long userId){

    }
}

4、自定義使用

如果我們想自定義一個驗證的注解,那么需要怎么做呢?

  • 定義一個注解
  • 編寫一個驗證類
  • 使用

**(1)**我們首先定義一個像上面的@Null 這樣的注解

@Documented
// 這里標(biāo)注該注解是使用在filed和參數(shù)上的
@Target({ElementType.PARAMETER, ElementType.FIELD})
// 運行時生效
@Retention(RetentionPolicy.RUNTIME)
// 指定驗證的類是哪個   MyValidator 就是第二步做的事情
@Constraint(validatedBy = MyValidator.class)
public @interface MyValid {
	// 提供自定義異常的信息,可以指定默認(rèn)值
    String message() default "參數(shù)不合法";
    // 分組,詳細看 上面的介紹 
    Class<?>[] groups() default {};
	// 針對bean的,使用不多
    Class<? extends Payload>[] payload() default {};
}

(2)編寫一個驗證類

我們需要編寫一個 實現(xiàn) ConstraintValidator 類實現(xiàn)類,來指定我們的校驗規(guī)則

如果不指定特定注解的情況下,直接使用

// 這個是Max的指定的驗證規(guī)則源碼
public abstract class AbstractMaxValidator<T> implements ConstraintValidator<Max, T> {
    protected long maxValue;

    public AbstractMaxValidator() {
    }
    public void initialize(Max maxValue) {
        this.maxValue = maxValue.value();
    }
    public boolean isValid(T value, ConstraintValidatorContext constraintValidatorContext) {
        if (value == null) {
            return true;
        } else {
            return this.compare(value) <= 0;
        }
    }
    protected abstract int compare(T var1);
}

// 自定義的驗證類
public class MyValidator implements ConstraintValidator {
    @Override
    public void initialize(Annotation constraintAnnotation) {
		// 可以獲取注解的值 ,一般寫在該方法中
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        // 編寫自己屬性驗證的規(guī)則,o 則是待驗證的值
        return false;
    }
}

如果在指定特定注解的情況下,那么我們就可特定 注解

// 自定義的驗證類
public class MyValidator implements ConstraintValidator<MyValid , Object> {
    @Override
    public void initialize(MyValid myValid) {
		// 可以獲取注解的值 ,一般寫在該方法中
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        // 編寫自己屬性驗證的規(guī)則,o 則是待驗證的值
        return false;
    }
}

(3)使用。就跟正常的那些注解一樣使用即可。

@Data
public Class Example{
    @NotBlank(message = "姓名不能為空")
    @MyValid(message = "姓名有誤,請核對后提交")
    private String name;
}

總結(jié)

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

相關(guān)文章

  • springMvc請求的跳轉(zhuǎn)和傳值的方法

    springMvc請求的跳轉(zhuǎn)和傳值的方法

    本篇文章主要介紹了springMvc請求的跳轉(zhuǎn)和傳值的方法,這里整理了幾種跳轉(zhuǎn)方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • java服務(wù)器的簡單實現(xiàn)過程記錄

    java服務(wù)器的簡單實現(xiàn)過程記錄

    在線瀏覽網(wǎng)頁離不開服務(wù)器,用戶發(fā)出請求request,服務(wù)器做出響應(yīng)response,提供給用戶需要的頁面,這篇文章主要給大家介紹了關(guān)于java服務(wù)器簡單實現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Springboot整合多數(shù)據(jù)源代碼示例詳解

    Springboot整合多數(shù)據(jù)源代碼示例詳解

    這篇文章主要介紹了Springboot整合多數(shù)據(jù)源代碼示例詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • springboot結(jié)合ehcache防止惡意刷新請求的實現(xiàn)

    springboot結(jié)合ehcache防止惡意刷新請求的實現(xiàn)

    這篇文章主要介紹了springboot結(jié)合ehcache防止惡意刷新請求的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 通過Java實現(xiàn)中文分詞與文本關(guān)鍵詞提取

    通過Java實現(xiàn)中文分詞與文本關(guān)鍵詞提取

    這篇文章主要為大家詳細介紹了如何利用Java實現(xiàn)中文分詞以及文本關(guān)鍵詞提取功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)
    2023-06-06
  • java 線程創(chuàng)建多線程詳解

    java 線程創(chuàng)建多線程詳解

    本文主要講解java 線程創(chuàng)建多線程的知識,這里對java線程的創(chuàng)建做了詳細介紹,并附簡單示例代碼,有興趣的小伙伴可以參考下
    2016-09-09
  • Spring Boot分頁方法定義示例

    Spring Boot分頁方法定義示例

    這篇文章主要為大家介紹了Spring Boot 分頁方法定義,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • SpringBoot中封裝Cors自動配置方式

    SpringBoot中封裝Cors自動配置方式

    這篇文章主要介紹了SpringBoot中封裝Cors自動配置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 淺談MyBatis 如何執(zhí)行一條 SQL語句

    淺談MyBatis 如何執(zhí)行一條 SQL語句

    Mybatis 是 Java 開發(fā)中比較常用的 ORM 框架。在日常工作中,我們都是直接通過 Spring Boot 自動配置,并直接使用,但是卻不知道 Mybatis 是如何執(zhí)行一條 SQL 語句的,下面就一起講解一下
    2021-05-05

最新評論