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

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

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

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

其實(shí)可根據(jù)一些校驗(yàn)的注解來實(shí)現(xiàn)我們的參數(shù)校驗(yàn),主要介紹一下常用的 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>

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

2、使用

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

下面再分別介紹

注解名稱驗(yàn)證得類型描述
AssertFalseBoolean,boolean被注解的元素屬性值必須為false
AssertTrueBoolean,boolean被注解的元素屬性值必須為true
DecimalMaxBigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數(shù)字)子類型驗(yàn)證注解的元素值小于等于指定的value值
DecimalMinBigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數(shù)字)子類型驗(yàn)證注解的元素值大于等于指定的value值
DigitsBigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數(shù)字)子類型驗(yàn)證注解的元素值的整數(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)證它們是嚴(yán)格負(fù)數(shù),不包括0
NegativeOrZero數(shù)值適用于數(shù)值并驗(yàn)證它們是嚴(yán)格負(fù)數(shù),包括0
NotBlankCharSequence子類型驗(yàn)證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應(yīng)用于字符串且在比較時會去除字符串的首位空格
NotEmptyCharSequence子類型、Collection、Map、數(shù)組驗(yàn)證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0)
NotNull任意類型被注解的元素屬性值必須非null
Null任意類型被注解的元素屬性值必須為null
PatternString,任何CharSequence的子類型被注解的元素值必須符合指定的正則表達(dá)式
Positive數(shù)值適用于數(shù)值并驗(yàn)證它們是嚴(yán)格正數(shù),不包括0
PositiveOrZero數(shù)值適用于數(shù)值并驗(yàn)證它們是嚴(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 注解詳細(xì)屬性的介紹

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

2.1.1 不能自定義值的

以下面的這些注解為代表

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

@AssertFalse為例,該注解的詳細(xì)內(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 指定驗(yàn)證類,如果不自定義指定,實(shí)現(xiàn)其默認(rèn)的驗(yàn)證類 ,如果指定
// @Constraint(validatedBy = { MyValidator.class })
@Constraint(validatedBy = {})
public @interface AssertFalse {
    // 校驗(yàn)失敗的信息,可以自定義
    String message() default "{javax.validation.constraints.AssertFalse.message}";
    // 這里主要進(jìn)行將validator進(jìn)行分類,不同的類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 能自定義值的

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

@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 {
    // 校驗(yàn)失敗的信息,可以自定義
    String message() default "{javax.validation.constraints.Max.message}";

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

    Class<? extends Payload>[] payload() default {};
	// 與上面不同的就是多了個value,這個需要自定義參數(shù)傳入的值與這個value值對比,也就是校驗(yàn)的參考值
    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ù)多種校驗(yàn)規(guī)則的時候,這個屬性就起作用了。

如果我們在一個屬性使用注解的時候,如果不指定groups的時候,其實(shí)默認(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)建用戶組別、更新用戶組別(其實(shí)就是兩個接口,里面不用有方法,但是要注意要繼承Default接口,理由下面會說

import javax.validation.groups.Default;

public interface CreateUser extends Default {
}

import javax.validation.groups.Default;

public interface UpdateUser extends Default{
}

(2)使用組別

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

這里需要注意:定義的組別最好要繼承Default接口,不然當(dāng)我們在指定規(guī)則的校驗(yàn)時候,那么不標(biāo)注groups的屬性就不再校驗(yàn)了,因?yàn)槟J(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 = "手機(jī)號不能為空")
        @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手機(jī)號格式有誤")
        private String mobile;
    
        @Future(message = "時間在當(dāng)前時間之后才可以通過")
        private Date date;
}

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

兩個接:

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

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

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


 /**
     * 走參數(shù)校驗(yàn)注解的 groups 組合校驗(yàn)
     *
     * @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 定義驗(yàn)證規(guī)則以
  • pojo作為參數(shù)傳參

(1)User pojo類 定義校驗(yàn)規(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 = "手機(jī)號不能為空")
        @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手機(jī)號格式有誤")
        private String mobile;
    
        @Future(message = "時間在當(dāng)前時間之后才可以通過")
        private Date date;
}

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

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

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

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

其他需要處理 ConstraintViolationException異常進(jìn)行處理

一般像異常捕捉的,可以自定義一個異常捕捉Handler,實(shí)現(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ù)校驗(yàn)
     */
    @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、自定義使用

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

  • 定義一個注解
  • 編寫一個驗(yàn)證類
  • 使用

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

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

(2)編寫一個驗(yàn)證類

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

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

// 這個是Max的指定的驗(yàn)證規(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);
}

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

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

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

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

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

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

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

總結(jié)

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

相關(guān)文章

最新評論

同江市| 商都县| 南木林县| 海林市| 佳木斯市| 宁都县| 句容市| 宝兴县| 吴江市| 分宜县| 阿拉善右旗| 汝州市| 巢湖市| 金溪县| 来宾市| 临颍县| 法库县| 广宗县| 五指山市| 无为县| 衡水市| 会宁县| 遵义县| 醴陵市| 东丰县| 佛山市| 彭水| 临夏县| 苏州市| 通山县| 葵青区| 兴国县| 八宿县| 巢湖市| 鄄城县| 怀化市| 漾濞| 洪洞县| 丹阳市| 长泰县| 江北区|