在我们的项目中,大量使用了枚举类型。在某些业务情况下,我们需要限制枚举类型仅接受特定的枚举值。例如,思考一个订单状态的枚举变量,其中包含【用户撤销】和【管理员撤销】等值。不过,在前端修改订单状态的接口中,我们只允许将订单状态设置为【用户撤销】。为了实现这种限制,我们可以使用自定义参数验证规则。
通过自定义参数验证规则,我们可以确保只有指定的枚举值可以作为参数值被接受。这样,无论是在前端请求还是后端处理过程中,我们都可以验证参数的有效性。这种方式既可以提高数据的一致性,又能为开发人员提供有意义的错误消息和准确的验证结果。
通过自定义参数验证规则,我们能够更好地控制枚举类型参数的取值范围,满足特定业务需求,并保持代码的可读性和可维护性。这样的优化措施能够提高项目的质量、开发效率和用户体验。
定义允许枚举值约束
# platform-module/platform-module-validate/src/main/java/com/tinem/platform/module/validate/EnumAllowedValuesConstraint.java
package com.tinem.platform.module.validate;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 允许枚举值约束
*/
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumAllowedValuesValidator.class)
public @interface EnumAllowedValuesConstraint {
String message() default "Invalid value";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String[] allowedValues();
}
定义允许枚举值约束验证规则
# platform-module/platform-module-validate/src/main/java/com/tinem/platform/module/validate/EnumAllowedValuesValidator.java
package com.tinem.platform.module.validate;
import cn.hutool.core.util.ReflectUtil;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
/**
* 允许枚举值约束验证
*/
public class EnumAllowedValuesValidator implements ConstraintValidator<EnumAllowedValuesConstraint, Object> {
private List<String> allowedValues;
@Override
public void initialize(EnumAllowedValuesConstraint constraintAnnotation) {
allowedValues = Arrays.asList(constraintAnnotation.allowedValues());
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if (value == null) {
return true; // 允许为空值
}
if (value instanceof String) {
return allowedValues.stream()
.anyMatch(v->v.equals(value));
}
if (value instanceof Integer) {
return allowedValues.stream()
.map(Integer::parseInt)
.anyMatch(v->v.equals(value));
}
if (value instanceof Short) {
return allowedValues.stream()
.map(Short::parseShort)
.anyMatch(v->v.equals(value));
}
if (value instanceof Byte) {
return allowedValues.stream()
.map(Byte::parseByte)
.anyMatch(v->v.equals(value));
}
if (value instanceof Boolean) {
return allowedValues.stream()
.map(Boolean::parseBoolean)
.anyMatch(v->v.equals(value));
}
if (value instanceof Float) {
return allowedValues.stream()
.map(Float::parseFloat)
.anyMatch(v->v.compareTo((Float) value) == 0);
}
if (value instanceof Double) {
return allowedValues.stream()
.map(Double::parseDouble)
.anyMatch(v->v.compareTo((Double) value) == 0);
}
if (value instanceof BigDecimal) {
return allowedValues.stream()
.map(BigDecimal::new)
.anyMatch(v->v.compareTo((BigDecimal)value)==0);
}
if (value.getClass().isEnum()) {
Method valueOf = ReflectUtil.getMethod(value.getClass(),"name");
String name = ReflectUtil.invoke(value,valueOf);
return allowedValues.stream()
.anyMatch(v->v.equals(name));
}
return false; // 值无效
}
}
编写测试类
# platform-module/platform-module-validate/src/test/java/com/tinem/platform/module/validate/EnumAllowedValuesValidatorTest.java
package com.tinem.platform.module.validate;
import lombok.Data;
import org.junit.Test;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.math.BigDecimal;
import java.util.Set;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* 测试自定义枚举类型验证
*/
public class EnumAllowedValuesValidatorTest {
private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
/**
* 测试传入正确的枚举值
*/
@Test
public void allowed(){
Params params = new Params();
params.value = EnumTest.allowed;
params.i = 1;
params.f = 2;
params.d = 3;
params.s = "4";
params.b = new BigDecimal("5");
params.b2 = 6;
params.s2 = 7;
Set<ConstraintViolation<Params>> violations = validator.validate(params,Default.class);
assertTrue(violations.isEmpty());
}
/**
* 测试传入错误的枚举值
*/
@Test
public void notAllow(){
Params params = new Params();
params.value = EnumTest.not_allow;
params.i = -1;
params.f = -2;
params.d = -3;
params.s = "-4";
params.b = new BigDecimal("-5");
params.b2 = -6;
params.s2 = -7;
Set<ConstraintViolation<Params>> violations = validator.validate(params,Default.class);
violations.stream().map(ConstraintViolation::getMessage).forEach(System.out::println);
assertFalse(violations.isEmpty());
}
/**
* 测试参数对象
*/
@Data
class Params{
@EnumAllowedValuesConstraint(allowedValues = {"allowed"},message = "仅支持:allowed")
EnumTest value;
@EnumAllowedValuesConstraint(allowedValues = {"1","2","3"},message = "仅支持:1")
int i;
@EnumAllowedValuesConstraint(allowedValues = {"2"},message = "仅支持:2")
float f;
@EnumAllowedValuesConstraint(allowedValues = {"3"},message = "仅支持:3")
double d;
@EnumAllowedValuesConstraint(allowedValues = {"4"},message = "仅支持:4")
String s;
@EnumAllowedValuesConstraint(allowedValues = {"5"},message = "仅支持:5")
BigDecimal b;
@EnumAllowedValuesConstraint(allowedValues = {"6"},message = "仅支持:6")
byte b2;
@EnumAllowedValuesConstraint(allowedValues = {"7"},message = "仅支持:7")
short s2;
}
/**
* 测试枚举类型
*/
enum EnumTest{
// 被允许的值
allowed,
// 不被允许的值
not_allow
}
}
测试结果

字符串类型值约束
这里还有一个验证规则是验证字符串类型的值仅支持部分内容。

具体代码请参考:微服务项目代码说明
© 版权声明
文章版权归作者所有,未经允许请勿转载。如内容涉嫌侵权,请在本页底部进入<联系我们>进行举报投诉!
THE END















- 最新
- 最热
只看作者