检验字段升级版
接着之前的if(a ==null)的判断方式,得益于勇哥的指导,我又改进了一版,去掉aop等。。。只需要一个全局异常类,两个校验类的maven坐标即可完成
准备工作
- springboot项目
- 校验工具坐标
- 全局异常类
开始:在springboot项目加入以下maven坐标
<!--校验工具-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
全局异常类:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ApiResponse handlerException(Exception e, HttpServletRequest request) {
if (e instanceof NoHandlerFoundException) {
log.error("【全局异常拦截】NoHandlerFoundException: 请求方法:{}, 请求路径:{}", ((NoHandlerFoundException) e).getRequestURL(), ((NoHandlerFoundException) e).getHttpMethod());
return ApiResponse.respond(StateEnum.REQUEST_NOT_FOUND);
} else if (e instanceof HttpRequestMethodNotSupportedException) {
log.error("【全局异常拦截】HttpRequestMethodNotSupportedException: 当前请求方式:{}, 支持请求方式:{}", ((HttpRequestMethodNotSupportedException) e).getMethod(), JSONUtil.toJsonStr(((HttpRequestMethodNotSupportedException) e).getSupportedHttpMethods()));
return ApiResponse.respond(StateEnum.HTTP_BAD_METHOD);
} else if (e instanceof MethodArgumentNotValidException) {
log.error("【全局异常拦截】MethodArgumentNotValidException:{}", e.getMessage());
return ApiResponse.respond(StateEnum.BAD_REQUEST.getCode(), ((MethodArgumentNotValidException) e).getBindingResult()
.getAllErrors()
.get(0)
.getDefaultMessage(), null);
} else if (e instanceof ConstraintViolationException) {
log.error("【全局异常拦截】ConstraintViolationException", e);
return ApiResponse.respond(StateEnum.BAD_REQUEST.getCode(), CollUtil.getFirst(((ConstraintViolationException) e).getConstraintViolations())
.getMessage(), null);
} else if (e instanceof MethodArgumentTypeMismatchException) {
log.error("【全局异常拦截】MethodArgumentTypeMismatchException: 参数名:{}, 异常信息:{}", ((MethodArgumentTypeMismatchException) e).getName(), ((MethodArgumentTypeMismatchException) e).getMessage());
return ApiResponse.respond(StateEnum.PARAM_NOT_MATCH);
} else if (e instanceof HttpMessageNotReadableException) {
log.error("【全局异常拦截】HttpMessageNotReadableException: 错误信息:{}", ((HttpMessageNotReadableException) e).getMessage());
return ApiResponse.respond(StateEnum.PARAM_NOT_NULL);
} else if (e instanceof ApiBaseEnum) {
log.error("【全局异常拦截】BaseException: 接口:{}, 状态码 {}, 异常信息:{}", request.getRequestURI(), ((ApiBaseEnum) e).getCode(), e.getMessage());
return ApiResponse.respond((ApiBaseEnum) e);
}
log.error("【全局异常拦截】异常堆栈信息: ", e);
return ApiResponse.respond(StateEnum.ERROR, "系统繁忙,请稍后重试");
}
}
全局异常类用到的枚举
@AllArgsConstructor
public enum StateEnum implements ApiBaseEnum {
REQUEST_NOT_FOUND(404, "REQUEST_NOT_FOUND", "方法没找到"),
HTTP_BAD_METHOD(400, "HTTP_BAD_METHOD", "参数错误"),
BAD_REQUEST(400, "BAD_REQUEST", "参数异常"),
PARAM_NOT_MATCH(401, "PARAM_NOT_MATCH", "参数不匹配"),
PARAM_NOT_NULL(402, "PARAM_NOT_NULL", "参数不能为空"),
ERROR(500, "ERROR", "错误"),
LENGTH_NO_SUPPORT(615, "length is too long", "长度超出范围");
/**
* api响应code码
*/
private int code;
/**
* api错误码描述
*/
private String msg;
/**
* 错误详细备注
*/
private String note;
@Override
public int getCode() {
return code;
}
@Override
public String getMsg() {
return msg;
}
@Override
public String getNote() {
return note;
}
}
统一返回实体类
@Data
public class ApiResponse<T> {
private int code;
private String msg;
private T data;
private String note;
private long timestamp;
private String version = "v1.0.0";
private ApiResponse(ApiBaseEnum apiBaseEnum) {
this.code = apiBaseEnum.getCode();
this.msg = apiBaseEnum.getMsg().toLowerCase();
this.note = apiBaseEnum.getNote();
this.timestamp = System.currentTimeMillis();
}
private ApiResponse(ApiBaseEnum apiBaseEnum, T data) {
this(apiBaseEnum);
this.data = data;
}
private ApiResponse(ApiBaseEnum apiBaseEnum, T data, String note) {
this(apiBaseEnum);
this.data = data;
if (StringUtils.isNotBlank(note)) {
this.note = note;
}
}
private ApiResponse(int customCode, T data, String customNote) {
this.code = customCode;
this.timestamp = System.currentTimeMillis();
this.data = data;
if (StringUtils.isNotBlank(customNote)) {
this.note = customNote;
}
}
public ApiResponse() {
}
public static <T> ApiResponse<T> respond() {
return new ApiResponse<>(ApiResponseEnum.SUCCESS);
}
public static <T> ApiResponse<T> respond(T data) {
return new ApiResponse<>(ApiResponseEnum.SUCCESS, data);
}
public static <T> ApiResponse<T> respond(T data, ApiBaseEnum apiBaseEnum) {
return new ApiResponse<>(apiBaseEnum, data);
}
public static <T> ApiResponse<T> respond(ApiBaseEnum apiBaseEnum) {
return new ApiResponse<>(apiBaseEnum);
}
public static <T> ApiResponse<T> respond(T data, ApiBaseEnum apiBaseEnum, String customNote) {
return new ApiResponse<>(apiBaseEnum, data, customNote);
}
public static <T> ApiResponse<T> respond(T data, int customCode, String customNote) {
return new ApiResponse<>(customCode, data, customNote);
}
public static <T> ApiResponse<T> respond(ApiBaseEnum apiBaseEnum, String errors) {
ApiResponse<T> apiResponse = respond(apiBaseEnum);
if (errors == null) {
return apiResponse;
} else {
apiResponse.note = errors;
return apiResponse;
}
}
public static <T> ApiResponse<T> respond(String errors) {
ApiResponse<T> apiResponse = new ApiResponse<>(ApiResponseEnum.FAIL);
apiResponse.note = errors;
return apiResponse;
}
public static <T> ApiResponse<T> respond(int code, T str, String customNote) {
return new ApiResponse<>(code, str, customNote);
}
}
开始controller、实体类的测试:
@Data
public class Employee {
private Integer id;
// @NotBlank(message = "请输入姓名")
@Length(message = "名称不能超过个 {max} 字符", max = 10)
private String name;
@NotNull(message = "请输入年龄")
@Min(1)
@Max(100)
private Integer age;
}
@RestController
@RequestMapping("valid")
public class ValidTestController {
@PostMapping("employee")
public Employee employee(@RequestBody @Valid Employee employee) {
System.out.println(employee.getAge());
System.out.println(employee.getName());
employee.setId(1);
return employee;
}
}