springboot validation參數校驗及異常捕獲

validation註解

經常使用註解

constraint 說明 支持類型
@Null 被註釋的元素必須爲null Object
@NotNull 被註釋的元素不能爲null,但能夠爲empty,沒有Size的約束 Object
@NotEmpty [字符串、數組、集合、Map]不能爲null&長度不爲0 字符串、Object[]、基礎類型數組、[Collection、Map]接口實現類
@NotBlank 只用於String,不能爲null且trim()以後size>0 字符串
@Length 字符串長度爲min至max之間 字符串
@Size(max,min) [字符串、數組、集合、Map]長度爲min至max之間 字符串、Object[]、基礎類型數組、[Collection、Map]接口實現類
@Range [字符串、數字]大小在min和max之間,字符串必須是數字格式 數值、數值格式的字符串
@AssertTrue 被註釋的元素必須爲true boolean
@AssertFalse 被註釋的元素必須爲false boolean
@Min(value) [字符串長度、數字]不能小於value 數值、數值格式的字符串
@Max(value) [字符串長度、數字]不能大於value 數值、數值格式的字符串
@DecimalMin(value) 被註釋的元素必須是一個數字,不能小於等於value; inclusive爲false時, 不能小於value 數值、數值格式的字符串
@DecimalMax(value) 被註釋的元素必須是一個數字,不能大於等於value; inclusive爲false時, 不能大於value 數值、數值格式的字符串
@Digits(integer,fraction) 被註釋的元素必須是一個數字,其值必須在可接受的範圍內,整數位數不能大於integer, 小數位數不能大於fraction 數值、數值格式的字符串
@Past 被註釋的元素必須是一個過去的日期 時間
@PastOrPresent 只能是過去時間或當前時間 時間
@Future 被註釋的元素必須是一個未來的日期 時間
@FutureOrPresent 只能是將來時間或當前時間 時間
@Pattern(value) 被註釋的元素必須符合指定的正則表達式 字符串
@Email 被註釋的元素必須是電子郵件地址,能夠使用regex指定格式 字符串
@Negative 只能爲負數 數值
@NegativeOrZero 只能爲負數或0 數值
@Positive 只能爲正數 數值
@PositiveOrZero 只能爲正數或0 數值

使用@Valid 或者 @Validated驗證。java

使用@RequestBody驗證body數據。git

模式

  • 效驗模式:若是出現多個字段效驗失敗,會返回全部的驗證失敗錯誤信息。一般狀況下,當第一個字段/參數效驗失敗時,直接返回。
  • 普通模式:默認使用的就是普通模式,校驗完全部的屬性以後,返回全部的驗證失敗信息。
  • 快速失敗模式:只要有一個字段效驗失敗,直接返回。

快速失敗模式配置web

@Configuration
public class ValidationConfig {
    /**
     * 效驗@RequestBody時,採用快速失敗模式
     */
    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
            .configure()
            //快速失敗
            .failFast(true)
            .buildValidatorFactory();
        return validatorFactory.getValidator();
    }

    /**
     * 效驗@RequestParam時,採用快速失敗模式
     */
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor(Validator validator) {
        MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
        // 設置validator
        postProcessor.setValidator(validator);
        return postProcessor;
    }
}

舉例

  • UsersController
package com.chenglulu.controller.users;

import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;

@RestController
@RequestMapping( value = "/", produces = {MediaType.APPLICATION_JSON_VALUE})
public class UsersController {
    
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public void registerUser(HttpServletRequest request, @Validated @RequestBody RegisterUsersParams params){
       
    }
}
  • RegisterUsersParams
package com.chenglulu.controller.users.domain;

import com.chenglulu.constant.Validation;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

@Data
public class RegisterUsersParams {
    @NotBlank(message = "username is blank")
    private String username;
    
    @NotBlank(message = "phone is blank")
    @Pattern(regexp = Validation.PHONE)
    private String phone;
    
    @Email
    private String email;
}

全局異常處理

經常使用註解

@ControllerAdvice
@ExceptionHandler  異常類型
@ResponseStatus  異常響應狀態
@ResponseBody

舉例

package com.chenglulu.exception;

import com.chenglulu.constant.Constants;
import com.chenglulu.constant.ErrorCode;
import com.chenglulu.controller.users.domain.BaseResponse;
import com.chenglulu.utils.ResponseUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.support.RequestContextUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Locale;
@ControllerAdvice
public class GlobalExceptionHandler {
    @Autowired
 private MessageSource messageSource;
    
    /**
    * 未知異常處理 
    * @param request 請求
    * @param ex 異常對象
    */ 
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @ResponseBody
 public HttpEntity<BaseResponse> handlerMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException ex){
        String requestId = getRequestIdHeader(request);
        
        String code = ErrorCode.PARAMETER_ERROR;
        Locale locale = RequestContextUtils.getLocale(request);
        BindingResult br = ex.getBindingResult();
        StringBuilder msgStr = new StringBuilder();
        List<FieldError> feList = br.getFieldErrors();
        for (FieldError fe : feList) {
            String message = fe.getDefaultMessage();
            String field = fe.getField();
            msgStr.append(field).append(message).append("; ");
        }
        Object[] msgArg = new Object[]{msgStr};
        String message = messageSource.getMessage(code, msgArg, locale);
        BaseResponse res = ResponseUtil.error(requestId, code, message);
        return new HttpEntity<BaseResponse>(res);
    }
    
    /**
    * 未知異常處理 
    * @param request 請求
    * @param ex 異常對象
    */ 
    @ExceptionHandler(value = {Exception.class})
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
 public HttpEntity<BaseResponse> handlerException(HttpServletRequest request, Exception ex){
        String requestId = getRequestIdHeader(request);
        
        String code = ErrorCode.UNKNOWN_ERROR;
        BaseResponse res = ResponseUtil.error(request, requestId, code, null);
        return new HttpEntity<BaseResponse>(res);
    }
    
    private String getRequestIdHeader(HttpServletRequest request) {
        return request.getHeader(Constants.HEADER_X_REQUEST_ID);
    }
    
    private String getLocaleMessage(HttpServletRequest request) {
    }
}
相關文章
相關標籤/搜索