Board logo

标题: Hibernate 能够满足我们的验证需求(2)验证和应用程序层 [打印本页]

作者: look_w    时间: 2018-7-20 08:27     标题: Hibernate 能够满足我们的验证需求(2)验证和应用程序层

验证和应用程序层编写验证代码是一个烦人且耗时的过程。通常,很多开发人员都会放弃在特定的层进行有效性验证,从而可以节省一些时间;但是所节省的时间是否能够弥补在这个地方因忽略部分功能所引起的缺陷却非常值得探讨。如果在所有应用程序层中创建并维护验证所需要的时间可以极大地减少,那么争论的焦点就会转向是否要在多个层次中进行有效性验证。假设有一个应用程序,它让用户使用一个用户名、密码和信用卡号来创建一个帐号。在这个应用程序中所希望进行验证的组件如下:
进行验证的一种典型方法是对简单的验证使用 Commons Validator,并在控制器中编写其他一些验证逻辑。Commons Validator 可以生成 JavaScript 来对视图中的验证进行处理。但是 Commons Validator 也有自己的缺陷:它只能处理简单的验证问题,并且将验证的信息都保存到了 XML 文件中。Commons Validator 被设计用来与 Struts 一起使用,而且没有提供一种简单的方法在应用程序层间重用验证的声明。
在规划有效性验证策略时,选择在错误发生时简单地处理这些错误是远远不够的。一种良好的设计同时还要通过生成一个友好的用户界面来防止出现错误。采用预先进行的方法进行验证可以极大地增强用户对于应用程序的理解。不幸的是,Commons Validator 并没有对此提供支持。假设希望 HTML 文件设置文本域的 maxlength 属性来与验证匹配,或者在文本域之后放上一个百分号(%)来表示要输入百分比的值。通常,这些信息都被硬编写到 HTML 文档中了。如果决定修改 name 属性来支持 75 个字符,而不是 60 个字符,那么需要改动多少地方呢?在很多应用程序中,通常都需要:
更好的方法是使用 Hibernate Validator。验证的定义都被通过注释 添加到了模型层中,同时还有对所包含的验证处理的支持。如果选择充分利用所有的 Hibernate,这个 Validator 就可以在 DAO 和 DBMS 层也提供验证。在下面给出的样例代码中,将使用 reflection 和 JSP 2.0 标签文件多执行一个步骤,从而充分利用注释 为视图层动态生成代码。这可以清除在视图中使用的硬编写的业务逻辑。
在清单 3 中,dateOfBirth 被注释为 NotNull 和过去的日期。  Hibernate 的 DDL 生成代码对这个列添加了一个非空约束,以及一个要求日期必须是之前日期的检查约束。e-mail 地址也是非空的,必须匹配 e-mail 地址的格式。这会生成一个非空约束,但是不会生成匹配这种格式的检查约束。
清单 3. 通过 Hibernate Annotations 进行映射的简单联系方式
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/**
* A Simplified object that stores contact information.
*
* @author Ted Bergeron
* @version $Id: Contact.java,v 1.1 2006/04/24 03:39:34 ted Exp $
*/
@MappedSuperclass
@Embeddable
public class Contact implements Serializable {
    public static final int MAX_FIRST_NAME = 30;
    public static final int MAX_MIDDLE_NAME = 1;
    public static final int MAX_LAST_NAME = 30;

    private String fname;
    private String mi;
    private String lname;
    private Date dateOfBirth;
    private String emailAddress;

    private Address address;

    public Contact() {
        this.address = new Address();
    }

    @Valid
    @Embedded
    public Address getAddress() {
        return address;
    }

    public void setAddress(Address a) {
        if (a == null) {
            address = new Address();
        } else {
            address = a;
        }
    }

    @NotNull
    @Length(min = 1, max = MAX_FIRST_NAME)
    @Column(name = "fname")
    public String getFirstname() {
        return fname;
    }

    public void setFirstname(String fname) {
        this.fname = fname;
    }

    @Length(min = 1, max = MAX_MIDDLE_NAME)
    @Column(name = "mi")
    public String getMi() {
        return mi;
    }

    public void setMi(String mi) {
        this.mi = mi;
    }

    @NotNull
    @Length(min = 1, max = MAX_LAST_NAME)
    @Column(name = "lname")
    public String getLastname() {
        return lname;
    }

    public void setLastname(String lname) {
        this.lname = lname;
    }

    @NotNull
    @Past
    @Column(name = "dob")
    public Date getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    @NotNull
    @Email
    @Column(name = "email")
    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }




样例应用程序在  一节,您可以下载一个样例应用程序,它展示了本文中采用的设计思想和代码。由于这是一个可以工作的应用程序,因此代码比本文中讨论的的内容更为复杂。例如,清单 9 就节选于标签文件 text.tag;这个样例应用程序具有标签文件使用的所有代码,以及其他三个类似的标签文件使用的代码(用于选择、隐藏和检查框的 HTML 元素)。由于这是一个可以工作的应用程序,它包含了一个在这种类型的应用程序中都可以找到的架构。还有一个 Ant 构建文件、Spring 和 Hibernate XML 封装代码,以及 log4j 配置。虽然这些都不是本文介绍的重点,但是您会发现仔细研究一下这个样例应用程序的源代码是非常有用的。

如果需要,Hibernate DAO 实现也可以使用 Validation Annotations。所需做的是在 hibernate.cfg.xml 文件中指定基于 Hibernate 事件的验证规则。(更多信息请参考 Hibernate Validator 的文档;可以在  一节中找到相关的链接)。如果真地希望抄近路,您可以只捕获服务或控制器中的 InvalidStateException 异常,并循环遍历 InvalidValue 数组。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0