日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解

瀏覽:113日期:2023-03-22 11:51:24

如果只想查看注解,請?zhí)轿恼履┪膊糠?/b>

簡介

在前后端進行數(shù)據(jù)交互中,在前端把數(shù)據(jù)傳送到后端前,一般會先進行校驗一次,校驗成功之后,才把數(shù)據(jù)發(fā)送到后端。但是我們在服務端還得在對數(shù)據(jù)進行一次校驗。因為請求數(shù)據(jù)發(fā)送的鏈接很容易獲取,可以不經(jīng)過前端界面,使用postman等工具直接向后臺發(fā)送數(shù)據(jù),這就可能造成發(fā)送的數(shù)據(jù)是不合法的情況。

項目創(chuàng)建

首先創(chuàng)建一個springboot項目

使用的springboot版本為:(本文代碼以該版本為準,不同版本springboot,在下面內(nèi)容會出現(xiàn)一些差異

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>

引入如下依賴

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> </dependencies>

這個作標在新一點的springboot版本中,需要單獨引入。在老版本是默認引入的。這個是用來引入對jsr303注解的支持。

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>

接著創(chuàng)建一個Java Bean

package cn.jxj4869.demo.entity;import lombok.Data;import javax.validation.constraints.NotNull;@Datapublic class User { @NotNull private Integer id; private String username; private String password; private String email;}

返回類型的JavaBean

package cn.jxj4869.demo.entity;import java.util.HashMap;public class R extends HashMap<String, Object> {private static final long serialVersionUID = 1L;public R() {put('code', 0);put('msg', 'success');}public static R error(int code, String msg) {R r = new R();r.put('code', code);r.put('msg', msg);return r;}public static R ok(String msg) {R r = new R();r.put('msg', msg);return r;}public R put(String key, Object value) {super.put(key, value);return this;}}

創(chuàng)建一個controller。

index方法用來跳轉(zhuǎn)到首頁。

package cn.jxj4869.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;@Controllerpublic class UserController { @RequestMapping('/') public String index(){ return 'index'; }}

首頁代碼放到resources/templates目錄下

<!DOCTYPE html><html lang='en'><head> <meta charset='UTF-8'> <title>Title</title> <style> div{ margin-top: 50px; } </style></head><body><div> 新增表單 <br><br> <form method='post'> <label>用戶名</label> <input type='text' name='username'/> <br> <label>密碼</label> <input type='text' name='password'/> <br> <label>郵箱</label> <input type='email' name='email'/> <br> <input type='submit' value='提交'/> </form></div><div> 更新表單 <br><br> <form method='post'> <input type='hidden' name='id' value='1'> <label>用戶名</label> <input type='text' name='username'/> <br> <label>密碼</label> <input type='text' name='password'/> <br> <label>郵箱</label> <input type='email' name='email'/> <br> <input type='submit' value='提交'/> </form></div></body></html>傳統(tǒng)的檢驗方式

要在后端進行數(shù)據(jù)校驗,傳統(tǒng)的校驗方式在controller層接受數(shù)據(jù)后,按照要求對數(shù)據(jù)進行校驗

比如要接收一個user bean對象。

現(xiàn)在要對user對象中的username屬性進行非空校驗,password屬性進行非空校驗和長度校驗。

@PostMapping('/user') @ResponseBody public R user1(User user) throws Exception { if(StringUtils.isEmpty(user.getUsername())) { return R.error(400,'username不能為空'); } if(StringUtils.isEmpty(user.getPassword())||user.getPassword().length()>8||user.getPassword().length() <4) { return R.error(400,'password無效'); } return null; }

如果有多個方法都需要接受user對象, 而且要校驗的屬性可能不止username和password這兩個屬性,如果每個方法里面都采用上面這種校驗方式的話,代碼就會很臃腫,而且不好維護,當改變了userbean的屬性,或者對校驗規(guī)則進行修改后,就得對所有的校驗代碼進行更新。 這是一件工程量很大的事。

使用JSR303

為了解決上述問題,我們可以使用JSR303提供的注解進行校驗。

JSR是Java Specification Requests的縮寫,意思是Java 規(guī)范提案。JSR303也就是第303號提案。

使用JSR303的方法很簡單,例如上面的需求,我們只需要在user的屬性上加上注解即可。

步驟如下:

1、給Bean添加校驗注解,一般是在 javax.validation.constraints這個包下,也還有一些是hibernate提供的。

2、開啟校驗功能@Valid。

3、當校驗失敗的時候,會拋出org.springframework.validation.BindException異常。

常用的校驗注解在文末

package cn.jxj4869.demo.entity;import lombok.Data;import org.hibernate.validator.constraints.Length;import javax.validation.constraints.NotNull;@Datapublic class User { private Integer id; @NotBlank private String username; @NotBlank @Length(min = 4,max = 8) private String password; private String email;}

然后在controller里面的方法上,加上@Valid注解即可

@PostMapping('/user2') @ResponseBody public R user2(@Valid User user) throws Exception { System.out.println(user); return null; }

當校驗失敗后,會出現(xiàn)如下錯誤。并且會給出默認的提示信息。

SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解

自定義錯誤信息

那這個錯誤信息是怎么來的呢。

進入@NotNULL注解的代碼里面

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@Repeatable(List.class)@Documented@Constraint(validatedBy = { })public @interface NotBlank {String message() default '{javax.validation.constraints.NotNull.message}';............ ............ ............}

會有一個message屬性。顯然就是指定錯誤的提示內(nèi)容。而這些錯誤提示是在一個叫validationMessages.properties的文件中,用idea的搜索工具可以找到,雙擊shift鍵打開搜索。

發(fā)現(xiàn)有這么多validationMessages.properties的文件,而且支持國際化。

SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解

打開validationMessages_zh.properties,可以看到里面定義了這么多的提示。而錯誤提示就是從這文件中獲取的。

SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解

如果我們不想用默認的校驗提示信息的話,可以自己指定。

指定message的值即可。

@NotBlank(message = '用戶名不能為空') private String username;

SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解

錯誤信息的獲取與響應

當校驗出錯時,會默認返回一個錯誤界面,或者返回錯誤提示的json數(shù)據(jù)。但默認提供的顯然不是我們想要的,如果可以拿到錯誤信息,那我們就能自定義相應數(shù)據(jù)了。

拿到錯誤信息的方式也很簡單,只要在方法中加上BindingResult result這個參數(shù),錯誤信息就會封裝這里面。

@PostMapping('/user2') @ResponseBody public R user2(@Valid User user, BindingResult result) throws Exception { System.out.println(user); if(result.hasErrors()) { //判斷是否有錯誤 Map<String,String> map = new HashMap<>(); //1、獲取校驗的錯誤結(jié)果 result.getFieldErrors().forEach((item)->{ //FieldError 獲取到錯誤提示 String message = item.getDefaultMessage(); //獲取錯誤的屬性的名字 String field = item.getField(); map.put(field,message); }); return R.error(400,'提交的數(shù)據(jù)不合法').put('data',map); } // 若沒有錯誤,則進行接下去的業(yè)務操作。 return null; }

不過不推薦上面這種方式,理由同上,當校驗的地方多了,每個方法里面都加上這么個異常處理,會讓代碼很臃腫。

不知道你們是否還記得,springmvc里面有個全局的異常處理,我們可以自定義一個異常處理,在這里面統(tǒng)一處理異常。

統(tǒng)一處理BinException。這樣就可以不用在controller中去處理錯誤信息了。

package cn.jxj4869.demo.execption;import cn.jxj4869.demo.entity.R;import org.springframework.validation.BindException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.HashMap;import java.util.Map;@RestControllerAdvice(basePackages = 'cn.jxj4869.demo.controller')public class MyExceptionControllerAdvice { @ExceptionHandler(value = BindException.class) public R handleVaildException(BindException e) { Map<String,String> map = new HashMap<>(); //1、獲取校驗的錯誤結(jié)果 e.getFieldErrors().forEach((item)->{ //FieldError 獲取到錯誤提示 String message = item.getDefaultMessage(); //獲取錯誤的屬性的名字 String field = item.getField(); map.put(field,message); }); return R.error(400,'提交的數(shù)據(jù)不合法').put('data',map); }}錯誤異常類型補充

校驗出錯的時候,會拋出兩種異常

org.springframework.validation.BindException

使用@Valid注解進行校驗的時候拋出的

org.springframework.web.bind.MethodArgumentNotValidException

使用@validated校驗的時候拋出的

在異常捕獲中加入下面這個

@ExceptionHandler(value= MethodArgumentNotValidException.class) public R handleVaildException(MethodArgumentNotValidException e){ BindingResult bindingResult = e.getBindingResult(); Map<String,String> map = new HashMap<>(); bindingResult.getFieldErrors().forEach((fieldError)->{ map.put(fieldError.getField(),fieldError.getDefaultMessage()); }); return R.error(400,'提交的數(shù)據(jù)不合法').put('data',map); }分組校驗

在不同業(yè)務場景下,校驗規(guī)則是不一樣的,比如user對象中id這個屬性,在新增的時候,這個屬性是不用填的,要為null,但是在修改的時候,id屬性是不能為null的。

可以用注解中的groups屬性來指定,在什么場合下使用改注解

@Documented@Constraint(validatedBy = { })@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@Repeatable(List.class)public @interface NotBlank {Class<?>[] groups() default { };........}

首先定義兩個接口AddGroup和UpdateGroup,不需要做任何實現(xiàn)

package cn.jxj4869.demo.valid;public interface UpdateGroup {}

package cn.jxj4869.demo.valid;public interface AddGroup {}

在user中指定group。

id屬性在AddGroup的時候,要為null,在UpdateGroup的時候不能為null username屬性在AddGroup和Update的時候,都要進行校驗,不能為空。 password屬性,當校驗的時候指定分組的話,會不起作用,因為沒有給它指定校驗的分組

package cn.jxj4869.demo.entity;import cn.jxj4869.demo.valid.AddGroup;import cn.jxj4869.demo.valid.UpdateGroup;import lombok.Data;import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotEmpty;import javax.validation.constraints.NotNull;import javax.validation.constraints.Null;@Datapublic class User { @Null(groups = {AddGroup.class}) @NotNull(groups = {UpdateGroup.class}) private Integer id; @NotBlank(message = '用戶名不能為空',groups = {AddGroup.class,UpdateGroup.class}) private String username; @NotEmpty private String password; private String email;}

在controller中用@Validated注解,指定校驗的分組

@PostMapping('/user3') @ResponseBody public R user3(@Validated(UpdateGroup.class) User user) { System.out.println(user); return null; }

結(jié)果如下圖所示,因為password屬性沒有指定校驗的分組,所以在校驗的時候,都不會對它進行合法性檢查。

SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解

SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解

自定義校驗

當提供的注解不能滿足我們需求的時候,可以自定義注解。

例如我們現(xiàn)在給user新加一個屬性status,并要求這個屬性的值只能是0或者1。

新建一個@StatusValue注解。

根據(jù)jsr303的規(guī)范,校驗注解得有三個屬性。

message:用來獲取錯誤提示的 groups:指定校驗分組的。 payload:可以自定義一些負載信息

使用@Constraint注解指定該注解的校驗器

package cn.jxj4869.demo.valid;import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;import static java.lang.annotation.ElementType.TYPE_USE;import static java.lang.annotation.RetentionPolicy.RUNTIME;@Documented@Constraint(validatedBy = { StatusValueConstraintValidator.class })@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@interface StatusValue { String message() default '{cn.jxj4869.valid.StatusValue.message}'; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; int[] value() default { };}

自定義校驗器

需要實現(xiàn)ConstraintValidator這個接口,第一個泛型是表示要校驗哪個注解,第二個泛型是要校驗的數(shù)據(jù)的類型。

initialize是初始化方法 isValid校驗方法,判斷是否校驗成功

package cn.jxj4869.demo.valid;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;import java.util.HashSet;import java.util.Set;public class StatusValueConstraintValidator implements ConstraintValidator<StatusValue,Integer> { private Set<Integer> set = new HashSet<>(); //初始化方法 @Override public void initialize(StatusValue constraintAnnotation) { int[] value = constraintAnnotation.value(); for (int val : value) { set.add(val); } } /** * 判斷是否校驗成功 * @param value * @param context * @return */ @Override public boolean isValid(Integer value, ConstraintValidatorContext context) { return set.contains(value); }}

最后在resources目錄下添加一個ValidationMessages.properties文件

用來指定錯誤信息。

cn.jxj4869.valid.StatusValue.message=必須提交指定的值

UserBean

@Datapublic class User { @Null(groups = {AddGroup.class}) @NotNull(groups = {UpdateGroup.class}) private Integer id; @NotBlank(message = '用戶名不能為空',groups = {AddGroup.class,UpdateGroup.class}) private String username; @NotEmpty private String password; private String email; @StatusValue(value = {0,1},groups = {AddGroup.class,UpdateGroup.class}) private Integer status;}

SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解

SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解

常用注解匯總

注解 功能 @Null 對象必須為null @NotNull 對象必須不為null,無法檢查長度為0的字符串 @NotBlank 字符串必須不為Null,且去掉前后空格長度必須大于0 @NotEmpty 字符串必須非空 @Length(min = 1,max = 50) 字符串必須在指定長度內(nèi) @Range(min = 0,max = 100) 必須在指定范圍內(nèi) @AssertTrue 對象必須為true @AssertFalse 對象必須為false @Max(Value) 必須為數(shù)字,且小于或等于Value @Min(Value) 必須為數(shù)字,且大于或等于Value @DecimalMax(Value) 必須為數(shù)字( BigDecimal ),且小于或等于Value。小數(shù)存在精度 @DecimalMin(Value) 必須為數(shù)字( BigDecimal ),且大于或等于Value。小數(shù)存在精度 @Digits(integer,fraction) 必須為數(shù)字( BigDecimal ),integer整數(shù)精度,fraction小數(shù)精度 @Size(min,max) 對象(Array、Collection、Map、String)長度必須在給定范圍 @Email 字符串必須是合法郵件地址 @Past Date和Calendar對象必須在當前時間之前 @Future Date和Calendar對象必須在當前時間之后 @Pattern(regexp=“正則”) 字符串滿足正則表達式的值

到此這篇關(guān)于SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)校驗JSR303的使用內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標簽: Spring
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美亚洲日本精品| 亚洲午夜一级| 综合一区在线| 亚洲精品123区| 亚洲国产成人二区| 神马久久午夜| 久久九九国产| 亚洲国产一区二区在线观看| 五月精品视频| 久久亚洲欧美| 中文字幕一区日韩精品| 一区二区日韩免费看| 日韩一区二区三区高清在线观看| 亚洲图片久久| 91精品啪在线观看国产爱臀| 国产亚洲观看| 老司机精品视频在线播放| 国产伊人久久| 日本精品在线中文字幕| 欧美成a人免费观看久久| 99精品小视频| 亚洲欧美日韩视频二区| 日韩一区网站| 国产剧情在线观看一区| 精品国产中文字幕第一页| 91日韩欧美| 欧美精品一卡| 日本亚洲视频| 久久伊人亚洲| 在线日韩av| 四虎国产精品免费久久| 国产精品资源| 亚洲黄色免费看| 香蕉久久夜色精品国产| 伊人www22综合色| 国产精品第一国产精品| 丝袜诱惑一区二区| 玖玖玖国产精品| 国产精品欧美大片| 成人美女视频| 免费看日韩精品| 另类小说一区二区三区| 婷婷精品进入| 国产精品亚洲欧美| 日韩精品影视| 日韩二区三区四区| 亚洲成av在线| 久久狠狠久久| 91精品一区二区三区综合| 奶水喷射视频一区| 欧美精品99| 亚洲激情婷婷| 久久精品一本| 老色鬼久久亚洲一区二区| 国产精品一区免费在线| 激情视频一区二区三区| 国产亚洲精品美女久久| 日韩精品网站| 国产毛片久久久| 黄色精品网站| 精品久久久久中文字幕小说| 亚洲精品午夜av福利久久蜜桃| 国产一区 二区| 精品在线99| 欧美亚洲综合视频| 欧美日韩中文一区二区| 亚洲乱亚洲高清| 日韩成人亚洲| 国产精品.xx视频.xxtv| 欧美1区2区3区| 国产精品宾馆| 免费在线观看一区二区三区| 精品美女在线视频| 日韩在线一二三区| 成人精品亚洲| 你懂的亚洲视频| 亚洲精品韩国| 欧美99久久| 成人一区而且| 亚洲精品动态| 欧美亚洲精品在线| 精品久久美女| 国产欧美大片| 亚洲精品无播放器在线播放| 久久蜜桃av| 福利一区视频| 欧美日韩亚洲一区在线观看| 中文一区在线| 99久精品视频在线观看视频| 国内精品美女在线观看| 欧美欧美黄在线二区| 午夜一级在线看亚洲| 欧美不卡高清一区二区三区| 美女视频黄免费的久久| 国产一区成人| 91精品精品| 樱桃视频成人在线观看| 久久亚洲道色| 日韩精品一级| 天堂成人免费av电影一区| 国产精品99一区二区| sm久久捆绑调教精品一区| 国产精品久久久久久久免费软件| 在线观看一区| 狠狠操综合网| 亚洲午夜黄色| 999国产精品视频| 日韩影院二区| 日韩av在线中文字幕| 国产精品免费99久久久| 日本在线观看不卡视频| 亚洲深深色噜噜狠狠爱网站| 国产免费成人| 最新日韩av| 性欧美69xoxoxoxo| 久久视频精品| 久久久久蜜桃| 日韩黄色大片网站| av最新在线| 成人免费网站www网站高清| 高清日韩欧美| 日产精品一区| 91精品一区二区三区综合在线爱| 日韩精品一区二区三区免费观影 | 日本免费久久| 成人日韩精品| 国产精品av一区二区| 亚洲午夜电影| 99亚洲精品| 波多野结衣一区| 国产午夜精品一区二区三区欧美 | 欧美va天堂在线| 午夜久久影院| 免费观看在线色综合| 亚州av一区| 欧美亚洲自偷自偷| 国产精品久久久久久妇女| 久久亚洲道色| 夜鲁夜鲁夜鲁视频在线播放| 久久免费高清| 国产偷自视频区视频一区二区| 免费视频最近日韩| 久久黄色影视| 都市激情国产精品| 91精品国产乱码久久久久久久| 亚洲深夜影院| 日本一区二区三区视频在线看 | 日本蜜桃在线观看视频| 亚洲a在线视频| 一本色道久久精品| 日本国产一区| 国产精品嫩草影院在线看| 国产不卡av一区二区| 综合色就爱涩涩涩综合婷婷| 国产欧美精品久久| 伊人久久国产| 丝袜a∨在线一区二区三区不卡| 日韩午夜视频在线| 黄色精品视频| 欧美日韩国产综合网| 国产亚洲欧美日韩精品一区二区三区 | 欧美特黄一区| 亚洲三级国产| 久久久免费人体| 欧美日韩一区二区三区视频播放| 亚洲伊人精品酒店| 久久精品国产99| 日韩国产在线| 亚洲一二av| 黄色aa久久| 视频一区免费在线观看| 国产精品15p| 亚洲成人一区| 国产亚洲一区| 99精品一区| 欧美亚洲三级| 日韩精品免费一区二区三区| 免费在线观看一区二区三区| 精品国产乱码久久久| 伊人精品视频| 国产精品久久久久77777丨| 99成人在线视频| 亚州国产精品| 国产99久久久国产精品成人免费| 日韩精彩视频在线观看| 中文字幕在线视频久| 一区二区国产在线| 91欧美日韩| 91麻豆精品| 欧美在线网站| 久久精品系列| 亚洲精品极品| 久久久精品五月天| 欧美日韩1区| 在线精品视频在线观看高清| 国产精品草草| 亚洲日本免费电影| 亲子伦视频一区二区三区| 国产精品极品| 亚洲精品乱码久久久久久蜜桃麻豆 |