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,"非法請求參數");// .......} }這種寫法我認為有三個弊端:
下面來看看如何重構這個代碼:
首先引入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,实现参数的合法性校验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python入门之函数调用educode
- 下一篇: django手机访问_Django从入门