欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章,主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等,同时欢迎大家加我个人微信「java_front」一起交流学习
1 文章概述
javax.validation是基于JSR-303标准定义的一组接口,目的是使开发者简洁地校验参数,hibernate-validator实现了这一组接口,可以作为工具独立引用。
javax.validation
validation-api
1.1.0.Final
org.hibernate
hibernate-validator
6.0.18.Final
如果是SpringBoot项目则无需显示引用上述依赖,因为SpringBoot已经将上述依赖进行了集成。
2 基本使用 2.1 定义模型
import java.math.BigDecimal;
import java.util.List;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import lombok.Data;
@Data
public class OrderModelA {
@Min(value = 1, message = "订单编号必须大于等于1")
@Max(value = 100, message = "订单编号必须小于等于100")
private Integer orderId;
@NotBlank(message = "订单名称不能为空")
private String orderName;
@Size(min = 1, max = 10)
private List<String> goodsList;
@DecimalMin(value = "1", message = "订单金额必须大于等于1")
private BigDecimal amount;
}
2.2 定义接口
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.validation.annotation.Validated;
import com.java.front.validation.model.OrderModelA;
@Validated
public interface BizValidateService {
void bizMethodA(@Valid OrderModelA model, @NotNull String param);
}
2.3 接口实现
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.java.front.validation.model.OrderModelA;
@Component
public class BizValidateServiceImpl implements BizValidateService {
@Override
public void bizMethodA(@Valid OrderModelA model, @NotNull String param) {
System.out.println("execute bizA model=" + JSON.toJSONString(model) + ",param=" + param);
}
}
2.4 测试用例
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestAuthApplication {
@Autowired
private BizValidateService bizValidateService;
@Test
public void testBizValidateA_correct() {
OrderModelA model = new OrderModelA();
model.setOrderId(1);
model.setOrderName("订单名称");
List<String> goodsList = new ArrayList<String>();
goodsList.add("goods1");
goodsList.add("goods2");
goodsList.add("goods3");
model.setGoodsList(goodsList);
model.setAmount(new BigDecimal("10"));
bizValidateService.bizMethodA(model, "param");
}
@Test
public void testBizValidateA_error() {
OrderModelA model = new OrderModelA();
model.setOrderId(0);
model.setOrderName("订单名称");
List<String> goodsList = new ArrayList<String>();
goodsList.add("goods1");
goodsList.add("goods2");
goodsList.add("goods3");
model.setGoodsList(goodsList);
model.setAmount(new BigDecimal("10"));
bizValidateService.bizMethodA(model, "param");
}
}
2.5 报错信息
javax.validation.ConstraintViolationException: bizMethodA.model.orderId: 订单编号必须大于等于1
at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at com.java.front.validation.BizValidateServiceImpl$$EnhancerBySpringCGLIB$$42c25c43.bizMethodA()
at com.java.front.TestAuthApplication.testBizValidateA_error(TestAuthApplication.java:62)
3 复杂应用
现在我们假设一种场景,订单新增了type1、type2两个字段,这两个字段影响对于orderId值范围判断,也就是说orderId范围判断不再是静态的,而是受其它字段影响。
针对这种情况第一步我们可以构造type1、type2、orderId组合字段,第二步自定义校验器将组合字段拆开进行业务校验。
3.1 定义注解
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD })
@Constraint(validatedBy = TypeAndOrderIdValidator.class)
public @interface TypeAndOrderIdValid {
String message() default "不满足业务条件";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
3.2 定义校验器
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.java.front.validation.model.OrderModelB;
public class TypeAndOrderIdValidator implements ConstraintValidator<TypeAndOrderIdValid, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
String[] array = value.split(OrderModelB.JOINT);
int type1 = Integer.parseInt(array[0]);
int type2 = Integer.parseInt(array[1]);
int orderId = Integer.parseInt(array[2]);
if (type1 == 1 && type2 == 2) {
return orderId > 20;
}
return true;
}
}
3.3 定义模型
import java.math.BigDecimal;
import java.util.List;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import com.alibaba.fastjson.annotation.JSONField;
import com.java.front.server.validation.extend.TypeAndOrderIdValid;
import lombok.Data;
@Data
public class OrderModelB {
public static final String JOINT = "_";
@Min(value = 1, message = "订单编号必须大于等于1")
@Max(value = 100, message = "订单编号必须小于等于100")
private Integer orderId;
@NotBlank(message = "订单名称不能为空")
private String orderName;
@Size(min = 1, max = 10)
private List<String> goodsList;
@DecimalMin(value = "1", message = "订单金额必须大于等于1")
private BigDecimal amount;
private int type1;
private int type2;
@JSONField(serialize = false)
private String typeAndOrderIdComposite;
@TypeAndOrderIdValid
public String getTypeAndOrderIdComposite() {
return getType1() + JOINT + getType2() + JOINT + getOrderId();
}
}
3.4 定义接口
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.validation.annotation.Validated;
import com.java.front.validation.model.OrderModelB;
@Validated
public interface BizValidateService {
void bizMethodB(@Valid OrderModelB model, @NotNull String param);
}
3.5 接口实现
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.java.front.server.validation.model.OrderModelB;
@Component
public class BizValidateServiceImpl implements BizValidateService {
@Override
public void bizMethodB(@Valid OrderModelB model, @NotNull String param) {
System.out.println("execute bizB model=" + JSON.toJSONString(model) + ",param=" + param);
}
}
3.6 测试用例
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestAuthApplication {
@Autowired
private BizValidateService bizValidateService;
@Test
public void testBizValidateB_correct() {
OrderModelB model = new OrderModelB();
model.setOrderId(30);
model.setOrderName("订单名称");
List<String> goodsList = new ArrayList<String>();
goodsList.add("goods1");
goodsList.add("goods2");
goodsList.add("goods3");
model.setGoodsList(goodsList);
model.setAmount(new BigDecimal("10"));
model.setType1(1);
model.setType2(2);
bizValidateService.bizMethodB(model, "param");
}
@Test
public void testBizValidateB_error() {
OrderModelB model = new OrderModelB();
model.setOrderId(1);
model.setOrderName("订单名称");
List<String> goodsList = new ArrayList<String>();
goodsList.add("goods1");
goodsList.add("goods2");
goodsList.add("goods3");
model.setGoodsList(goodsList);
model.setAmount(new BigDecimal("10"));
model.setType1(1);
model.setType2(2);
bizValidateService.bizMethodB(model, "param");
}
}
3.7 错误信息
javax.validation.ConstraintViolationException: bizMethodB.model.typeAndOrderIdComposite: 不满足业务条件
at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at com.java.front.validation.BizValidateServiceImpl$$EnhancerBySpringCGLIB$$7c26a7cb.bizMethodB()
at com.java.front.server.TestAuthApplication.testBizValidateB_error(TestAuthApplication.java:94)
4 文章总结
本文第一章节介绍了validation基本概念,第二章节介绍了validation基本应用,第三章节介绍了通过自定义注解动态校验字段,希望本文对大家有所帮助。
欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章,主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等,同时欢迎大家加我个人微信「java_front」一起交流学习
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)