博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于Bean Validation
阅读量:5103 次
发布时间:2019-06-13

本文共 5935 字,大约阅读时间需要 19 分钟。

Bean Validation 中的 constraint

表 1. Bean Validation 中内置的 constraint
表 2. Hibernate Validator 附加的 constraint

一个 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
1
2
3
4
5
6
7
8
9
10
11
public class Product {
 
// 必须非空
 
@NotEmpty
 
private String productName;
 
// 必须在 8000 至 10000 的范围内
 
// @Price 是一个定制化的 constraint
 
@Price
 
private float price;
 
Getter 和 setter
 
}
清单 3. OrderQuery.java
1
2
3
4
5
6
7
8
9
// '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 部分
1
2
3
4
5
6
7
8
9
10
11
12
// @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 部分
1
2
3
4
5
6
7
8
9
@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 部分
1
2
3
4
5
6
7
8
9
10
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. 代码片段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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 去对数据进行校验,然后将校验后的结果返回。

转载于:https://www.cnblogs.com/zhengwuchao/p/8125360.html

你可能感兴趣的文章
jquery获取复选框checkbox的值
查看>>
SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
查看>>
[个人原创]关于java中对象排序的一些探讨(一)
查看>>
Unix/Linux笔记全集
查看>>
转: Oracle AWR 报告 每天自动生成并发送邮箱
查看>>
让div容器中的图片水平、垂直居中
查看>>
uboot之uboot.lds文件分析
查看>>
10_android打包的过程
查看>>
MySql update inner join!MySql跨表更新 多表update sql语句?如何将select出来的部分数据update到另一个表里面?...
查看>>
我最宏大的个人愿望
查看>>
北漂周记--第5记--拼命编程
查看>>
比赛总结一
查看>>
SpringBoot项目打包
查看>>
JSP的3种方式实现radio ,checkBox,select的默认选择值
查看>>
Linux操作系统 和 Windows操作系统 的区别
查看>>
《QQ欢乐斗地主》山寨版
查看>>
文件流的使用以及序列化和反序列化的方法使用
查看>>
Android-多线程AsyncTask
查看>>
第一个Spring冲刺周期团队进展报告
查看>>
C++函数基础知识
查看>>