SpringBoot使用validation-api實(shí)現(xiàn)參數(shù)校驗(yàn)的示例
我們?cè)陂_發(fā)Java項(xiàng)目的時(shí)候,經(jīng)常需要對(duì)參數(shù)進(jìn)行一些必填項(xiàng)、格式、長度等進(jìn)行校驗(yàn),如果手寫代碼對(duì)參數(shù)校驗(yàn),每個(gè)接口會(huì)需要很多低級(jí)的代碼,這樣會(huì)降低代碼的可讀性。那么我們能不能使用一種比較優(yōu)雅的方式來實(shí)現(xiàn),對(duì)請(qǐng)求中的參數(shù)進(jìn)行校驗(yàn)?zāi)兀?/p>
knife4j的安裝與使用可參考我的博客:SpringBoot使用knife4j進(jìn)行在線接口調(diào)試
正文
ValidationApi框架就是用來解決參數(shù)校驗(yàn)中代碼冗余問題,ValidationApi框架提供一些注解用來幫助我們對(duì)請(qǐng)求參數(shù)進(jìn)行校驗(yàn):

SpringBoot使用validation-api實(shí)現(xiàn)參數(shù)校驗(yàn)
注入依賴
<!--參數(shù)校驗(yàn)--> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <!--提供一些字符串操作--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.3.2</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.2</version> <optional>true</optional> </dependency> <!--knife4j接口--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.4</version> </dependency>
UserPojoReq.java請(qǐng)求封裝類
如果成員變量是其他對(duì)象實(shí)體,該變量必須加 @Valid,否則嵌套中的驗(yàn)證不生效
@Setter
@Getter
@ToString
@ApiModel("用戶對(duì)象")
public class UserPojoReq extends Request implements Serializable {
private static final long serialVersionUID = -354657839724457905L;
@ApiModelProperty(required = true, notes = "主鍵", example = "123")
private String id;
@ApiModelProperty(required = true, notes = "用戶名", example = "luo")
@NotNull(message = "用戶姓名為必填項(xiàng),不得為空")
@Size(min = 2,max = 20,message = "用戶名長度要在2—8個(gè)字符")
private String name;
@ApiModelProperty(required = true, notes = "消息", example = "消息")
private String msg;
}
CouponTypeEnum.class :錯(cuò)誤碼枚舉類
@Getter
public enum CouponTypeEnum {
PARAMETER_ERROR(1001, "請(qǐng)求參數(shù)有誤!"),
UNKNOWN_ERROR(9999, "未知的錯(cuò)誤!”);
/**
* 狀態(tài)值
*/
private int couponType;
/**
* 狀態(tài)描述
*/
private String couponTypeDesc;
CouponTypeEnum(int couponType, String couponTypeDesc){
this.couponType = couponType;
this.couponTypeDesc = couponTypeDesc;
}
public static String getDescByType(int couponType) {
for (CouponTypeEnum type : CouponTypeEnum.values()) {
if (type.couponType == couponType) {
return type.couponTypeDesc;
}
}
return null;
}
public String getcouponTypeStr(){
return String.valueOf(this.couponType);
}
}
BusinessException.java:自定義業(yè)務(wù)異常類
/**
* 業(yè)務(wù)自定義異常
*/
@Getter
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = -1895174013651345407L;
private final CouponTypeEnum errorCode;
private String primaryErrorCode;
private String primaryErrorMsg;
private String primaryErrorIP;
public BusinessException(CouponTypeEnum errorCode) {
this(errorCode, errorCode.getCouponTypeDesc());
}
public BusinessException(CouponTypeEnum errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public BusinessException(CouponTypeEnum errorCode, String message,String primaryErrorCode,String primaryErrorMsg,String primaryErrorIP) {
super(message);
this.errorCode = errorCode;
this.primaryErrorCode=primaryErrorCode;
this.primaryErrorMsg=primaryErrorMsg;
this.primaryErrorIP=primaryErrorIP;
}
public BusinessException(CouponTypeEnum errorCode,String primaryErrorCode,String primaryErrorMsg,String primaryErrorIP) {
this(errorCode, errorCode.getCouponTypeDesc());
this.primaryErrorCode=primaryErrorCode;
this.primaryErrorMsg=primaryErrorMsg;
this.primaryErrorIP=primaryErrorIP;
}
}
GlobalExceptionHandler.class 攔截異常并統(tǒng)一處理
MissingServletRequestParameterException:必填項(xiàng)為null異常HttpMessageNotReadableException:參數(shù)類型不匹配異常MethodArgumentNotValidException:JSON校驗(yàn)失敗異常(比如長度等)BusinessException:自定義的異常Exception:其他異常
@RestControllerAdvice("com.luo.producer.controller")
@Slf4j
public class GlobalExceptionHandler {
/**
* 忽略參數(shù)異常處理器
*
* @param e 忽略參數(shù)異常
* @return Response
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MissingServletRequestParameterException.class)
public Response parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
log.error("", e);
return new Response(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), "請(qǐng)求參數(shù) " + e.getParameterName() + " 不能為空");
}
/**
* 缺少請(qǐng)求體異常處理器
*
* @param e 缺少請(qǐng)求體異常
* @return Response
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public Response parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
log.error("", e);
return new Response(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), "參數(shù)體不能為空");
}
/**
* 參數(shù)效驗(yàn)異常處理器
*
* @param e 參數(shù)驗(yàn)證異常
* @return ResponseInfo
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Response parameterExceptionHandler(MethodArgumentNotValidException e) {
log.error("", e);
// 獲取異常信息
BindingResult exceptions = e.getBindingResult();
// 判斷異常中是否有錯(cuò)誤信息,如果存在就使用異常中的消息,否則使用默認(rèn)消息
if (exceptions.hasErrors()) {
List<ObjectError> errors = exceptions.getAllErrors();
if (!errors.isEmpty()) {
// 這里列出了全部錯(cuò)誤參數(shù),按正常邏輯,只需要第一條錯(cuò)誤即可
FieldError fieldError = (FieldError) errors.get(0);
return new Response(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), fieldError.getDefaultMessage());
}
}
return new Response(CouponTypeEnum.PARAMETER_ERROR);
}
/**
* 自定義參數(shù)錯(cuò)誤異常處理器
*
* @param e 自定義參數(shù)
* @return ResponseInfo
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({BusinessException.class})
public Response paramExceptionHandler(BusinessException e) {
log.error("", e);
// 判斷異常中是否有錯(cuò)誤信息,如果存在就使用異常中的消息,否則使用默認(rèn)消息
if (!StringUtils.isEmpty(e.getMessage())) {
return new Response(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), e.getMessage());
}
return new Response(CouponTypeEnum.PARAMETER_ERROR);
}
/**
* 其他異常
*
* @param e
* @return
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({Exception.class})
public Response otherExceptionHandler(Exception e) {
log.error("其他異常", e);
// 判斷異常中是否有錯(cuò)誤信息,如果存在就使用異常中的消息,否則使用默認(rèn)消息
if (!StringUtils.isEmpty(e.getMessage())) {
return new Response(CouponTypeEnum.UNKNOWN_ERROR.getcouponTypeStr(), e.getMessage());
}
return new Response(CouponTypeEnum.UNKNOWN_ERROR);
}
}
驗(yàn)證
測試接口
@Valid被標(biāo)記的實(shí)體將會(huì)開啟一個(gè)校驗(yàn)的功能
@RequestBody:請(qǐng)求實(shí)體需要加上@RequestBody否則MethodArgumentNotValidException異常將會(huì)被識(shí)別成Exception異常,提示信息將與預(yù)期不符。
@RestController
@Slf4j
public class UserController {
@PostMapping("/helloluo")
@MyPermissionTag(value = "true")
public String helloluo(@RequestBody @Valid UserPojoReq userPojoReq){
return "Hello World”+userPojoReq;
}
}
模擬請(qǐng)求參數(shù),進(jìn)行接口訪問:

到此這篇關(guān)于SpringBoot使用validation-api實(shí)現(xiàn)參數(shù)校驗(yàn)的示例的文章就介紹到這了,更多相關(guān)SpringBoot validation參數(shù)校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring?Boot集成validation實(shí)現(xiàn)參數(shù)校驗(yàn)功能
- SpringBoot使用Validation包進(jìn)行輸入?yún)?shù)校驗(yàn)
- SpringBoot使用Validation進(jìn)行參數(shù)校驗(yàn)的示例詳解
- SpringBoot集成Validation參數(shù)校驗(yàn)
- SpringBoot使用validation做參數(shù)校驗(yàn)的實(shí)現(xiàn)步驟
- SpringBoot使用validation-api實(shí)現(xiàn)對(duì)枚舉類參數(shù)校驗(yàn)的方法
- spring boot validation參數(shù)校驗(yàn)實(shí)例分析
- springboot+dubbo+validation 進(jìn)行rpc參數(shù)校驗(yàn)的實(shí)現(xiàn)方法
- spring?參數(shù)校驗(yàn)Validation示例詳解
相關(guān)文章
使用RestTemplate訪問https實(shí)現(xiàn)SSL請(qǐng)求操作
這篇文章主要介紹了使用RestTemplate訪問https實(shí)現(xiàn)SSL請(qǐng)求操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
Spring?Boot項(xiàng)目集成Knife4j接口文檔的實(shí)例代碼
Knife4j就相當(dāng)于是swagger的升級(jí)版,對(duì)于我來說,它比swagger要好用得多<BR>,這篇文章主要介紹了Spring?Boot項(xiàng)目集成Knife4j接口文檔的示例代碼,需要的朋友可以參考下2021-12-12
Springboot項(xiàng)目啟動(dòng)到一半卡住了,不報(bào)錯(cuò)問題及解決
這篇文章主要介紹了Springboot項(xiàng)目啟動(dòng)到一半卡住了,不報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
java 中序列化與readResolve()方法的實(shí)例詳解
這篇文章主要介紹了java 中序列化與readResolve()方法的實(shí)例詳解的相關(guān)資料,這里提供實(shí)例幫助大家理解這部分知識(shí),需要的朋友可以參考下2017-08-08
SpringMVC+Mybatis實(shí)現(xiàn)的Mysql分頁數(shù)據(jù)查詢的示例
本篇文章主要介紹了SpringMVC+Mybatis實(shí)現(xiàn)的Mysql分頁數(shù)據(jù)查詢的示例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08
Springboot詳解整合SpringSecurity實(shí)現(xiàn)全過程
Spring Security基于Spring開發(fā),項(xiàng)目中如果使用Springboot作為基礎(chǔ),配合Spring Security做權(quán)限更加方便,而Shiro需要和Spring進(jìn)行整合開發(fā)。因此作為spring全家桶中的Spring Security在java領(lǐng)域很常用2022-07-07
java實(shí)現(xiàn)Runnable接口適合資源的共享
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)Runnable接口適合資源的共享,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07

