日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用Hibernate-Validator优雅的验证RESTful Web Services的参数

發布時間:2024/4/14 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Hibernate-Validator优雅的验证RESTful Web Services的参数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

何為Hibernate-Validator

在RESTful Web Services的接口服務中,會有各種各樣的入參,我們不可能完全不做任何校驗就直接進入到業務處理的環節,通常我們會有一個基礎的數據驗證的機制,待這些驗證過程完畢,結果無誤后,參數才會進入到正式的業務處理中。而數據驗證又分為兩種,一種是無業務關聯的規則性驗證,一種是根據現有數據進行的聯動性數據驗證(簡單來說,參數的合理性,需要查數據庫)。而Hibernate-Validator則適合做無業務關聯的規則性驗證。

Hibernate-Validator的相關依賴

如果項目的框架是spring boot的話,在spring-boot-starter-web 中已經包含了Hibernate-validator的依賴,我們點開spring-boot-starter-web的pom.xml則可以看到相關的依賴內容。

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starters</artifactId><version>1.5.10.RELEASE</version></parent><artifactId>spring-boot-starter-web</artifactId><name>Spring Boot Web Starter</name><description>Starter for building web, including RESTful, applications using SpringMVC. Uses Tomcat as the default embedded container</description><url>http://projects.spring.io/spring-boot/</url><organization><name>Pivotal Software, Inc.</name><url>http://www.spring.io</url></organization><properties><main.basedir>${basedir}/../..</main.basedir></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency></dependencies> 復制代碼

如果是其他的框架風格的話,引入如下的依賴就可以了。

<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>6.0.10.Final</version> </dependency> 復制代碼

初步使用Hibernate-Validator

以下代碼環境均在Spring boot 1.5.10的版本下運行。

Hibernate-Validator的主要使用的方式就是注解的形式,并且是“零配置”的,無需配置也可以使用。下面用一個最簡單的案例。

  • Hibernate-Validator 最基本的使用

    1.添加一個普通的接口信息,參數是@RequestParam類型的,傳入的參數是id,且id不能小于10。

@RestController @RequestMapping("/example") @Validated public class ExampleController {/*** 用于測試* @param id id數不能小于10 @RequestParam類型的參數需要在Controller上增加@Validated* @return*/@RequestMapping(value = "/info",method = RequestMethod.GET)public String test(@Min(value = 10, message = "id最小只能是10") @RequestParam("id")Integer id){return "恭喜你拿到參數了";} } 復制代碼

2.在全局異常攔截中添加驗證異常的處理

@Slf4j @ControllerAdvice @Component public class GlobalExceptionHandler {@ExceptionHandler@ResponseBody@ResponseStatus(HttpStatus.BAD_REQUEST)public String handle(ConstraintViolationException exception, HttpServletRequest request) {Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();StringBuffer errorInfo = new StringBuffer();for (ConstraintViolation<?> item : violations) {/**打印驗證不通過的信息*/errorInfo.append(item.getMessage());errorInfo.append(",");}log.error("{}接口參數驗證失敗,內容如下:{}",request.getRequestURI(),errorInfo.toString());return "您的請求失敗,參數驗證失敗,失敗信息如下:"+ errorInfo.toString();} } 復制代碼

3.一個簡單的測試。

  • 驗證復雜參數的案例

    1.添加一個vo的實體信息。

/*** 用戶的vo類* @author dengyun*/ @Data public class ExampleVo {@NotBlank(message = "用戶名不能為空")private String userName;@Range(min = 18,max = 60,message = "只能填報年齡在18~60歲的")private String age; }復制代碼

2.添加一個POST請求的接口。

/*** 用于測試* @param vo 按照vo的驗證* @return*/@RequestMapping(value = "/info1",method = RequestMethod.POST)public String test1(@Valid @RequestBody ExampleVo vo){return "恭喜你拿到參數了";} 復制代碼

3.在全局異常攔截中添加驗證處理的結果

@ResponseBody@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(MethodArgumentNotValidException.class)public String handle(MethodArgumentNotValidException exception,HttpServletRequest request) {StringBuffer errorInfo=new StringBuffer();List<ObjectError> errors = exception.getBindingResult().getAllErrors();for(int i=0;i<errors.size();i++){errorInfo.append(errors.get(i).getDefaultMessage()+",");}log.error("{},接口參數驗證失敗:{}",request,errorInfo.toString());return "您的請求失敗,參數驗證失敗,失敗信息如下:"+errorInfo.toString();} 復制代碼

4.一個簡單的測試

我個人比較推薦使用全局異常攔截處理的方式去處理Hibernate-Validator的驗證失敗后的處理流程,這樣能能減少Controller層或Services層的代碼邏輯處理。雖然它也能在Controller中增加BindingResult的實例來獲取數據,但是并不推薦。

更加靈活的運用

首先列舉一下Hibernate-Validator所有的內置驗證注解。

@Null 被注釋的元素必須為 null
@NotNull 被注釋的元素必須不為 null
@AssertTrue 被注釋的元素必須為 true
@AssertFalse 被注釋的元素必須為 false
@Min(value) 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值 @Max(value) 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值 @DecimalMin(value) 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值
@DecimalMax(value) 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值
@Size(max=, min=) 被注釋的元素的大小必須在指定的范圍內
@Digits (integer, fraction) 被注釋的元素必須是一個數字,其值必須在可接受的范圍內
@Past 被注釋的元素必須是一個過去的日期
@Future 被注釋的元素必須是一個將來的日期
@Pattern(regex=,flag=) 被注釋的元素必須符合指定的正則表達式
Hibernate Validator 附加的 constraint
@NotBlank(message =) 驗證字符串非null,且長度必須大于0
@Email 被注釋的元素必須是電子郵箱地址
@Length(min=,max=) 被注釋的字符串的大小必須在指定的范圍內
@NotEmpty 被注釋的字符串的必須非空
@Range(min=,max=,message=) 被注釋的元素必須在合適的范圍內

這些注解能適應我們絕大多數的驗證場景,但是為了應對更多的可能性,我們需要增加注解功能配合Hibernate-Validator的其他的特性,來滿足驗證的需求。

1. 自定義注解

  • 添加自定義注解

我們一定會用到這么一個業務場景,vo中的屬性必須符合枚舉類中的枚舉。Hibernate-Validator中還沒有關于枚舉的驗證規則,那么,我們則需要自定義一個枚舉的驗證注解。

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = EnumCheckValidator.class) public @interface EnumCheck {/*** 是否必填 默認是必填的* @return*/boolean required() default true;/*** 驗證失敗的消息* @return*/String message() default "枚舉的驗證失敗";/*** 分組的內容* @return*/Class<?>[] groups() default {};/*** 錯誤驗證的級別* @return*/Class<? extends Payload>[] payload() default {};/*** 枚舉的Class* @return*/Class<? extends Enum<?>> enumClass();/*** 枚舉中的驗證方法* @return*/String enumMethod() default "validation"; } 復制代碼
  • 注解的業務邏輯實現類
public class EnumCheckValidator implements ConstraintValidator<EnumCheck,Object> {private EnumCheck enumCheck;@Overridepublic void initialize(EnumCheck enumCheck) {this.enumCheck =enumCheck;}@Overridepublic boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {// 注解表明為必選項 則不允許為空,否則可以為空if (value == null) {return this.enumCheck.required()?false:true;}//最終的返回結果Boolean result=Boolean.FALSE;// 獲取 參數的數據類型Class<?> valueClass = value.getClass();try {Method method = this.enumCheck.enumClass().getMethod(this.enumCheck.enumMethod(), valueClass);result = (Boolean)method.invoke(null, value);result= result == null ? false : result;//所有異常需要在開發測試階段發現完畢} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}finally {return result;}} }復制代碼
  • 編寫枚舉類
public enum Sex{MAN("男",1),WOMAN("女",2);private String label;private Integer value;public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}Sex(String label, int value) {this.label = label;this.value = value;}/*** 判斷值是否滿足枚舉中的value* @param value* @return*/public static boolean validation(Integer value){for(Sex s:Sex.values()){if(Objects.equals(s.getValue(),value)){return true;}}return false;} } 復制代碼
  • 使用方式
@EnumCheck(message = "只能選男:1或女:2",enumClass = Sex.class)private Integer sex; 復制代碼
  • 一個簡單的測試

我們甚至可以在自定義注解中做更加靈活的處理,甚至把與數據庫的數據校驗的也寫成自定義注解,來進行數據驗證的調用。

2. Hibernate-Validator的分組驗證

同一個校驗規則,不可能適用于所有的業務場景,對此,對每一個業務場景去編寫一個校驗規則,又顯得特別冗余。這里我們剛好可以用到Hibernate-Validator的分組功能。

  • 添加一個名為ValidGroupA的接口(接口內容可以是空的,所以就不列舉代碼)
  • 添加一個需要分組校驗的字段
@Data public class ExampleVo {@NotNull(message = "主鍵不允許為空",groups = ValidGroupA.class)private Integer id;@NotBlank(message = "用戶名不能為空",groups = Default.class)private String userName;@Range(min = 18,max = 60,message = "只能填報年齡在18~60歲的",groups = Default.class)private String age;@EnumCheck(message = "只能選男:1或女:2",enumClass = Sex.class,groups = Default.class)private Integer sex; } 復制代碼
  • 改動接口的內容
@RequestMapping(value = "/info1",method = RequestMethod.POST)public String test1(@Validated({ValidGroupA.class,Default.class}) @RequestBody ExampleVo vo){return "恭喜你拿到參數了";} 復制代碼

這里我們可以注意一下,校驗的注解由 @Valid 改成了 @Validated

  • 進行測試,保留ValidGroupA.class和去掉ValidGroupA.class的測試。

    • 保留ValidGroupA.class

    • 去掉ValidGroupA.class

使用分組能極大的復用需要驗證的類信息。而不是按業務重復編寫冗余的類。然而Hibernate-Validator還提供組序列的形式進行順序式校驗,此處就不重復列舉了。我認為順序化的校驗,場景更多的是在業務處理類,例如聯動的屬性驗證,值的有效性很大程度上不能從代碼的枚舉或常量類中來校驗。

部分引用及參考的文章

  • springboot使用hibernate- validator校驗

總結

以上是生活随笔為你收集整理的使用Hibernate-Validator优雅的验证RESTful Web Services的参数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。