1. 程式人生 > >Spring Boot 全域性異常處理 與 Hibernate Validator校驗框架整合

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);
    }

返回值類 (用於返回給前端固定格式的值)

public class ResponseMessage<T> implements Serializable {
    /**
     * 1:成功 -1:失敗
     */
    private int code;
    /**
     * 資訊
     */
    private String msg;
    /**
     * 資料
     */
    private T data;
}

 

全域性異常捕獲處理

/**
 * 全域性異常捕獲處理
 * @author 向振華
 * @date 2018/11/21 10:37
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Log LOG = LogFactory.getLog(GlobalExceptionHandler.class);

    /**
     * 所有驗證框架異常捕獲處理
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class})
    public Object validationExceptionHandler(Exception exception) {
        BindingResult bindResult = null;
        if (exception instanceof BindException) {
            bindResult = ((BindException) exception).getBindingResult();
        } else if (exception instanceof MethodArgumentNotValidException) {
            bindResult = ((MethodArgumentNotValidException) exception).getBindingResult();
        }
        String msg;
        if (bindResult != null && bindResult.hasErrors()) {
            msg = bindResult.getAllErrors().get(0).getDefaultMessage();
            if (msg.contains("NumberFormatException")) {
                msg = "引數型別錯誤!";
            }
        }else {
            msg = "系統繁忙,請稍後重試...";
        }
        return new ResponseMessage(-1, msg);
    }

    /**
     * 業務異常
     * @param exception
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = BusinessException.class)
    public Object allBusinessExceptionHandler(BusinessException exception) {
        return new ResponseMessage(-1, exception.getMessage());
    }

    /**
     * 未知的異常捕獲處理
     * @param exception
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Object allUnknowExceptionHandler(HttpServletRequest request, Exception exception) {
        String error = logError(request, exception);
        //可以傳送郵件通知開發
        return new ResponseMessage(-1, "系統繁忙,請稍後重試!");
    }

    private String logError(HttpServletRequest request, Exception exception) {
        LOG.error("發生未知異常:", exception);
        StringWriter sw = new StringWriter();
        sw.append(String.format("Date:{%s};\n", DateUtil.dateToString(new Date())));
        sw.append(String.format("url:{%s}產生錯誤;\n", request.getRequestURI()));
        sw.append(String.format("請求IP:{%s};\n", request.getRemoteAddr()));
        sw.append(String.format("type:{%s};\n", request.getMethod()));
        sw.append(String.format("請求引數:{%s};\n", JSONObject.toJSONString(request.getParameterMap())));
        exception.printStackTrace(new PrintWriter(sw));
        return sw.toString();
    }
}