spring boot參數驗證

#必需要知道html

  • 簡述 JSR303/JSR-349,hibernate validation,spring validation 之間的關係 JSR303 是一項標準,JSR-349 是其的升級版本,添加了一些新特性,他們規定一些校驗規範即校驗註解,如 @Null,@NotNull,@Pattern,他們位於 javax.validation.constraints 包下,只提供規範不提供實現; hibernate validation 是對這個規範的實踐,他提供了相應的實現,並增長了一些其餘校驗註解,如 @Email,@Length,@Range 等等,他們位於 org.hibernate.validator.constraints 包下; spring validation,是對 hibernate validation 進行了二次封裝,在 springmvc 模塊中添加了自動校驗,並將校驗信息封裝進了特定的類中;

#spring mvc對spring validation的應用 ##get請求 參數驗證java

@RestController
@RequestMapping("/beavalidate")
public class BeanValidateController {

    @GetMapping("/testget")
    public ResultBody testGet(@Valid @NotBlank @RequestParam("name") String name){
        return ResultBody.successBody("get方式驗證成功!");
    }
}

##post請求 參數驗證spring

@RestController
@RequestMapping("/beavalidate")
public class BeanValidateController {

    @PostMapping("/testpost")
    public ResultBody testPost(@Valid  @RequestBody TagAddForm tagAddForm){
        return ResultBody.successBody("驗證成功!");
    }
}

##參數驗證異常統一處理 若是咱們沒有對驗證錯誤進行處理,調用接口的客戶端沒法知道究竟是什麼參數發生了錯誤, 還有就是若是先後端分離咱們通常都是規定json格式傳輸數據,因此咱們最好針對這個錯誤進行處理並返回格式化的內容。json

###定義錯誤相關的枚舉後端

public interface IResult extends Serializable {
    
    Integer getCode();

    String getMessage();
}

public enum ResultEnum implements IResult {
    /**
     * 成功
     */
    SUCCESS(10000, "成功"),
    /**
     * 請求參數異常
     */
    ARGUMENT_EXCEPTION(10001, "請求信息異常");
	
    private Integer code;
    private String message;

    ResultEnum(Integer code, String msg) {
        this.code = code;
        this.message = msg;
    }

    @Override
    public Integer getCode() {
        return code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

###定義統一的json對象mvc

@Data
public class ResultBody<T> {
    /**
     * 錯誤碼
     */
    private Integer code;

    /**
     * 提示信息
     */
    private String message;

    /**
     * 具體數據
     */
    private T body;

    private ResultBody() {

    }

    /**
     * 構形成功包體
     *
     * @return 成功的包體
     */
    public static ResultBody successBody() {
        return dowith(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), new HashMap<>(1));
    }

    /**
     * 構形成功的包體
     *
     * @param body 包體中body的內容
     * @return 成功的包體
     */
    public static ResultBody successBody(Object body) {
        return dowith(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), body);
    }

    /**
     * 構造調用失敗的包體
     *
     * @param result 錯誤碼和提示信息內容
     * @return 失敗的包體
     */
    public static ResultBody errorBody(IResult result) {
        return dowith(result.getCode(), result.getMessage(), new HashMap<>(1));
    }

    /**
     * 構造調用失敗的包體
     *
     * @param result 錯誤碼和提示信息內容
     * @param body   包體內容
     * @return 失敗的包體
     */
    public static ResultBody errorBody(IResult result, Object body) {
        return dowith(result.getCode(), result.getMessage(), body);
    }

    /**
     * 構造調用失敗的包體
     *
     * @param result 錯誤碼和提示信息內容
     * @return 失敗的包體
     */
    public static ResultBody errorBody(IResult result, String message) {
        return dowith(result.getCode(), message, null);
    }

    /**
     * 構造調用失敗的包體
     *
     * @param result 錯誤碼和提示信息內容
     * @param body   包體內容
     * @return 失敗的包體
     */
    public static ResultBody errorBody(IResult result, Object body, String message) {
        return dowith(result.getCode(), message, body);
    }

}

###定義異常處理器app

@ControllerAdvice
public class ValidationExceptionHandler {
    
	/**
	 * 處理post方式參數驗證異常
     * @param e 
     * @return
     */
	@ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public ResultBody notValidException(MethodArgumentNotValidException e) {
        log.error("API參數校驗異常:{}", e);
        return this.wrapperBindingResult(e.getBindingResult());
    }
	
	/**
	 * 處理get方式參數驗證異常
     * @param e 
     * @return
     */
	@ResponseBody
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public ResultBody requestMissingParamsErrorHandler(MissingServletRequestParameterException e) {
        log.error("MissingServletRequestParameterException:{}", e);
        String errorMessage = e.getMessage();
        ResultEnum resultEnum = ResultEnum.ARGUMENT_EXCEPTION;

        return ResultBody.errorBody(resultEnum);
    }
	
	private ResultBody wrapperBindingResult(BindingResult bindingResult) {
        ResultEnum resultEnum = ResultEnum.ARGUMENT_EXCEPTION;
        StringBuilder errorMessage = new StringBuilder();
        if ("prod".equals(this.profile)) {
            errorMessage.append("請求信息異常");
        } else {
            Iterator var4 = bindingResult.getFieldErrors().iterator();

            while(var4.hasNext()) {
                FieldError fieldError = (FieldError)var4.next();
                errorMessage.append(fieldError.getField()).append(fieldError.getDefaultMessage()).append(";");
            }
        }

        resultEnum.setMessage(errorMessage.toString());
        return ResultBody.errorBody(resultEnum);
    }
}

###效果框架

  • get方式參數驗證 前後端分離

  • post方式參數驗證: ide

#非mvc環境下使用驗證 在一些狀況下咱們並非只是驗證http請求參數的綁定,咱們還須要java方法之間調用的參數驗證。 不適用驗證框架咱們通常都是手動驗證,可是手動驗證是很費力的,下面就介紹一下在非mvc的狀況下使用spring validation框架進行驗證。

##手動驗證 ###定義bean添加驗證註解

@Data
public class TagAddForm {

    @NotEmpty(message = "標籤名稱不能爲空")
    private String name;

    @Min(value = 1,message = "標籤類型不能爲空")
    private int type;

}

###編寫手動驗證邏輯

@Component
public class TagValidate {


    /**
     * 驗證bean的參數
     * <p>
     *     手動驗證
     * </p>
     */
    public void validateBean(){
        TagAddForm tagAddForm=new TagAddForm();
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<TagAddForm>> violations = validator.validate(tagAddForm);
        //爲空表明驗證經過
        if (violations.size()==0){
            return;
        }
        for(ConstraintViolation<TagAddForm> violation: violations) {
            System.out.println((violation.getMessage()));
        }
    }


}

###單元測試

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestValidate {
    @Autowired
    private TagValidate tagValidate;
    @Autowired
    private UserValidate userValidate;

    @Test
    public void test(){
        tagValidate.validateBean();
    }
}

結果:

##自動驗證 ###業務類編寫 在類上添加註解:@Validated 在方法上添加:@Valid註解

import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;

@Validated
@Component
public class UserValidate {

    public void add(@Valid TagAddForm tagAddForm){
        System.out.println("添加標籤");
    }
}

###測試

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestValidate {
    @Autowired
    private UserValidate userValidate;


    @Test
    public void test2(){
         //new一個 TagAddForm對象做爲參數並無爲其賦值
        TagAddForm tagAddForm=new TagAddForm();
        userValidate.add(tagAddForm);
    }
}

結果

原文出處:https://www.cnblogs.com/wangsen/p/11671941.html

相關文章
相關標籤/搜索