实习笔记---springboot的参数校验

前言

以后的知识点呀、报错修复啥的都改成实习笔记啦,除非我实习期结束啦。这几天鉴权部分基本完成了,老板让我写CRUD,秉承着代码优雅的前提,我开始看参数校验。

整齐但是不优雅的if-else

你在日常敲代码中,有没有遇到这种情况,前端传到后端的参数多,且大多数都需要校验,这样子你是不是需要很多if来判断他们是否是符合逻辑的。比如:

if(schoolInfo!=null&&schoolInfo.getId()!=null) {
            return RestResult.failure();
        }

以上举个小例子,这样子写虽然看起来很整齐且易懂,但是参数一多,逻辑还没开始,就一堆if语句在上面,有点不太优雅。

@Validated

其实springboot官方文档里有推荐使用这个东西来做参数校验,用法也很简单,有兴趣的小伙伴可以去网上搜索下用法,这里举个例子

@Null

表示参数必须为空,只需要在实体类的参数上标识即可,您还可以加上报错信息,例如:

@Null(message = "Id存在非法值")
private String id;

标识后,在接收参数的controller上,使用@Validated注解,例如

public RestResult addSchool(@Validated SchoolInfo schoolInfo)

如此,如果id中有值,会报异常,异常错误信息是你在message中填写的字。

不太好看的返回

如果您将错误信息直接返回的话,会是一大串字符串,这里测试的时候忘记截图了,小伙伴可以自己看看,为了使返回好看一点,有请今天的第二个主角:

@ControllerAdvice 统一异常处理

首先,我们要知道,在不同情况下,@Validated 返回的异常是不同的,以下:

//处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常,详情继续往下看代码
BindException e
//处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是
ConstraintViolationException e
//处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常。
MethodArgumentNotValidException e

当我们知道这些之后,就可以开始写异常处理:

/**
 * 统一异常处理
 * jackson
 * 时间:2020年04月10日16:03:05
 */

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

	@ExceptionHandler(Exception.class)
	public RestResult handle(Throwable e,  HttpServletRequest request)  {

		/**
		 * 参数校验
		 */
		if(e instanceof BindException)
			return this.BindExceptionHandler((BindException) e);
		if(e instanceof ConstraintViolationException)
			return this.ConstraintViolationExceptionHandler((ConstraintViolationException) e);
		if(e instanceof MethodArgumentNotValidException)
			return this.MethodArgumentNotValidExceptionHandler((MethodArgumentNotValidException) e);
			
	}
	
	//处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常,详情继续往下看代码
	public RestResult  BindExceptionHandler(BindException e) {
		log.error("参数异常");
		String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
		return RestResult.failure(message);
	}

	//处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是javax.validation.ConstraintViolationException
	public RestResult ConstraintViolationExceptionHandler(ConstraintViolationException e) {
		log.error("参数异常");
		String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
		return RestResult.failure(message);
	}

	//处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常。
	public RestResult MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
		log.error("参数异常");
		String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
		return RestResult.failure(message);
	}
}

如果对统一异常管理不了解的小伙伴,建议去别人的博客观摩观摩,这里controller一旦抛出异常,会被@RestControllerAdvice捕获到,进入逻辑判断,这里比对了三个不同的异常,进行不同的处理。
为了方便小伙伴,我贴下我的返回类

/**
 * Description: 返回结果对象
 * Author:  jackson
 * Date: 2020年04月10日10:16:46
 **/

@Data
public class RestResult<T> implements Serializable {

    private String msg;

    private Integer code;

    private T data;

    Long count;//数据数量

    List<T> datas;//返回数据

    public RestResult(Integer code, String msg) {
        super();
        this.code = code;
        this.msg = msg;
    }

    public RestResult(Integer code, String msg,T data) {
        super();
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public RestResult(Integer code, String msg, List<T> datas, Long count) {
        this.code = code;
        this.msg = msg;
        this.datas = datas;
        this.count = count;
    }


    /* 无数据传输的 成功返回 */
    public static <T> RestResult<T> success() {
        return new RestResult<T>( ErrorCode.SUCCESS.getErrorCode(),  ErrorCode.SUCCESS.getErrorMsg());
    }

//    public static  RestResult success(String msg) {
//        return new RestResult(ErrorCode.SUCCESS.getErrorCode(), msg);
//    }

    public static <T> RestResult<T> success(ErrorCode errorCode) {
        return new RestResult<T>( errorCode.getErrorCode(),  errorCode.getErrorMsg());
    }

    /* 单个数据传输的 成功返回 */
    public static <T> RestResult<T> success(T data) {
        return new RestResult<T>( ErrorCode.SUCCESS.getErrorCode(),  ErrorCode.SUCCESS.getErrorMsg(), data);
    }

    public static <T> RestResult<T> success(String msg, T data) {
        return new RestResult<T>(ErrorCode.SUCCESS.getErrorCode(), msg, data);
    }

    public static <T> RestResult<T> success(ErrorCode errorCode, T data) {
        return new RestResult<T>( errorCode.getErrorCode(),  errorCode.getErrorMsg(), data);
    }

    /* 分页数据传输的 成功返回 */
    public static <T> RestResult<T> success(Long count, List<T> datas) {
        return new RestResult<T>(ErrorCode.SUCCESS.getErrorCode(),ErrorCode.SUCCESS.getErrorMsg(),datas,count);
    }

    public static <T> RestResult<T> success(String msg, Long count, List<T> datas) {
        return new RestResult<T>(ErrorCode.SUCCESS.getErrorCode(), msg, datas, count);
    }

    public static <T> RestResult<T> success(ErrorCode resultCode, Long count, List<T> datas) {
        return new RestResult<T>( resultCode.getErrorCode(),  resultCode.getErrorMsg(), datas ,count);
    }

    /* 无数据传输的 失败返回 */
    public static <T> RestResult<T> failure(String message) {
        return new RestResult<T>( ErrorCode.FAILED.getErrorCode(), message);
    }

    public static <T> RestResult<T> failure() {
        return new RestResult<T>( ErrorCode.FAILED.getErrorCode(), ErrorCode.FAILED.getErrorMsg());
    }

    public static <T> RestResult<T> failure(ErrorCode resultCode) {
        return new RestResult<T>( resultCode.getErrorCode(),  resultCode.getErrorMsg());
    }

    public static <T> RestResult<T> failure(CustomizeException c) {
        return new RestResult<T>( c.getCode(),c.getMessage());
    }


    public static <T> RestResult<T> failure(Integer code, String msg) {
        return new RestResult<T>( code,  msg);
    }

}

哎哟,还是觉得自己的异常捕获类写的不太好,不知道有没有大佬指正下。

以上,希望能帮助到小伙伴。

你可能感兴趣的:(springboot,学习之路)