應用:
1. @Validated 聲明要檢查的參數
這里我們在控制器層進行注解聲明
/** * 走參數校驗注解 * * @param userDTO * @return */ @PostMapping("/save/valid") public RspDTO save(@RequestBody @Validated UserDTO userDTO) { userService.save(userDTO); return RspDTO.success(); }
2. 對參數的字段進行注解標注
import lombok.Data; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.*; import java.io.Serializable; import java.util.Date; /** * @ClassName: UserDTO * @Description: 用戶傳輸對象 * @date 2019/7/30 13:55 */ @Data public class UserDTO implements Serializable { private static final long serialVersionUID = 1L; /*** 用戶ID*/ @NotNull(message = "用戶id不能為空") private Long userId; /** 用戶名*/ @NotBlank(message = "用戶名不能為空") @Length(max = 20, message = "用戶名不能超過20個字符") @Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "用戶昵稱限制:最多20字符,包含文字、字母和數字") private String username; /** 手機號*/ @NotBlank(message = "手機號不能為空") @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手機號格式有誤") private String mobile; /**性別*/ private String sex; /** 郵箱*/ @NotBlank(message = "聯系郵箱不能為空") @Email(message = "郵箱格式不對") private String email; /** 密碼*/ private String password; /*** 創建時間 */ @Future(message = "時間必須是將來時間") private Date createTime; }
3. 在全局校驗中增加校驗異常
MethodArgumentNotValidException
是springBoot中進行綁定參數校驗時的異常,需要在springBoot中處理,其他需要 處理ConstraintViolationException異常進行處理.
- 為了優雅一點,我們將參數異常,業務異常,統一做了一個全局異常,將控制層的異常包裝到我們自定義的異常中
- 為了優雅一點,我們還做了一個統一的結構體,將請求的code,和msg,data一起統一封裝到結構體中,增加了代碼的復用性
import com.boot.lea.mybot.dto.RspDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DuplicateKeyException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.NoHandlerFoundException; import javax.validation.ConstraintViolationException; import javax.validation.ValidationException; /** * @ClassName: GlobalExceptionHandler * @Description: 全局異常處理器 * @date 2019/7/30 13:57 */ @RestControllerAdvice public class GlobalExceptionHandler { private Logger logger = LoggerFactory.getLogger(getClass()); private static int DUPLICATE_KEY_CODE = 1001; private static int PARAM_FAIL_CODE = 1002; private static int VALIDATION_CODE = 1003; /** * 處理自定義異常 */ @ExceptionHandler(BizException.class) public RspDTO handleRRException(BizException e) { logger.error(e.getMessage(), e); return new RspDTO(e.getCode(), e.getMessage()); } /** * 方法參數校驗 */ @ExceptionHandler(MethodArgumentNotValidException.class) public RspDTO handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { logger.error(e.getMessage(), e); return new RspDTO(PARAM_FAIL_CODE, e.getBindingResult().getFieldError().getDefaultMessage()); } /** * ValidationException */ @ExceptionHandler(ValidationException.class) public RspDTO handleValidationException(ValidationException e) { logger.error(e.getMessage(), e); return new RspDTO(VALIDATION_CODE, e.getCause().getMessage()); } /** * ConstraintViolationException */ @ExceptionHandler(ConstraintViolationException.class) public RspDTO handleConstraintViolationException(ConstraintViolationException e) { logger.error(e.getMessage(), e); return new RspDTO(PARAM_FAIL_CODE, e.getMessage()); } @ExceptionHandler(NoHandlerFoundException.class) public RspDTO handlerNoFoundException(Exception e) { logger.error(e.getMessage(), e); return new RspDTO(404, "路徑不存在,請檢查路徑是否正確"); } @ExceptionHandler(DuplicateKeyException.class) public RspDTO handleDuplicateKeyException(DuplicateKeyException e) { logger.error(e.getMessage(), e); return new RspDTO(DUPLICATE_KEY_CODE, "數據重復,請檢查后提交"); } @ExceptionHandler(Exception.class) public RspDTO handleException(Exception e) { logger.error(e.getMessage(), e); return new RspDTO(500, "系統繁忙,請稍后再試"); } }
4.測試
如下文:確實做到了參數校驗時返回異常信息和對應的code,方便了我們不再繁瑣的處理參數校驗
