全局异常处理器+参数校验(最佳实践)

需结合前两篇《全局异常处理器》+《参数校验》!!!!

之前的参数校验还不够优雅!每次都需要在 controller 层手动获取校验错误,然后再返回参数,一坨一坨的,每次都要手动写未免太难看了。我们将使用全局异常管理器来优化这块,告别每次手动获取校验错误信息再返回。

参数校验不通过,会抛出什么异常?

会了弄清楚 validation 在参数校验不通过时,会抛出具体什么异常,需要将 TestController 中的 /test 接口中的 BindingResult 参数去掉,代码如下:

@PostMapping("/test")
    @ApiOperationLog(description = "测试接口")
    public Response test(@RequestBody @Validated User user) {
        return Response.success();
    }

重启项目,通过 Apifox再次请求该接口,就能在控制台看到具体的异常信息了:

可以看到异常类名为 MethodArgumentNotValidException , 我们可以通过它来获取参数校验相关的错误信息。 

全局异常处理器捕获该异常

为了解放双手,我们可以通过全局异常处理器来捕获该异常,统一返回错误信息,改造 GlobalExceptionHandler 类,添加 handleMethodArgumentNotValidException() 方法,代码如下:

/**
     * 捕获参数校验异常
     * @return
     */
    @ExceptionHandler({ MethodArgumentNotValidException.class })
    @ResponseBody
    public Response<Object> handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) {
        // 参数错误异常码
        String errorCode = ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode();

        // 获取 BindingResult
        BindingResult bindingResult = e.getBindingResult();

        StringBuilder sb = new StringBuilder();

        // 获取校验不通过的字段,并组合错误信息,格式为: email 邮箱格式不正确, 当前值: '123124qq.com';
        Optional.ofNullable(bindingResult.getFieldErrors()).ifPresent(errors -> {
            errors.forEach(error ->
                    sb.append(error.getField())
                            .append(" ")
                            .append(error.getDefaultMessage())
                            .append(", 当前值: '")
                            .append(error.getRejectedValue())
                            .append("'; ")

            );
        });

        // 错误信息
        String errorMessage = sb.toString();

        log.warn("{} request error, errorCode: {}, errorMessage: {}", request.getRequestURI(), errorCode, errorMessage);

        return Response.fail(errorCode, errorMessage);
    }

上述代码中,我们通过 @ExceptionHandler 注解捕获了MethodArgumentNotValidException.class 类型的异常,并从异常实体类中获取了 BindingResult 对象,从而获取到具体哪些字段校验不通过,最终组合错误信息并返回。

添加参数错误枚举

上面代码中,还需要添加一个 PARAM_NOT_VALID 枚举值,表示参数错误

package com.yanxiaosheng.xx.common.enums;

import com.yanxiaosheng.xx.common.exception.BaseExceptionInterface;
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * @author: 闫小生
 * @date: 2023-08-15 10:33
 * @description: 响应异常码
 **/
@Getter
@AllArgsConstructor
public enum ResponseCodeEnum implements BaseExceptionInterface {

    // ----------- 通用异常状态码 -----------
	...省略
    PARAM_NOT_VALID("10001", "参数错误"),


	...省略
}

测试看下最终效果

修改 TestController 中的 /test 接口,记住不要添加参数 BindingResult, 将 MethodArgumentNotValidException 异常统一抛给全局异常管理器来处理:

@PostMapping("/test")
    @ApiOperationLog(description = "测试接口")
    public Response test(@RequestBody @Validated User user) {
        return Response.success();
    }

重启项目,通过 Apifox 调用 /test 接口,看看返参效果:

可以看到,返参明确返回了哪些字段校验不通过、当前值、以及注解中填写的提示信息,这样返回的好处是,当和前端联调接口时,前端小伙伴可根据提示信息就知道哪个字段出现了问题,避免扯皮。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值