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 2021/4/26 15:34
* @Description
*/
@Data
@ApiModel("新增用户请求体")
@AgeAdultCompare
public 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 2021/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 2021/4/26 15:41
* @Description
*/
public class AgeAdultValidator implements ConstraintValidator<AgeAdultCompare, Object> {
@Override
public 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 2021/4/26 15:49
* @Description
*/
@RestController
@RequestMapping("/api/v1")
@Api(tags = "人员控制类")
public class PersonController {
@Resource
private 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;
@RestControllerAdvice
public 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 2021/4/15 20:12
* @Description
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public 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);
}
}
可以根据自己的需求删减和补充。
最后附上一个测试结果图