




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
告別if-else校驗代碼,參數(shù)校驗這么寫才足夠優(yōu)雅很痛苦遇到大量的參數(shù)進(jìn)行校驗,在業(yè)務(wù)中還要拋出異?;蛘卟粩嗟姆祷禺惓r的校驗信息,在代碼中相當(dāng)冗長,充滿了if-else這種校驗代碼,今天我們就來學(xué)習(xí)spring的javax.validation注解式參數(shù)校驗.為什么要用validatorjavax.validation的一系列注解可以幫我們完成參數(shù)校驗,免去繁瑣的串行校驗不然我們的代碼就像下面這樣:
//
http://localhost:8080/api/user/save/serial
/**
*
走串行校驗
*
*
@param
userVO
*
@return
*/
@PostMapping("/save/serial")
public
Object
save(@RequestBody
UserVO
userVO)
{
String
mobile
=
userVO.getMobile();
//手動逐個
參數(shù)校驗~
寫法
if
(StringUtils.isBlank(mobile))
{
return
RspDTO.paramFail("mobile:手機號碼不能為空");
}
else
if
(!Pattern.matches("^[1][3,4,5,6,7,8,9][0-9]{9}$",
mobile))
{
return
RspDTO.paramFail("mobile:手機號碼格式不對");
}
//拋出自定義異常等~寫法
if
(StringUtils.isBlank(userVO.getUsername()))
{
throw
new
BizException(Constant.PARAM_FAIL_CODE,
"用戶名不能為空");
}
//
比如寫一個map返回
if
(StringUtils.isBlank(userVO.getSex()))
{
Map
result
=
new
HashMap<>(5);
result.put("code",
Constant.PARAM_FAIL_CODE);
result.put("msg",
"性別不能為空");
return
result;
}
//.........各種寫法
...
userService.save(userVO);
return
RspDTO.success();
}
這被大佬看見,一定說,都9102了還這么寫,然后被勸退了.....什么是javax.validationJSR303是一套JavaBean參數(shù)校驗的標(biāo)準(zhǔn),它定義了很多常用的校驗注解,我們可以直接將這些注解加在我們JavaBean的屬性上面(面向注解編程的時代),就可以在需要校驗的時候進(jìn)行校驗了,在SpringBoot中已經(jīng)包含在starter-web中,再其他項目中可以引用依賴,并自行調(diào)整版本:
javax.validation
validation-api
1.1.0.Final
org.hibernate
hibernate-validator
5.2.0.Final
注解說明
1.@NotNull:不能為null,但可以為empty("","
","
")
2.@NotEmpty:不能為null,而且長度必須大于0
("
","
")
3.@NotBlank:只能作用在String上,不能為null,而且調(diào)用trim()后,長度必須大于0("test")
即:必須有實際字符
驗證注解驗證的數(shù)據(jù)類型說明@AssertFalseBoolean,boolean驗證注解的元素值是false@AssertTrueBoolean,boolean驗證注解的元素值是true@NotNull任意類型驗證注解的元素值不是null@Null任意類型驗證注解的元素值是null@Min(value=值)BigDecimal,BigInteger,byte,short,int,long,等任何Number或CharSequence(存儲的是數(shù)字)子類型驗證注解的元素值大于等于@Min指定的value值@Max(value=值)和@Min要求一樣驗證注解的元素值小于等于@Max指定的value值@DecimalMin(value=值)和@Min要求一樣驗證注解的元素值大于等于@DecimalMin指定的value值@DecimalMax(value=值)和@Min要求一樣驗證注解的元素值小于等于@DecimalMax指定的value值@Digits(integer=整數(shù)位數(shù),fraction=小數(shù)位數(shù))和@Min要求一樣驗證注解的元素值的整數(shù)位數(shù)和小數(shù)位數(shù)上限@Size(min=下限,max=上限)字符串、Collection、Map、數(shù)組等驗證注解的元素值的在min和max(包含)指定區(qū)間之內(nèi),如字符長度、集合大小@Pastjava.util.Date,java.util.Calendar;JodaTime類庫的日期類型驗證注解的元素值(日期類型)比當(dāng)前時間早@Future與@Past要求一樣驗證注解的元素值(日期類型)比當(dāng)前時間晚@NotBlankCharSequence子類型驗證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應(yīng)用于字符串且在比較時會去除字符串的首位空格@Length(min=下限,max=上限)CharSequence子類型驗證注解的元素值長度在min和max區(qū)間內(nèi)@NotEmptyCharSequence子類型、Collection、Map、數(shù)組驗證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0)@Range(min=最小值,max=最大值)BigDecimal,BigInteger,CharSequence,byte,short,int,long等原子類型和包裝類型驗證注解的元素值在最小值和最大值之間@Email(regexp=正則表達(dá)式,flag=標(biāo)志的模式)CharSequence子類型(如String)驗證注解的元素值是Email,也可以通過regexp和flag指定自定義的email格式@Pattern(regexp=正則表達(dá)式,flag=標(biāo)志的模式)String,任何CharSequence的子類型驗證注解的元素值與指定的正則表達(dá)式匹配@Valid任何非原子類型指定遞歸驗證關(guān)聯(lián)的對象如用戶對象中有個地址對象屬性,如果想在驗證用戶對象時一起驗證地址對象的話,在地址對象上加@Valid注解即可級聯(lián)驗證此處只列出HibernateValidator提供的大部分驗證約束注解,請參考hibernatevalidator官方文檔了解其他驗證約束注解和進(jìn)行自定義的驗證約束注解定義。實戰(zhàn)演練話不多說,直接走實踐路線,同樣使用的是SpringBoot的快速框架,詳細(xì)代碼見:/leaJone/myb…在公眾號后端架構(gòu)師后臺回復(fù)“架構(gòu)整潔”,獲取一份驚喜禮包。1.@Validated聲明要檢查的參數(shù)這里我們在控制器層進(jìn)行注解聲明
/**
*
走參數(shù)校驗注解
*
*
@param
userDTO
*
@return
*/
@PostMapping("/save/valid")
public
RspDTO
save(@RequestBody
@Validated
UserDTO
userDTO)
{
userService.save(userDTO);
return
RspDTO.success();
}
2.對參數(shù)的字段進(jìn)行注解標(biāo)注import
lombok.Data;
import
org.hibernate.validator.constraints.Length;
import
javax.validation.constraints.*;
import
java.io.Serializable;
import
java.util.Date;
/**
*
@author
LiJing
*
@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字符,包含文字、字母和數(shù)字")
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
=
"聯(lián)系郵箱不能為空")
@Email(message
=
"郵箱格式不對")
private
String
email;
/**
密碼*/
private
String
password;
/***
創(chuàng)建時間
*/
@Future(message
=
"時間必須是將來時間")
private
Date
createTime;
}
3.在全局校驗中增加校驗異常MethodArgumentNotValidException是springBoot中進(jìn)行綁定參數(shù)校驗時的異常,需要在springBoot中處理,其他需要處理ConstraintViolationException異常進(jìn)行處理.為了優(yōu)雅一點,我們將參數(shù)異常,業(yè)務(wù)異常,統(tǒng)一做了一個全局異常,將控制層的異常包裝到我們自定義的異常中為了優(yōu)雅一點,我們還做了一個統(tǒng)一的結(jié)構(gòu)體,將請求的code,和msg,data一起統(tǒng)一封裝到結(jié)構(gòu)體中,增加了代碼的復(fù)用性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;
/**
*
@author
LiJing
*
@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());
}
/**
*
方法參數(shù)校驗
*/
@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,
"數(shù)據(jù)重復(fù),請檢查后提交");
}
@ExceptionHandler(Exception.class)
public
RspDTO
handleException(Exception
e)
{
logger.error(e.getMessage(),
e);
return
new
RspDTO(500,
"系統(tǒng)繁忙,請稍后再試");
}
}
4.測試如下確實做到了參數(shù)校驗時返回異常信息和對應(yīng)的code,方便了我們不再繁瑣的處理參數(shù)校驗在ValidationMperties就是校驗的message,有著已經(jīng)寫好的默認(rèn)的message,且是支持i18n的,大家可以閱讀源碼賞析自定義參數(shù)注解1.比如我們來個自定義身份證校驗注解@Documented
@Target({ElementType.PARAMETER,
ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy
=
IdentityCardNumberValidator.class)
public
@interface
IdentityCardNumber
{
String
message()
default
"身份證號碼不合法";
Class[]
groups()
default
{};
Class[]
payload()
default
{};
}
這個注解是作用在Field字段上,運行時生效,觸發(fā)的是IdentityCardNumber這個驗證類。message定制化的提示信息,主要是從ValidationMperties里提取,也可以依據(jù)實際情況進(jìn)行定制groups這里主要進(jìn)行將validator進(jìn)行分類,不同的類group中會執(zhí)行不同的validator操作payload主要是針對bean的,使用不多。2.然后自定義Validator這個是真正進(jìn)行驗證的邏輯代碼:public
class
IdentityCardNumberValidator
implements
ConstraintValidator<IdentityCardNumber,
Object>
{
@Override
public
void
initialize(IdentityCardNumber
identityCardNumber)
{
}
@Override
public
boolean
isValid(Object
o,
ConstraintValidatorContext
constraintValidatorContext)
{
return
IdCardValidatorUtils.isValidate18Idcard(o.toString());
}
}
IdCardValidatorUtils在項目源碼中,可自行查看3.使用自定義的注解
@NotBlank(message
=
"身份證號不能為空")
@IdentityCardNumber(message
=
"身份證信息有誤,請核對后提交")
private
String
clientCardNo;
4.使用groups的校驗有的寶寶說同一個對象要復(fù)用,比如UserDTO在更新時候要校驗userId,在保存的時候不需要校驗userId,在兩種情況下都要校驗username,那就用上groups了:在公眾號頂級架構(gòu)師后臺回復(fù)“架構(gòu)”,獲取一份驚喜禮包。先定義groups的分組接口Create和Updateimport
javax.validation.groups.Default;
public
interface
Create
extends
Default
{
}
import
javax.validation.groups.Default;
public
interface
Update
extends
Default{
}
再在需要校驗的地方@Validated聲明校驗組
/**
*
走參數(shù)校驗注解的
groups
組合校驗
*
*
@param
userDTO
*
@return
*/
@PostMapping("/update/groups")
public
RspDTO
update(@RequestBody
@Validated(Update.class)
UserDTO
userDTO)
{
userService.updateById(userDTO);
return
RspDTO.success();
}
在DTO中的字段上定義好groups={}的分組類型@Data
public
class
UserDTO
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L;
/***
用戶ID*/
@NotNull(message
=
"用戶id不能為空",
groups
=
Update.class)
private
Long
userId;
/**
*
用戶名
*/
@NotBlank(message
=
"用戶名不能為空")
@Length(max
=
20,
message
=
"用戶名不能超過20個字符",
groups
=
{Create.class,
Update.class})
@Pattern(regexp
=
"^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$",
message
=
"用戶昵稱限制:最多20字符,包含文字、字母和數(shù)字")
private
String
username;
/**
*
手機號
*/
@NotBlank(message
=
"手機號不能為空")
@Pattern(regexp
=
"^[1][3,4,5,6,7,8,9][0-9]{9}$",
message
=
"手機號格式有誤",
groups
=
{Create.class,
Update.class})
private
String
mobile;
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國古式桌子數(shù)據(jù)監(jiān)測研究報告
- 黑龍江省哈爾濱工大附中2024-2025學(xué)年九年級下學(xué)期化學(xué)寒假調(diào)研測試題(含答案)
- 2025年軍隊文職人員招聘之軍隊文職政治學(xué)練習(xí)題(一)及答案
- 2019-2025年消防設(shè)施操作員之消防設(shè)備中級技能通關(guān)提分題庫及完整答案
- 產(chǎn)品采購協(xié)議細(xì)節(jié)
- 房地產(chǎn)公司涉及的設(shè)計方面協(xié)議年
- 促銷活動效果分析統(tǒng)計表
- 慢病相關(guān)知識培訓(xùn)課件
- 人力資源招聘與員工離職統(tǒng)計表
- 河南省駐馬店上蔡縣2024-2025學(xué)年七年級上學(xué)期期末生物學(xué)試題(含答案)
- 人際關(guān)系與溝通技巧-職場中的上行溝通-下屬與上司溝通
- 超聲引導(dǎo)下椎管內(nèi)麻醉
- 幼兒園科學(xué)課件:《大肚子媽媽》
- (完整版)200210號文-工程勘察設(shè)計收費標(biāo)準(zhǔn)(2002年修訂本)本月修正2023簡版
- 基于核心素養(yǎng)下小學(xué)英語單元整體作業(yè)設(shè)計實踐研究 論文
- XX學(xué)校初高貫通銜接培養(yǎng)實施方案
- 2022版《義務(wù)教育科學(xué)課程標(biāo)準(zhǔn)》試題及答案
- 組織效能概述和提高組織效能的方法
- 私募股權(quán)投資業(yè)務(wù)激勵管理辦法
- 廣東省深圳市南山區(qū)2022-2023學(xué)年下學(xué)期學(xué)科素養(yǎng)期末學(xué)業(yè)評價三年級科學(xué)試卷(掃描版無答案)
- 高考日語基礎(chǔ)歸納總結(jié)與練習(xí)(一輪復(fù)習(xí))
評論
0/150
提交評論