成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

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

Spring Boot利用JSR303實(shí)現(xiàn)參數(shù)驗(yàn)證的方法實(shí)例

瀏覽:110日期:2023-05-16 18:04:49

簡介

JSR-303 是 JAVA EE 6 中的一項(xiàng)子規(guī)范,叫做 Bean Validation。

在任何時(shí)候,當(dāng)你要處理一個(gè)應(yīng)用程序的業(yè)務(wù)邏輯,數(shù)據(jù)校驗(yàn)是你必須要考慮和面對的事情。應(yīng)用程序必須通過某種手段來確保輸入進(jìn)來的數(shù)據(jù)從語義上來講是正確的。在通常的情況下,應(yīng)用程序是分層的,不同的層由不同的開發(fā)人員來完成。很多時(shí)候同樣的數(shù)據(jù)驗(yàn)證邏輯會出現(xiàn)在不同的層,這樣就會導(dǎo)致代碼冗余和一些管理的問題,比如說語義的一致性等。為了避免這樣的情況發(fā)生,最好是將驗(yàn)證邏輯與相應(yīng)的域模型進(jìn)行綁定。

Bean Validation 為 JavaBean 驗(yàn)證定義了相應(yīng)的元數(shù)據(jù)模型和 API。缺省的元數(shù)據(jù)是 Java Annotations,通過使用 XML 可以對原有的元數(shù)據(jù)信息進(jìn)行覆蓋和擴(kuò)展。在應(yīng)用程序中,通過使用 Bean Validation 或是你自己定義的 constraint,例如 @NotNull, @Max, @ZipCode, 就可以確保數(shù)據(jù)模型(JavaBean)的正確性。constraint 可以附加到字段,getter 方法,類或者接口上面。對于一些特定的需求,用戶可以很容易的開發(fā)定制化的 constraint。Bean Validation 是一個(gè)運(yùn)行時(shí)的數(shù)據(jù)驗(yàn)證框架,在驗(yàn)證之后驗(yàn)證的錯(cuò)誤信息會被馬上返回。

Bean Validation 規(guī)范內(nèi)嵌的約束注解

Spring Boot利用JSR303實(shí)現(xiàn)參數(shù)驗(yàn)證的方法實(shí)例

實(shí)例

基本應(yīng)用

引入依賴

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

給參數(shù)對象添加校驗(yàn)注解

@Datapublic class User { private Integer id; @NotBlank(message = '用戶名不能為空') private String username; @Pattern(regexp = '^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$', message = '密碼必須為8~16個(gè)字母和數(shù)字組合') private String password; @Email private String email; private Integer gender;}

Controller 中需要校驗(yàn)的參數(shù)Bean前添加 @Valid 開啟校驗(yàn)功能,緊跟在校驗(yàn)的Bean后添加一個(gè)BindingResult,BindingResult封裝了前面Bean的校驗(yàn)結(jié)果。

@RestController@RequestMapping('/user')public class UserController { @PostMapping('') public Result save (@Valid User user , BindingResult bindingResult) { if (bindingResult.hasErrors()) { Map<String , String> map = new HashMap<>(); bindingResult.getFieldErrors().forEach( (item) -> { String message = item.getDefaultMessage(); String field = item.getField(); map.put( field , message ); } ); return Result.build( 400 , '非法參數(shù) !' , map); } return Result.ok(); }}

測試如下:

Spring Boot利用JSR303實(shí)現(xiàn)參數(shù)驗(yàn)證的方法實(shí)例

異常的統(tǒng)一處理

參數(shù)校驗(yàn)不通過時(shí),會拋出 BingBindException 異常,可以在統(tǒng)一異常處理中,做統(tǒng)一處理,這樣就不用在每個(gè)需要參數(shù)校驗(yàn)的地方都用 BindingResult 獲取校驗(yàn)結(jié)果了。

@Slf4j@RestControllerAdvice(basePackages = 'com.itwolfed.controller')public class GlobalExceptionControllerAdvice { @ExceptionHandler(value= {MethodArgumentNotValidException.class , BindException.class}) public Result handleVaildException(Exception e){ BindingResult bindingResult = null; if (e instanceof MethodArgumentNotValidException) { bindingResult = ((MethodArgumentNotValidException)e).getBindingResult(); } else if (e instanceof BindException) { bindingResult = ((BindException)e).getBindingResult(); } Map<String,String> errorMap = new HashMap<>(16); bindingResult.getFieldErrors().forEach((fieldError)-> errorMap.put(fieldError.getField(),fieldError.getDefaultMessage()) ); return Result.build(400 , '非法參數(shù) !' , errorMap); }}

分組解決校驗(yàn)

新增和修改對于實(shí)體的校驗(yàn)規(guī)則是不同的,例如id是自增的時(shí)候,新增時(shí)id要為空,修改則必須不為空;新增和修改,若用的恰好又是同一種實(shí)體,那就需要用到分組校驗(yàn)。

校驗(yàn)注解都有一個(gè)groups屬性,可以將校驗(yàn)注解分組,我們看下@NotNull的源碼:

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@Repeatable(List.class)@Documented@Constraint(validatedBy = { })public @interface NotNull { String message() default '{javax.validation.constraints.NotNull.message}'; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) @Documented @interface List { NotNull[] value(); }}

從源碼可以看出 groups 是一個(gè)Class<?>類型的數(shù)組,那么就可以創(chuàng)建一個(gè)Groups.

public class Groups { public interface Add{} public interface Update{}}

給參數(shù)對象的校驗(yàn)注解添加分組

@Datapublic class User { @Null(message = '新增不需要指定id' , groups = Groups.Add.class) @NotNull(message = '修改需要指定id' , groups = Groups.Update.class) private Integer id; @NotBlank(message = '用戶名不能為空') @NotNull private String username; @Pattern(regexp = '^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$', message = '密碼必須為8~16個(gè)字母和數(shù)字組合') private String password; @Email private String email; private Integer gender;}

Controller 中原先的@Valid不能指定分組 ,需要替換成@Validated

@RestController@RequestMapping('/user')public class UserController { @PostMapping('') public Result save (@Validated(Groups.Add.class) User user) { return Result.ok(); }}

測試如下:

Spring Boot利用JSR303實(shí)現(xiàn)參數(shù)驗(yàn)證的方法實(shí)例

自定義校驗(yàn)注解

雖然JSR303和springboot-validator 已經(jīng)提供了很多校驗(yàn)注解,但是當(dāng)面對復(fù)雜參數(shù)校驗(yàn)時(shí),還是不能滿足我們的要求,這時(shí)候我們就需要 自定義校驗(yàn)注解。

例如User中的gender,用 1代表男 2代表女,我們自定義一個(gè)校驗(yàn)注解@ListValue,指定取值只能1和2。

創(chuàng)建約束規(guī)則

@Documented@Constraint(validatedBy = { ListValueConstraintValidator.class })@Target({ METHOD, FIELD, ANNOTATION_TYPE })@Retention(RUNTIME)public @interface ListValue { String message() default ''; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; int[] vals() default { };}

一個(gè)標(biāo)注(annotation) 是通過@interface關(guān)鍵字來定義的. 這個(gè)標(biāo)注中的屬性是聲明成類似方法 的樣式的. 根據(jù)Bean Validation API 規(guī)范的要求:

message屬性, 這個(gè)屬性被用來定義默認(rèn)得消息模版, 當(dāng)這個(gè)約束條件被驗(yàn)證失敗的時(shí)候,通過 此屬性來輸出錯(cuò)誤信息。 groups 屬性, 用于指定這個(gè)約束條件屬于哪(些)個(gè)校驗(yàn)組. 這個(gè)的默認(rèn)值必須是Class<?>類型數(shù)組。 payload 屬性, Bean Validation API 的使用者可以通過此屬性來給約束條件指定嚴(yán)重級別. 這個(gè)屬性并不被API自身所使用。

除了這三個(gè)強(qiáng)制性要求的屬性(message, groups 和 payload) 之外, 我們還添 加了一個(gè)屬性用來指定所要求的值. 此屬性的名稱vals在annotation的定義中比較特 殊, 如果只有這個(gè)屬性被賦值了的話, 那么, 在使用此annotation到時(shí)候可以忽略此屬性名稱.

另外, 我們還給這個(gè)annotation標(biāo)注了一些元標(biāo)注( meta annotatioins):

@Target({ METHOD, FIELD, ANNOTATION_TYPE }): 表示此注解可以被用在方法, 字段或者 annotation聲明上。 @Retention(RUNTIME): 表示這個(gè)標(biāo)注信息是在運(yùn)行期通過反射被讀取的. @Constraint(validatedBy = ListValueConstraintValidator.class): 指明使用哪個(gè)校驗(yàn)器(類) 去校驗(yàn)使用了此標(biāo)注的元素. @Documented: 表示在對使用了該注解的類進(jìn)行javadoc操作到時(shí)候, 這個(gè)標(biāo)注會被添加到 javadoc當(dāng)中.

創(chuàng)建約束校驗(yàn)器

import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;import java.util.HashSet;import java.util.Set;public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> { private Set<Integer> set = new HashSet<>(); /** * 初始化方法 */ @Override public void initialize(ListValue constraintAnnotation) { int[] vals = constraintAnnotation.vals(); for (int val : vals) { set.add(val); } } /** * 判斷是否校驗(yàn)成功 * * @param value 需要校驗(yàn)的值 * @param context * @return */ @Override public boolean isValid(Integer value, ConstraintValidatorContext context) { return set.contains(value); }}

ListValueConstraintValidator定義了兩個(gè)泛型參數(shù), 第一個(gè)是這個(gè)校驗(yàn)器所服務(wù)到標(biāo)注類型(在我們的例子中即ListValue), 第二個(gè)這個(gè)校驗(yàn)器所支持到被校驗(yàn)元素的類型 (即Integer)。

如果一個(gè)約束標(biāo)注支持多種類型的被校驗(yàn)元素的話, 那么需要為每個(gè)所支持的類型定義一個(gè)ConstraintValidator,并且注冊到約束標(biāo)注中。

這個(gè)驗(yàn)證器的實(shí)現(xiàn)就很平常了, initialize() 方法傳進(jìn)來一個(gè)所要驗(yàn)證的標(biāo)注類型的實(shí)例, 在本 例中, 我們通過此實(shí)例來獲取其vals屬性的值,并將其保存為Set集合中供下一步使 用。

isValid()是實(shí)現(xiàn)真正的校驗(yàn)邏輯的地方, 判斷一個(gè)給定的int對于@ListValue這個(gè)約束條件來說 是否是合法的。

在參數(shù)對象中使用@ListValue注解。

@Datapublic class User { @Null(message = '新增不需要指定id' , groups = Groups.Add.class) @NotNull(message = '修改需要指定id' , groups = Groups.Update.class) private Integer id; @NotBlank(message = '用戶名不能為空') @NotNull private String username; @Pattern(regexp = '^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$', message = '密碼必須為8~16個(gè)字母和數(shù)字組合') private String password; @Email private String email; @ListValue( message = '性別應(yīng)指定相應(yīng)的值' , vals = {1,2} , groups = {Groups.Add.class , Groups.Update.class}) private Integer gender;}

測試如下:

Spring Boot利用JSR303實(shí)現(xiàn)參數(shù)驗(yàn)證的方法實(shí)例

源碼地址

https://github.com/gf-huanchupk/SpringBootLearning

參考

https://www.ibm.com/developerworks/cn/java/j-lo-jsr303/index.html https://docs.jboss.org/hibernate/validator/4.3/reference/zh-CN/pdf/hibernate validator reference.pdf

總結(jié)

到此這篇關(guān)于Spring Boot利用JSR303實(shí)現(xiàn)參數(shù)驗(yàn)證的文章就介紹到這了,更多相關(guān)Spring Boot用JSR303參數(shù)驗(yàn)證內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
欧美色电影在线| 99热国产精品| 波多野洁衣一区| 欧美日韩国产电影| 首页欧美精品中文字幕| 在线精品亚洲一区二区| 久久亚洲精品小早川怜子| 成人精品高清在线| 91精品国产综合久久久蜜臀粉嫩 | 在线成人国产| ww久久中文字幕| 97se亚洲国产综合自在线不卡 | 国产一区视频导航| 欧美亚洲免费高清在线观看| 中文字幕日韩一区二区| 91在线观看免费视频| 亚洲一区精彩视频| 亚洲大片在线观看| 色菇凉天天综合网| 日韩激情中文字幕| 欧美午夜一区二区三区 | 欧美成人三级在线| 成人午夜激情影院| 日韩写真欧美这视频| 九色综合狠狠综合久久| 欧美探花视频资源| 黑人巨大精品欧美黑白配亚洲| 亚洲黄色天堂| 亚洲欧美另类久久久精品2019| 国产精品一区二区无线| 欧美精品一二三区| 国产精品亚洲午夜一区二区三区 | 亚洲精品在线免费播放| 久久精品五月| 美女网站视频久久| 欧美精品亚洲二区| 成人免费电影视频| 国产欧美日韩三区| 亚洲黑丝一区二区| 婷婷中文字幕综合| 欧美视频在线一区| 国产成人一级电影| 精品成人一区二区| 91视频观看视频| 国产精品高潮呻吟| 亚洲在线视频| 国产在线视频一区二区| 日韩欧美不卡在线观看视频| 欧美激情第二页| 亚洲黄色性网站| 久久国产精品第一页| 精品播放一区二区| 在线精品一区二区| 夜夜操天天操亚洲| 中文乱码免费一区二区| 亚洲欧美成人一区二区三区| 欧美性猛片aaaaaaa做受| 成人在线综合网| 一区二区三区免费网站| 欧美精品亚洲二区| 在线观看亚洲视频啊啊啊啊| 免费高清在线视频一区·| 精品一区二区三区欧美| 欧美精品第一页| 亚洲人体一区| 国产mv日韩mv欧美| 肉丝袜脚交视频一区二区| 51精品久久久久久久蜜臀| 欧美日韩一区二区视频在线观看| 亚洲一区三区在线观看| 欧美三级特黄| 视频一区中文字幕国产| 欧美日韩一级二级三级| 91美女视频网站| 日韩成人精品视频| 一区二区欧美国产| 亚洲高清久久久| 91久久精品一区二区别| 久久精品国产99| 日韩综合小视频| 欧美美女一区二区| 成人午夜私人影院| 日韩美女久久久| 欧美在线|欧美| 欧美在线网址| 日韩1区2区日韩1区2区| 精品日本一线二线三线不卡| 亚洲天堂偷拍| 久久国产三级精品| 中文一区一区三区高中清不卡| 久久精品国产一区二区| 日韩欧美你懂的| 亚洲欧洲精品一区二区三区波多野1战4 | 欧美丰满少妇xxxbbb| 色综合久久综合网| 香蕉加勒比综合久久| 久久久777精品电影网影网 | 天天综合色天天| 7777精品伊人久久久大香线蕉完整版 | 日韩欧美精品三级| 亚洲高清资源综合久久精品| 久久aⅴ国产欧美74aaa| 国产精品欧美一区喷水| 精品污污网站免费看| 欧美午夜视频在线| 久久99精品久久久久久动态图| 欧美日韩精品一区二区在线播放| 日本免费在线视频不卡一不卡二| 色综合激情五月| 91女厕偷拍女厕偷拍高清| 午夜欧美在线一二页| 精品国产乱码久久久久久图片 | 久久国产精品99久久人人澡| 久久综合久色欧美综合狠狠| 亚洲美女啪啪| 春色校园综合激情亚洲| 久久婷婷一区二区三区| 狂野欧美性猛交xxxx巴西| 91亚洲永久精品| 久久精品国产久精国产爱| 亚洲女同一区二区| 精品va天堂亚洲国产| 在线视频欧美精品| 日韩视频在线播放 | 你懂的视频一区二区| 性做久久久久久免费观看| 久久久久久久av麻豆果冻| 久久一区中文字幕| 99久久婷婷国产综合精品电影 | 久久疯狂做爰流白浆xx| 国产日产欧美一区| 91精品蜜臀在线一区尤物| 色婷婷亚洲一区二区三区| 亚洲精品视频一区二区三区 | 日韩一区二区在线看片| 激情综合网址| 99国产精品视频免费观看| 国产一区二区三区黄视频| 日韩精品欧美精品| 亚洲自拍偷拍网站| 亚洲色图在线看| 欧美激情综合五月色丁香小说| 亚洲综合二区| 亚洲激情在线| 国产一区二区无遮挡| 91婷婷韩国欧美一区二区| 国产福利一区二区三区在线视频| 国产三级精品三级在线专区| 欧美日韩精品一区二区三区| 亚洲一区二区免费看| 亚洲成人手机在线| 亚洲一区欧美一区| 亚洲欧美日韩系列| 中文字幕亚洲不卡| 亚洲国产精品av| 欧美日韩国语| 欧美日韩视频一区二区三区| 99国产精品久| 99免费精品视频| 99视频精品全部免费在线| 国产成人精品影院| 国产乱码精品1区2区3区| 看电视剧不卡顿的网站| 日本不卡的三区四区五区| 丝袜亚洲精品中文字幕一区| 亚洲一二三专区| 一区二区三区不卡视频在线观看| 欧美高清你懂得| 欧美亚洲国产一卡| 欧美三区免费完整视频在线观看| 伊人色综合久久天天五月婷| 欧美激情综合| 99re热这里只有精品视频| 91视频国产观看| 欧美日韩另类丝袜其他| 欧美私人啪啪vps| 亚洲午夜精品福利| 一本色道婷婷久久欧美| 亚洲一区二区三区高清不卡| 麻豆av福利av久久av| 色吊一区二区三区| 欧美裸体一区二区三区| 91精品国产综合久久久蜜臀粉嫩| 亚洲一区欧美激情| 国产精品亚洲欧美| 久久久久久久波多野高潮日日| 91网站在线播放| 色综合咪咪久久| 伊人久久婷婷色综合98网| 一区二区三区欧美在线| 99视频精品| 久久九九电影| 欧美三区在线视频| 精品日韩99亚洲| 国产精品私人影院| 亚洲一区视频在线观看视频| 日本不卡的三区四区五区| 精品一区二区三区蜜桃| 国产 日韩 欧美大片| 欧美日本二区|