作用:校驗請求參數中,有對應枚舉類類型的字段,判斷取值是否為枚舉類内的值,以及是否可以為空。
借鑒其他大神部落格,原文在枚舉類中定義校驗方法,本文利用反射去除了枚舉類中校驗方法,實作注解與枚舉類解耦。原文部落格位址找不到了實在抱歉。如有錯誤歡迎指正聯系。
僅作自己記錄
一:定義注解
package com.example.demo.anno;
import lombok.SneakyThrows;
import java.lang.annotation.*;
import java.lang.reflect.Method;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ValidEnum.Validator.class)
public @interface ValidEnum {
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<? extends Enum<?>> enumClass(); // 枚舉類
boolean allowNull() default false; // 是否允許為空
String message() default "{enum.value.invalid}"; // 錯誤資訊
class Validator implements ConstraintValidator<ValidEnum, Object> {
private Class<? extends Enum<?>> enumClass;
private boolean allowNull;
@Override
public void initialize(ValidEnum enumValue) {
enumClass = enumValue.enumClass();
allowNull = enumValue.allowNull();
}
@SneakyThrows
@Override
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
// 是否允許為null 或者 “”
if (value == null || value.equals("")) {
return allowNull;
}
// 參照枚舉類為空說明不校驗直接傳回true
if (enumClass == null ) {
return Boolean.TRUE;
}
//校驗是否為枚舉類中的值
Boolean flag = false;
Enum<?>[] enumConstants = enumClass.getEnumConstants();
for (Enum<?> enumConstant : enumConstants) {
Method method = enumConstant.getClass().getMethod("status");
Class<?> returnType = method.getReturnType();
String s = value.getClass().toString();
// 如果方法傳回值不同,立即傳回錯誤
if (!returnType.toString().equals(s)){
return false;
}
// 如果有值相等則傳回true
Object status = method.invoke(enumConstant, null);
if (status.equals(value)){
flag = true;
return flag;
}
}
return flag;
}
}
}
二:枚舉類
package com.example.demo.anno;
public enum FundStatusEnum {
SUBMITTED("Submitted", "已送出"),
SETTLED("Settled", "已結算"),
PENDING_SETTLEMENT("PS", "待結算"),
PENDING_TOPUP("PT", "待充值"),
CANCELLED("Cancelled", "已取消");
private final String status;
private final String description;
FundStatusEnum(String status, String description) {
this.status = status;
this.description = description;
}
public String status() {
return status;
}
public String description() {
return description;
}
}
三:請求體使用注解
@ValidEnum(enumClass = FundStatusEnum.class,allowNull = true,message = "不在枚舉類範圍内")
private String fundStatus;
四:controller層接口
package com.example.demo.anno;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
public class TestController {
@RequestMapping(value = "/record")
public String update(@Valid @RequestBody UpdateTxnReqVO updateTxnReqVO, BindingResult bindingResult) {
// 參數不符合校驗規則,則傳回定義錯誤資訊
if (bindingResult.hasErrors()) {
return bindingResult.getAllErrors().get(0).getDefaultMessage();
}
return "OK";
}
}