springboot validator枚舉值校驗(yàn)功能實(shí)現(xiàn)
這篇文章主要介紹了springboot validator枚舉值校驗(yàn)功能實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(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)的邏輯。
二、需求
我們先明確下我們的需求,在程序開(kāi)發(fā)過(guò)程中,我們經(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)開(kāi)啟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)不通過(guò)的,按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í)有所幫助,也希望大家多多支持我們。
上一篇:spring為java.util.Properties類型的屬性進(jìn)行賦值過(guò)程解析
欄 目:Java
下一篇:JDK13.0.1安裝與環(huán)境變量的配置教程圖文詳解(Win10平臺(tái)為例)
本文標(biāo)題:springboot validator枚舉值校驗(yàn)功能實(shí)現(xiàn)
本文地址:http://www.jygsgssxh.com/a1/Java/8728.html
您可能感興趣的文章
- 01-10Springboot中@Value的使用詳解
- 01-10springboot實(shí)現(xiàn)文件上傳步驟解析
- 01-10springboot jta atomikos實(shí)現(xiàn)分布式事物管理
- 01-10SpringBoot使用RabbitMQ延時(shí)隊(duì)列(小白必備)
- 01-10如何基于SpringBoot部署外部Tomcat過(guò)程解析
- 01-10springboot集成fastDfs過(guò)程代碼實(shí)例
- 01-10SPRINGBOOT讀取PROPERTIES配置文件數(shù)據(jù)過(guò)程詳解
- 01-10springboot 配置DRUID數(shù)據(jù)源的方法實(shí)例分析
- 01-10springboot2.0使用Hikari連接池的方法(替換druid)
- 01-10springboot單元測(cè)試兩種方法實(shí)例詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)模擬時(shí)鐘
- 01-10Springboot中@Value的使用詳解
- 01-10JavaWeb實(shí)現(xiàn)郵件發(fā)送功能
- 01-10利用Java實(shí)現(xiàn)復(fù)制Excel工作表功能
- 01-10Java實(shí)現(xiàn)動(dòng)態(tài)數(shù)字時(shí)鐘
- 01-10java基于poi導(dǎo)出excel透視表代碼實(shí)例
- 01-10java實(shí)現(xiàn)液晶數(shù)字字體顯示當(dāng)前時(shí)間
- 01-10基于Java驗(yàn)證jwt token代碼實(shí)例
- 01-10Java動(dòng)態(tài)顯示當(dāng)前日期和時(shí)間
- 01-10淺談Java中真的只有值傳遞么
隨機(jī)閱讀
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?


