天天看點

SpringBoot 2.0參數校驗Hibernate Validator

Spring Boot (v2.0.5.RELEASE) Hibernate Validator

springboot

起步依賴自動添加了對

hibernate validator

的依賴

SpringBoot 2.0參數校驗Hibernate Validator

hibernate validator依賴

或者也可以自己手動添加依賴

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>6.0.13.Final</version>
</dependency>
           
  1. 建立配置類

    HibernateValidatorConfiguration.class

package com.futao.springmvcdemo.utils;

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

import javax.validation.Validation;
import javax.validation.Validator;

/**
 * @author futao
 * Created on 2018/9/23-20:00.
 * Hibernate Validator配置類
 */
@Configuration
public class HibernateValidatorConfiguration {

    /**
     * JSR和Hibernate validator的校驗隻能對Object的屬性進行校驗
     * 不能對單個的參數進行校驗
     * spring 在此基礎上進行了擴充
     * 添加了MethodValidationPostProcessor攔截器
     * 可以實作對方法參數的校驗
     *
     * @return
     */
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
        processor.setValidator(validator());
        return processor;
    }

    @Bean
    public static Validator validator() {
        return Validation
                .byProvider(HibernateValidator.class)
                .configure()
                //快速傳回模式,有一個驗證失敗立即傳回錯誤資訊
                .failFast(true)
                .buildValidatorFactory()
                .getValidator();
    }
//
//    public static <T> void validate(T obj) {
//        Set<ConstraintViolation<T>> constraintViolations = validator().validate(obj);
//        if (constraintViolations.size() > 0) {
//            throw LogicException.le(constraintViolations.iterator().next().getMessage());
//        }
//    }
}
           

2.定義錯誤消息(

統一異常處理請檢視

)

package com.futao.springmvcdemo.model.entity.constvar;

/**
 * @author futao
 * Created on 2018/9/21-15:29.
 * 錯誤提示集合類
 * 錯誤碼構成:   01程式員編号
 * 001該程式員定義的錯誤碼
 * 後面再跟上錯誤資訊
 */
public final class ErrorMessage {
    public static final String SYSTEM_EXCEPTION = "系統繁忙,請稍後再試";
    public static final String NOT_LOGIN = "01001_您還未登陸或者登陸已逾時,請重新登陸";
    public static final String MOBILE_ALREADY_REGISTER = "01002_該手機号已經被注冊了";
    public static final String LOGIC_EXCEPTION = "01003_對不起,你是真的沒有我帥";
    public static final String MOBILE_LEN_ILLEGAL = "01004_手機号長度不合法";
    public static final String EMAIL_ILLEGAL = "01005_郵箱格式不合法";
    public static final String USERNAME_LEN_ILLEGAL = "01006_名字長度不合法";
}
           

3.在全局異常處理類中攔截驗證架構抛出的

ConstraintViolationException

異常,

通過調試可以看到我們定義的異常資訊在

((ConstraintViolationException) e).getConstraintViolations().iterator().next().getMessage()

SpringBoot 2.0參數校驗Hibernate Validator

調試異常資訊

package com.futao.springmvcdemo.foundation;

import com.alibaba.fastjson.JSONObject;
import com.futao.springmvcdemo.model.entity.constvar.ErrorMessage;
import com.futao.springmvcdemo.model.system.RestResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;

/**
 * @author futao
 * Created on 2018/9/21-15:13.
 * 異常統一處理,
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Object logicExceptionHandler(HttpServletRequest request, Exception e, HttpServletResponse response) {
        //系統級異常,錯誤碼固定為-1,提示語固定為系統繁忙,請稍後再試
        RestResult result = new RestResult(false, "-1", e.getMessage(), ErrorMessage.SYSTEM_EXCEPTION);
        //如果是業務邏輯異常,傳回具體的錯誤碼與提示資訊
        if (e instanceof LogicException) {
            LogicException logicException = (LogicException) e;
            result.setCode(logicException.getCode());
            result.setErrorMessage(logicException.getErrorMsg());
            //Validator驗證架構抛出的業務邏輯異常
        } else if (e instanceof ConstraintViolationException) {
            String message = ((ConstraintViolationException) e).getConstraintViolations().iterator().next().getMessage();
            result.setCode(message.substring(0, 5));
            result.setErrorMessage(message.substring(6));
        } else {
            //對系統級異常進行日志記錄
            logger.error("系統異常:" + e.getMessage(), e);
        }
        return JSONObject.toJSON(result);
    }
}
           

3 使用

  • 可以在進入業務邏輯之前的controller層對資料進行驗證,即把參數驗證注解打在controller的入參

    3.1 将驗證注解打在controller層

/**
 * @author futao
 * Created on 2018/9/19-15:05.
 */
@RequestMapping(path = "User", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@RestController
@Validated
public class UserController {

    @Resource
    private UserService userService;

/**
     * 使用者注冊
     *
     * @param username 使用者名
     * @param age      年齡
     * @param mobile   手機号
     * @param email    郵箱
     * @param address  位址
     * @return
     */
    @PostMapping("register")
    public JSONObject register(
            /*使用@RequestBody注解需要保證該對象有預設的空的構造函數
             * 是流的形式讀取,那麼流讀了一次就沒有了
             * */
            @RequestParam("username")
            @Size(min = 3, max = 8, message = ErrorMessage.USERNAME_LEN_ILLEGAL)
                    String username,
            @RequestParam("age")
                    String age,
            @Size(max = 11, message = ErrorMessage.MOBILE_LEN_ILLEGAL)
            @RequestParam("mobile")
                    String mobile,
            @RequestParam("email")
            @Email(message = ErrorMessage.EMAIL_ILLEGAL)
                    String email,
            @NotBlank
            @RequestParam("address")
                    String address
    ) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("result", "注冊失敗");
        if (userService.register(username, age, mobile, email, address)) {
            jsonObject.put("result", "注冊成功");
        }
        return jsonObject;
    }
}
           

測試驗證:

SpringBoot 2.0參數校驗Hibernate Validator

使用者名不合法

SpringBoot 2.0參數校驗Hibernate Validator

郵箱格式不合法

下一篇: 轉存