關注微信公眾號:CodingTechWork,一起學習進步。
引言
在java開發中,經常需要和外界系統進行參數對接,api設計中難免會遇到json傳參不一致的情況,雖然紙面或者接口規范約束了應該怎么傳參,仍然不可避免在對接過程中,出現傳參不符合要求的,如傳空值、傳超過范圍的值等。除了在Controllers層面使用@Validated
或者@Valid
注解外,本文將總結使用javax.validation.*;
下的包進行校驗的模板和常用的注解含義。
常用注解
注解 | 類型 | 說明 |
---|---|---|
@NotNull | 任意類型 | 驗證注解的元素值不是null,但可以為empty |
@NotEmpty | CharSequence子類型(如String、StringBuilder、StringBuffer、CharBuffer)、Collection、Map、數組 | 驗證注解的元素值不為null且size>0 |
@NotBlank | 只能作用於字符串 | 驗證注解的元素值不是null,且不能為空白空字符,如" " , 即該字符串調用trim()后,長度需大於0,才能驗證通過 |
@Null | 任意類型 | 驗證注解的元素值是null |
@Min(value=值) | BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數字)子類型 | 驗證注解的元素值大於等於指定的value值 |
@Max(value=值) | BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數字)子類型 | 驗證注解的元素值小於等於指定的value值 |
@Size(min=下限, max=上限) | 字符串、Collection、Map、數組等 | 驗證注解的元素值的在min和max(包含)指定區間之內,如字符長度、集合大小 |
@Range(min=最小值, max=最大值) | BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子類型和包裝類型 | 驗證注解的元素值在最小值和最大值之間 |
@Length(min=下限, max=上限) | CharSequence子類型 | 驗證注解的元素值長度在min和max區間內 |
@DecimalMin | 這個約束的參數是一個通過BigDecimal定義的最小值的字符串表示.小數存在精度 | 驗證注解的值不小於約束中指定的最小值 |
@DecimalMax(value=值) | 這個約束的參數是一個通過BigDecimal定義的最大值的字符串表示.小數存在精度 | 驗證注解的值不大於約束中指定的最大值 |
@Digits(integer=整數位數, fraction=小數位數) | BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存儲的是數字)子類型 | integer為整數個數最大值,fraction為小數個數最大值 |
@AssertTrue | 布爾類型 | 驗證注解的元素值是true |
@AssertFalse | 布爾類型 | 驗證注解的元素值是false |
@Past | java.util.Date,java.util.Calendar;Joda Time類庫的日期類型 | 驗證注解的元素值(日期類型)比當前時間早 |
@Future | java.util.Date,java.util.Calendar;Joda Time類庫的日期類型 | 驗證注解的元素值(日期類型)比當前時間晚 |
@Email(regexp=正則表達式,flag=標志的模式) | CharSequence子類型(如String等) | 驗證注解的元素值是Email,也可以通過regexp和flag指定 |
@Pattern(regexp=正則表達式,flag=標志的模式) | String,任何CharSequence的子類型 | 驗證注解的元素值與指定的正則表達式匹配 |
校驗模板
程序
實體類示例
package com.example.andya.demo.bean;
import javax.validation.constraints.*;
import java.util.Date;
import java.util.List;
/**
* @author andya
* @date 2021/2/25
*/
public class PersonBean {
@NotBlank(message = "name should not be blank")
private String name;
@NotNull(message = "alias should not be null")
private List<String> alias;
@Min(value = 1, message = "age should > 0")
private int age;
@Size(min = 11, max = 11, message = "telPhone's length should be 11")
private String telPhone;
@Email(message = "email should be valid")
private String email;
@AssertTrue(message = "isChinese should be true")
private boolean isChinese;
@Future(message = "futurePlanDate should be future")
private Date futurePlanDate;
@Past(message = "pastPlanDate should be past")
private Date pastPlanDate;
@Digits(integer = 3, fraction = 2, message = "hight should be 3 integer and 2 fraction, (165.23)")
private double hight;
@Digits(integer = 2, fraction = 1, message = "weight should be 2 integer and 1 fraction, (60.5) kg")
private String weight;
public PersonBean() {
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public double getHight() {
return hight;
}
public void setHight(double hight) {
this.hight = hight;
}
public Date getPastPlanDate() {
return pastPlanDate;
}
public void setPastPlanDate(Date pastPlanDate) {
this.pastPlanDate = pastPlanDate;
}
public Date getFuturePlanDate() {
return futurePlanDate;
}
public void setFuturePlanDate(Date futurePlanDate) {
this.futurePlanDate = futurePlanDate;
}
public boolean isChinese() {
return isChinese;
}
public void setChinese(boolean chinese) {
isChinese = chinese;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getAlias() {
return alias;
}
public void setAlias(List<String> alias) {
this.alias = alias;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getTelPhone() {
return telPhone;
}
public void setTelPhone(String telPhone) {
this.telPhone = telPhone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
模板示例
package com.example.andya.demo.service;
import com.example.andya.demo.bean.PersonBean;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author andya
* @date 2021/2/25
*/
public class ValidParamsCheckService {
/**
* check bean params valid
* @param t
* @param <T>
* @return
*/
public static <T> Map<String, String> checkServiceParamsValid(T t) {
Map<String, String> booleanStringMap = new HashMap<>();
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<T>> violations = validator.validate(t);
if (violations != null && violations.size() > 0) {
StringBuilder stringBuilder = new StringBuilder();
violations.forEach(
e -> stringBuilder.append(e.getMessage()).append(", "));
booleanStringMap.put("valid", "false");
booleanStringMap.put("message", stringBuilder.toString().substring(0, stringBuilder.length() - 2));
return booleanStringMap;
}
booleanStringMap.put("valid", "true");
booleanStringMap.put("message", "valid");
return booleanStringMap;
}
public static void main(String[] args) throws ParseException {
PersonBean personBean = new PersonBean();
personBean.setName("");
personBean.setAge(0);
personBean.setEmail("fdsaf");
personBean.setTelPhone("0123456789");
personBean.setChinese(false);
personBean.setFuturePlanDate(new Date());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
personBean.setPastPlanDate(simpleDateFormat.parse("2022-01-01 00:00:00"));
personBean.setHight(165.2);
personBean.setWeight("53.25");
Map<String, String> map = checkServiceParamsValid(personBean);
System.out.println("PersonBean check valid result map: " + map);
PersonBean personBean1 = new PersonBean();
personBean1.setName("小王");
List<String> list = new ArrayList<>();
list.add("王二");
personBean1.setAlias(list);
personBean1.setAge(1);
personBean1.setEmail("xiaowang@163.com");
personBean1.setTelPhone("01234567890");
personBean1.setChinese(true);
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
personBean1.setFuturePlanDate(simpleDateFormat1.parse("2022-01-01 00:00:00"));
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
personBean1.setPastPlanDate(simpleDateFormat2.parse("2021-01-01 00:00:00"));
personBean1.setHight(165.23);
personBean1.setWeight("53.2");
Map<String, String> map1 = checkServiceParamsValid(personBean1);
System.out.println("PersonBean check valid result map: " + map1);
}
}
運行結果
PersonBean check valid result map: {valid=false, message=hight should be 3 integer and 2 fraction, (165.23) cm, telPhone's length should be 11, futurePlanDate should be future, weight should be 2 integer and 1 fraction, (60.5) kg, name should not be blank, age should > 0, pastPlanDate should be past, isChinese should be true, email should be valid, alias should not be null}
PersonBean check valid result map: {valid=true, message=valid}