Spring Boot 全局异常处理 与 Hibernate Validator校验框架整合

Hibernate Validator校验框架的使用

Spring boot已经集成了hibernate-validator,不需要引入maven,其他框架也可以自己引入:

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.3.5.Final</version>
        </dependency>

注解详解(需要校验的model类)

import io.swagger.models.Model;
import org.hibernate.validator.constraints.*;

import javax.validation.Valid;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.List;

/**
 * @author 向振华
 * @date 2018/11/21 09:59
 */
public class Eg {

    /**空检查*/

    //验证对象是否为null
    @Null(message = "")//message为异常类中的message
    private Model model1;

    //检查基本类型是否为空
    @NotNull(message = "")
    private Integer integer;

    //检查约束字符串是不是Null还有被Trim的长度是否大于0,且会去掉前后空格
    @NotBlank(message = "")
    private String string;

    //检查集合是否为NULL或者是EMPTY
    @NotEmpty(message = "")
    private List<String> stringList;


    /**Booelan检查*/

    //验证 Boolean 对象是否为 true
    @AssertTrue(message = "")
    private Boolean tBoolean;

    //验证 Boolean 对象是否为 false
    @AssertFalse(message = "")
    private Boolean fBoolean;


    /**长度检查*/

    //验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
    @Size(min = 1, max = 100, message = "范围1~100!")
    private List<String> stringLists;

    //验证字符串长度是否在指定范围
    @Length(min=1, max=20, message = "范围1~20")
    private String stringl;


    /**日期检查*/

    //验证 Date 和 Calendar 对象是否在当前时间之前
    @Past()
    private java.util.Date date1;

    //验证 Date 和 Calendar 对象是否在当前时间之后
    @Future()
    private java.util.Date date2;


    /**字符串正则检查*/

    //验证 String 对象是否符合正则表达式的规则
    @Pattern(regexp = "[1][3456789]\\d{9}", message = "手机号格式不正确")
    private String mobile;


    /**数值检查*/
    //建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null

    //验证 Number 和 String 对象是否大等于指定的值
    @Min(10)
    private Integer integer1;

    //验证 Number 和 String 对象是否小等于指定的值
    @Max(20)
    private Integer integer2;

    //被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
    @DecimalMax("10.1")
    private BigDecimal bigDecimal1;

    //被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
    @DecimalMin("20.2")
    private BigDecimal bigDecimal2;

    //验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。
    @Digits(integer= 1,fraction= 2)
    private Integer integerh;

    //验证值是否在指定的范围
    @Range(min=10000,max=50000)
    private BigDecimal wage;

    //递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
    @Valid
    //添加其他注解校验
    private List<Integer> integers;

    //信用卡验证
    @CreditCardNumber

    //验证是否是邮件地址,如果为null,不进行验证,算通过验证。
    @Email
    private String mailbox;

//    @ScriptAssert(lang= ,script=, alias=)

//    @URL(protocol=,host=, port=,regexp=, flags=)
}

需要在Controller方法参数前面加@Validated使校验框架生效

    @Override
    public ResponseMessage send(@RequestBody @Validated Eg eg) {
        return sendService.send(eg);
    }

 注意:如果有嵌套校验,需要加上@Valid注解,如下所示:

public class Eg {
    
    @NotNull(message = "")
    @Valid
    private User user;
}

返回值类 (用于返回给前端固定格式的值)

public class ResponseMessage<T> implements Serializable {
    static final long serialVersionUID = 1L;

    /**
     * 0:成功 1:失败
     */
    private int code;

    /**
     * 信息
     */
    private String msg;

    /**
     * 数据
     */
    private T data;

    /**
     * 失败情况
     *
     * @param msg
     */
    public ResponseMessage(String msg) {
        this.code = 1;
        this.msg = msg;
        this.data = null;
    }

    /**
     * 成功情况
     *
     * @param data
     */
    public ResponseMessage(T data) {
        this.code = 0;
        this.msg = null;
        this.data = data;
    }

    public ResponseMessage(int code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
}

全局异常捕获处理

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.bzcst.bop.common.saas.SaasContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * 全局异常捕获处理
 *
 * @author 向振华
 * @date 2021/12/09 14:51
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 异常处理程序
     *
     * @param request
     * @param exception
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public Object handler(HttpServletRequest request, Exception exception) {
        String message;
        if (exception instanceof BusinessException) {
            BusinessException e = (BusinessException) exception;
            message = e.getMsg();
        } else if (exception instanceof BindException) {
            BindException e = (BindException) exception;
            message = e.getBindingResult().getFieldError().getDefaultMessage();
        } else if (exception instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException e = (MethodArgumentNotValidException) exception;
            message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        } else if (exception instanceof HttpMessageNotReadableException) {
            message = "参数格式错误";
        } else if (exception instanceof NumberFormatException) {
            message = "数字格式错误";
        } else if (exception instanceof HttpMessageConversionException) {
            message = "参数类型错误";
        } else if (exception instanceof HttpRequestMethodNotSupportedException) {
            message = "请求方式错误";
        } else if (exception instanceof HttpMediaTypeNotSupportedException) {
            message = "媒体类型错误";
        } else if (exception instanceof MissingServletRequestParameterException) {
            message = "缺少请求参数";
        } else if (exception instanceof MaxUploadSizeExceededException) {
            message = "文件超过最大上传大小";
        } else if (StringUtils.isNotBlank(exception.getMessage()) && exception.getMessage().contains("Data too long for column")) {
            message = "参数长度超限制";
        } else if (StringUtils.isNotBlank(exception.getMessage()) && exception.getMessage().contains("You have an error in your SQL syntax")) {
            message = "SQL语法错误";
        } else {
            message = "网络异常,请稍后重试";
        }
        String errorLog = this.errorLog(request, exception);
        log.error("异常---> {}", errorLog);
        return new ResponseMessage<>(message);
    }

    private String errorLog(HttpServletRequest request, Exception exception) {
        StringWriter sw = new StringWriter();
        sw.append("\n");
        sw.append(String.format("【时间】 %s\n", DateUtil.now()));
        sw.append(String.format("【接口】 %s\n", request.getRequestURI()));
        sw.append(String.format("【用户】 %s\n", JSONUtil.toJsonStr(SaasContext.getUserToken())));
        sw.append("----------------------------------------\n");
        exception.printStackTrace(new PrintWriter(sw));
        return sw.toString();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值