在编写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" }
咱们能够在代码中增长异常处理,简化、统一处理异常信息,这块优化不在本节内容之中。