欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

sql2008安装时提示参数不能为空_Java Validation API,实现参数的合法性校验

发布时间:2024/8/1 42 豆豆
生活随笔 收集整理的这篇文章主要介绍了 sql2008安装时提示参数不能为空_Java Validation API,实现参数的合法性校验 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

Hibernate Validator是Java Validation API(JSR 303)标准的一个具体实现,用于对参数进行合法性校验。校验数据在任何应用中都是一个很常见的任务,所以JCP组织定义了一个标准来规范化这个任务操作,那就是Java Validation API。

先来探讨下如何在SpringMVC中集成Java Validation API实现Controller方法入参校验。可以说,所有的Java Web应用都会涉及到对Controller方法入参做校验,在不使用Java Validation API之前,做校验时有人是这样写的:

@Controller @RequestMapping("/order") public class OrderController {@ResponseBody@RequestMapping(value = "/getOrderDetails", method = RequestMethod.POST)public OrderDetailsVo getOrderDetails(@RequestBody JSONObject json) {String token = json.optString("token");Assert.hasLength(token,1101,"非法请求参数"); String orderCode = json.optString("orderCode");Assert.hasLength(orderCode,1101,"非法请求参数");// .......} }

这种写法我认为有三个弊端:

  • 用JSONObject来接收入参,取值非常麻烦,很容易就弄错字段名
  • 如果入参非常复杂,用JSONObject的话,下一个接手的人就很难搞错清整个方法入参的JSON结构,可维护性极差
  • 方法里校验逻辑啰嗦重复
  • 下面来看看如何重构这个代码:

    首先引入validator依赖,如果是springboot项目,那么引入此依赖:

    <dependency><groupId>org.springframework.boot</group><artifactId>spring-boot-starter-validation</artifactId> </dependency>

    一般spring项目可引入此三个依赖:

    <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.4.1.Final</version> </dependency> <dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>3.0.0</version> </dependency> <dependency><groupId>org.glassfish</groupId><artifactId>javax.el</artifactId><version>3.0.0</version> </dependency>

    好的写法应该是这样:

    @RestController @RequestMapping("/order") public class OrderController {@RequestMapping(value = "/getOrderDetails", method = RequestMethod.POST)public OrderDetailsResVo getOrderDetails(@Validated @RequestBody OrderDetailsReqVo reqVo) {// .......} }

    其中OrderDetailsReqVo类定义:

    public class OrderDetailsReqVo {@NotBlank // 此注解表明字段不能为null,也不能为空字符串private String token;@NotBlank // 此注解表明字段不能为null,也不能为空字符串private String orderCode;// get set...... }

    添加@Validated就是提示Spring在将JSON入参转换为OrderDetailsReqVo对象后,对此对象进行校验。如果校验不通过Spring则会抛出MethodArgumentNotValidException异常。

    在这里统一捕捉校验失败的MethodArgumentNotValidException异常:

    // 不熟悉这些Spring注解的推荐去看《Spring实战》书籍 @ControllerAdvice public class GlobalHandler {private final Logger logger = LoggerFactory.getLogger(GlobalHandler.class);/*** 所有的校验失败情况都会由这里处理*/@ResponseBody@ExceptionHandler(MethodArgumentNotValidException.class)public Result exceptionHandler(MethodArgumentNotValidException e) {Result result = new Result("1101","非法请求参数");logger.error("req params error", e);return result;}// ...... }

    好,开始Java Validation API的学习,先看下都有哪些注解可用:

    JSR 303提供的标准注解:

    Hibernate 提供的额外注解:

    我讲一些比较常用的,其它的就由各位同学自己探索吧

    Car类定义:

    public class Car {@NotBlank // 不能为null,不能为空字符串private String manufacturer;@NotNull // 不能为null@Size(min = 2, max = 14) // 字符串长度位于2到14之间private String licensePlate;@Min(2)@Max(5) // 注意,未添加NotNull注解,所以seatCount可以为null,只有当seatCount不为null@Min @Max才会做校验private Integer seatCount;@AssertTrue // registered不为null时,则值需是trueprivate Boolean registered;// groups用于指定所属的校验组@AssertTrue(message = "The car has to pass the vehicle inspection first", groups = CarChecks.class)private Boolean passedVehicleInspection;@Valid // 表明应对driver对象内字段继续做校验@NotNullprivate Driver driver;@Valid // 表明应对passengers里的Person对象内字段继续做校验@Size(max = 2) // 表明passengers最多只能有两个对象private List<Person> passengers = new ArrayList<>();private String brand;@Range(min = 2,max = 4) // 作用同@Min @Maxprivate Integer doors;private CarTypeEnum carTypeEnum;// get set...... }

    Driver类定义:

    public class Driver extends Person {@NotNull@Min(value = 18, message = "必须年满18岁", groups = DriverChecks.class)public Integer age;@NotNull@AssertTrue(message = "必须具有驾照", groups = DriverChecks.class)public Boolean hasDrivingLicense;// get set...... }

    Person类定义:

    public class Person {private long personId = 0;@NotBlank@CheckCase(value = CaseMode.UPPER, message = "名字必须为大写")private String name;public Address address;public Date birthday;// get set...... }

    RentalCar类定义:

    @GroupSequence({RentalChecks.class, CarChecks.class, RentalCar.class}) public class RentalCar extends Car {@AssertFalse(message = "The car is currently rented out", groups = RentalChecks.class)private boolean rentalStation = true;// get set...... }

    注意各个类上添加的注解

    测试代码:

    public class ValidationTest {private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();@Testpublic void test() {// 可以试着给不同字段赋值查看校验效果Car car = new Car();car.setManufacturer("benz");car.setLicensePlate("234234");car.setSeatCount(5);car.setRegistered(true);car.setPassedVehicleInspection(true);Driver driver = new Driver();driver.setName("JACK");driver.setAge(11);driver.setHasDrivingLicense(false);car.setDriver(driver);car.setPassengers(new ArrayList<>());car.setBrand("");car.setDoors(4);car.setCarTypeEnum(CarTypeEnum.BENZ);// 不传递校验顺序,则只校验groups为Default的,没有显式在注解写明groups属性的,则默认为DefaultvalidateBean(car);// 校验顺序显式传递validateBean(car, OrederedChecks.class);car.getDriver().setAge(20);car.getDriver().setHasDrivingLicense(true);validateBean(car, OrederedChecks.class);car.setSeatCount(1);Set<ConstraintViolation<Car>> constraintViolations3 = validator.validateProperty(car, "seatCount");System.err.println(constraintViolations3.iterator().next().getMessage());Set<ConstraintViolation<Car>> constraintViolations4 = validator.validateValue(Car.class, "registered", false);System.err.println(constraintViolations4.iterator().next().getMessage());// 校验顺序写在bean的类注解上RentalCar rentalCar = new RentalCar();Set<ConstraintViolation<RentalCar>> constraintViolations5 = validator.validate(rentalCar);System.err.println(constraintViolations5.iterator().next().getMessage());}@Testpublic void test1() {// 测试自定义校验注解Person person = new Person("John");Set<ConstraintViolation<Person>> constraintViolations = validator.validate(person);ConstraintViolation<Person> constraintViolation = constraintViolations.iterator().next();System.out.println(constraintViolation.getMessage());}public static <T> void validateBean(T bean, Class<?>... groups) {Set<ConstraintViolation<T>> constraintViolations = validator.validate(bean, groups);if (constraintViolations.isEmpty()) {System.out.println("校验通过");return;}List<String> errors = new ArrayList<>(10);for (ConstraintViolation<T> constraintViolation : constraintViolations) {errors.add(constraintViolation.getPropertyPath() + constraintViolation.getMessage());}//throw new ValidationException(StringUtils.join(errors, ","));System.err.println(StringUtils.join(errors, ","));} }

    其中Person类@CheckCase是自定义的校验,也就是说我们可以自定义自己的校验逻辑,这里@CheckCase(value = CaseMode.UPPER, message ="名字必须为大写")就是说字段值必须为大写,那么要如何做呢?分三步:

    第一步:定义校验注解

    @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = CheckCaseValidator.class) //CheckCaseValidator类在下面 @Documented public @interface CheckCase {String message() default "";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};CaseMode value(); }public enum CaseMode {UPPER,LOWER; }

    第二部:编写校验逻辑实现

    public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> {private CaseMode caseMode;@Overridepublic void initialize(CheckCase constraintAnnotation) {this.caseMode = constraintAnnotation.value();}@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {if (value == null) {return true;}if (caseMode == CaseMode.UPPER) {return value.equals(value.toUpperCase());} else {return value.equals(value.toLowerCase());}} }

    第三步:在bean添加注解即可生效

    public class Person {private long personId = 0;@CheckCase(value = CaseMode.UPPER, message = "名字必须为大写")private String name;public Address address;public Date birthday;// ...... }

    源码github地址:

    jufeng98/java-master​github.com

    总结

    以上是生活随笔为你收集整理的sql2008安装时提示参数不能为空_Java Validation API,实现参数的合法性校验的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。