<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>peak</title>
    <description></description>
    <link>http://peak.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>CVS在Linux中的配置和使用</title>
        <author>peak</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://peak.javaeye.com">peak</a>&nbsp;
          链接：<a href="http://peak.javaeye.com/blog/200035" style="color:red;">http://peak.javaeye.com/blog/200035</a>&nbsp;
          发表时间: 2008年06月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span><span style="font-size: medium;"><strong>
1、&nbsp;&nbsp;&nbsp;  CVS简述：略</strong>
</span>
<br />
<span style="font-size: medium;"><strong>
2、&nbsp;&nbsp;&nbsp;  CVS服务器的安装</strong>
</span>
<br />
默认情况下，CVS在Redhat Linux中已经安装，这一点可以通过在Linux命令行的情况下运行：<br />
<span style="color: #0000ff;"><strong>
rpm &ndash;q cvs</strong>
</span>
<br />
如果出现CVS的版本信息就证明已经安装成功了。<br />
CVS服务器安装包可以从网上的很多地方下载，也可以到CVS的官方网站进行下载。根据你所使用的系统，下载相应的版本，然后进行安装。因为我们的项目是
在Redhat Linux下使用CVS服务器进行版本管理，所以本文将主要基于Redhat
Linux进行介绍。首先下载CVS服务器的rpm包，当然也可以下载其它方式的包如源程序包，然后采用以下命令进行安装： <br />
<strong><span style="color: #0000ff;">
rpm -ivh cvs-1.11.1p1-7.rpm</span>
</strong>
<br />
<strong><span style="font-size: medium;">
3、&nbsp;&nbsp;&nbsp;  CVS服务器的配置</span>
</strong>
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  安装完之后的第一件事就是要配置CVS服务器的配置文件，使其能正常的工作。首先在/etc/services文件中添加cvspserver，使其成为Linux的一种服务也就是cvs服务器例程的入口，配置如下： <br />
<span style="color: #339966;"><strong>
cvspserver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2401/tcp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # cvs client/server operations <br />
cvspserver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2401/udp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # cvs client/server operations </strong>
</span>
<br />
如果文件中已经存在上面的两行文字，就不用添加了。<br />
<strong><span style="font-size: medium;">
4、&nbsp;&nbsp;&nbsp;  配置xinetd，用xinetd来启动CVS验证服务器：</span>
</strong>
<br />
进入到/etc/xinetd.d/目录，然后编辑一个文本文件，名字一定要与/etc/services中的入口名字cvspserver一致，所以这里用cvspserver作为文件名，文件的内容如下所示： <br />
<span style="color: #339966;"><strong>
service cvspserver<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  disable = no<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  flags = REUSE<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  socket_type = stream<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  wait = no<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  user = root<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  server = /usr/bin/cvs<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  server_args = -f --allow-root=/usr/cvsroot pserver<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  log_on_failure += USERID<br />
}</strong>
</span>
<br />
编辑文件之后测试cvspserver服务是否配置成功。<br />
执行<br />
<strong><span style="color: #0000ff;">
/etc/init.d/xinetd restart</span>
</strong>
<br />
重新启动服务，启动成功之后，执行下面的语句，验证服务是否启动正常：<br />
<strong><span style="color: #0000ff;">
telnet localhost 2401</span>
</strong>
<br />
如果出现如下字样：<br />
<strong><span style="color: #339966;">
Trying 127.0.0.1...<br />
Connected to localhost.</span>
</strong>
<br />
<strong><span style="color: #339966;">
Escape character is '^]'.</span>
</strong>
<br />
输入<strong><span style="color: #0000ff;">hi</span>
</strong>
，会继续输出如下字样<br />
<strong><span style="color: #339966;">
cvs [pserver aborted]: bad auth protocol start: hi<br />
Connection closed by foreign host.</span>
</strong>
<br />
出现以上的现象表示CVS用户验证服务器已经配置成功。<br />
如果出现如下字样，表示配置不成功，请重新检查以上的配置：<br />
<strong><span style="color: #339966;">
Trying 127.0.0.1...<br />
telnet: connect to address 127.0.0.1: Connection refused</span>
</strong>
<br />
<strong><span style="font-size: medium;">
5、&nbsp;&nbsp;&nbsp;  配置CVS用户：</span>
</strong>
<br />
首先建立一个用户组cvs，可以使用groupadd或者addgroup命名，也可以直接编辑/etc/group文件添加这个组，然后添加一个用户cvsuser：<br />
<strong><span style="color: #0000ff;">
groupadd cvs<br />
useradd cvsuser &ndash;g cvs <br />
passwd cvsuser</span>
</strong>
<br />
设置新的密码。<br />
在/usr目录下建立cvsroot目录（也可以在其它的目录下建，但是应该和cvspserver文件中的选项一致），然后修改/usr/cvsroot的属主及属性：<br />
<strong><span style="color: #0000ff;">
cd /usr<br />
mkdir cvsroot<br />
chown &ndash;R cvsuser:cvs cvsroot<br />
chmod &ndash;R 771 cvsroot</span>
</strong>
<br />
<strong><span style="font-size: medium;">
6、&nbsp;&nbsp;&nbsp;  初始化CVS服务器</span>
</strong>
<br />
安装完CVS服务器之后的另一件重要的事情就是要初始化CVS服务器的根目录，以后创建的CVS项目都将建立在这个目录下，采用的命令如下：<br />
<strong><span style="color: #0000ff;">
cvs &ndash;d /usr/cvsroot init</span>
</strong>
<br />
如果没有任何提示，表示初始化成功。初始化成功之后，会在/usr/cvsroot目录中创建CVSROOT目录，目录中有如下文件：<br />
<strong><span style="color: #339966;">
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  493 Apr  5 20:19 checkoutlist<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  693 Apr  5 20:19 checkoutlist,v<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  760 Apr  5 20:19 commitinfo<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  960 Apr  5 20:19 commitinfo,v<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  527 Apr  5 20:19 config<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  727 Apr  5 20:19 config,v<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  753 Apr  5 20:19 cvswrappers<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  953 Apr  5 20:19 cvswrappers,v<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1025 Apr  5 20:19 editinfo<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1225 Apr  5 20:19 editinfo,v<br />
drwxrwxr-x&nbsp;&nbsp;&nbsp;  2 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  4096 Apr  5 20:19 Emptydir<br />
-rw-rw-rw-&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0 Apr  5 20:19 history<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1141 Apr  5 20:19 loginfo<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1341 Apr  5 20:19 loginfo,v<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1151 Apr  5 20:19 modules<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1351 Apr  5 20:19 modules,v<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  564 Apr  5 20:19 notify<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  764 Apr  5 20:19 notify,v<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  649 Apr  5 20:19 rcsinfo<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  849 Apr  5 20:19 rcsinfo,v<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  879 Apr  5 20:19 taginfo<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1079 Apr  5 20:19 taginfo,v<br />
-rw-rw-rw-&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0 Apr  5 20:19 val-tags<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1026 Apr  5 20:19 verifymsg<br />
-r--r--r--&nbsp;&nbsp;&nbsp;  1 root&nbsp;&nbsp;&nbsp;&nbsp;  root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1226 Apr  5 20:19 verifymsg,v</span>
</strong>
<br />
这样目录/usr/cvsroot就成为CVS服务器的根目录，以后创建的目录都将默认的存放在这个目录下。<br />
<span style="color: #000000;"><strong><span style="font-size: medium;">
7、&nbsp;&nbsp;&nbsp;  登录cvs服务器（在Linux或其它Unix系统下进行登录的情况）：</span>
</strong>
</span>
<br />
输入如下命令：<br />
<strong><span style="color: #0000ff;">
cvs -d :pserver:cvsuser@localhost:/usr/cvsroot login</span>
</strong>
<br />
提示输入密码，输入上面设置的密码，如果没有任何提示，就证明成功登录了<br />
登录成功之后在当前用户的$HOME目录中生成.cvspass文件，可以利用vi对文件进行察看。<br />
由于以&ldquo;.&rdquo;开头的文件在Linux中是隐藏的，所以可以利用如下命令进行察看：<br />
<strong><span style="color: #0000ff;">
ls &ndash;a</span>
</strong>
<br />
这个文件记载了用户的登录信息。执行注销命令可以删除该文件中的登录信息<br />
<strong><span style="color: #0000ff;">
cvs -d :pserver:cvsuser@localhost:/usr/cvsroot logout</span>
</strong>
<br />
下面对登录命令的语法进行说明： <br />
其中，:pserver表示采用pserver方式进行用户登录认证，一般的CVS服务器都采用这种方式，当然也可以采用其它方式，具体参考相应的资料； <br />
:cvsuser表示要登录的用户名，只要是cvs组的成员都可以，如：cvsuser； <br />
@host表示要登录的服务器，可以是DNS名，也可以是IP地址，如：192.168.0.1； <br />
:/usr/cvsroot表示CVS在服务器上的目录，也可以是其它目录（由第6中你所指定的用来做init初始化的目录决定）； <br />
提示：<br />
a、也可以把export CVSROOT=:pserver:cvsuser@192.168.0.1:/usr/cvsroot这一句直接写在用户的初始化文件中（如：.bash_profile），这样用户每次登录时，只需输入： <br />
<strong><span style="color: #0000ff;">
cvs login </span>
</strong>
<br />
然后输入相应的口令就可以登录到cvs服务器上。 <br />
b、如果是本地登录，可以直接把export CVSROOT=/usr/cvsroot这一句写在用户的初始化文件如：/etc/profile中；然后执行如下命令使环境变量生效：<br />
<strong><span style="color: #0000ff;">
source /etc/profile</span>
</strong>
<br />
<strong><span style="font-size: medium;">
8、&nbsp;&nbsp;&nbsp;  向CVS添加新的项目模块</span>
</strong>
<br />
一般我们都已经有一个或多个项目了，这样我们可以用下面步骤生成一个新的CVS项目。将一个工程文件置于CVS中进行版本控制，在CVS 术语中称作导入(import)。从名字上就可以看出，在导入前需要为此作些准备工作。<br />
输入操作的基本要求是有个&quot;干净&quot;的目录结构。&quot;干净&quot;的意思是不需要版本控制的文件都被移走了（如编译生成的文件，备份文件等等）。如果工程已经开始一
段时间了，这就显得很重要。在目录中也许有些是不打算将其置于版本控制下的文件，但是又想将他们放在这里，这种情况下，你要在输入之前将它们移走，然后再
移回来。<br />
注意的是CVS 认为空目录是不存在的。如果想增加一个既不包含文件又不包含子目录的目录，需要在其下创建一个哑文件。建议你创建一个名为 README.txt 的文件，其内容为对目录的简要说明。<br />
进入到已有项目的目录，比如叫 cvstest：<br />
<strong><span style="color: #0000ff;">
cd /home/cvsuser/cvstest</span>
</strong>
<br />
运行命令将项目文件导入到cvs仓库中：<br />
<strong><span style="color: #0000ff;">
cvs import -m &quot;this is a cvstest project&quot; cvstest tengtu start&nbsp;&nbsp;&nbsp;&nbsp;</span>
</strong>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br />
说明：import 是cvs的命令之一，表示向cvs仓库输入项目文件． <br />
　　 -m参数后面的字串是描述文本，对项目进行描述，如果不加 -m
参数，那么cvs会自动运行一个编辑器（一般是vi，但是可以通过修改环境变量EDITOR来改成你喜欢用的编辑器）让你输入信息，cvstest
是项目名称（实际上是仓库名，在CVS服务器上会存储在以这个名字命名的仓库里）<br />
tengtu是这个厂商标记．<br />
start 是每次 import 标识文件的输入层次的标记。<br />
<strong><span style="font-size: medium;">
9、&nbsp;&nbsp;&nbsp;  从cvs本地服务器上checkout相应的模块：</span>
</strong>
<br />
a、如果是在CVS服务器所在计算机上，可以直接采用如下命令： <br />
<strong><span style="color: #0000ff;">
cvs checkout cvstest </span>
</strong>
<br />
这样将把cvstest项目模块checkout到当前目录下。 <br />
b、如果是在远程运行Linux或其它Unix系统上，在第7中登录之后也可以用上边的命令把相应的项目模块checkout到当前目录下。 <br />
另外，如果是在windows端进行checkout，可以采用WinCVS，那么还要对WinCVS进行其它的一些配置，下一部分将具体介绍它的配置方法。 </span>
</p>
          <br/>
          <span style="color:red;">
            <a href="http://peak.javaeye.com/blog/200035#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 04 Jun 2008 11:41:00 +0800</pubDate>
        <link>http://peak.javaeye.com/blog/200035</link>
        <guid>http://peak.javaeye.com/blog/200035</guid>
      </item>
      <item>
        <title>EXT2.0官方教程中文版</title>
        <author>peak</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://peak.javaeye.com">peak</a>&nbsp;
          链接：<a href="http://peak.javaeye.com/blog/159069" style="color:red;">http://peak.javaeye.com/blog/159069</a>&nbsp;
          发表时间: 2008年01月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <ul class="menu"><li class="leaf"><a href="http://www.dojochina.com/?q=node/548">Ext 2 Overview (EXT2.0概述,来自官方)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/526">ext 2.0 Combos 使用指南</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/522">EXT 树的拖放</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/506">EXT 的继承 Manual:Intro:Inheritance</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/508">Javascript中的作用域（scope）</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/518">Manual:Core:Ext.Ajax 类</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/520">Manual:Core:Working with JSON (EXT 与json的交互)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/521">Manual:Ext Source Overview (EXT 学习原始资料)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/519">Manual:Utilities:Function(EXT 内建函数对象)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/514">Tutorial: Grid组件的简易分页</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/509">Tutorial:Application Layout for Beginners (布局的初级入门)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/549">Tutorial:Building Ext From Source(制定自己的EXT版本)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/510">Tutorial:DomQuery Basics(DomQuery的基础)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/515">Tutorial:Ext Menu Widget (EXT 菜单组件)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/511">Tutorial:Extending Ext Class  (EXT 的类继承概念)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/516">Tutorial:Getting Started with Templates(模板)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/507">Tutorial:Introduction to Ext (EXT 介绍入门)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/622">Tutorial:Playing With Ext The Easy Way (玩EXT简单方法)--firebug下调试ext</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/577">Tutorial:TabPanel Basics (TabPanel 类的基础)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/513">Tutorial:Using Layouts with Ext - Part 1 (ext 的布局)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/517">Tutorial:Utilizing Format Features of Templates (模板引擎的应用)</a></li><li class="leaf"><a href="http://www.dojochina.com/?q=node/543">Tutorial:What is that Scope all about(关于作用域的问题)</a></li></ul>
          <br/>
          <span style="color:red;">
            <a href="http://peak.javaeye.com/blog/159069#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 24 Jan 2008 14:06:33 +0800</pubDate>
        <link>http://peak.javaeye.com/blog/159069</link>
        <guid>http://peak.javaeye.com/blog/159069</guid>
      </item>
      <item>
        <title>Ext2.0 学习系列 ------- Ext Grid （二）</title>
        <author>peak</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://peak.javaeye.com">peak</a>&nbsp;
          链接：<a href="http://peak.javaeye.com/blog/158348" style="color:red;">http://peak.javaeye.com/blog/158348</a>&nbsp;
          发表时间: 2008年01月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ext2.0 学习系列(转) ------- Ext Grid （一）中已经介绍了静态的Grid如何显示，本章要简单的讲述一下，如何使用Struts和JSON，在Grid上显示数据。<br /><br />JSON （JavaScript Object Notation）一种简单的数据格式，比xml更轻巧。JSON 是JavaScript 原生格式，这意味着在JavaScript 中处理JSON 数据不需要任何特殊的API 或工具包。<br /><br />    JSON的规则很简单： 对象是一个无序的“‘名称/值’对”集合。一个对象以“{”（左括号）开始，“}”（右括号）结束。每个“名称”后跟一个“:”（冒号）；“‘名称/值’ 对”之间使用“,”（逗号）分隔。具体细节参考http://www.json.org/json-zh.html。<br /><br />    最近正好在学习Struts2.0，在此记录一下Struts2中使用JSON的一种方法。<br /><br />1. 首先当然是搭建好你的Struts2的环境<br />2. 到http://json-lib.sourceforge.net下载需要依赖的jar包，json-lib-2.1-jdk15.jar。json还依赖了以下的第三方包：<br />  commons-beanutils.jar， commons-collections-3.1.jar， commons-lang-2.3.jar， ezmorph-1.0.4.jar<br />3. 下载JSON插件(jsonplugin-0.19.jar)，地址：http://code.google.com/p/jsonplugin/downloads/list，这个很好用！呵呵<br />4. 创建Action如下：<pre name="code" class="java">public class JsonAction extends ActionSupport {

    List&lt;Person> pList = new ArrayList&lt;Person>();

    public String execute() {

        Person p1 = new Person();
        Person p2 = new Person();
        p1.setName("shenchong");
        p1.setSex("男");
        p2.setName("sophia");
        p2.setSex("女");
        pList.add(p1);
        pList.add(p2);
        return SUCCESS;
    }

    @JSON(name = "Person")
    public List&lt;Person> getPList() {
        return pList;
    }

}</pre><br />其中，Person类是一个最简单的POJO，有两个属性name和sex。<br />5. 配置Action<pre name="code" class="xml">&lt;!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
     "http://struts.apache.org/dtds/struts-2.0.dtd">
&lt;struts>
    &lt;package name="com.demo" extends="json-default">
        &lt;action name="Json" class="com.demo.JsonAction">
            &lt;result type="json"/>
        &lt;/action>
        &lt;!-- Add your actions here -->
    &lt;/package>
&lt;/struts></pre><br />    上面配置文件的“package”元素和以往不同的是，它扩展了“json- default”而不是“struts-default”。“json-default”是在jsonplugin-0.19.jar包里的struts -plugin.xml中定义的。该文件同时定义了“json”的结果类型，有兴趣的朋友可以打开此文件看看。<br />    如果你现在就访问http://localhost:8080/XXXX/Json.action，会出现出现下载文件对话框，原因是JSON插件将HTTP响应（Response）的MIME类型设为 “application/json”。把文件下载下来，用记事本打开，内容如下：<br />{"Person":[{"name":"shenchong","sex":"男"},{"name":"sophia","sex":"女"}]}<br />6. EXT的js这样写就可以了<br /><pre name="code" class="java">
Ext.onReady(function(){
	
	var store = new Ext.data.Store({
		proxy: new Ext.data.HttpProxy({
			url:'Json.action',
			method: 'GET'
		}),
		reader: new Ext.data.JsonReader({     
            root: 'Users',      
            id: 'id'
			},[{name: 'name', mapping: 'name'},
                 {name: 'sex', mapping: 'sex'}]     
		)
	});
	var column = new Ext.grid.ColumnModel([
		{header: '姓名', dataIndex: 'name', width: 100},
		{header: '性别', dataIndex: 'sex', width: 50}
	]);
	column.defaultSortable = true;
});
</pre><br />后面就是创建一个Grid显示了。<br /><pre name="code" class="java">
var grid = new Ext.grid.GridPanel({
		el: 'listUser-grid',
		width:700,     
		height:500,  
		title:'用户表',
		store: store,
		cm: column,
		trackMouseOver: false,
		sm: new Ext.grid.RowSelectionModel(),
bbar: new Ext.PagingToolbar({     
           pageSize: 25,     
           store: store,     
           displayInfo: true,     
           displayMsg: ' 本页显示从{0} 到 {1} 条，共 {2} 条数据',     
           emptyMsg: "没有可以显示的数据"     
       }) 
});
   grid.render();
   store.load();

</pre><br /><br />jsp页面上加入一个div就可以了，id一定要是listUser-grid
          <br/>
          <span style="color:red;">
            <a href="http://peak.javaeye.com/blog/158348#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 Jan 2008 16:16:18 +0800</pubDate>
        <link>http://peak.javaeye.com/blog/158348</link>
        <guid>http://peak.javaeye.com/blog/158348</guid>
      </item>
      <item>
        <title>Ext2.0 学习系列(转) ------- Ext Grid （一）</title>
        <author>peak</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://peak.javaeye.com">peak</a>&nbsp;
          链接：<a href="http://peak.javaeye.com/blog/158324" style="color:red;">http://peak.javaeye.com/blog/158324</a>&nbsp;
          发表时间: 2008年01月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="font-family: Courier New">现在的JS框架已经越来越多了，新兴的一些框架使用率上升非常快，因此不能落后啊！<br />&nbsp;&nbsp;&nbsp; 最近开始学习Ext2.0，据说功能非常强大，呵呵！无论是界面之美，还是功能之强，ext的表格控件都高居榜首。单选行，多选行，高亮显示选中的行，推拽改变列宽度，按列排序，这些基本功能咱们就不提了。下面记录我的学习点滴。<br /><br /><span style="color: #ff9900"><strong><span style="font-size: x-small">如何用三种基本类型的数据（Array, Json, Xml）来创建最简单的表格</span></strong><br /></span>最简单的表格由以下几个元素组成：<br />1. 列定义(ColumnModel)<br />&nbsp;&nbsp;&nbsp;
首先我们知道表格肯定是二维的，横着叫行，竖着叫列。跟设计数据库，新建表一样，我们要先设置这个表有几列，每列叫啥名字，啥类型，咋显示，这个表格的骨
架也就出来了。这里我们建立一个四列的表格，第一列叫编号(id)，第二列叫性别(sex)，第三列叫名称(name)，第四列叫描述(descn)。</span><div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%"><div><span style="font-family: Courier New"><span style="color: #008000">&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000">&nbsp;定义一个ColumnModel</span></span><span style="color: #008000"><br /></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;cm&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.grid.ColumnModel([<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{header:</span><span style="color: #000000">'</span><span style="color: #000000">编号</span><span style="color: #000000">'</span><span style="color: #000000">,dataIndex:</span><span style="color: #000000">'</span><span style="color: #000000">id</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{header:</span><span style="color: #000000">'</span><span style="color: #000000">性别</span><span style="color: #000000">'</span><span style="color: #000000">,dataIndex:</span><span style="color: #000000">'</span><span style="color: #000000">sex</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{header:</span><span style="color: #000000">'</span><span style="color: #000000">名称</span><span style="color: #000000">'</span><span style="color: #000000">,dataIndex:</span><span style="color: #000000">'</span><span style="color: #000000">name</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{header:</span><span style="color: #000000">'</span><span style="color: #000000">描述</span><span style="color: #000000">'</span><span style="color: #000000">,dataIndex:</span><span style="color: #000000">'</span><span style="color: #000000">descn</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">}<br />&nbsp;&nbsp;&nbsp;&nbsp;]);<br />&nbsp;&nbsp;&nbsp;&nbsp;cm.defaultSortable&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span></span><span style="color: #000000"><span style="font-family: Courier New">;<br /></span></span></div></div><p><span style="font-family: Courier New">其中，cm.defaultSortable = true;这句话表示默认为可排序的表格，可以先不要去管它<br /><br />2. 数据(Data)<br />&nbsp;&nbsp;&nbsp; 有了表格的骨架，现在我们要向里边添加数据了。这个数据当然也是二维了，下面分别介绍三种数据类型的使用方法：<br />(1) Array Data</span></p><div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%"><div><span style="font-family: Courier New"><span style="color: #008000">&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000">&nbsp;ArrayData</span></span><span style="color: #008000"><br /></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;data&nbsp;</span><span style="color: #000000">=</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="color: #000000">'</span><span style="color: #000000">1</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">male</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">name1</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">descn1</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="color: #000000">'</span><span style="color: #000000">2</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">male</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">name1</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">descn2</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="color: #000000">'</span><span style="color: #000000">3</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">male</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">name3</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">descn3</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="color: #000000">'</span><span style="color: #000000">4</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">male</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">name4</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">descn4</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="color: #000000">'</span><span style="color: #000000">5</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">male</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">name5</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">descn5</span><span style="color: #000000">'</span></span><span style="color: #000000"><span style="font-family: Courier New">]<br />&nbsp;&nbsp;&nbsp;&nbsp;];</span></span></div></div><p><span style="font-family: Courier New">(2) Json Data</span></p><div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%"><div><span style="font-family: Courier New"><span style="color: #008000">&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000">JsonData</span></span><span style="color: #008000"><br /></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;people&nbsp;</span><span style="color: #000000">=</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">coders</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">:&nbsp;[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">id</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">1</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">sex</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">male</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">name</span><span style="color: #000000">'</span><span style="color: #000000">:</span><span style="color: #000000">'</span><span style="color: #000000">McLaughlin</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">descn</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">brett@newInstance.com</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">id</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">2</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">sex</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">male</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">name</span><span style="color: #000000">'</span><span style="color: #000000">:</span><span style="color: #000000">'</span><span style="color: #000000">Hunter</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">descn</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">jason@servlets.com</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">id</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">3</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">sex</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">female</span><span style="color: #000000">'</span><span style="color: #000000">,</span><span style="color: #000000">'</span><span style="color: #000000">name</span><span style="color: #000000">'</span><span style="color: #000000">:</span><span style="color: #000000">'</span><span style="color: #000000">Harold</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">descn</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">elharo@macfaq.com</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">musicians</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">:&nbsp;[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">id</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">1</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">name</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">Clapton</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">descn</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">guitar</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">id</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">2</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">name</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">Rachmaninoff</span><span style="color: #000000">'</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">descn</span><span style="color: #000000">'</span><span style="color: #000000">:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">piano</span><span style="color: #000000">'</span></span><span style="color: #000000"><span style="font-family: Courier New">&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div></div><p><span style="font-family: Courier New">(3) Xml Data<br />&nbsp;&nbsp;&nbsp; Xml类型的数据一般是由一个.xml文件提供的，通过http请求的方式得到。<br /><br />3. 数据的读取<br />&nbsp;&nbsp;&nbsp;
定义好数据之后，我们需要将其转换为能够为grid所用的页面，ext为咱们提供了一个桥梁，Ext.data.Store，通过它我们可以把任何格式的
数据转化成grid可以使用的形式，这样就不需要为每种数据格式写一个grid的实现了。现在咱们就来看看这个Ext.data.Store是如何转换三
种数据的。<br />(1) ArrayReader</span></p><div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%"><div><span style="font-family: Courier New"><span style="color: #008000">&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000">&nbsp;ArrayReader</span></span><span style="color: #008000"><br /></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;ds1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.data.Store({<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy:&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.data.MemoryProxy(data),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reader:&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.data.ArrayReader({},&nbsp;[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">id</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">sex</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">name</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">descn</span><span style="color: #000000">'</span></span><span style="color: #000000"><span style="font-family: Courier New">}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;])<br />&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;ds1.load();</span></span></div></div><p><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp; ds要对应两个部分：proxy和reader。proxy告诉我们从哪里获得数据，reader告诉我们如何解析这个数据。<br />&nbsp;&nbsp;&nbsp;
现在我们用的是Ext.data.MemoryProxy，它是专门用来解析js变量的。你可以看到，我们直接把data作为参数传递进去了。
Ext.data.ArrayReader专门用来解析数组，并且告诉我们它会按照定义的规范进行解析，每行读取三个数据，第一个叫id，第二个叫
sex，第三个叫name，第四个descn。这些是跟cm定义中的dataIndex对应的。这样cm就知道哪列应该显示那条数据了。<br />记得要执行一次ds.load()，对数据进行初始化。</span><span style="color: #000000"><br /></span><br /><span style="font-family: Courier New">(2) JsonReader</span></p><div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%"><div><span style="font-family: Courier New"><span style="color: #008000">&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000">&nbsp;JsonReader</span></span><span style="color: #008000"><br /></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;ds2&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.data.Store({<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy:&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.data.MemoryProxy(people),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reader:&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Ext.data.JsonReader({root:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">coders</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},&nbsp;[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">id</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">sex</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">name</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">descn</span><span style="color: #000000">'</span></span><span style="color: #000000"><span style="font-family: Courier New">}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;])<br />&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;ds2.load();</span></span></div></div><p><span style="font-family: Courier New">其中，root: 'colders'表示取数据的时候取的是'coders'这个节点的数据，而不是'musician'<br /><br />(3) XmlReader</span></p><div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%"><div><span style="font-family: Courier New"><span style="color: #008000">&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000">&nbsp;XmlReader</span></span><span style="color: #008000"><br /></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;ds3&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.data.Store({<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">test.xml</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reader:&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Ext.data.XmlReader({record:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">item</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},&nbsp;[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">id</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">sex</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">name</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{name:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">descn</span><span style="color: #000000">'</span></span><span style="color: #000000"><span style="font-family: Courier New">}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;])<br />&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;ds3.load();</span></span></div></div><p><span style="font-family: Courier New">其中，record: 'item'表示每条记录对应的节点是'item'，下面我会给出test.xml文件的内容，便于更好的理解<br /><br />test.xml</span></p><div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%"><div><span style="font-family: Courier New"><span style="color: #0000ff">&lt;?</span><span style="color: #ff00ff">xml&nbsp;version=&quot;1.0&quot;&nbsp;encoding=&quot;UTF-8&quot;</span><span style="color: #0000ff">?&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">dataset</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">results</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">2</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">results</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">1</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">male</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Taylor</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Coder</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">2</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">female</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Sophia</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Civil&nbsp;Servant</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">3</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">male</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Taylor</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Coder</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">4</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">female</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Sophia</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Civil&nbsp;Servant</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">5</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">id</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">female</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">sex</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Sophia</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Civil&nbsp;Servant</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">descn</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">item</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">dataset</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span></div></div><p><span style="font-family: Courier New">4. 下面组装数据，也分三个表格来显示</span></p><div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%"><div><span style="font-family: Courier New"><span style="color: #008000">&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000">&nbsp;对应Array</span></span><span style="color: #008000"><br /></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;grid1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.grid.GridPanel({<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;el:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">grid1</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ds:&nbsp;ds1,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cm:&nbsp;cm<br />&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;grid1.render();<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;对应Json</span></span><span style="color: #008000"><br /></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;grid2&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.grid.GridPanel({<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;el:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">grid2</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ds:&nbsp;ds2,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cm:&nbsp;cm<br />&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;grid2.render();<br />&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008000">&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000">&nbsp;对应Xml</span></span><span style="color: #008000"><br /></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;grid3&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span></span><span style="font-family: Courier New"><span style="color: #000000">&nbsp;Ext.grid.GridPanel({<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renderTo:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">example-grid</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ds:&nbsp;ds3,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cm:&nbsp;cm,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;title:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">HelloWorld</span><span style="color: #000000">'</span></span><span style="font-family: Courier New"><span style="color: #000000">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;autoHeight:&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">true</span><span style="color: #000000">'</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;})</span></span></div></div><p><span style="font-family: Courier New">其中，grid1和grid2中都有个el属性以及render()方法，这个意思是，当执行该方法的时候，会自动去找页面中id=xxx的标签，然后在里面插入表格；效果跟grid3中的方式是一样的。<br /><br />5. 页面代码（举例）</span></p><div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%"><div><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">html</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">head</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">meta&nbsp;</span><span style="color: #ff0000">http-equiv</span><span style="color: #0000ff">=&quot;Content-Type&quot;</span><span style="color: #ff0000">&nbsp;content</span><span style="color: #0000ff">=&quot;text/html;&nbsp;charset=utf-8&quot;</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">title</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Grid3&nbsp;Example</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">title</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">link&nbsp;</span><span style="color: #ff0000">rel</span><span style="color: #0000ff">=&quot;stylesheet&quot;</span><span style="color: #ff0000">&nbsp;type</span><span style="color: #0000ff">=&quot;text/css&quot;</span><span style="color: #ff0000">&nbsp;href</span><span style="color: #0000ff">=&quot;../../resources/css/ext-all.css&quot;</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span></span><span style="color: #000000"><br /><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;GC&nbsp;</span><span style="color: #008000">--&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;LIBS&nbsp;</span><span style="color: #008000">--&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">script&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;text/javascript&quot;</span><span style="color: #ff0000">&nbsp;src</span><span style="color: #0000ff">=&quot;../../adapter/ext/ext-base.js&quot;</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">script</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;ENDLIBS&nbsp;</span><span style="color: #008000">--&gt;</span></span><span style="color: #000000"><br /><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">script&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;text/javascript&quot;</span><span style="color: #ff0000">&nbsp;src</span><span style="color: #0000ff">=&quot;../../ext-all.js&quot;</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">script</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">script&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;text/javascript&quot;</span><span style="color: #ff0000">&nbsp;src</span><span style="color: #0000ff">=&quot;testGrid.js&quot;</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">script</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">link&nbsp;</span><span style="color: #ff0000">rel</span><span style="color: #0000ff">=&quot;stylesheet&quot;</span><span style="color: #ff0000">&nbsp;type</span><span style="color: #0000ff">=&quot;text/css&quot;</span><span style="color: #ff0000">&nbsp;href</span><span style="color: #0000ff">=&quot;grid-examples.css&quot;</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span></span><span style="color: #000000"><br /><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;Common&nbsp;Styles&nbsp;for&nbsp;the&nbsp;examples&nbsp;</span><span style="color: #008000">--&gt;</span></span><span style="color: #000000"><br /><span style="font-family: Courier New">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">link&nbsp;</span><span style="color: #ff0000">rel</span><span style="color: #0000ff">=&quot;stylesheet&quot;</span><span style="color: #ff0000">&nbsp;type</span><span style="color: #0000ff">=&quot;text/css&quot;</span><span style="color: #ff0000">&nbsp;href</span><span style="color: #0000ff">=&quot;../examples.css&quot;</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span></span><span style="color: #000000"><br /><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">head</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">body</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">script&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">=&quot;text/javascript&quot;</span><span style="color: #ff0000">&nbsp;src</span><span style="color: #0000ff">=&quot;../examples.js&quot;</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">script</span><span style="color: #0000ff">&gt;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">&nbsp;EXAMPLES&nbsp;</span><span style="color: #008000">--&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">h1</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">TestGrid&nbsp;Example1</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">h1</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">p</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Note&nbsp;that&nbsp;the&nbsp;js&nbsp;is&nbsp;not&nbsp;minified&nbsp;so&nbsp;it&nbsp;is&nbsp;readable.&nbsp;See&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">a&nbsp;</span><span style="color: #ff0000">href</span><span style="color: #0000ff">=&quot;testGrid.js&quot;</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">testGrid.js</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">a</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">.</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">p</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">div&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">=&quot;grid1&quot;</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">br</span><span style="color: #0000ff">/&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">div&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">=&quot;grid2&quot;</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">br</span><span style="color: #0000ff">/&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;</span><span style="color: #800000">div&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">=&quot;example-grid&quot;</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">div</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">body</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span><span style="font-family: Courier New"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">html</span><span style="color: #0000ff">&gt;</span></span><span style="color: #000000"><br /></span></div></div><p><span style="font-family: Courier New">其中的testGrid.js的内容就是上面的js代码，注意要写在<br />Ext.onReady(function(){})事件中哦！</span></p>
          <br/>
          <span style="color:red;">
            <a href="http://peak.javaeye.com/blog/158324#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 Jan 2008 15:14:25 +0800</pubDate>
        <link>http://peak.javaeye.com/blog/158324</link>
        <guid>http://peak.javaeye.com/blog/158324</guid>
      </item>
      <item>
        <title>struts2.0中struts.xml配置文件详解 </title>
        <author>peak</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://peak.javaeye.com">peak</a>&nbsp;
          链接：<a href="http://peak.javaeye.com/blog/147511" style="color:red;">http://peak.javaeye.com/blog/147511</a>&nbsp;
          发表时间: 2007年12月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">&lt;!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" >
&lt;struts>

    &lt;!-- include节点是struts2中组件化的方式 可以将每个功能模块独立到一个xml配置文件中 然后用include节点引用 -->
    &lt;include file="struts-default.xml">&lt;/include>
    
    
    &lt;!-- package提供了将多个Action组织为一个模块的方式
        package的名字必须是唯一的 package可以扩展 当一个package扩展自
        另一个package时该package会在本身配置的基础上加入扩展的package
        的配置 父package必须在子package前配置 
        name：package名称
        extends:继承的父package名称
        abstract:设置package的属性为抽象的 抽象的package不能定义action 值true:false
        namespace:定义package命名空间 该命名空间影响到url的地址，例如此命名空间为/test那么访问是的地址为http://localhost:8080/struts2/test/XX.action
     -->
    &lt;package name="com.kay.struts2" extends="struts-default" namespace="/test">
        &lt;interceptors>
            &lt;!-- 定义拦截器 
                name:拦截器名称
                class:拦截器类路径
             -->
            &lt;interceptor name="timer" class="com.kay.timer">&lt;/interceptor>
            &lt;interceptor name="logger" class="com.kay.logger">&lt;/interceptor>
            &lt;!-- 定义拦截器栈 -->
            &lt;interceptor-stack name="mystack">
                &lt;interceptor-ref name="timer">&lt;/interceptor-ref>
                &lt;interceptor-ref name="logger">&lt;/interceptor-ref>
            &lt;/interceptor-stack>
        &lt;/interceptors>
        
        &lt;!-- 定义默认的拦截器 每个Action都会自动引用
         如果Action中引用了其它的拦截器 默认的拦截器将无效 -->
        &lt;default-interceptor-ref name="mystack">&lt;/default-interceptor-ref>
        
        
        &lt;!-- 全局results配置 -->
        &lt;global-results>
            &lt;result name="input">/error.jsp&lt;/result>
        &lt;/global-results>
        
        &lt;!-- Action配置 一个Action可以被多次映射(只要action配置中的name不同)
             name：action名称
             class: 对应的类的路径
             method: 调用Action中的方法名
        -->
        &lt;action name="hello" class="com.kay.struts2.Action.LoginAction">
            &lt;!-- 引用拦截器
                name:拦截器名称或拦截器栈名称
             -->
            &lt;interceptor-ref name="timer">&lt;/interceptor-ref>
        
            &lt;!-- 节点配置
                name : result名称 和Action中返回的值相同
                type : result类型 不写则选用superpackage的type struts-default.xml中的默认为dispatcher
             -->
         &lt;result name="success" type="dispatcher">/talk.jsp&lt;/result>
         &lt;!-- 参数设置 
             name：对应Action中的get/set方法 
         -->
         &lt;param name="url">http://www.sina.com&lt;/param>
        &lt;/action>
    &lt;/package>
&lt;/struts>
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://peak.javaeye.com/blog/147511#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 11 Dec 2007 11:55:30 +0800</pubDate>
        <link>http://peak.javaeye.com/blog/147511</link>
        <guid>http://peak.javaeye.com/blog/147511</guid>
      </item>
      <item>
        <title>spring2.0和AOP</title>
        <author>peak</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://peak.javaeye.com">peak</a>&nbsp;
          链接：<a href="http://peak.javaeye.com/blog/136730" style="color:red;">http://peak.javaeye.com/blog/136730</a>&nbsp;
          发表时间: 2007年10月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font color="#ff0000">转帖</font></p>
<p>在Spring 2.0中最激动人心的增强之一是关于Spring AOP，它变得更加便于使用而且更加强大，主要是通过复杂而成熟的AspectJ语言的支持功能来实现，而同时保留纯的基于代理的Java运行时。</p>
<p>我们一直坚信AOP（面向切面编程）很重要。为什么？因为它提供给我们一种新的思考程序结构的方法，能够解决很多纯OOP无法解决的问题&mdash;&mdash;让我们能够在一个模块中实现某些需求，而不是以发散的方式实现。</p>
<p>为了理解这些好处，让我们考虑一些我们可以在需求中表达但无法直接用纯OO代码实现的情况。企业开发者使用一个通常的词汇表来让他们进行清楚的沟通。比如，像服务层，DAO层，Web层或者Web控制器这样的术语，这不需要什么解释。</p>
<p>许多需求是用这个词汇表中的术语来表达的。比如：</p>
<ul>
    <li>服务层应该是可以处理事务的。 </li>
    <li>当DAO操作失败时，SQLException或者其他特殊持久化技术的异常应该被翻译，以确保DAO接口不会有漏掉的抽象。 </li>
    <li>服务层对象不应该调用Web层，因为各层应该只依赖直接处在其下方的层。 </li>
    <li>由于并发相关操作的失败而导致失败的等幂业务服务可以重试。 </li>
</ul>
<p>虽然这些需求都是现实存在的，并来自于经验，但它们并不能用纯OOP来优雅地解决。为什么？主要有两个原因：</p>
<ul>
    <li>这些来自于我们词汇表的术语有意义，但它们并不是抽象。我们不能使用术语编程；我们需要抽象。 </li>
    <li>所有这些都是所谓横切关注点的例子。一个横切关注点，在用传统OO方法实现时，会分解成很多类和方法。比如，想象一下在跨DAO层遭遇特殊异常时要使用重试逻辑。这个关注点横切许多DAO方法，而且在传统的方式中会需要实现许多单独的修改。 </li>
</ul>
<p>AOP就是通过对横切关注点进行模块化，并让我们从普通的还可以编程的抽象的词汇表来表达术语，来解决这样问题的技术，这些抽象叫做切入点，我很快会再解释一些关于它们的细节。这种方法带来一些主要好处，比如：</p>
<ul>
    <li>因为减少了剪切粘贴风格的复制而减少代码行数。这在像异常转换和性能监测这样的try/catch/finally习惯用法中尤其有效。 </li>
    <li>在单个代码模块中捕捉这样需求的能力，提升可追踪能力。 </li>
    <li>在单个地方修补bug的能力，而不需要重新访问应用程序中许多位置。 </li>
    <li>确保横切关注点不混淆主要的业务逻辑&mdash;&mdash;随着开发的进展，这很有可能成为危险之处。 </li>
    <li>开发者和团队之间更好的职责分离。比如，重试功能可以有单个开发者或者团队来编码，而不需要由许多开发者跨多个子系统进行编码。 </li>
</ul>
<p>因此AOP很重要，我们想提供最好的解决方案。</p>
<p>Spring AOP无疑是最广泛使用的AOP技术，归功于以下优点：</p>
<ul>
    <li>采用成本几近为零。 </li>
    <li>提供正确的切入点，这才称得上是AOP而不仅仅是拦截。 </li>
    <li>提供一个支持许多使用方式的灵活的框架，可编程也可通过XML。 </li>
</ul>
<p>然而，在Spring 2.0之前，Spring中的AOP有一些缺点：</p>
<ul>
    <li>不写Java代码，只能表达简单的切入点。并没有一种切入点表达语言来以字符串形式，简洁表达复杂的切入点，虽然RegexpMethodPointcutAdvisor允许定义简单正规的基于表达的切入点。 </li>
    <li>当配置复杂AOP使用场景时，XML配置会变得很复杂。泛型元素被用来配置AOP类；虽然这对一致性来说很棒，对切面和类提供DI和其他服务，但它没有一个专门的配置方法来得简洁。 </li>
    <li>Spring AOP不适合通知细粒度的对象&mdash;&mdash;对象需要由Spring管理或者通过编程被代理。 </li>
    <li>基于代理的方法的性能负载在少数案例中成为问题。 </li>
    <li>因为Spring AOP分离了代理和目标（被修饰或者被通知的对象），如果某个目标方法调用了目标上的方法，就不会使用到代理，意味着AOP通知并不适用。AOP使用基于代理的方法的正反面影响超出了本文的范围：有一些积极的因素（比如能够对同一个类的不同实例应用不同的通知），但主要还是消极的。 </li>
</ul>
<p>为了在Spring 2.0中增强这个重要领域，我们希望在它的优势上构建，同时解决缺点。</p>
<h3>目标</h3>
<p>最先的两个缺点也是最显著的。它们都跟切入点相关。后面的三个缺点在Spring用户的正常使用中很少发生，如果它们证明是的确有问题的，我们建议使用AspectJ。（就像你会看到的，这是Spring AOP直接的进步。）</p>
<p>XML配置扩展解决了关键的挑战之一。因为我们想要保持Spring模块的设计，我们过去不能在Spring DTD中提供特定于AOP的标签&mdash;&mdash;因此在这种情况下需要依赖可以详细一点的通用配置。随着Spring 2.0的出现，这样的问题没有了，因为XML schema并不像DTD，它允许扩展。我们可以提供一个AOP命名空间，看起来能让Ioc容器识别AOP结构，但不会影响模块化。</p>
<h3>AOP术语101：理解切入点和通知</h3>
<p>让我们简要地修正一下某些AOP术语。如果你使用过AOP这些概念，可能对你来说很熟悉&mdash;&mdash;这些概念是相同的，仅仅有一点不同，即更加优雅和强大的表达方式。</p>
<p>切入点是匹配规则。它在程序执行中确定应该应用某个切面的点的集合。这些点叫做连接点。在应用程序运行时，连接点随时会有，比如对象的实例化和方法的调用。在Spring AOP（所有版本）的案例中，唯一支持的连接点是公有方法的执行。</p>
<p>通知是可以被切面应用到连接点的行为。通知能在连接点之前或之后应用。通知的所有类型包括：</p>
<ul>
    <li>Before advice：在连接点之前调用的通知。比如，记录方法调用即将发生的日志。 </li>
    <li>After returning adive：如果在连接点的方法正常返回时调用的通知。 </li>
    <li>AfterThrowing advice（在Spring1.x中叫做Throws通知）：如果连接点的方法抛出一个特殊的异常时调用的通知。 </li>
    <li>After advice：在连接点之后调用的通知，无论结果是什么。特别像Java中的finally。 </li>
    <li>Around advice：能够完全控制是否执行连接点的通知。比如，用来在事务中封装某个方法调用，或者记录方法的执行时间。 </li>
</ul>
<p>切面是结合切入点和通知成一个模块方案，解决特殊的横切问题。</p>
<p>如果这有点抽象，请不要担心：代码示例会很快解释清楚的。</p>
<blockquote>对在Spring 2.0和AspectJ的环境中关于AOP基础的更深讨论，请参考Adrian在InfoQ上很棒的文章，&quot;<a href="http://www.infoq.com/articles/Simplifying-Enterprise-Apps">Simplifying Enterprise Applications with Spring 2.0 and AspectJ.</a>&quot;</blockquote>
<h3>为什么会是AspectJ切入点表达式？</h3>
<p>迄今为止，我们讨论过的概念都是基本的AOP概念，对于Spring AOP或者AspectJ而且这并不特别，在Spring1.x中已经是存在的。那么为什么我们选择在Spring 2.0中采用AspectJ呢？</p>
<p>如果我们需要一种切入点表达语言，那么选择就会很简单。AspectJ有个思路很好，严格定义和充足文档的切入点语言。它最近实现了一个当在Java 5上运行时，能对采用Java 5语法的编码全面检查。它不仅有很棒的参考材料，而且很多书籍和文章都对它进行了介绍。</p>
<p>我们不相信重新发明的轮子，而且定义我们自己的切入点表达语言是不合理的。进一步而言，自从AspectWerkz在2005年早期和冰岛AspectJ项目之后，很明显AspectJ是除了Spring 2.0之外唯一一个主流的AOP技术。因此关键的合并既是一种考虑也是一种技术优势。</p>
<h3>新的XML语法</h3>
<p>新的AOP命名空间允许Spring XML配置指定AspectJ切入点表达式，通过由切入点匹配的方法将通知指向任何Spring bean。</p>
<p>考虑一下我们上面看到的Person类。它有个age属性，以及一个增加age的birthday方法：</p>
<pre><font color="#660033"><strong>public void</strong></font> birthday() {<br />      ++<font color="#0000ff">age;</font><br /> }</pre>
<p>我们假设有这样的需求，任何时候调用birthday方法，我们都应该发送一张生日贺卡给过生日的人。这是一个经典的横切需求：它并不是我们主要的业务逻辑部分，而是个单独的关注点。理想的情况下，我们希望能够将那个功能模块化，而不影响Person对象。</p>
<p>让我们考虑一下通知。实际上，邮递发送一张生日贺卡，或者甚至发送一张电子贺卡，当然会是这个方法的主要工作。然而，由于这篇文章中我们的兴趣在于触发的基础结构，而不是发送生日贺卡的机制。因此我们就简单使用控制台输出。这个方法需要访问到过生日的这个Person，而且无论何时brithday方法被调用，它都应该被调用。下面是简单的通知实现：</p>
<pre><font color="#660033"><strong>public class</strong></font> BirthdayCardSender {<br />   <font color="#660033"><strong>public void</strong></font> onBirthday(Person person) {<br />      System.<font color="#0000ff">out</font>.println(<font color="#0000ff">&quot;I will send a birthday card to &quot;</font> +<br />             person.getName() + <font color="#0000ff">&quot;; he has just turned &quot;</font><br />             person.getAge());<br />   }<br /><br /> }</pre>
<p>本质上我们在Person上想要一种Observer机制，但并不把Person修改成可被观察的。请同时注意在这个例子中，BirthdayCardSender对象被用作一个切面，但不需要实现任何特定于框架的接口。这样就使得使用已经存在的类作为切面成为可能，而且扩展Spring的非入侵编程模型到潜在的切面以及普通的类。</p>
<p>通过Spring 2.0，我们可以像下面这样把BirthdayCardSender当作一个切面来使用。首先，我们把BirthdayCardSender类定义成一个bean。这很简单：</p>
<bean class="com.interface21.spring2.aop.BirthdayCardSender" id="birthdayCardSenderAspect"></bean>
<p>我们可以依赖注入这个对象，或者应用任何其他的Spring组件模型服务，如果我们愿意的话。</p>
<p>下一步，我们添加AOP配置来告诉Spring，无论何时Spring管理的Person对象的birthday()方法被调用了，就调用BirthdayCardSenderbean的onBirthday()方法。这是通过使用新的<aop:config>和<aop:aspect>标签来实现的。首先，我们必须导入方便的AOP命名空间：</aop:aspect></aop:config></p>
<pre><font color="#0000ff">&lt;?xml version=</font>&quot;1.0&quot; <font color="#0000ff">encoding=</font>&quot;UTF-8&quot;<font color="#0000ff">?&gt;</font><br /> <font color="#0000ff">&lt;beans xmlns=</font>&quot;http://www.springframework.org/schema/beans&quot;<br />     <font color="#0000ff">xmlns:xsi=</font>&quot;http://www.w3.org/2001/XMLSchema-instance&quot;<br />     <font color="#0000ff">xmlns:aop=</font>&quot;http://www.springframework.org/schema/aop&quot;<br />     <font color="#0000ff">xsi:schemaLocation=</font>&quot;http://www.springframework.org/schema/beans<br /> http://www.springframework.org/schema/beans/spring-beans.xsd<br />     <strong>http://www.springframework.org/schema/aop<br /> http://www.springframework.org/schema/aop/spring-aop-2.0.xsd&quot;&gt;</strong></pre>
<p>接着我们使用新的AOP标签，就像下面这样。这是应用这个切面的完整的配置：</p>
<p><aop:after>标签适用于after 通知。它指定方法调用onBirthday（），也就是通知。它指明了<strong>什么时候</strong>调用这个方法&mdash;&mdash;切入点&mdash;&mdash;以一个AspectJ切入点表达式的形式。</aop:after></p>
<p>切入点表达式是关键。让我们进一步来研究它。</p>
<pre>execution(void com.interface21..Person.birthday()) and this(person)</pre>
<p>execution()前缀表明我们正在匹配某个方法的执行。也就是说，我们在改变方法的行为。</p>
<p>execution()一句的类型定义了匹配的方法。我们可以在这编写一个表达式来匹配许多类的方法的集合。（实际上，那是一种更普遍更有价值的用法：当通知只匹配一个方法，实际上也没什么意义）最后，我们把被调用的对象<strong>绑定</strong>到onBirthday()方法的参数。这样缩小了切入点，可以仅仅匹配到一个Person对象的执行&mdash;&mdash;而且提供一种优雅的方式来获得被调用的对象，而不需要任何查找。我们可以使用参数绑定来绑定方法参数，返回类型和异常，以及我们希望的目标。去掉查找的代码应该听起来很熟悉：这是对被通知的类型的依赖有效的<strong>注入</strong>！在Spring的精神中，它去掉了一个API，无意间却也使单元测试通知方法更简单。</p>
<p>如果切入点表达式匹配一个或多个方法，任何定义在Spring上下文中的Person会被自动代理。那些没有包含对于这个切入点的匹配的类的Bean不会受到影响，匹配切入点的没有被Spring容器实例化的对象也一样（不会受到影响）。这个切面配置是设计用来添加到上面Ioc实例中已有的bean配置，或者在一个额外的XML文件中，或者在同一个文件中。提示一下，Person定义成如下这样：</p>
<pre>&lt;bean class=&quot;com.interface21.spring2.ioc.Person&quot;<br />     p:name=&quot;Tony&quot;<br />     p:age=&quot;53&quot;<br />     p:house-ref=&quot;number10&quot;<br /> /&gt;</pre>
<p>不需要任何配置来使Person或者其他的bean定义符合通知。当我们调用某个配置在Spring上下文中的Person对象的birthday()方法时，我们看到下面这样的输出：</p>
<pre>I will send a birthday card to Tony; he has just turned 54</pre>
<h3>@AspectJ语法</h3>
<p>通知总是包含在Java方法中。但到目前为止，我们看到的是定义在Spring XML中的切入点。</p>
<p>AspectJ 5也提供一种完美的解决方案，来定义切面，通知包含在方法中以及切入点在Java 5的注解中。这种切入点表达语言和AspectJ自己的语法一样，而且语义相同。但以这种风格&mdash;&mdash;叫做@<strong>AspectJ</strong>模型&mdash;&mdash;切面能使用javac进行编译。</p>
<blockquote><strong>通过@AspectJ语法，特定于框架的注解存在于切面中，而不是业务逻辑中。没有必要把注解引入到业务逻辑中来驱动切面。</strong></blockquote>
<p>这种注解驱动的编程模型最先由AspectWerkz提出，在2005年早期它合并入AspectJ项目。在AspectJ中，@AspectJ 切面被<strong>加载时织入</strong>（load time weaving）运用：类加载器钩子修改正在加载的类的字节码，来应用这些切面。AspectJ编译器也明白这些切面，因此有个实现策略的选择。</p>
<p>Spring 2.0为@AspectJ切面提供一种额外的选择：Spring可以使用它的基于代理的AOP运行时来将这样的切面应用到Spring beans。</p>
<p>让我们看一下，我们早先例子中同样的功能是如何使用这种风格实现的。</p>
<p>这个切面类包含和BirthdayCardSender类相同的通知方法体，但使用org.aspectj.lang.annotation.Aspect注解来把它识别为一个切面。在同一个包中更多的注解定义了通知方法。</p>
<pre>@Aspect<br /> <font color="#660033"><strong>public class</strong></font> AnnotatedBirthdayCardSender {<br /><br />    @After(<font color="#0000ff">&quot;execution(void com.interface21..Person.birthday()) and this(person)&quot;</font>)<br />   <font color="#660033"><strong>public void</strong></font> onBirthday(Person person) {<br />      System.<font color="#0000ff">out.</font>println(&quot;<font color="#0000ff">I will send a birthday card to &quot;</font> +<br />             person.getName() +<font color="#0000ff"> &quot;; he has just turned &quot;</font> +<br />             person.getAge());<br />   }<br /> }</pre>
<p>这将切入点和通知方法结合在一起，使切面成为一个完整的模块。@AspectJ 切面,就像所有的AspectJ 切面，可以包含任意数目的切入点和通知方法。</p>
<p>在Spring XML中，我们再次把这个定义成一个bean，并添加一个额外的标签来引起自动应用切面。</p>
<pre>&lt;aop:aspectj-autoproxy /&gt;<br /><br />   &lt;bean id=<font color="#0000ff">&quot;birthdayCardSenderAspect&quot;</font><br />      class=<font color="#0000ff">&quot;com.interface21.spring2.aop.AnnotatedBirthdayCardSender&quot;</font> /&gt;</pre>
<p>这个自动代理aspectj标签告诉Spring自动识别@AspectJ切面，并把它们应用到任何与它们的切入点相匹配的相同上下文中bean中。</p>
<h3>在XML和@AspectJ风格之间选择</h3>
<p>哪个方法更好呢&mdash;&mdash;XML还是注解？首先，因为注解存在于切面中，而不是核心业务逻辑，所以转换的成本并不高。决定通常取决于使切入点描述完全从Java代码具体出来是否有意义。</p>
<p>如果你的切面是特定领域的，就考虑注解风格：也就是说，切入点和通知是紧密相联的，而且通知并不普通，不可能在不同的场景中重复使用。比如说，发送生日贺卡对于注解风格是个很好的选择 ，因为它是特定于一个特殊应用类（Person）的。然而，一个性能监测切面可能在不同的应用中有不同的使用，通知方法最好从切入点解耦出来，切入点存在于XML配置中更自然一些。</p>
<p>使用XML如果：</p>
<ul>
    <li>你不能使用Java 5，而且没有其他选择。Spring 2.0的AOP增强，除了能处理@AspectJ语法，也能工作在Java1.3，1.4以及Java 5上，虽然你不能编写切入点表达式匹配注解或者其他的Java 5结构。 </li>
    <li>你可能想要在不同的上下文中使用通知。 </li>
    <li>你想要使用已有代码作为通知，而且不想引入AspectJ注解：比如，引入一个Observer行为调用任意POJO的方法。 </li>
</ul>
<h3>编程用法</h3>
<p>你也可以以编程的方式创建AOP代理，像下面这样使用@AspectJ 切面：</p>
<pre>Person tony = <font color="#660033"><strong>new</strong></font> Person();<br /> tony.setName(<font color="#0000ff">&quot;Tony&quot;</font>);<br /> tony.setAge(53);<br /><br /> AspectJProxyFactory ajpf = <font color="#660033"><strong>new</strong></font> AspectJProxyFactory(tony);<br /> ajpf.addAspect(<font color="#660033"><strong>new</strong></font> AnnotatedBirthdayCardSender());<br /> Person proxy = ajpf.getProxy();</pre>
<p>AnnotatedBirthdayCardSender会被自动识别为一个@AspectJ 切面，而且代理会使用它定义的行为来修饰目标。这种风格并不需要Spring Ioc容器。</p>
<p>编程式的代理创建在编写基础结构代码和测试时比较有用，但在通常的业务应用中并不经常使用。</p>
<h3>通过AspectJ切入点你能做的很棒的事情</h3>
<p>到目前为止我们看到的仅仅是表面的东西。</p>
<p>让我们来看一些AspectJ切入点表达式更高级的能力，在Spring XML中，以@AspectJ风格（或者当然，AspectJ语言本身）：</p>
<ul>
    <li>参数，目标，异常以及返回值绑定。 </li>
    <li>从类型安全中受益，其中方法签名中的类型是在切入点中指定。 </li>
    <li>用切入点表达式的组合来构建复杂的表达式。 </li>
    <li>切入点表达式的重复使用。 </li>
</ul>
<p>我们已经见过了目标绑定。让我们举一个参数绑定的例子：</p>
<pre>@Aspect<br /> public class ParameterCaptureAspect {<br /><br />   @Before(&quot;execution(* *.*(String, ..)) <strong>&amp;&amp; args(s)</strong>&quot;)<br />   public void logStringArg(String s) {<br />     System.out.println(&quot;String arg was '&quot; + s + &quot;'&quot;);<br />   }<br /> }</pre>
<p>args()子句绑定到被匹配的方法中的参数，缩小范围到具有第一个参数类型是String的方法。因为切入点绑定了第一个参数，必须是String类型的参数，在通知方法中做强制转换就没有必要了。</p>
<p>这种机制很自然地提供了类型安全。这个切入点的通知目标永远不可能被错误调用，通过错误类型的参数，或者没有匹配的参数。</p>
<p>为了给一个这种机制的优越性的例子，下面是在Spring1.x MethodBefore通知中看起来的样子。因为通过一个AOP Alliance MethodInterceptor（在Spring1.x中最通用的接口），我们需要遍历一个参数数组来找出我们要寻找的参数：</p>
<pre>public class ParameterCaptureInterceptor implements MethodBeforeAdvice {<br />   public void before(Method method, Object[] args, Object target) throws Throwable {<br />      if (args.length &gt;= 1 &amp;&amp; method.getParameterTypes()[0] == String.class) {<br />          String s = (String) args[0];<br />          System.out.println(&quot;String arg was '&quot; + s + &quot;'&quot;);<br />      }<br />   }<br /> }</pre>
<p>我们可以使用一个Spring AOP切入点来去除MethodBefore通知中的保护，但正如前面提到的，这样可能需要编写Java代码。在拦截器中有个保护比使用切入点要慢，因为它不允许AOP运行时优化出永远不能调用的通知。</p>
<p>在这里我们能够看到从拦截中去除AOP是多么的正确，以及为什么更简单和更强大。EJB3.0拦截显然比Spring的第一代AOP功能更加糟糕，因为它缺少一个真实的切入点机制，这意味着ClassCastException和ArrayIndexOutofBoundsException很可能是风险。同样有必要使用Around通知（拦截器）而不是Before通知，因为EJB3.0没有提供特殊的通知类型。而且，需要提供一个InvocationContext对象使得单元测试通知方法困难得多。</p>
<blockquote><strong>AspectJ切入点表达式语言的强大不仅仅是关于复杂的结构。它也在避免潜在的错误和应用程序更加智能化方面扮演重要的角色。它还能通过在通知方法中移除所需的保护代码，显著地减少所需代码的数量。</strong></blockquote>
<p>组合和重用是真实语言的特征。AspectJ的主要目标就是把它们提供给切入点表达式。</p>
<p>让我们看一下实际中切入点的重用。</p>
<p>@AspectJ语法（就像Spring 2.0的AOP XML格式）允许我们定义有名字的切入点。在@AspectJ语法，我们在一个void方法上使用@Pointcut注解，就像下面这样：</p>
<pre>@Pointcut(<font color="#0000ff">&quot;execution(public !void get*())&quot;</font>)<br /> <font color="#660033"><strong>public void</strong></font> getter() {}</pre>
<p>@Pointcut注解允许我们定义切入点表达式，而且必要时，还有被切入点绑定的参数的个数和类型。方法名被用作切入点的名称。</p>
<p>上面的切入点匹配JavaBean的getter方法。请注意这里匹配的优势：我们不仅仅处理通配符，而且处理语言语义。这方法会把getter方法看作任何名称以get开头的方法。这种切入点要健壮得多，因为它断言getter是公有的，有一个非void的返回（!void）以及没有参数（通过对参数的圆括号来指明）。</p>
<p>让我们添加一种切入点来匹配返回int的方法：</p>
<pre>@Pointcut(<font color="#0000ff">&quot;execution(public int *())&quot;</font>)<br /> <font color="#660033"><strong>public void</strong></font> methodReturningInt() {}</pre>
<p>现在我们可以根据这些切入点来表达通知。我们第一个例子简单引用了我们的第一个有名称的切入点，&ldquo;getter&rdquo;：</p>
<pre>@After(<font color="#0000ff">&quot;getter()&quot;</font>)<br />   <font color="#660033"><strong>public void</strong></font> getterCalled(JoinPoint jp) {<br />      System.<font color="#0000ff"><em>out</em></font>.println(<font color="#0000ff">&quot;Method &quot;</font>  + jp.getSignature().getName() +<br />            <font color="#0000ff">&quot; is a getter&quot;</font>);<br />   }</pre>
<p>然而，现在事情变得更有趣了。我们通过把两个切入点加到一个表达式，对一个返回in的getter应用通知：</p>
<pre>@After(<font color="#0000ff">&quot;getter() and methodReturningInt()&quot;</font>)<br /> <font color="#660033"><strong>public void</strong></font> getterCalledThatReturnsInt(JoinPoint jp) {<br />    System.<font color="#0000ff"><em>out</em></font>.println(<font color="#0000ff">&quot;ANDing of pointcuts: Method &quot;</font> + <br />   jp.getSignature().getName() +<br />          <font color="#0000ff">&quot; is a getter that also returns int&quot;</font>);<br /> }</pre>
<p>ANDing意味着两个切入点都必须应用。ORing意味着必须应用其中一个切入点。我们可以构建我们需要的任何复杂程度的表达式。</p>
<p>在下面这个完整的切面中演示了ANDing和ORing：</p>
<pre>@Aspect <font color="#660033"><strong>public class</strong></font> PointcutReuse {<br /><br />    @Pointcut(<font color="#0000ff">&quot;execution(public !void get*())&quot;</font> )<br />   <font color="#660033"><strong>public void</strong></font> getter() {}<br /><br />    @Pointcut(<font color="#0000ff">&quot;execution(public int *())&quot;</font> )<br />   <font color="#660033"><strong>public void</strong></font> methodReturningInt() {}<br /><br />    @Pointcut(<font color="#0000ff">&quot;execution(public void *(..))&quot;</font> )<br />   <font color="#660033"><strong>public void</strong></font> voidMethod() {}<br /><br />    @Pointcut(<font color="#0000ff">&quot;execution(public * *())&quot;</font> )<br />   <font color="#660033"><strong>public void</strong></font> takesNoArgs() {}<br /><br />    @After(<font color="#0000ff">&quot;methodReturningInt()&quot;</font> )<br />   <font color="#660033"><strong>public void</strong></font> returnedInt(JoinPoint jp) {<br />     System.<font color="#0000ff">out</font> .println(<font color="#0000ff">&quot;Method &quot;</font>  + jp.getSignature().getName() +<br />           <font color="#0000ff">&quot; returned int&quot;</font> );<br /> }<br /><br />    @After(<font color="#0000ff">&quot;getter()&quot;)<br />   <font color="#660033"><strong>public void</strong></font> getterCalled(JoinPoint jp) {<br />     System.<font color="#0000ff">out</font> .println(<font color="#0000ff">&quot;Method &quot;</font>  + jp.getSignature().getName() +<br />           &quot; is a getter&quot;</font> );<br /> }<br /><br />    @After(<font color="#0000ff">&quot;getter() and methodReturningInt()&quot;</font> )<br />   <font color="#660033"><strong>public void</strong></font> getterCalledThatReturnsInt(JoinPoint jp) {<br />     System.<font color="#0000ff">out</font>.println(<font color="#0000ff">&quot;ANDing of pointcuts: Method &quot;</font> + <br />jp.getSignature().getName() +<br />           <font color="#0000ff">&quot; is a getter that also returns int&quot;</font>);<br /> }<br /><br />    @After(<font color="#0000ff">&quot;getter() or voidMethod()&quot;</font> )<br />   <font color="#660033"><strong>public void</strong></font> getterOrVoidMethodCalled(JoinPoint jp) {<br />     System.<font color="#0000ff">out</font> .println(<font color="#0000ff">&quot;ORing of pointcuts: Method &quot; </font> + <br />jp.getSignature().getName() +<br />           <font color="#0000ff">&quot; is a getter OR is void&quot;</font> );<br />   }<br /><br />  }</pre>
<p>这会产生下面的输出，显示切入点表达式的ORing和ANDing：</p>
<pre>Method getName is a getter<br /> ORing of pointcuts: Method getName is a getter OR is void<br /> ORing of pointcuts: Method birthday is a getter OR is void<br /> Method getName is a getter<br /> ORing of pointcuts: Method getName is a getter OR is void<br /> Method getAge returned int<br /> Method getAge is a getter<br /> ANDing of pointcuts: Method getAge is a getter that also returns int<br /> ORing of pointcuts: Method getAge is a getter OR is void<br /> I will send a birthday card to Tony; he has just turned 54</pre>
<p>切入点组合同样可以在Spring AOP XML中完成。在那种情况下，使用&ldquo;and&rdquo;和&ldquo;or&rdquo;替代&ldquo;&amp;&amp;&rdquo;和&ldquo;||&rdquo;操作符来避免使用XML属性值的问题。</p>
<h3>为高级用户重用AspectJ库切面</h3>
<p>重用AspectJ语言编写的AspectJ切入点表达式，并编译成一个JAR文件是可能的。如果你使用Eclipse，你可以使用AJDT插件开发这样的切面。或者，如果你已经在使用AspectJ，你就已经拥有这样的切面而且想要重用它们。</p>
<p>作为演示，我会重写我们早先例子的一部分，把切入点放在一个AspectJ切面中：</p>
<pre>public aspect LibraryAspect {<br /><br />    pointcut getter() :<br />                <font color="#0000ff">execution(public !void get*());<br /> ...</font><br /> }</pre>
<p>这个切面用Aspect语言编写，因此需要由AspectJ ajc编译器来编译。请注意我们可以使用<strong>aspect</strong>和<strong>pointcut</strong>关键词。</p>
<p>我们可以像下面这样，在被用在Spring中的@AspectJ 切面中，引用这个切面。请注意我们使用了这个切面的FQN，它通常会被打包在某个位于类路径的JAR文件中：</p>
<pre>@Aspect<br /> <font color="#660033"><strong>public class</strong></font> PointcutReuse {<br />    @After(<font color="#0000ff">&quot;mycompany.mypackage.LibraryAspect.getter()&quot;</font>)<br />   <font color="#660033"><strong>public void</strong></font> getterCalled(JoinPoint jp) {<br />      System.<font color="#0000ff">out</font>.println(<font color="#0000ff">&quot;Method &quot;</font> + jp.getSignature().getName() +<br />            <font color="#0000ff"> &quot; is a getter&quot;</font>);<br />   }</pre>
<p>这个类，在另一方面，可以使用javac进行编译并由Spring应用。</p>
<p>你也可以在Spring XML中引用AspectJ 切面。正如你能看到的，Spring 2.0 AOP和AspectJ集成得非常紧密，虽然Spring AOP提供了一个完整的运行时，而不需要使用AspectJ编译器或编织器。</p>
<p>如果你有非常复杂的切入点表达式，那使用AspectJ库的切面是最好的实践，因为那样Aspect语言和工具支持是非常引人注目的。</p>
<h3>最佳实践</h3>
<p>那么这对Spring用户意味着什么？</p>
<p>很希望你同意AOP解决了企业软件中很重要的问题，而且你意识到AspectJ编程模型相比较AOP或者任何可用于拦截的选择，是多么的强大和优雅。</p>
<p>你没有必要把你已有的Spring MethodInterceptors或者其他的通知实现迁移到新的编程模型：它们仍然能工作的很好。但再往后，应该采用新的编程模型，它会更加引人注目。</p>
<blockquote><strong>如果你在使用ProxyFactoryBean或者TransactionProxyFactoryBean来一次一个地配置代理，你会发现自动代理（它在Spring 2.0中变得更容易更自然）能够显著减少Spring配置的工作量，以及在团队成员间更好的分工。</strong></blockquote>
<h3>运行时看起来怎样？</h3>
<p>虽然用法模型看起来不同，但记住概念很重要&mdash;&mdash;连接点、切入点和通知&mdash;&mdash;就跟Spring自2003年已经实现的Spring AOP和AOP Alliance API中的一模一样。Spring AOP对这些概念一直有对应的接口。</p>
<p>也许更令人惊讶的是，表面以下的实现实际上更加相同。新的编程模型，支持AspectJ结构，构建于已有的Spring AOP运行时之上。Spring AOP一直非常灵活，因此这不需要什么显著的改变。（org.springframework.aop.framework.Advised接口仍然能够用来查询和修改AOP代理的状态，就像Spring1.x中那样。）</p>
<p>这意味着你能够使用AspectJ风格的切面，混合和匹配AOP Alliance和Spring AOP 切面：如果你想要支持已有的切面这尤其重要。</p>
<p>让我们增加编程式创建代理的例子来演示这个。我们会增加一个传统的Spring AOP风格的MethodInterceptor：</p>
<pre>Person tony = <font color="#660033"><strong>new</strong></font> Person();<br /> tony.setName(<font color="#0000ff">&quot;Tony&quot;</font>);<br /> tony.setAge(53);<br /><br />  AspectJProxyFactory ajpf = <font color="#660033"><strong>new</strong></font> AspectJProxyFactory(tony);<br /> ajpf.addAspect(<font color="#660033"><strong>new</strong></font> AnnotatedBirthdayCardSender());<br /> Person proxy = ajpf.getProxy();<br /> ajpf.addAdvice(<font color="#660033"><strong>new</strong></font> MethodInterceptor() {<br /> <font color="#660033"><strong>public</strong></font> Object invoke(MethodInvocation mi) <font color="#660033">throws</font> Throwable {<br />   System.<font color="#0000ff">out</font>.println(<font color="#0000ff">&quot;MethodInterceptor: Call to &quot;</font> + mi.getMethod());<br />   <font color="#660033"><strong>return</strong></font> mi.proceed();<br />   }<br /> });</pre>
<p>这会产生下面的输出，来自于MethodInterceptor的输出（没有切入点，匹配所有的方法调用）和来自于@AspectJ风格编写的BirthdayCardSender的输出混杂在一起。</p>
<pre>MethodInterceptor: Call to public void<br /> com.interface21.spring2.ioc.Person.birthday()<br /> MethodInterceptor: Call to public java.lang.String <br />com.interface21.spring2.ioc.Person.getName()<br /> MethodInterceptor: Call to public int<br />com.interface21.spring2.ioc.Person.getAge()<br /> I will send a birthday card to Tony; he has just turned 54</pre>
<h3>向着AOP统一</h3>
<p>Spring 2.0给AOP的世界带来一种新的受欢迎的统一。第一次，切面的实现独立于它的部署模型。我们看到的每一个@AspectJ例子都能使用AspectJ编译器编译，或者使用AspectJ加载时织入来使用，也能被Spring应用。在Spring的精神中，我们有一个能够跨越不同运行时场景的编程模型。</p>
<p>而且如果你想要采用AspectJ本身，这会有正常的进步，因为Spring把AspectJ切入点表达式概念带给了更广泛的受众。</p>
<p>你什么时候应该使用AspectJ呢？下面是一些指示：</p>
<ul>
    <li>你想要通知细粒度的对象，它们可能不会被Spring容器实例化。 </li>
    <li>除了公有方法的执行，你想要通知连接点，比如字段访问或者对象创建。 </li>
    <li>你想要以透明的方式通知自调用。 </li>
    <li>当一个对象需要被通知会被多次调用，而且不接受任何代理性能负载。（在这个基础上做决定前要小心基准：Spring AOP代理的负载在通常使用中是无法觉察到的。） </li>
    <li>你想要使用AspectJ的能力来声明由编译器标记的警告或者错误。这对架构增强尤其有用。 </li>
</ul>
<p>没有必要有什么或者的选择。同时使用AspectJ和Spring AOP是可能的：它们并不冲突。</p>
<h2>Java 5</h2>
<p>Spring 2.0保持向后对Java1.3和1.4的兼容。然而，Java 5带来越来越多的新特性。</p>
<p>其中一些，比如已经讨论过的类型推断，可以随意使用。而其他的需要自己来选择。让我们快速预览其中的一些。</p>
<h3>新的API</h3>
<p>大量的新的API在核心功能上提供Java 5的功能，这些核心功能继续运行在Java的早些版本上。</p>
<p>尤其是：</p>
<ul>
    <li>SimpleJdbcTemplate：和熟悉的JdbcTemplate类似的新类，这使得JDBC使用更加简单。 </li>
    <li>AspectJProxyFactory：和ProxyFactory类似的新类，设计用来使用@AspectJ 切面以编程方式创建代理。 </li>
</ul>
<p>随着时间延续，这样的类的数目会越来越多。</p>
<p>SimpleJdbcTemplate是用来例证的。让我们看一下在调用一个计算总数功能时的效果。在Java 5之前使用JdbcTemplate，我们需要在一个数组中封装绑定参数，就像下面这样：</p>
<pre>jdbcTemplate.queryForInt(&quot;SELECT COUNT(0) FROM T_CLIENT WHERE TYPE=? AND CURRENCY=?&quot;,<br />   new Object[] { new Integer(13), &quot;GBP&quot; }<br /> );</pre>
<p>如果我们使用Java 5，自动装箱去除了一点困扰，因为我们不再需要原始封装器类型。这仅仅来自于语言特性，而不需要Spring提供任何新的东西：</p>
<pre>jdbcTemplate.queryForInt(&quot;SELECT COUNT(0) FROM T_CLIENT WHERE TYPE=? AND CURRENCY=?&quot;,<br />   new Object[] { 13, &quot;GBP&quot; }<br /> );</pre>
<p>然而，通过采用Java 5我们能够完全不再需要对象数组。下面的例子显示了SimpleJdbcTemplate是如何使用变参来绑定变量的，意味着开发者可以提供任意数目的变参，而不需要数组：</p>
<pre>simpleJdbcTemplate.queryForInt(&quot;SELECT COUNT(0) FROM T_CLIENT WHERE TYPE=? AND CURRENCY=?&quot;,<br />   13, &quot;GBP&quot;<br /> );</pre>
<p>作为增加的一个好处，我们不再需要区分带有绑定和没绑定参数的情况。虽然这需要JdbcTemplate上的两个方法，来避免需要给执行SQL的重载方法传入一个空的Object数组，但通过SimpleJdbcTemplate，框架代码可以检查变参的长度。这样下面的例子调用同一个方法：</p>
<pre>simpleJdbcTemplate.queryForInt(&quot;SELECT COUNT(0) FROM T_CLIENT&quot;);</pre>
<p>还有更显著的好处。泛型使得签名更加清晰，并去除强制转换。比如，JdbcTemplate的queryForMap()方法返回一个ResultSet中的从列名到列值的Map。当它是SimpleJdbcTemplate上方法签名的显式部分时，这就变得清楚得多：</p>
<pre>public Map&lt;String, Object&gt; queryForMap(String sql, Object... args)<br />                          throws DataAccessException</pre>
<p>如果是返回这种map的列表的方法，那还会更清楚：</p>
<pre>public List&lt;Map&lt;String, Object&gt;&gt; queryForList(String sql, Object ... args)<br />                        	throws DataAccessException</pre>
<p>增加SimpleJdbcTemplate的目标之一是，提供那些最经常使用的方法。JdbcTemplate是Spring中最大的类之一，有很多的方法，其中一些是用于非常深奥的用途。在这种高级的情况下，根据全部问题的复杂性，语言语法糖就可能不再重要。对于这样的案例，SimpleJdbcTemplate封装了一个JdbcTemplate实例，通过getJdbcOperations()方法可以访问到。</p>
<p>为了支持扩展DAO支持类的用法模型，Spring 2.0提供了SimpleJdbcDaoSupport类，提供一个预先配置的JdbcTemplate。SimpleJdbcTemplate也象JdbcTemplate一样很易于实例化或者直接注入，通过仅仅提供一个javax.sql.Datasource实现&mdash;&mdash;这是Spring对所有关系型数据库访问的支持的开始点。就像JdbcTemplate，SimpleJdbcTemplate可以当作一个类库来使用，而无需使用Spring的其他部分。</p>
<h3>注解</h3>
<p>我们首先在Spring1.2中引入注解，作为一个可选的特性，而且我们逐渐增加更多。</p>
<p>我已经提到过来自于AspectJ的对AOP的注解的使用。它提供一种在单个代码模块中表达切入点和通知的优雅的方式。</p>
<p>Spring还提供许多它自己的某些领域的注解，比如事务管理。下面这些在1.2中引入：</p>
<ul>
    <li>@Transactional:标记一个类，接口或者方法为可事务的。 </li>
    <li>不同的注解，包括在org.springframework.jmx.export.annotation包中的@ManagedResource，识别操作、属性和对象来到处以便JMX管理。 </li>
</ul>
<p>下面是2.0中最重要的新的注解：</p>
<ul>
    <li>@Configurable：表明某个特殊的对象应该在构建后使用Spring依赖注入，虽然它不是由Spring实例化的。驱动一个AspectJ DI切面，这在本文的第二部分中描述。 </li>
    <li>@Required：指明所需的某个JavaBean 的setter方法。为了采用这个增强，在你的应用上下文中定义RequiredAnnotationBeanPostProcessor。在Spring的非入侵编程模型精神中，以及与已有代码一起共同工作的能力，Spring也能加强其他注解的使用来指明某个所需的属性，通过RequiredAnnotationBeanPostProcessor的配置。 </li>
  