`
freeroy
  • 浏览: 74540 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

JSR 303 - Bean Validation 介绍及最佳实践 【转】

    博客分类:
  • Java
阅读更多

原文链接:http://www.ibm.com/developerworks/cn/java/j-lo-jsr303/index.html

 

 

关于 Bean Validation

在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情。应用程序必须通过某种手段来确保输入进来的数据从语 义上来讲是正确的。在通常的情况下,应用程序是分层的,不同的层由不同的开发人员来完成。很多时候同样的数据验证逻辑会出现在不同的层,这样就会导致代码 冗余和一些管理的问题,比如说语义的一致性等。为了避免这样的情况发生,最好是将验证逻辑与相应的域模型进行绑定。

Bean Validation 为 JavaBean 验证定义了相应的元数据模型和 API。缺省的元数据是 Java Annotations,通过使用 XML 可以对原有的元数据信息进行覆盖和扩展。在应用程序中,通过使用 Bean Validation 或是你自己定义的 constraint,例如 @NotNull , @Max , @ZipCode , 就可以确保数据模型(JavaBean)的正确性。constraint 可以附加到字段,getter 方法,类或者接口上面。对于一些特定的需求,用户可以很容易的开发定制化的 constraint。Bean Validation 是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回。

下载 JSR 303 – Bean Validation 规范 http://jcp.org/en/jsr/detail?id=303

Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。如果想了解更多有关 Hibernate Validator 的信息,请查看 http://www.hibernate.org/subprojects/validator.html

Bean Validation 中的 constraint


表 1. Bean Validation 中内置的 constraint

Constraint详细信息
@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(value) 被注释的元素必须符合指定的正则表达式



表 2. Hibernate Validator 附加的 constraint

Constraint详细信息
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内

 

一个 constraint 通常由 annotation 和相应的 constraint validator 组成,它们是一对多的关系。也就是说可以有多个 constraint validator 对应一个 annotation。在运行时,Bean Validation 框架本身会根据被注释元素的类型来选择合适的 constraint validator 对数据进行验证。

有些时候,在用户的应用中需要一些更复杂的 constraint。Bean Validation 提供扩展 constraint 的机制。可以通过两种方法去实现,一种是组合现有的 constraint 来生成一个更复杂的 constraint,另外一种是开发一个全新的 constraint。

创建一个包含验证逻辑的简单应用(基于 JSP)

在本文中,通过创建一个虚构的订单管理系统(基于 JSP 的 web 应用)来演示如何在 Java 开发过程中应用 Bean Validation。该简化的系统可以让用户创建和检索订单。

系统设计和运用的技术


图 1. 系统架构
图 1. 系统架构

图 1 是报表管理系统的结构图,是典型的 MVC(Model-View-Controller)应用。Controller 负责接收和处理请求,Servlet 扮演 Controller 的角色去处理请求、业务逻辑并转向合适的 JSP 页面。在 Servlet 中对数据进行验证。JSP 扮演 View 的角色以图型化界面的方式呈现 Model 中的数据方便用户交互。Model 就是此系统进行操作的数据模型,我们对这部分加以简化不对数据进行持久化。

数据模型


图 2. 数据模型
图 2. 数据模型

图 2 展示的是订单管理系统的数据模型。

声明了 contraint 的 JavaBean


清单 1. Order.java

				 
 public class Order { 
 // 必须不为 null, 大小是 10 
 @NotNull 
 @Size(min = 10, max = 10) 
 private String orderId; 
 // 必须不为空
 @NotEmpty 
 private String customer; 
 // 必须是一个电子信箱地址
 @Email 
 private String email; 
 // 必须不为空
 @NotEmpty 
 private String address; 
 // 必须不为 null, 必须是下面四个字符串'created', 'paid', 'shipped', 'closed'其中之一
 // @Status 是一个定制化的 contraint 
 @NotNull 
 @Status 
 private String status; 
 // 必须不为 null 
 @NotNull 
 private Date createDate; 
 // 嵌套验证
 @Valid 
 private Product product; 

…
 getter 和 setter 
 } 



清单 2. Product.java

				 
 public class Product { 
 // 必须非空
 @NotEmpty 
 private String productName; 
 // 必须在 8000 至 10000 的范围内
 // @Price 是一个定制化的 constraint 
 @Price 
 private float price; 
…
 Getter 和 setter 
 }


			



清单 3. OrderQuery.java

				 
 // 'to'所表示的日期必须在'from'所表示的日期之后
 // @QueryConstraint 是一个定制化的 constraint 
 @QueryConstraint 
 public class OrderQuery { 
 private Date from; 
 private Date to; 
… omitted …
 Getter and setter 
 } 

 

定制化的 constraint

@Price 是一个定制化的 constraint,由两个内置的 constraint 组合而成。


清单 4. @Price 的 annotation 部分

				 
 // @Max 和 @Min 都是内置的 constraint 
 @Max(10000) 
 @Min(8000) 
 @Constraint(validatedBy = {}) 
 @Documented 
 @Target( { ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD }) 
 @Retention(RetentionPolicy.RUNTIME) 
 public @interface Price { 
 String message() default "错误的价格"; 
 Class<?>[] groups() default {}; 
 Class<? extends Payload>[] payload() default {}; 
 } 

 

@Status 是一个新开发的 constraint.


清单 5. @Status 的 annotation 部分

				 
 @Constraint(validatedBy = {StatusValidator.class}) 
 @Documented 
 @Target( { ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD }) 
 @Retention(RetentionPolicy.RUNTIME) 
 public @interface Status { 
 String message() default "不正确的状态 , 应该是 'created', 'paid', shipped', closed'其中之一"; 
 Class<?>[] groups() default {}; 
 Class<? extends Payload>[] payload() default {}; 
 } 



清单 6. @Status 的 constraint validator 部分

				 
 public class StatusValidator implements ConstraintValidator<Status, String>{ 
 private final String[] ALL_STATUS = {"created", "paid", "shipped", "closed"}; 
 public void initialize(Status status) { 
 } 
 public boolean isValid(String value, ConstraintValidatorContext context) { 
 if(Arrays.asList(ALL_STATUS).contains(value)) 
 return true; 
 return false; 
 } 
 } 

 

Bean Validation API 使用示例

创建订单

用户在创建一条订单记录时,需要填写以下信息:订单编号,客户,电子信箱,地址,状态,产品名称,产品价格


图 3. 创建订单
图 3. 创建订单

对这些信息的校验,使用 Bean Validation API


清单 7. 代码片段

				 
 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
 throws ServletException, IOException { 
 HttpSession session = req.getSession(); 
 // 从 request 中获取输入信息
 String orderId = (String) req.getParameter("orderId"); 
 String customer = (String) req.getParameter("customer"); 
 String email = (String) req.getParameter("email"); 
 String address = (String) req.getParameter("address"); 
 String status = (String) req.getParameter("status"); 
 String productName = (String) req.getParameter("productName"); 
 String productPrice = (String) req.getParameter("productPrice"); 
 // 将 Bean 放入 session 中
 Order order = new Order(); 
 order.setOrderId(orderId); 
 order.setCustomer(customer); 
 order.setEmail(email); 
 order.setAddress(address); 
 order.setStatus(status); 
 order.setCreateDate(new Date()); 
 Product product = new Product(); 
 product.setName(productName); 
 if(productPrice != null && productPrice.length() > 0) 
 product.setPrice(Float.valueOf(productPrice)); 
 order.setProduct(product); 
 session.setAttribute("order", order); 
 ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
 Validator validator = factory.getValidator(); 
 Set<ConstraintViolation<Order>> violations = validator.validate(order); 
 if(violations.size() == 0) { 
 session.setAttribute("order", null); 
 session.setAttribute("errorMsg", null); 
 resp.sendRedirect("creatSuccessful.jsp"); 
 } else { 
 StringBuffer buf = new StringBuffer(); 
 ResourceBundle bundle = ResourceBundle.getBundle("messages"); 
 for(ConstraintViolation<Order> violation: violations) { 
 buf.append("-" + bundle.getString(violation.getPropertyPath().toString())); 
 buf.append(violation.getMessage() + "<BR>\n"); 
 } 
 session.setAttribute("errorMsg", buf.toString()); 
 resp.sendRedirect("createOrder.jsp"); 
 } 
 } 

 

如果用户不填写任何信息提交订单,相应的错误信息将会显示在页面上


图 4. 验证后返回错误信息
图 4. 验证后返回错误信息

其实在整个程序的任何地方都可以调用 JSR 303 API 去对数据进行校验,然后将校验后的结果返回。


清单 8. 调用 JSR 303 API 进行校验

				 
 Order order = new Order(); 
…
 ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
 Validator validator = factory.getValidator(); 
 Set<ConstraintViolation<Order>> violations = validator.validate(order); 

 

结束语

JSR 303 的发布使得在数据自动绑定和验证变得简单,使开发人员在定义数据模型时不必考虑实现框架的限制。当然 Bean Validation 还只是提供了一些最基本的 constraint,在实际的开发过程中,用户可以根据自己的需要组合或开发出更加复杂的 constraint

分享到:
评论

相关推荐

    Mybatis JSR303 bean validation plugin

    在提供的文件中,`validation-api-1.0.0.GA.jar`是Bean Validation API的实现,包含了验证规则和对应的注解,如`javax.validation.constraints.NotNull`等。而`JSR303Plugin.java`则是Mybatis插件的核心代码,它实现...

    wicket-bean-validation-0.6.zip

    Wicket-Bean-Validation是基于JSR 303/JSR 349(Bean Validation)标准的,它允许开发者通过注解来定义对象属性的验证规则,提高了代码的可读性和维护性。 【开源项目】 作为开源项目,Wicket-Bean-Validation遵循...

    angulargwt-jsr303-1.1.2.zip

    JSR303,即Java Bean Validation,是一个Java标准,用于验证对象的属性,确保输入数据的正确性和一致性。JSR303的实现如Hibernate Validator,可以与AngularGWT结合使用,以在客户端和服务器端提供数据验证。 ...

    JSR303依赖的jar包

    JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是Hibernate Validator。JSR 303 用于对 Java Bean 中的字段的值进行验证。 Spring MVC 3.x 之中也大力支持 JSR-303,可以在控制器中对...

    spring-boot-starter-validation-1.3.5.RELEASE.zip

    它的“starter”组件是为了快速引入特定功能而设计的,例如这里的"spring-boot-starter-validation"是为了在Spring Boot应用中轻松集成JSR-303/JSR-349(Bean Validation)标准,进行数据校验。 2. **Bean ...

    JSR-303接口标准和参考实现

    JSR-303接口标准,全称为Java Specification Request 303,是Java平台上的一个规范,旨在提供一种统一的、与框架无关的bean验证框架。该标准由Java Community Process(JCP)提出,目的是简化Java应用中的数据验证...

    gwt-bean-validators-0.22.0.zip

    JSR-303(Bean Validation)和其后续版本JSR-349,是Java平台上的标准规范,用于验证Java对象的属性值。这个规范定义了一种声明式的方式来验证业务对象,使得开发者可以更方便地检查对象是否满足特定的约束条件。...

    validation-api-1.1.0.Final.jar

    JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,现在一共有两个规范:BeanValidation1.0(即JSR303)和BeanValidation1.1(即JSR349),主要用于对数据进行校验,确保输入进来的数据从语 义上来讲是正确的。...

    vavr-beanvalidation2:用于vavr的Bean验证模块-与任何JSR380提供程序集成

    Vavr-Beanvalidation 2.0 此模块提供对bean验证2.0(JSR380)的支持。 可以与bean验证规范的任何服务提供者一起使用,例如org.hibernate.validator:hibernate-validator 添加了验证: @Size的Traversable&lt;T&gt; @...

    JSR303jar包

    3. `validation-api-1.1.0.cr1.jar`:这是Bean Validation API的实现,包含了JSR303/JSR349规范定义的接口和类,如`javax.validation.Constraint`、`javax.validation.ConstraintValidator`等,是所有JSR303实现的...

    Bean Validation 技术规范特性概述

    - **JSR 303/JSR 349**:Bean Validation 1.0和1.1是作为JSR(Java Specification Request)发布的,分别为JSR 303和JSR 349,适用于Java EE环境。 - **Hibernate Validator**:它是Bean Validation的参考实现,同时...

    JSR303Test.zip

    JSR 303/Bean Validation提供了一种统一的方式来验证Java对象的属性,使得开发者可以在不侵入业务逻辑的情况下实现数据验证。 在描述中提到的"基于JSR303的参数验证"是指利用JSR 303提供的注解来对方法参数或bean...

    Bean Validation示例代码

    这个框架的核心是JSR 303和JSR 349标准,它提供了统一的方式来处理业务逻辑中的数据验证,增强了代码的可读性和可维护性。在本示例代码中,我们将深入探讨如何使用Bean Validation来实现这一功能。 首先,我们需要...

    Bean Validator JSR303

    JSR 303介绍 JSR 303全称为Java Specification Request 303,是Java Community Process(JCP)发布的一个关于验证的规范。这个规范的主要目标是为Java应用程序提供一个统一的、可扩展的验证框架,使得开发者能够...

    SpringMVC使用JSR-303进行验证Bean.docx

    本篇文章将详细介绍如何在SpringMVC中使用JSR-303进行Bean验证。 首先,我们需要引入JSR-303的实现库。通常使用的是Hibernate Validator,它是JSR-303规范的一个成熟实现。在不使用Maven的情况下,我们需要下载`...

    JSR303.zip

    JSR303主要由JSR349进一步扩展,统称为Bean Validation,是Java世界中处理数据验证的核心规范。它的目标是简化并标准化对象验证,使得开发者能够方便地对业务对象进行约束验证,而无需编写大量的重复代码。通过注解...

    springmvc&JSR303;的jar包

    Spring MVC是Spring框架的一部分,用于构建MVC(Model-View-Controller)架构的Web应用,而JSR303(Java Bean Validation)则提供了一种标准的数据验证机制。 Spring MVC详解: Spring MVC 是一个轻量级的MVC框架,...

    JSR303 jar包 文档

    1. `validation-api-1.1.0.jar`:这是Bean Validation API的实现,它定义了验证注解和验证接口。这些注解如`@NotNull`, `@Size`, `@Min`, `@Max`等,用于标记需要验证的字段,而验证接口如`Validator`则提供了执行...

Global site tag (gtag.js) - Google Analytics