互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 5.1应用程序的需求和目标84 确地说应该是199年,Inomⅸx公司收购了 Cloudscape公司,JBMS产品作为其中一部分被收购了 公司并购的势头延续了下去,在2001年,IBM公司购买了 fornix公司的资产,其中包括JBMS。随 后,IM公司将它重新命名为 BM Cloudscape,并向公众发布。最后,也就是2004年8月,IBM公 司把 Cloudscape捐献给了 Apache基金会。之后,它被更名为 Apache Derby,此后的一切则不必说了。 不管如何,对今天来说这是一个历史教训。现在, Derby到底是什么呢?其实比较简单, Derby 是一个完全基于Java的关系数据库。 Derby的代码体积较小,而且是可嵌入的,对今天要实现的目 标来说非常重要。可嵌入意味着可以方便地把它作为应用程序的一个组件,这个特性得益于它有 个内联的JDBC驱动。 Derby还可以用于更加传统的客户机-服务器模式,如果你需要这样的话 Derby最大的优点是安装和使用非常容易! 为安装 Derby,你需要做的仅是将 derby.jar文件加入到自己的项目中,然后就可以开始了 除此之外, Derby的用法与其他你熟悉的 RDBMS基本一致。因此,要开始的话,可以像下面这样 加载 Derby的JDBC驱动 Class forName ( "org. apache derby. jdbC. EmbeddedDriver").newInstance( 只要Deby的JAR文件在类路径中,就可以很好地工作了。在驱动加载完毕之后,可以继续 建立到数据库的连接。 Properties props s new Properties( props. put("user","user1 ) props, put("password","uscr1") Connection conn DriverManager getConnection ("jdbc: derby: testDB; create=true", props); Derby的一项很不错的功能是,当数据库不存在的时候,它可以即时地创建一个数据库。这 就是连接URI中 create=true部分的意思。这样,在开发了一个应用程序之后,你可以立即开始 运行,既快又简单 在获取数据库连接之后,可以继续进行标准的JDBC编程,这与其他的JBC编程并无两样。 当然,如果你喜欢的话,还可以使用 Hibernate或BATS这样的应用程序(假设它们都支持 Derby, Hibernate是肯定支持的, IBATIS好像也是支持的)。还可以使用 Spring框架的JDBC支持。在 WIki 应用程序中,我们就是采用这种技术,接下来,我们会讲到它。 很明显,这里只是简单地介绍 Derby。在讲解DWk代码的过程中会介绍更多功能,但是 Derby提供的功能远不止在本章中看到的这些,因此建议你自己找时间研究它。你会发现,这种 嵌入式工作模式特別方便应用程序的开发。例如,我所在的公司就是使用 Oracle来提供所有的数 据库功能。不过,我们平时会遇到许多情形需要创建或者以后修改数据库,这时候,可以使用 Derby的嵌入式工作模式来开发基本的数据库模式,并让应用程序大致运行起来。当部署应用程 序时,才开始安装 Oracle,并用 Oracle来运行应用程序。除此之外,可嵌入意味着你可以发布一 个使用数据库的应用程序,具体是什么应用,我不知道。比如说,一本书中的Wk应用程序 使用这个应用程序的(或者阅读此书的)人并不需要关心数据库安装,除非他或她想自己安装 数据库。因而,我猜你会需要它的网址,是吧?去访问这个地址吧:htp;∥/db. apache.org/ /derby
5.1 应用程序的需求和目标 84 确地说应该是1999年,Informix公司收购了Cloudscape公司,JBMS产品作为其中一部分被收购了。 公司并购的势头延续了下去,在2001年,IBM公司购买了Informix公司的资产,其中包括JBMS。随 后,IBM公司将它重新命名为IBM Cloudscape,并向公众发布。最后,也就是2004年8月,IBM公 司把Cloudscape捐献给了Apache基金会。之后,它被更名为Apache Derby,此后的一切则不必说了。 不管如何,对今天来说这是一个历史教训。现在,Derby到底是什么呢?其实比较简单,Derby 是一个完全基于Java的关系数据库。Derby的代码体积较小,而且是可嵌入的,对今天要实现的目 标来说非常重要。可嵌入意味着可以方便地把它作为应用程序的一个组件,这个特性得益于它有一 个内联的JDBC驱动。Derby还可以用于更加传统的客户机—服务器模式,如果你需要这样的话。 Derby最大的优点是安装和使用非常容易! 为安装Derby,你需要做的仅是将derby.jar文件加入到自己的项目中,然后就可以开始了! 除此之外,Derby的用法与其他你熟悉的RDBMS基本一致。因此,要开始的话,可以像下面这样 加载Derby的JDBC驱动。 只要Derby的JAR文件在类路径中,就可以很好地工作了。在驱动加载完毕之后,可以继续 建立到数据库的连接。 Derby的一项很不错的功能是,当数据库不存在的时候,它可以即时地创建一个数据库。这 就是连接URI中create=true部分的意思。这样,在开发了一个应用程序之后,你可以立即开始 运行,既快又简单。 在获取数据库连接之后,可以继续进行标准的JDBC编程,这与其他的JDBC编程并无两样。 当然,如果你喜欢的话,还可以使用Hibernate或iBATIS这样的应用程序(假设它们都支持Derby, Hibernate是肯定支持的,iBATIS好像也是支持的)。还可以使用Spring框架的JDBC支持。在DWiki 应用程序中,我们就是采用这种技术,接下来,我们会讲到它。 很明显,这里只是简单地介绍Derby。在讲解DWiki代码的过程中会介绍更多功能,但是 Derby提供的功能远不止在本章中看到的这些,因此建议你自己找时间研究它。你会发现,这种 嵌入式工作模式特别方便应用程序的开发。例如,我所在的公司就是使用Oracle来提供所有的数 据库功能。不过,我们平时会遇到许多情形需要创建或者以后修改数据库,这时候,可以使用 Derby的嵌入式工作模式来开发基本的数据库模式,并让应用程序大致运行起来。当部署应用程 序时,才开始安装Oracle,并用Oracle来运行应用程序。除此之外,可嵌入意味着你可以发布一 个使用数据库的应用程序,具体是什么应用,我不知道。比如说,一本书中的Wiki应用程序, 使用这个应用程序的(或者阅读此书的)人并不需要关心数据库安装,除非他或她想自己安装 数据库。因而,我猜你会需要它的网址,是吧?去访问这个地址吧:http://db.apache.org/derby
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 51应用程序的需求和目标85 5.1.3 Spring JDBC 除非在过去的两年中一直孤陋寡闻,否则你一定听说过 Spring框架,而且很可能最早在依赖 注入或者loC场合听到过这个概念,它们也是 Spring框架中两个知名的概念。不过,我们将会看到, Spring框架的内容可不止这些,至少在某种程度上是这样。 Spring是一个被称作全栈( full-stack)的框架,这意味着它几乎覆盖了JEE开发人员可能需 要的所有基础构件。它采用了分层的架构,即每个“模块”的功能或多或少都可以独立使用,可 以仅加入自己需要的功能。 Spring涉及方方面面的内容,从之前提到的依赖注入到Web的MVC 再到诸如字符串操作、ORM( Object- Relational Mapping,对象-关系映射)以及JDBC等各种通用 目的的工具函数。 JDBC实际上是DWik需要的功能单元。 Spring JDBC包包含一些方便使用JDBC的类,更重要 的是,使用它不容易出错。使用JDBC编程的问题之一是,开发人员有时非常容易健忘,当他们 操作完数据库之后,会忘记做类似释放数据库连接之类的操作。不幸的是,无论什么样的规则都 不能解决这个问题。这会导致资源泄露,并最终导致应用程序崩溃或者更糟,让整个服务器宕机。 有了 Spring jDBC,这种类型的错误实际上就不可能发生。 使用 Spring JDBC,数据库访问基本上可以简化为两步。第一步,获取工作的数据源;第二 步,执行相关的SQL语句。在第一步中,会使用下面的代码 DriverManagerData Source dataSource- new DriverManagerDataSource O); dataSource. setDriverClassName( Config. getDatabaseDriver(); dataSource. sctUrl(Config. gctDatabascURIO) data Source. setUsername( Config. getDatabaseUsername o) data Source. setPassword( Config. getDatabasePassword() Config类(后面会进一步介绍)包含DWk会用到的许多配置参数,包括连接数据库的细节, 例如,使用的数据库驱动程序、URL、用户名以及密码等。当有了数据源之后,第二步可以通过 下面的代码完成 JdbcTemplate jt new JdbcTemplate(data Source); List rows jt queryForList("SELECT FROM my Table "); JdbcTemplate类是实现 Spring JDBC的关键。你会看到,它提供了一个 query ForDist()方法, 返回一个表示结果集的工ist对象。这里并不需要繁杂的代码来获取 Resultset对象。当然也提 供了一些其他的方法,比如 query ForMap(),用于从数据库中检索单个记录,并返回一个Map对 象,从而使得对记录字段的访问变得非常简单。请注意,此处并没有显示任何连接处理的代码, 也没有显示清除这个类的代码。这是因为数据库和模板能够为我们处理这一切。不用担心关闭数 据库或者处理语句等典型的JDBC工作, 为什么 Spring会迅速流行起来呢 Spring能够快速发展起来在很大程度上归因于原创者 Rod Johnson构建此项目时所坚持的 核心理念。他认为,J2EE世界中的编程过于复杂,可以利用说明规范来简化这个过程。这听 起来可能会有些争议(虽然这几乎是对Rod本人原话的逐字引用),但是我想他真正的意思是
5.1 应用程序的需求和目标 85 5.1.3 Spring JDBC 除非在过去的两年中一直孤陋寡闻,否则你一定听说过Spring框架,而且很可能最早在依赖 注入或者IoC场合听到过这个概念,它们也是Spring框架中两个知名的概念。不过,我们将会看到, Spring框架的内容可不止这些,至少在某种程度上是这样。 Spring是一个被称作全栈(full-stack)的框架,这意味着它几乎覆盖了J2EE开发人员可能需 要的所有基础构件。它采用了分层的架构,即每个“模块”的功能或多或少都可以独立使用,可 以仅加入自己需要的功能。Spring涉及方方面面的内容,从之前提到的依赖注入到Web的MVC, 再到诸如字符串操作、ORM(Object-Relational Mapping,对象-关系映射)以及JDBC等各种通用 目的的工具函数。 JDBC实际上是DWiki需要的功能单元。Spring JDBC包包含一些方便使用JDBC的类,更重要 的是,使用它不容易出错。使用JDBC编程的问题之一是,开发人员有时非常容易健忘,当他们 操作完数据库之后,会忘记做类似释放数据库连接之类的操作。不幸的是,无论什么样的规则都 不能解决这个问题。这会导致资源泄露,并最终导致应用程序崩溃或者更糟,让整个服务器宕机。 有了Spring JDBC,这种类型的错误实际上就不可能发生。 使用Spring JDBC,数据库访问基本上可以简化为两步。第一步,获取工作的数据源;第二 步,执行相关的SQL语句。在第一步中,会使用下面的代码: Config类(后面会进一步介绍)包含DWiki会用到的许多配置参数,包括连接数据库的细节, 例如,使用的数据库驱动程序、URL、用户名以及密码等。当有了数据源之后,第二步可以通过 下面的代码完成: JdbcTemplate类是实现Spring JDBC的关键。你会看到,它提供了一个queryForList()方法, 返回一个表示结果集的List对象。这里并不需要繁杂的代码来获取ResultSet对象。当然也提 供了一些其他的方法,比如queryForMap(),用于从数据库中检索单个记录,并返回一个Map对 象,从而使得对记录字段的访问变得非常简单。请注意,此处并没有显示任何连接处理的代码, 也没有显示清除这个类的代码。这是因为数据库和模板能够为我们处理这一切。不用担心关闭数 据库或者处理语句等典型的JDBC工作。 为什么Spring会迅速流行起来呢 Spring能够快速发展起来在很大程度上归因于原创者Rod Johnson构建此项目时所坚持的 核心理念。他认为,J2EE世界中的编程过于复杂,可以利用说明规范来简化这个过程。这听 起来可能会有些争议(虽然这几乎是对Rod本人原话的逐字引用),但是我想他真正的意思是
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 52剖析 WIki8 使用说明规范可以很容易地构建应用。一个重要的例子是,在EJB3.0出来之前,企业 JavaBean 直非常复杂,不易于新入门的开发人员学习。对大多数人来讲,它也是复杂的。通过引入POJO 的思想,即在需要的类中注入POJO, Spring框架既能够提供EB承诺的所有优势,又能够简化 EB的代码编写。这就是 Spring能够流行起来的根本原因 有趣的是,现在有的人说 Spring本身至少也和说明规范一样膨胀起来,变得非常复杂了 它应该首先被简化!我把这个留给你(知识丰富的读者)来判断! 关于 Spring JDBC,最后要讨论的一件事情是,它把 SQLException包装在定制的异常类中, 这样你的代码完全可以从标准JDBC类中抽象出来。例如,如果数据库表存在阻止重复记录的约 束,那么当插入相同的记录时 JdbcTemplate类会抛出 DataIntegrityviolationException 对象,你可以捕捉它,并做适当的处理。 Spring JDBC提供的异常层次结构比JDBC的异常机制更 加直观,更加有用,因此使用它们肯定是个好事 Spring JDBC使得我们不必关心JDBC编程的细节,同时也使得JDBC在进程中更加安全。如 果不想(或无需)迁移到目前流行的 Hibernate等ORM工具,或者EJB30,或者类似的东西上,我 极力推荐使用 Spring JDBC,而不要直接进行JDBC编程。它本身非常有用,更不要说它可以节省 大量的调试时间! JDBC包仅是 Spring的一小部分,有大量的相关信息可帮助你更快更好地开发应用程序。花 些时间浏览一下Spring提供的功能,我想你会喜欢在www.springframework.org上发现的东西。 52剖析DWki 好吧,现在开始讲解 WIki应用程序。首先,看一下它的目录结构和文件。在图5-2中,可以 看到它的目录结构。我并没有把img目录展开,由于该目录下存放着用户界面的所有图片,所以 展开它之后抓屏会比较困难!
5.2 剖析 DWiki 86 使用说明规范可以很容易地构建应用。一个重要的例子是,在EJB 3.0出来之前,企业JavaBean 一直非常复杂,不易于新入门的开发人员学习。对大多数人来讲,它也是复杂的。通过引入POJO 的思想,即在需要的类中注入POJO,Spring框架既能够提供EJB承诺的所有优势,又能够简化 EJB的代码编写。这就是Spring能够流行起来的根本原因。 有趣的是,现在有的人说Spring本身至少也和说明规范一样膨胀起来,变得非常复杂了, 它应该首先被简化!我把这个留给你(知识丰富的读者)来判断! 关于Spring JDBC,最后要讨论的一件事情是,它把SQLException包装在定制的异常类中, 这样你的代码完全可以从标准JDBC类中抽象出来。例如,如果数据库表存在阻止重复记录的约 束,那么当插入相同的记录时JdbcTemplate类会抛出DataIntegrityViolationException 对象,你可以捕捉它,并做适当的处理。Spring JDBC提供的异常层次结构比JDBC的异常机制更 加直观,更加有用,因此使用它们肯定是个好事。 Spring JDBC使得我们不必关心JDBC编程的细节,同时也使得JDBC在进程中更加安全。如 果不想(或无需)迁移到目前流行的Hibernate等ORM工具,或者EJB3.0,或者类似的东西上,我 极力推荐使用Spring JDBC,而不要直接进行JDBC编程。它本身非常有用,更不要说它可以节省 大量的调试时间! JDBC包仅是Spring的一小部分。有大量的相关信息可帮助你更快更好地开发应用程序。花 些时间浏览一下Spring提供的功能,我想你会喜欢在www.springframework.org上发现的东西。 5.2 剖析 DWiki 好吧,现在开始讲解DWiki应用程序。首先,看一下它的目录结构和文件。在图5-2中,可以 看到它的目录结构。我并没有把img目录展开,由于该目录下存放着用户界面的所有图片,所以 展开它之后抓屏会比较困难!
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 52剖析 WIki87 a styles.as o darroch 图5-2DWik应用程序的目录结构 在根目录中,可以看到三个文件: index.jsp、 login.jsp以及 loginok.jsp。第一个文 件是这个应用程序的主要标记页面,后两个文件用于处理用户登录。 头到尾浏览这里的每个目录,你会发现,css目录中只有一个文件 styles.css,它是应 用程序的样式表。跳过imng目录,看下一个目录js,它包含两个文件 DWikiclass.js和 Rol1 overs- Class.js。前者是这个应用程序的主要 JavaScript文件,后者负责处理菜单项的图 片翻转 接下来是 templates目录,它包含这个应用程序所使用的所有 FreeMarker模板。在此不再 一列出,稍后会仔细讲解它们。 templates目录下面是标准的WEB-INF目录,在这个目录里面你可以看到两个文件:一个是 web.xm1,这个当然是 Java Web应用程序的标准描述器,另一个文件dwr.xm1是DWk应用程序的 DWR配置文件。 在WEB-INF目录中,我可以看到有个c1 asses目录。该目录除包含编译后的DWik谈类外,还 包含另外三个文件。第一个是 wiki. properties,它是该应用程序的配置文件。另外两个分别 是 commons-1 ogging. properties和 simple1 og properties,它们是 Jakarta通用日志的配置 文件。 commons-1 ogging. properties文件用于日志包自身的配置, simplelog properties 用于配置 Simplelog日志工具,而 Simplelogt仅仅把日志信息输出到 sysout。日志的配置本身也
5.2 剖析 DWiki 87 图5-2 DWiki应用程序的目录结构 在根目录中,可以看到三个文件:index.jsp、login.jsp以及loginOk.jsp。第一个文 件是这个应用程序的主要标记页面,后两个文件用于处理用户登录。 从头到尾浏览这里的每个目录,你会发现,css目录中只有一个文件styles.css,它是应 用程序的样式表。跳过img目录,看下一个目录js,它包含两个文件DWikiClass.js和 Rollovers- Class.js。前者是这个应用程序的主要JavaScript文件,后者负责处理菜单项的图 片翻转。 接下来是templates目录,它包含这个应用程序所使用的所有FreeMarker模板。在此不再一 一列出,稍后会仔细讲解它们。 templates目录下面是标准的WEB-INF目录,在这个目录里面你可以看到两个文件:一个是 web.xml,这个当然是Java Web应用程序的标准描述器,另一个文件dwr.xml是DWiki应用程序的 DWR配置文件。 在WEB-INF目录中,我可以看到有个classes目录。该目录除包含编译后的DWiki类外,还 包含另外三个文件。第一个是dwiki.properties,它是该应用程序的配置文件。另外两个分别 是commons-logging.properties和simplelog.properties,它们是Jakarta通用日志的配置 文件。commons-logging.properties文件用于日志包自身的配置,simplelog.properties 用于配置SimpleLog日志工具,而SimpleLog仅仅把日志信息输出到sysout。日志的配置本身也
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 52剖析 WIki88 是一个完整的主题,我不打算用一节的内容来专门讲述它,但是为了不忽略任何一个部分,我将 在这里快速地介绍一下。打开 commons- logging. properties文件,会发现 Simplelog被指定 为默认的日志工具。而在simp1e1og. properties中,则定义了 Simplelog的默认日志级别为 错误级别,com. apress. dwrprojects. wiki包中类的日志级别为调试级别。这意味着,除 了跟踪消息外,可以看到 WIkis中类的所有消息,并且只能看到其他类(例如 Tomcat)的错误或 致命消息。开发类似的应用程序时,按照这种方式设置日志的级别是合适的。 c1 asses目录之后是1b目录,它包含该应用程序所需的所有JAR包。为节省篇幅,在此不详细 介绍这个目录,只简单说明其中包含的包。 commons- logging.jar是 Jakarta通用日志包。 commons-1ang.jar是 Jakarta的通用语言包,包含一组非常有用的“语言扩展”,这是对Java本 身而言的。 derby.jar是 Apache Derby数据库的JAR包。dwr.jar是个什么包,我想你应该知道! freemarker.jar是 FreeMarker模板引擎。之后是四个名为 spring*.jar的包,这里的星号分别 代表 beans、core、jdbc以及tx。在 Spring框架中使用JDBC包至少要包含这四个包 接下来是src目录,其中包含一个bui1d.xm1文件,它是应用程序的Ant生成脚本,还包含 build libs目录,其中包含编译时而不是运行时需要的JAR包〔运行时的包由 servlet容器在运行 时提供),一个是 servlet apl的JAR包,另一个是 USPAPI的JAR包 最后,看看com目录,其中包含 WIki的源代码树和文件。当然,我们会简单介绍它们,这 里就不列出来了。 下面开始详细讲解组成这个应用程序每部分的实际代码,先从配置文件开始。 考虑到本章内容可能会很长,为了节省篇幅,我删去了所有代码列表中的注释(特别是单 独占用多行的注释)以及一些空行。不过,我保诬,会保留适当的注释和空行以组织好代码, 从而方便读者阅读代码 521配置文件 DWkj配置总共用到四个配置文件,其中没有特别复杂的。 Piers morgan说过,如果没有对 它们一一做解释,则是我的失职 1.容器管理的安全配置 在这个应用程序中,我们有一些安全需求。也就是,一个没有在Wik上注册的用户不能创建 或修改文章,甚至不能给文章写评论(不过,可以阅读已有的评论)。为了做到这点,我决定使 用容器管理的安全,也就是J2EE安全。 使用DWR,实现这个目标非常简单,不过首先要配置容器,在这个例子中就是配置 Tomcat (假设你是运行在推荐的环境配置下)。这个配置实际上就是列出可以访问受保护资源的用户。回 Piers morgan是NBC电视台才艺真人秀《美国天才》( America' s Got talent)的评委。许多人都说他和 Simon cowell 样。( Simon是《美国偶像》( American idol)的评委,虽然尖酸刻薄,不过好像总是正确的。)是的,我承认,拿 这样一种流行文化做比方是有点扯远了
5.2 剖析 DWiki 88 是一个完整的主题,我不打算用一节的内容来专门讲述它,但是为了不忽略任何一个部分,我将 在这里快速地介绍一下。打开commons-logging.properties文件,会发现SimpleLog被指定 为默认的日志工具。而在simplelog.properties中,则定义了SimpleLog的默认日志级别为 错误级别,com.apress. dwrprojects.dwiki包中类的日志级别为调试级别。这意味着,除 了跟踪消息外,可以看到DWiki中类的所有消息,并且只能看到其他类(例如Tomcat)的错误或 致命消息。开发类似的应用程序时,按照这种方式设置日志的级别是合适的。 classes目录之后是lib目录,它包含该应用程序所需的所有JAR包。为节省篇幅,在此不详细 介绍这个目录,只简单说明其中包含的包。commons-logging.jar是Jakarta通用日志包。 commons- lang.jar是Jakarta的通用语言包,包含一组非常有用的“语言扩展”,这是对Java本 身而言的。derby.jar是Apache Derby数据库的JAR包。dwr.jar是个什么包,我想你应该知道! freemarker.jar是FreeMarker模板引擎。之后是四个名为spring*.jar的包,这里的星号分别 代表beans、core、jdbc以及tx。在Spring框架中使用JDBC包至少要包含这四个包。 接下来是src目录,其中包含一个build.xml文件,它是应用程序的Ant生成脚本,还包含 build_libs目录,其中包含编译时而不是运行时需要的JAR包(运行时的包由servlet容器在运行 时提供),一个是servlet API的JAR包,另一个是JSP API的JAR包。 最后,看看com目录,其中包含DWiki的源代码树和文件。当然,我们会简单介绍它们,这 里就不列出来了。 下面开始详细讲解组成这个应用程序每部分的实际代码,先从配置文件开始。 考虑到本章内容可能会很长,为了节省篇幅,我删去了所有代码列表中的注释(特别是单 独占用多行的注释)以及一些空行。不过,我保证,会保留适当的注释和空行以组织好代码, 从而方便读者阅读代码。 5.2.1 配置文件 DWiki配置总共用到四个配置文件,其中没有特别复杂的。Piers Morgan①说过,如果没有对 它们一一做解释,则是我的失职。 1. 容器管理的安全配置 在这个应用程序中,我们有一些安全需求。也就是,一个没有在Wiki上注册的用户不能创建 或修改文章,甚至不能给文章写评论(不过,可以阅读已有的评论)。为了做到这点,我决定使 用容器管理的安全,也就是J2EE安全。 使用DWR,实现这个目标非常简单,不过首先要配置容器,在这个例子中就是配置Tomcat (假设你是运行在推荐的环境配置下)。这个配置实际上就是列出可以访问受保护资源的用户。回 ① Piers Morgan是NBC电视台才艺真人秀《美国天才》(America’s Got Talent)的评委。许多人都说他和Simon Cowell 一样。(Simon是《美国偶像》(American Idol)的评委,虽然尖酸刻薄,不过好像总是正确的。)是的,我承认,拿 这样一种流行文化做比方是有点扯远了