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

springboot validator枚舉值校驗(yàn)功能實(shí)現(xiàn)

 更新時(shí)間:2020年01月06日 15:03:01   作者:天際星痕  
這篇文章主要介紹了springboot validator枚舉值校驗(yàn)功能實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

這篇文章主要介紹了springboot validator枚舉值校驗(yàn)功能實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

一、前言

在spring項(xiàng)目中,校驗(yàn)參數(shù)功能使用hibernate validator是一個(gè)不錯(cuò)的選擇,我們的項(xiàng)目中也是使用它來(lái)進(jìn)行校驗(yàn)的,省去了很多難看的校驗(yàn)邏輯,使代碼的可讀性也大大增加,本章將帶你使用hibernate validator自定義注解功能實(shí)現(xiàn)一個(gè) 枚舉值校驗(yàn)的邏輯。

二、需求

我們先明確下我們的需求,在程序開發(fā)過程中,我們經(jīng)常會(huì)有一個(gè)對(duì)象的屬性值只能出現(xiàn)在一組常量中的校驗(yàn)需求,例如:用戶性別字段gender只能等于MALE/FEMALE這兩個(gè)其中一個(gè)值,用戶賬號(hào)的狀態(tài)status只能等于:

NORMAL/DISABLED/DELETED其中一個(gè)等等,那么我們?cè)趺茨芨玫男r?yàn)這個(gè)參數(shù)呢?我們想擁有一個(gè)java注解,把它標(biāo)記在所要校驗(yàn)的字段上,當(dāng)開啟hibernate validator校驗(yàn)時(shí),就可以校驗(yàn)其字段值是否正確。

三、實(shí)現(xiàn)方案

上面提到的一組常量值,我們第一反應(yīng)應(yīng)該是定義一個(gè)枚舉類,盡量不要放在一個(gè)統(tǒng)一的constants類下,這樣當(dāng)系統(tǒng)一旦龐大起來(lái),常量是很難維護(hù)和查找的,所以前期代碼也應(yīng)該有一些規(guī)范性約束,這里我們約定一組常量值時(shí)使用枚舉,并把該枚舉類放在對(duì)應(yīng)的類對(duì)象里(以上述所說(shuō)的用戶功能為例,我們應(yīng)該把GenerEnum、UserStatusEnum枚舉放在User.java下,方便查找)

這里我們定義一個(gè)叫EnumValue.java的注解類,其下有兩個(gè)主要參數(shù)一個(gè)是enumClass用于指定枚舉類,enumMethod指定要校驗(yàn)的方法,下面我們看代碼實(shí)現(xiàn)。

四、代碼實(shí)現(xiàn)

package com.zhuma.demo.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
 
import org.assertj.core.util.Strings;
 
/**
 * @desc 校驗(yàn)枚舉值有效性
 *
 * @author zhumaer
 * @since 10/17/2017 3:13 PM
 */
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValue.Validator.class)
public @interface EnumValue {
 
  String message() default "{custom.value.invalid}";
 
  Class<?>[] groups() default {};
 
  Class<? extends Payload>[] payload() default {};
 
  Class<? extends Enum<?>> enumClass();
 
  String enumMethod();
 
  class Validator implements ConstraintValidator<EnumValue, Object> {
 
    private Class<? extends Enum<?>> enumClass;
    private String enumMethod;
 
    @Override
    public void initialize(EnumValue enumValue) {
      enumMethod = enumValue.enumMethod();
      enumClass = enumValue.enumClass();
    }
 
    @Override
    public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
      if (value == null) {
        return Boolean.TRUE;
      }
 
      if (enumClass == null || enumMethod == null) {
        return Boolean.TRUE;
      }
 
      Class<?> valueClass = value.getClass();
 
      try {
        Method method = enumClass.getMethod(enumMethod, valueClass);
        if (!Boolean.TYPE.equals(method.getReturnType()) && !Boolean.class.equals(method.getReturnType())) {
          throw new RuntimeException(Strings.formatIfArgs("%s method return is not boolean type in the %s class", enumMethod, enumClass));
        }
 
        if(!Modifier.isStatic(method.getModifiers())) {
          throw new RuntimeException(Strings.formatIfArgs("%s method is not static method in the %s class", enumMethod, enumClass));
        }
   
        Boolean result = (Boolean)method.invoke(null, value);
        return result == null ? false : result;
      } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        throw new RuntimeException(e);
      } catch (NoSuchMethodException | SecurityException e) {
        throw new RuntimeException(Strings.formatIfArgs("This %s(%s) method does not exist in the %s", enumMethod, valueClass, enumClass), e);
      }
    }
 
  }
}

備注

1) 自定義注解需要實(shí)現(xiàn)ConstraintValidator校驗(yàn)類,這里我們定義一個(gè)叫Validator的類來(lái)實(shí)現(xiàn)它,同時(shí)實(shí)現(xiàn)它下面的兩個(gè)方法initialize、isValid,一個(gè)是初始化參數(shù)的方法,另一個(gè)就是校驗(yàn)邏輯的方法,本例子中我們將校驗(yàn)類定義在該注解內(nèi),用@Constraint(validatedBy = EnumValue.Validator.class)注解指定校驗(yàn)類,內(nèi)部邏輯實(shí)現(xiàn)比較簡(jiǎn)單就是使用了靜態(tài)類反射調(diào)用驗(yàn)證方法的方式。

2) 對(duì)于被校驗(yàn)的方法我們要求,它必須是返回值類型為Boolean或boolean,并且必須是一個(gè)靜態(tài)的方法,返回返回值為null時(shí)我們認(rèn)為是校驗(yàn)不通過的,按false邏輯走。

五、使用演示

校驗(yàn)的目標(biāo)對(duì)象類

package com.zhuma.demo.model.po;
 
import java.io.Serializable;
import java.util.Date;
 
import javax.validation.constraints.Pattern;
 
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
 
import com.zhuma.demo.annotation.EnumValue;
import com.zhuma.demo.validator.CreateGroup;
 
/**
 * @desc 用戶PO
 
 * @author zhumaer
 * @since 6/15/2017 2:48 PM
 */
public class User implements Serializable {
 
  private static final long serialVersionUID = 2594274431751408585L;
 
  /**
   * 用戶ID
   */
  private Long id;
 
  /**
   * 登錄密碼
   */
  @NotBlank
  private String pwd;
 
  /**
   * 昵稱
   */
  @NotBlank
  @Length(min=1, max=64)
  private String nickname;
 
  /**
   * 頭像
   */
  private String img;
 
  /**
   * 電話
   */
  @Pattern(regexp = "^1[3-9]\\d{9}$")
  private String phone;
 
  /**
   * 賬號(hào)狀態(tài)
   */
  @EnumValue(enumClass=UserStatusEnum.class, enumMethod="isValidName")
  private String status;
 
  /**
   * 最新的登錄時(shí)間
   */
  private Date latestLoginTime;
 
  /**
   * 最新的登錄IP
   */
  private String latestLoginIp;
 
  private Date createTime;
  private Date updateTime;
   
  /**
   * 用戶狀態(tài)枚舉
   */
  public enum UserStatusEnum {
    /**正常的*/
    NORMAL,
    /**禁用的*/
    DISABLED,
    /**已刪除的*/
    DELETED;
 
    /**
     * 判斷參數(shù)合法性
     */
    public static boolean isValidName(String name) {
      for (UserStatusEnum userStatusEnum : UserStatusEnum.values()) {
        if (userStatusEnum.name().equals(name)) {
          return true;
        }
      }
      return false;
    }
  }
   
  //省略getter、setter方法
 
} 

controller類

package com.zhuma.demo.web.user;
 
import java.util.Date;
 
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
 
import com.zhuma.demo.model.po.User;
 
/**
 * @desc 用戶管理控制器
 *
 * @author zhumaer
 * @since 6/20/2017 16:37 PM
 */
@RestController
@RequestMapping("/users")
public class UserController {
 
  @PostMapping
  @ResponseStatus(HttpStatus.CREATED)
  public User addUser(@Validated @RequestBody User user) {
    user.setId(10000L);
    user.setCreateTime(new Date());
    return user;
  }
 
}  

校驗(yàn)結(jié)果

最后

好啦,一個(gè)簡(jiǎn)單的校驗(yàn)枚舉值的注解功能完成了。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JAVA冒泡排序和二分查找的實(shí)現(xiàn)

    JAVA冒泡排序和二分查找的實(shí)現(xiàn)

    本文詳細(xì)介紹了JAVA冒泡排序和二分查找的實(shí)現(xiàn),雖然這兩種算法比較簡(jiǎn)單,但是確實(shí)我們必須需要掌握的。下面來(lái)看看。
    2016-07-07
  • 深入了解java 8的函數(shù)式編程

    深入了解java 8的函數(shù)式編程

    函數(shù)式編程并不是Java新提出的概念,其與指令編程相比,強(qiáng)調(diào)函數(shù)的計(jì)算比指令的計(jì)算更重要;與過程化編程相比,其中函數(shù)的計(jì)算可以隨時(shí)調(diào)用。下面我們來(lái)詳細(xì)了解一下吧
    2019-06-06
  • Spring整合Kaptcha谷歌驗(yàn)證碼工具的開發(fā)步驟

    Spring整合Kaptcha谷歌驗(yàn)證碼工具的開發(fā)步驟

    這篇文章主要介紹了Spring整合Kaptcha谷歌驗(yàn)證碼工具的開發(fā)步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • 基于OpenID?Connect及Token?Relay實(shí)現(xiàn)Spring?Cloud?Gateway

    基于OpenID?Connect及Token?Relay實(shí)現(xiàn)Spring?Cloud?Gateway

    這篇文章主要介紹了基于OpenID?Connect及Token?Relay實(shí)現(xiàn)Spring?Cloud?Gateway,Spring?Cloud?Gateway旨在提供一種簡(jiǎn)單而有效的方式來(lái)路由到API,并為API提供跨領(lǐng)域的關(guān)注點(diǎn),如:安全性、監(jiān)控/指標(biāo)和彈性
    2022-06-06
  • SpringBoot+minio+kkfile實(shí)現(xiàn)文件預(yù)覽功能

    SpringBoot+minio+kkfile實(shí)現(xiàn)文件預(yù)覽功能

    在現(xiàn)代的 Web 應(yīng)用中,文件預(yù)覽功能是提升用戶體驗(yàn)的重要部分,尤其是在文檔管理系統(tǒng)中,本文將帶你逐步實(shí)現(xiàn)如何在 Spring Boot 項(xiàng)目中集成 MinIO(一個(gè)對(duì)象存儲(chǔ)系統(tǒng))與 KKFileView(一個(gè)開源文件預(yù)覽工具),以實(shí)現(xiàn)對(duì)各種類型文件的在線預(yù)覽,需要的朋友可以參考下
    2024-12-12
  • Spring Boot配置Swagger的實(shí)現(xiàn)代碼

    Spring Boot配置Swagger的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Spring Boot配置Swagger的實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2018-12-12
  • mybatis-plus @select動(dòng)態(tài)查詢方式

    mybatis-plus @select動(dòng)態(tài)查詢方式

    這篇文章主要介紹了mybatis-plus @select動(dòng)態(tài)查詢方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java案例實(shí)現(xiàn)不重復(fù)的隨機(jī)數(shù)

    Java案例實(shí)現(xiàn)不重復(fù)的隨機(jī)數(shù)

    這篇文章主要介紹了Java案例實(shí)現(xiàn)不重復(fù)的隨機(jī)數(shù),通過創(chuàng)建Set集合對(duì)象,可以使用HashSet也可以使用TreeSet,區(qū)別在于TreeSet是排序后的,創(chuàng)建隨機(jī)數(shù)對(duì)象,獲取一個(gè)隨機(jī)數(shù)去重等操作,需要的朋友可以參考一下
    2022-04-04
  • 基于SpringBoot + Android實(shí)現(xiàn)登錄功能

    基于SpringBoot + Android實(shí)現(xiàn)登錄功能

    在移動(dòng)互聯(lián)網(wǎng)的今天,許多應(yīng)用需要通過移動(dòng)端實(shí)現(xiàn)與服務(wù)器的交互功能,其中登錄是最常見且基礎(chǔ)的一種功能,本篇博客將詳細(xì)介紹如何使用 Spring Boot 和 Android 實(shí)現(xiàn)一個(gè)完整的登錄功能,需要的朋友可以參考下
    2024-11-11
  • Java 并發(fā)編程中的鎖機(jī)制示例詳解

    Java 并發(fā)編程中的鎖機(jī)制示例詳解

    本文探討了Java并發(fā)編程中的鎖機(jī)制,包括鎖的基本概念、Java中的鎖類型如synchronized、ReentrantLock、ReadWriteLock、鎖的優(yōu)化策略以及如何避免死鎖,文章強(qiáng)調(diào)了合理選擇和優(yōu)化鎖使用對(duì)于提升程序并發(fā)性能的重要性,并提供了實(shí)際應(yīng)用中的最佳實(shí)踐,感興趣的朋友一起看看吧
    2025-01-01

最新評(píng)論