Springboot版本:2.3.1.RELEASE
引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
ps:Springboot版本在2.3一下的引用的是别的依赖,可以查一下。
新增用户请求体
package com.study.bean.dto;import com.study.bean.volidate.AgeAdultCompare;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import javax.validation.constraints.Max;import javax.validation.constraints.Min;import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotNull;/*** @Author Curtain* @Date /4/26 15:34* @Description*/@Data@ApiModel("新增用户请求体")@AgeAdultComparepublic class AddPersonParam {/*** 姓名*/@NotBlank(message = "姓名不能为空")@ApiModelProperty(name = "name", value = "姓名", required = true)private String name;/*** 性别*/@NotBlank(message = "性别不能为空")@ApiModelProperty(name = "sex", value = "性别", required = true)private String sex;/*** 年龄*/@NotNull(message = "年龄不能为空")@Min(value = 0, message = "年龄最小为10岁")@Max(value = 1000, message = "人类目前年龄超不过1000岁")@ApiModelProperty(name = "age", value = "年龄", required = true)private Integer age;/*** 0未成年1成年*/@NotNull(message = "是否成年不能为空")@ApiModelProperty(name = "adult", value = "0未成年1成年", required = true)private Integer adult;}
这里涵盖了validate注解中的@NotNull、@NotBlank、@Min、@Max还有个自定义的validate注解@AgeAdultCompare。
除了自定义的validate注解以外,其他的几个注解想必大家一眼就能看出来是什么意思,这里就不再赘述。
自定义的@AgeAdultCompare注解
作用:用来校验年龄和是否成年这两个字段是否相对应(年龄大于18必须是成年,年龄小于18必须是未成年)
首先是定义一个validate类型的注解
package com.study.bean.volidate;import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.*;/*** @Author Curtain* @Date /4/26 15:40* @Description 自定义注解,校验年龄和是否成年*/@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Constraint(validatedBy = AgeAdultValidator.class)public @interface AgeAdultCompare {//校验未通过时的返回信息String message() default "年龄和是否成年要相对应";//以下两行未固定模板Class<?>[] groups() default { };Class<? extends Payload>[] payload() default { };}
其中的AgeAdultValidator就是我们要创建的校验类,里面写的是校验逻辑.
AgeAdultValidator
package com.study.bean.volidate;import com.study.bean.dto.AddPersonParam;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;/*** @Author Curtain* @Date /4/26 15:41* @Description*/public class AgeAdultValidator implements ConstraintValidator<AgeAdultCompare, Object> {@Overridepublic boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {if (o instanceof AddPersonParam){AddPersonParam param = (AddPersonParam) o;if (param.getAge() != null && param.getAdult() != null){if (param.getAge() > 17 && param.getAdult() == 0)return false;if (param.getAge() < 17 && param.getAdult() == 1)return false;}}return true;}}
这些都写完之后,我们要在接口上面的请求参数前加上@valid注解就完事了
package com.study.web.controller;import com.study.bean.dto.AddPersonParam;import com.study.bean.response.ResultBody;import com.study.service.api.db01.PersonService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import javax.validation.Valid;/*** @Author Curtain* @Date /4/26 15:49* @Description*/@RestController@RequestMapping("/api/v1")@Api(tags = "人员控制类")public class PersonController {@Resourceprivate PersonService personService;@PostMapping("/person")@ApiOperation(value = "新增人员", notes = "新增人员")ResultBody addPerson(@RequestBody @Valid AddPersonParam addPersonParam){return ResultBody.success(personService.add(addPersonParam));}}
测试接口的时候,不符合我们注解的要求都会抛出一个叫做MethodArgumentNotValidException的异常。
如果我们想把我们在validate相关注解中的message信息返回给调用的人,我们可以定义一个全局的异常捕获。
全局异常捕获类
package com.study.web.config;import com.study.bean.enums.ResponseEnum;import com.study.bean.exception.ApiException;import com.study.bean.response.ResultBody;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.MethodArgumentNotValidException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.validation.ConstraintViolationException;import java.util.stream.Collectors;@RestControllerAdvicepublic class GlobalExceptionHandler {private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);/*** 捕获全局入参错误异常* @param e* @return*/@ExceptionHandler(MethodArgumentNotValidException.class)public ResultBody handleGlobalException(MethodArgumentNotValidException e){return ResultBody.error(e.getBindingResult().getAllErrors().stream().map(a -> a.getDefaultMessage()).collect(Collectors.joining(",")));}}
这里的ResultBody是我自己写的一个返回实体类。
ResultBody
package com.study.bean.response;import com.study.bean.enums.ResponseEnum;import lombok.AllArgsConstructor;import lombok.Getter;import lombok.NoArgsConstructor;import lombok.Setter;/*** @Author Curtain* @Date /4/15 20:12* @Description*/@Getter@Setter@AllArgsConstructor@NoArgsConstructorpublic class ResultBody<T> {/*** 状态码*/private String code;/*** 状态信息*/private String message;/*** 接口返回数据*/private T result;public static ResultBody success(){return success(null);}public static <T> ResultBody<T> success(T o) {ResultBody resultBody = new ResultBody(ResponseEnum.SUCCESS);resultBody.setResult(o);return resultBody;}public static ResultBody error(String code, String message){return new ResultBody(code, message, null);}public static ResultBody error(String message){return new ResultBody("-1", message, null);}}
可以根据自己的需求删减和补充。
最后附上一个测试结果图