1.maven
SpringBoot starter-web自動引入其依賴,因為web模塊默認使用了hibernate-validator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.model校驗
對郵箱進行檢測注盈,message用作校驗失敗時的提示信息匙奴。
public class User {
private Long id;
private String name;
private Integer age;
@Email(message = "郵箱格式錯誤")
private String email;
..
..
}
3.在controller(Rest層)添加校驗
參數(shù)前需要加上@Validated注解魄健,表明需要spring對其進行校驗,而校驗的信息會存放到其后的BindingResult中殖告。
@RequestMapping(value = "/addUser", method = RequestMethod.PUT)
@ResponseBody
public String addUser(@RequestBody @Validated User user) {
User u = new User();
u.setName(user.getName());
u.setAge(user.getAge());
userMapper.insert(u);
return "success";
}
4.異常捕捉
你可以直接在方法里捕捉反饋驗證錯誤信息
而我是用了全局統(tǒng)一異常的處理
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class MyExceptionHandle {
private static final Logger logger = LoggerFactory.getLogger(MyExceptionHandle.class);
@ExceptionHandler(value = Exception.class)
@ResponseBody
public String handle(Exception e) {
if (e instanceof MethodArgumentNotValidException) {
MethodArgumentNotValidException ex=(MethodArgumentNotValidException)e;
BindingResult bindingResult = ex.getBindingResult();
StringBuffer stringBuffer = new StringBuffer();
if(bindingResult.hasErrors()){
for (FieldError fieldError : bindingResult.getFieldErrors()) {
//該格式僅僅作為response展示和log作用阿蝶,前端應(yīng)自己做校驗
stringBuffer.append(fieldError.getObjectName() + "--" +fieldError.getDefaultMessage() + " ");
}
}
logger.error(stringBuffer.toString());
return HttpStatus.BAD_REQUEST.value()+stringBuffer.toString();
}
e.printStackTrace(); // 打印異常棧
return e.getMessage();
}
}
測試
因為我用了swagger-ui,所以直接在這里面測試黄绩,你們可以訪問URL測試
HttpStatus.BAD_REQUEST.value()是檢測變量名羡洁,getFieldErrors()是一個List。
注意:參數(shù)前需要加上@Validated注解爽丹,表明需要spring對其進行校驗筑煮,而校驗的信息會存放到其后的BindingResult中。注意粤蝎,必須相鄰真仲,如果有多個參數(shù)需要校驗,形式可以如下初澎。foo(@Validated Foo foo, BindingResult fooBindingResult 秸应,@Validated Bar bar, BindingResult barBindingResult);即一個校驗類對應(yīng)一個校驗結(jié)果。
6.分組校驗
當我們遇到不同場景需要有不同的校驗規(guī)則時候碑宴,我們可以使用分組校驗软啼。如:一個請求只校驗id,一個請求只校驗email:
新建兩個分組(Name,Email)接口
public interface Name{
}
public interface Email{
}
修改實體類
public class User {
private Long id;
@Length(min = 2,message = "名字至少2位",groups = {Name.class})
private String name;
private Integer age;
@Email(message = "郵箱格式錯誤",,groups = {Email.class})
private String email;
..
..
}
@Validated屬性中指定需要校驗的分組名,可以指定1到多個,@Validated({a.class,b.class,...}) 延柠。指定到的分組名會全部進行校驗祸挪,不指定的不校驗,這里我們就只對Name組的驗證,而忽略其他的(Email)
@ResponseBody
public String addUser(@RequestBody @Validated({Name.class}) User user) {
User u = new User();
u.setName(user.getName());
u.setAge(user.getAge());
userMapper.insert(u);
return "success";
}
測試
7.對象級聯(lián)校驗
對象內(nèi)部包含另一個對象作為屬性贞间,屬性上加@Valid(不可以用@Validated贿条,參考10)雹仿,可以驗證作為屬性的對象內(nèi)部的驗證,來實現(xiàn)嵌套驗證整以。
現(xiàn)在有個實體叫做Item:
public class Item {
@NotNull(message = "id不能為空")
@Min(value = 1, message = "id必須為正整數(shù)")
private Long id;
@NotNull(message = "props不能為空")
@Size(min = 1, message = "至少要有一個屬性")
private List<Prop> props;
}
屬性這個實體也有自己的驗證機制胧辽,比如屬性和屬性值id不能為空,屬性名和屬性值不能為空等悄蕾。
public class Prop {
@NotNull(message = "pid不能為空")
@Min(value = 1, message = "pid必須為正整數(shù)")
private Long pid;
@NotNull(message = "vid不能為空")
@Min(value = 1, message = "vid必須為正整數(shù)")
private Long vid;
@NotBlank(message = "pidName不能為空")
private String pidName;
@NotBlank(message = "vidName不能為空")
private String vidName;
}
現(xiàn)在我們有個 ItemController 接受一個Item的入?yún)⑵惫耍胍獙tem進行驗證础浮,如下所示:
@RestController
public class ItemController {
@RequestMapping("/item/add")
public void addItem(@Validated Item item, BindingResult bindingResult) {
doSomething();
}
}
如果Item實體的props屬性不額外加注釋帆调,只有@NotNull和@Size,無論入?yún)⒉捎聾Validated還是@Valid驗證豆同,Spring Validation框架只會對Item的id和vid等屬性做非空和數(shù)量驗證番刊,不會對props字段里的Prop實體進行字段驗證,也就是@Validated和@Valid加在方法參數(shù)前影锈,都不會自動對參數(shù)進行嵌套驗證芹务。也就是說如果傳的List中有Prop的pid為空或者是負數(shù),入?yún)Ⅱ炞C不會檢測出來鸭廷。
為了能夠進行嵌套驗證枣抱,必須手動在Item實體的props字段上明確指出這個字段里面的實體也要進行驗證。由于@Validated不能用在成員屬性(字段)上辆床,但是@Valid能加在成員屬性(字段)上佳晶,而且@Valid類注解上也說明了它支持嵌套驗證功能,那么我們能夠推斷出:@Valid加在方法參數(shù)時并不能夠自動進行嵌套驗證讼载,而是用在需要嵌套驗證類的相應(yīng)字段上轿秧,來配合方法參數(shù)上@Validated或@Valid來進行嵌套驗證。
我們修改Item類如下所示:
public class Item {
@NotNull(message = "id不能為空")
@Min(value = 1, message = "id必須為正整數(shù)")
private Long id;
@Valid // 嵌套驗證必須用@Valid
@NotNull(message = "props不能為空")
@Size(min = 1, message = "props至少要有一個自定義屬性")
private List<Prop> props;
}
然后我們在ItemController的addItem函數(shù)上再使用@Validated或者@Valid咨堤,就能對Item的入?yún)⑦M行嵌套驗證菇篡。此時Item里面的props如果含有Prop的相應(yīng)字段為空的情況,Spring Validation框架就會檢測出來一喘,bindingResult就會記錄相應(yīng)的錯誤驱还。
8.GET參數(shù)校驗(@RequestParam參數(shù)校驗)
a.此時需要使用MethodValidationPostProcessor 的Bean
暫時不深究
b.方法所在的Controller上加注解@Validated
@RequestMapping("/validation")
@RestController
@Validated
public class ValidationController {
/**如果只有少數(shù)對象,直接把參數(shù)寫到Controller層凸克,然后在Controller層進行驗證就可以了议蟆。*/
@RequestMapping(value = "/demo3", method = RequestMethod.GET)
public void demo3(@Range(min = 1, max = 9, message = "年級只能從1-9")
@RequestParam(name = "grade", required = true)
int grade,
@Min(value = 1, message = "班級最小只能1")
@Max(value = 99, message = "班級最大只能99")
@RequestParam(name = "classroom", required = true)
int classroom) {
System.out.println(grade + "," + classroom);
}
}
9.hibernate的校驗?zāi)J?/strong>
1、普通模式(默認是這個模式)
普通模式(會校驗完所有的屬性触徐,然后返回所有的驗證失敗信息)咪鲜。但是在使用組序列驗證的時候,如果序列前邊的組驗證失敗撞鹉,則后面的組將不再給予驗證疟丙。
2颖侄、快速失敗返回模式
快速失敗返回模式(只要有一個驗證失敗,則返回)
3.如果需要配置為快速失敗返回享郊,則編寫配置文件
(hibernate.validator.fail_fast:true 快速失敗返回模式 false 普通模式)
@Configuration
public class ValidatorConfiguration {
@Bean
public Validator validator(){
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.addProperty( "hibernate.validator.fail_fast", "true" )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
return validator;
}
}
10.@Valid和@Validated的總結(jié)區(qū)分
Spring Validation驗證框架對參數(shù)的驗證機制提供了@Validated(Spring's JSR-303 規(guī)范览祖,是標準 JSR-303 的一個變種),javax提供了@Valid(標準JSR-303規(guī)范)炊琉,配合 BindingResult 可以直接提供參數(shù)驗證結(jié)果展蒂。@Validated是@Valid 的一次封裝,是Spring提供的校驗機制使用苔咪。在檢驗 Controller 的入?yún)⑹欠穹弦?guī)范時锰悼,使用 @Validated 或者 @Valid 在基本驗證功能上沒有太多區(qū)別。但是在分組团赏、注解地方箕般、嵌套驗證等功能上兩個有所不同:
分組
@Validated:提供了一個分組功能,可以在入?yún)Ⅱ炞C時舔清,根據(jù)不同的分組采用不同的驗證機制丝里,這個網(wǎng)上也有資料,不詳述体谒。@Valid:作為標準JSR-303規(guī)范杯聚,還沒有吸收分組的功能。注解地方
@Validated:可以用在類型抒痒、方法和方法參數(shù)上幌绍。但是不能用在成員屬性(字段)上
@Valid:可以用在方法、構(gòu)造函數(shù)评汰、方法參數(shù)和成員屬性(字段)上
兩者是否能用于成員屬性(字段)上直接影響能否提供嵌套驗證的功能纷捞。
所以可以搭配著用,我習慣是除嵌套驗證的屬性字段上用@Valid被去,其他都用@Validated主儡。
API
JSR提供的校驗注解
@Null 被注釋的元素必須為 null
@NotNull 被注釋的元素必須不為 null
@AssertTrue 被注釋的元素必須為 true
@AssertFalse 被注釋的元素必須為 false
@Min(value) 被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值
@Max(value) 被注釋的元素必須是一個數(shù)字惨缆,其值必須小于等于指定的最大值
@DecimalMin(value) 被注釋的元素必須是一個數(shù)字糜值,其值必須大于等于指定的最小值
@DecimalMax(value) 被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值
@Size(max=, min=) 被注釋的元素的大小必須在指定的范圍內(nèi)
@Digits (integer, fraction) 被注釋的元素必須是一個數(shù)字坯墨,其值必須在可接受的范圍內(nèi)
@Past 被注釋的元素必須是一個過去的日期
@Future 被注釋的元素必須是一個將來的日期
@Pattern(regex=,flag=) 被注釋的元素必須符合指定的正則表達式
-------------------------------------------------------------------------------------------------
Hibernate Validator提供的校驗注解
@NotBlank(message =) 驗證字符串非null寂汇,且長度必須大于0
@Email 被注釋的元素必須是電子郵箱地址
@Length(min=,max=) 被注釋的字符串的大小必須在指定的范圍內(nèi)
@NotEmpty 被注釋的字符串的必須非空
@Range(min=,max=,message=) 被注釋的元素必須在合適的范圍內(nèi)
參考文檔:
https://www.cnblogs.com/itrena/p/8833054.html(繁瑣但是詳細)
https://blog.csdn.net/qq_35703608/article/details/81304608(快速入手)
<--完-->