跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

EJB 最佳实践: 验证助手类

在数据格式验证中避免出现代码冗余方面提供一点帮助(助手类)

Brett McLaughlin (brett@oreilly.com), 作家兼编辑, O'Reilly and Associates
Brett McLaughlin 的照片
Brett McLaughlin 自 Logo 时代(还记得那个小三角吗?)起就一直从事计算机方面的工作。目前他致力于通过使用 Java 以及与 Java 相关的技术构建应用程序基础结构。近几年他在 Nextel Communications 和 Allegiance Telecom, Inc 从事这些基础结构的实现。Brett是 Java Apache 项目 Turbine 的共同创始人之一,该项目为使用 Java servlet 的 Web 应用程序开发构建可重用的组件体系结构。他还是 EJBoss 项目(一个开放源码 EJB 应用程序服务器)和 Cocoon(开放源码 XML Web 发布引擎)的志愿开发人员之一。可以通过 brett@oreilly.com与 Brett 联系。

简介: 设计良好的验证过程可以提高数据完整性、确保您的应用程序顺利运行并使未来的数据更改更易于处理。在这一期的 EJB 最佳实践中,Brett McLaughlin 扩充了上一篇技巧文章中讨论的验证技术,并改进了最初的概念。

发布日期: 2003 年 4 月 20 日
级别: 初级
访问情况 : 1473 次浏览
评论: 


上一篇专栏文章中,我们首先讨论了数据验证方面的问题,这是企业应用程序设计的基本组件之一。在快速检查了 数据格式验证特定于业务的验证这两种类型的数据验证之后,我们讨论了这两种验证逻辑在应用程序代码中最有利的布局。在结束时我们针对数据格式和特定于业务的验证,提出了很好且有效的解决方案,但我们没有真正解决您在这一编程领域可能会遇到的更复杂情况。

特别是对于数据格式验证代码,我们认为处理它的最佳方法是使它接近客户机,这样可以使处理开销保持最少。因为示例应用程序包含了一个业务委派类,所以我们在其中放置了验证逻辑。这个布局产生的问题是它会在您的代码中引入许多冗余。

变更管理和数据验证

在企业应用程序中更改数据格式是十分常见的情况。尽管 ISBN 和社会保障号的格式基本不变,但 IP 地址和 UPC 代码却不会一成不变。如果验证代码分散在整个应用程序中,那么您必须找到每个实例,并逐一更改它们,这个过程很繁琐,而且易于出错。另外,如果您漏改了一个或两个实例(这是人们常犯的错误),那么数据可能就最终被您自己的验证逻辑破坏!

如果您已经合并了验证逻辑,那么只要更改一处的格式,就可以使整个应用程序受益。

在本篇技巧文章中,我们将再次讨论数据格式验证,介绍数据验证助手类,它将让我们使验证过程接近客户机,同时不会引入任何不必要的代码。

合并验证逻辑

对跨多个业务委派中的多个业务方法使用相同的数据类型作为参数,这是十分常见的。例如,可以将一本书的 ISBN 传递给 Inventory 委派的搜索方法和 Payment 委派的采购方法。如果将验证逻辑与这两个业务委派(象上一篇技巧文章中的那样)联系在一起,那么最终这两个方法中都会有 ISBN 验证代码。

改进数据格式验证过程的第一步是将所有的验证逻辑都移至一个助手类中,其它方法可以按需从这个类上调用验证逻辑。这种合并不仅减少了代码冗余,而且当我们需要时,能够维护和更改应用程序的数据格式。

要实现这样的合并,我们将使用 Validator 类,它为我们需要验证的各种数据类型简单地提供了静态方法。清单 1 显示了这样一个类的框架:

注:可以从诸如业务委派等其它类上调用清单 1 中的简单方法,以按需执行验证逻辑。还要注意这些方法 返回布尔值。


清单 1. Validator 框架
package com.ibm.validation;
import java.util.Iterator;
import java.util.List;
public class Validator {
    public static void validateISBN(String isbn)
        throws InvalidDataException {
    
        // Check the data type, and throw an error if
        //   needed 
    }
    
    public static void validateIPAddress(String ipAddress)
        throws InvalidDataException {
        
        // Check data type
    }
    public static void validateUPC(String upc)
        throws InvalidDataException {
        
        // Check data type
    }
    
    public static void validateUPC(float upc)
        throws InvalidDataException {
        
        validateUPC(new String(upc));
    }
    
    public static void validateList(List list, Class class)
        throws InvalidDataException {
        
        for (Iterator i = list.iterator(); i.hasNext(); ) {
            Object obj = i.next();
            if !(obj instanceof class) {
             throw new InvalidDataException("This list only " +
                    "accepts objects of type " + 
                    class.getName());
            }
        }
        }
}

清单 2 显示了一种有点杂乱的代码,这是使用布尔返回值产生的结果。


清单 2. 在 Validator 中使用布尔返回值
   public boolean checkout(List books) throws ApplicationException {
    if (Validator.validateList(books, Book.class)) { 
                try {
                    return library.checkout(books);
                } catch (RemoteException e) {
                    throw new ApplicationException(e);
                }
        }
    }
    
    public Book lookup(String isbn) throws ApplicationException {
        if (Validator.validateISBN(isbn)) {
            try {
                return library.lookup(isbn);
            } catch (RemoteException e) {
                throw new ApplicationException(e);
            }
        }
    }

在更复杂的方法中,上述嵌套甚至会变得更为杂乱。通过允许抛出异常,我们已避免了这种杂乱所产生的额外复杂性,并使代码保持更“整洁”。另外,请注意 InvalidDataException 继承了 ApplicationException 。这允许所有委派方法的特征符保持不变,因而也允许通过相同机制来抛出任何验证异常。我们不必向方法特征符添加其它 throws 子句,也不必向方法主体添加其它 try/catch 块。简而言之,它使代码保持整洁和简单,而不会到处充斥括号、应用程序异常、验证异常以及 if/thentry/catch 块。


使用 Validator

针对我们需要验证的特定数据类型,在将 Validator 置于适当位置并对它作设置之后,在应用程序中使用它就很容易,在我们的业务委派方法中尤其如此。清单 3 中重写了上一篇技巧文章中的委派,以使它能使用新的 Validator 类。


清单 3. 业务委派中的数据格式验证
package com.ibm.library;
import java.rmi.RemoteException;
import java.util.Iterator;
import java.util.List;
import javax.ejb.CreateException;
import javax.naming.NamingException;
import com.ibm.validation.Validator;
import com.ibm.validation.InvalidDataException;
public class LibraryDelegate implements ILibrary {
    private ILibrary library;
    public LibraryDelegate() {
        init();
    }
    
    public void init() {
        // Look up and obtain our session bean
        try {
            LibraryHome libraryHome = 
                (LibraryHome)EJBHomeFactory.getInstance().lookup(
                    "java:comp/env/ejb/LibraryHome", LibraryHome.class);
            library = libraryHome.create();
        } catch (NamingException e) {
            throw new RuntimeException(e);
        } catch (CreateException e) {
            throw new RuntimeException(e);
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
    }
    
    // No validation required for accessor (getter) methods
        
    public boolean checkout(Book book) throws ApplicationException {
        // No validation required here; the object type
        //   takes care of it
    
        try {
            return library.checkout(book);
        } catch (RemoteException e) {
            throw new ApplicationException(e);
        }
    }
    
    public boolean checkout(List books) throws ApplicationException {
        // Validate list
        Validator.validateList(books, Book.class);
    
        try {
            return library.checkout(books);
        } catch (RemoteException e) {
            throw new ApplicationException(e);
        }
    }
    
    public Book lookup(String isbn) throws ApplicationException {
        // Validate ISBN
        Validator.validateISBN(isbn);
        
        try {
            return library.lookup(isbn);
        } catch (RemoteException e) {
            throw new ApplicationException(e);
        }
    }
        
    // And so on...    
    
    public void destroy() {
        // In this case, do nothing
    }
}

使用独立的 Validator 使代码更模块化和更易维护。另外,我们已将所有的验证逻辑移至一处,从而避免代码中出现冗余。其结果是一个更佳、更不易出错的应用程序。

在本系列的下一篇技巧文章中,我们将研究验证的另一方面:异常处理。那时网上见。


参考资料

关于作者

Brett McLaughlin 的照片

Brett McLaughlin 自 Logo 时代(还记得那个小三角吗?)起就一直从事计算机方面的工作。目前他致力于通过使用 Java 以及与 Java 相关的技术构建应用程序基础结构。近几年他在 Nextel Communications 和 Allegiance Telecom, Inc 从事这些基础结构的实现。Brett是 Java Apache 项目 Turbine 的共同创始人之一,该项目为使用 Java servlet 的 Web 应用程序开发构建可重用的组件体系结构。他还是 EJBoss 项目(一个开放源码 EJB 应用程序服务器)和 Cocoon(开放源码 XML Web 发布引擎)的志愿开发人员之一。可以通过 brett@oreilly.com与 Brett 联系。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology
ArticleID=54719
ArticleTitle=EJB 最佳实践: 验证助手类
publish-date=04202003
author1-email=brett@oreilly.com
author1-email-cc=brett@oreilly.com

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。