pom文件配置:
springboot项目需要的jar包引用。
快速创建springboot项目可在官网,地址:https://start.spring.io/
参数校验引入jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.5.0</version>
</dependency>
网上找的好多都是配置下面这个包,但是不生效,不知道什么原因:
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency>
封装统一的返回格式:
package cn.dto;
import cn.enums.ResEnum;
import com.alibaba.fastjson.JSONObject;
import java.io.Serializable;
public class ResDTO<T> implements Serializable {
private static final long serialVersionUID = -1391045602107628480L;
private Integer code;
private String msg;
private T data;
public ResDTO() {
}
public ResDTO(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public ResDTO(T data, Integer code, String msg) {
this.data = data;
this.code = code;
this.msg = msg;
}
public ResDTO(ResEnum resEnum) {
this.data = null;
this.code = resEnum.code();
this.msg = resEnum.message();
}
public ResDTO(ResEnum resEnum,T data) {
this.data = data;
this.code = resEnum.code();
this.msg = resEnum.message();
}
public static String error(){
return JSONObject.toJSONString(new ResDTO(ResEnum.ERROE));
}
public static String success(){
return JSONObject.toJSONString(new ResDTO(ResEnum.SUCESS));
}
public ResDTO<T> success(T data){
return new ResDTO<T>(ResEnum.SUCESS,data);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
package cn.enums;
public enum ResEnum {
SUCESS(1,"成功"),
IS_NULL(2,"查询接果为空"),
PARAM_IS_ERROR(3,"参数错误"),
EXCUTER_ERROR(4,"执行失败"),
ERROE(9,"系统异常");
private Integer code;
private String message;
ResEnum(int code, String message) {
this.code=code;
this.message=message;
}
public Integer code(){
return this.code;
}
public String message(){
return this.message;
}
}
实体类
package cn.entity;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
public class TestEntity implements Serializable {
private static final long serialVersionUID = -543680037107475493L;
@NotBlank(message = "id不能为空")
private String id;
@NotEmpty(message = "value不能为空")
private String value;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
控制层
package cn.controller;
import cn.enums.ResEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import cn.dto.*;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@ControllerAdvice
public class BaseController {
private Logger logger = LoggerFactory.getLogger(BaseController.class);
/**
* 参数校验异常
* @param ex
* @return
* @throws Exception
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public ResDTO bindExceptionHandler(MethodArgumentNotValidException ex) throws Exception {
BindingResult result = ex.getBindingResult();
StringBuilder s=new StringBuilder();
if (result.hasErrors()) {
List<ObjectError> errors = result.getAllErrors();
errors.forEach(p ->{
FieldError fieldError = (FieldError) p;
s.append(fieldError.getField()+":"+fieldError.getDefaultMessage());
});
}
logger.error("ExceptionController.bindExceptionHandler:"+s);
return new ResDTO(ResEnum.PARAM_IS_ERROR);
}
/**
* 处理其他异常
* @param ex
* @return
* @throws Exception
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public ResDTO exceptionHandler(Exception ex) throws Exception {
String msg = ex.getMessage();
logger.error("ExceptionController.exceptionHandler:"+msg);
return new ResDTO(ResEnum.ERROE);
}
}
package cn.controller;
import cn.dto.ResDTO;
import cn.entity.TestEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotBlank;
import java.util.List;
@RestController
@RequestMapping("/con")
@Validated
public class TestController extends BaseController{
@RequestMapping("/test")
public @ResponseBody ResDTO<TestEntity> test(@RequestBody @Validated TestEntity testEntity){
return new ResDTO<TestEntity>().success(testEntity);
}
@RequestMapping("/test2")
public @ResponseBody ResDTO test2(@NotBlank String id,
@NotBlank String value){
return new ResDTO().success();
}
}
测试ok:
127.0.0.1:8080/con/test
{"id":"","value":""}
返回:
{
"code": 3,
"msg": "参数错误",
"data": null
}
日志记录:
问题记录:
在controller类的方法参数请求方式上,如果需要用josn格式,需要加上 @RequestBody 否在 使用json格式提交会报错,返回对象加上 @ResponseBody 注解,返回格式会自动转成json,不需要单独自己去转换。
单个参数,不做对象传参时需要在controller类上加上@Validated注解
发现一个问题就是这种捕获的异常是exception异常,按照我的分装返回的就是系统异常,很明显这个返回不正确。
需要再增加一单个参数异常处理。
/**
* 单个参数校验时抛出的异常
* @param ex
* @return
*/
@ExceptionHandler(value = ConstraintViolationException.class)
@ResponseBody
public ResDTO handleBindGetException(ConstraintViolationException ex){
//获取参数校验异常message
List<String> defaultMsg = ex.getConstraintViolations()
.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toList());
logger.error("ExceptionController.exceptionHandler:"+ex);
return new ResDTO(ResEnum.PARAM_IS_ERROR);
}
还有在网上有很多介绍参数异常是BindException这个,这个异常已经不用了。