在編寫rest接口的時候,通常須要對參數進行校驗,常見的校驗好比java
等等,可是這些註解沒法知足咱們的需求的時候,該怎麼辦呢?難道須要在業務代碼中進行大量判斷嗎?非也!咱們能夠自定義參數校驗註解。web
package com.yefengyu.validate; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ValidateDemoApplication { public static void main(String[] args) { SpringApplication.run(ValidateDemoApplication.class, args); } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> <relativePath/> </parent> <groupId>com.yefengyu.validate</groupId> <artifactId>validate-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>validate-demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> </dependencies> </project>
package com.yefengyu.validate; import lombok.Data; @Data public class Event { private Long id; private Integer type; }
package com.yefengyu.validate; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @PostMapping("/test") public Event test(@RequestBody Event event) { return event; } }
如今一個簡單的rest接口編寫好了,咱們如今有了需求, type 只能傳遞 一、二、3 這三個數值,其它數值傳遞都視爲無效,該怎麼辦?不能使用業務代碼去判斷,由於相似這種類型、狀態的參數,能夠填寫的數值自己就很少,咱們能夠經過自定義校驗器來實現。
首先定義一個註解spring
package com.yefengyu.validate; import javax.validation.Constraint; import javax.validation.Payload; 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; @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = IntegerEnumValidator.class) public @interface IntegerEnum { String message() default "invalid number"; int[] values() default {}; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
上面代碼很簡單,可是多了以下這句:apache
@Constraint(validatedBy = IntegerEnumValidator.class)
其中 IntegerEnumValidator
類主要是爲了校驗 IntegerEnum
註解的,代碼以下:api
package com.yefengyu.validate; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class IntegerEnumValidator implements ConstraintValidator<IntegerEnum, Integer> { private IntegerEnum integerEnum; @Override public void initialize(IntegerEnum constraintAnnotation) { this.integerEnum = constraintAnnotation; } @Override public boolean isValid(Integer value, ConstraintValidatorContext context) { if (value == null) { return true; } int[] values = integerEnum.values(); if (values.length == 0) { return true; } for (int v : values) { if (value == v) { return true; } } return false; } }
此時咱們有了自定義的 整型校驗器,如今嘗試一下:app
1.實體增長註解:maven
package com.yefengyu.validate; import lombok.Data; @Data public class Event { private Long id; @IntegerEnum(values = {1, 2, 3}, message = "類型錯誤") private Integer type; }
主要是這句:ide
@IntegerEnum(values = {1, 2, 3}, message = "類型錯誤")
2.接口開啓註解spring-boot
package com.yefengyu.validate; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController public class TestController { @PostMapping("/test") public Event test(@Valid @RequestBody Event event) { return event; } }
主要是增長了 @Valid
測試
3.測試
{ "id" : 1, "type" : 11 }
當傳入參數 type 不是 一、二、3 的時候,那麼結果爲:
{ "timestamp": "2019-12-27T08:10:10.569+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "IntegerEnum.event.type", "IntegerEnum.type", "IntegerEnum.java.lang.Integer", "IntegerEnum" ], "arguments": [ { "codes": [ "event.type", "type" ], "arguments": null, "defaultMessage": "type", "code": "type" }, [ 1, 2, 3 ] ], "defaultMessage": "類型錯誤", "objectName": "event", "field": "type", "rejectedValue": 11, "bindingFailure": false, "code": "IntegerEnum" } ], "message": "Validation failed for object='event'. Error count: 1", "path": "/test" }
咱們能夠在代碼中增長異常處理,簡化、統一處理異常信息,這塊優化不在本節內容之中。