引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
部分注解说明
注解 | 说明 |
---|---|
@AssertFalse | 必须为 false |
@AssertTrue | 必须为true |
@DecimalMax(value) | 必须是一个数字,且值必须小于等于指定的值 |
@DecimalMin(vaule) | 必须是一个数字,且值必须大于等于指定的值 |
@Digits(integer,function) | 必须是一个数字,其值必须在可接受的范围内 |
@Null | 必须为空 |
@NotNull | 必须不为空 |
@Min(value) | 必须是一个数字,且值必须大于等于指定的值 |
@Ma(value) | 必须是一个数字,且值必须小于等于指定的值 |
@Size(min,max) | 长度必须在指定的范围内 |
@Past | 必须是一个过去的日期 |
@Future | 必须是一个未来的日期 |
@Pattern(value) | 必须符合指定的正则表达式 |
对实体类的属性添加注解
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
@Data
public class TestDTO {
@NotBlank(message = "用户名不能为空")
private String userName;
@Size(min = 6, max = 16,message = "密码长度必须是6-16个字符")
private String password;
@NotBlank(message = "邮箱格式不正确")
@Email(message = "邮箱格式不正确")
private String email;
}
接口添加注解
@RestController
public class TestController{
// @RequestBody 表示接收JSON数据
// @Valid 表示此参数需要校验
@PostMapping("/user")
public String user(@RequestBody @Valid TestDTO dto){
return JSONObject.toJSONString(dto);
}
}
测试
到这一步,参数校验已经生效了,但是校验的提示信息没有在接口中返回
![image.png](https://img-blog.csdnimg.cn/img_convert/684e01aa6344b18d803796d0e920d589.png#averageHue=#fcfbfb&clientId=u0fa3065b-fcfe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=459&id=ubf9d520f&margin=[object Object]&name=image.png&originHeight=459&originWidth=726&originalType=binary&ratio=1&rotation=0&showTitle=false&size=37290&status=done&style=none&taskId=u31024ea7-e360-41e0-b44b-0377ce90bb4&title=&width=726)
控制台输出
![image.png](https://img-blog.csdnimg.cn/img_convert/3c9528315a4646befe91db70cd56ac1e.png#averageHue=#f8f6f4&clientId=u0fa3065b-fcfe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=43&id=u93504054&margin=[object Object]&name=image.png&originHeight=43&originWidth=1259&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7030&status=done&style=none&taskId=uf5f12111-78ab-4773-a8d1-16613259e31&title=&width=1259)
DefaultMessageSourceResolvable: codes [testDTO.password,password]; arguments []; default message [password],16,6]; default message [密码长度必须是6-16个字符]] ]
编写全局统一异常处理
统一返回结构
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
private Integer code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
return new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), data);
}
public static <T> Result<T> success(String message, T data) {
return new Result<>(ResultEnum.SUCCESS.getCode(), message, data);
}
public static Result<?> failed() {
return new Result<>(ResultEnum.COMMON_FAILED.getCode(), ResultEnum.COMMON_FAILED.getMessage(), null);
}
public static Result<?> failed(String message) {
return new Result<>(ResultEnum.COMMON_FAILED.getCode(), message, null);
}
public static Result<?> failed(IResult errorResult) {
return new Result<>(errorResult.getCode(), errorResult.getMessage(), null);
}
public static <T> Result<T> instance(Integer code, String message, T data) {
Result<T> result = new Result<>();
result.setCode(code);
result.setMessage(message);
result.setData(data);
return result;
}
}
常用结果枚举类
//定义返回数据结构
public interface IResult {
Integer getCode();
String getMessage();
}
//常用结果的枚举
public enum ResultEnum implements IResult {
SUCCESS(2001, "接口调用成功"),
VALIDATE_FAILED(2002, "参数校验失败"),
COMMON_FAILED(2003, "接口调用失败"),
FORBIDDEN(2004, "没有权限访问资源");
private Integer code;
private String message;
ResultEnum(Integer code, String message){
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
}
自定义异常处理
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;
/**
* 全局异常处理
*
* @author master
*/
@RestControllerAdvice
public class ExceptionConfig {
/**
* 参数为实体类
* @param e
* @return
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public Result handleValidException(MethodArgumentNotValidException e) {
// 从异常对象中拿到ObjectError对象
ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
// 然后提取错误提示信息进行返回
return Result.failed(objectError.getDefaultMessage());
}
/**
* 参数为单个参数或多个参数
* @param e
* @return
*/
@ExceptionHandler(value = ConstraintViolationException.class)
public Result handleConstraintViolationException(ConstraintViolationException e) {
// 从异常对象中拿到ObjectError对象
String errorMessage = e.getConstraintViolations()
.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toList()).get(0);
return Result.failed(errorMessage);
}
}
再次测试
![image.png](https://img-blog.csdnimg.cn/img_convert/b17a9647c466fd7c38b6f10b9a0d4dba.png#averageHue=#fcfbfa&clientId=u0fa3065b-fcfe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=427&id=u015538df&margin=[object Object]&name=image.png&originHeight=427&originWidth=672&originalType=binary&ratio=1&rotation=0&showTitle=false&size=34656&status=done&style=none&taskId=ud1819a5b-84f3-44d4-ba27-53bf9e0e202&title=&width=672)
![image.png](https://img-blog.csdnimg.cn/img_convert/76408344ae9798f0a3dceed226e34367.png#averageHue=#fcfbfb&clientId=u0fa3065b-fcfe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=435&id=u66119d46&margin=[object Object]&name=image.png&originHeight=435&originWidth=715&originalType=binary&ratio=1&rotation=0&showTitle=false&size=34501&status=done&style=none&taskId=u474a5258-4c18-4452-8ffb-d93251da07f&title=&width=715)