<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>陌上花开</title>
    <description>闲散身无事，风光且乐游；断云江上月，解缆海中舟。</description>
    <link>http://pinco.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>使用Axis开发Web Service程序</title>
        <author>andyu2008</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://pinco.javaeye.com">andyu2008</a>&nbsp;
          链接：<a href="http://pinco.javaeye.com/blog/166922" style="color:red;">http://pinco.javaeye.com/blog/166922</a>&nbsp;
          发表时间: 2008年03月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          为了更多喜爱开发的程序员也能迅速了解Web Service的开发，我这里整理了一些通过Axis开发Web Service的一些要点，希望能让不熟悉Web Service的开发人员能够迅速掌握Web Service。 <br /><br />    一、Axis环境的安装 <br /><br />    1、安装环境 J2SE SDK 1.4，Tomcat 5.0，eclipse 3.2。 <br />    2、到 http://xml.apache.org 网站下载Axis安装包。 <br />    3、将Axis相关包文件放在WEB-INF\lib目录下。 <br />    4、Axis可选的包：activation.jar； mail.jar； xmlsec-1.4.Beta1.jar拷贝到WEB-INF目录下，生成客户端时候需要使用。 <br /><br />    Axis支持三种web service的部署和开发，分别为： <br /><br />    1、Dynamic Invocation Interface （DII） <br />    2、Dynamic Proxy方式 <br />    3、Stubs方式 <br /><br />    前两种方式我就不介绍了，因为大多数的使用不会是前两种方式，一般都是使用Stubs方式，因此我就主要就介绍一下第三种方式。注意，我自己的Java源代码是放在D：\workspace\test\目录下，Axis相关包文件放在D：\workspace\test\WEB-INF目录下。 <br /><br />    二、编写wsdd发布web服务，编写stub client访问web服务 <br /><br />    1、编写服务端程序server，SayHello.java，编译server.SayHello.java <br /><br /><pre name="code" class="java">package server;
public class SayHello
{
public String getName(String name)
{
return "hello "+name;
}
} </pre><br /><br />    2、编写wsdd文件 <br /><br />    deploy.wsdd文件内容如下： <br /><br /><pre name="code" class="java">&lt;deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
&lt;service name="SayHello" provider="java:RPC">
&lt;parameter name="className" value="server.SayHello.getName"/>
&lt;parameter name="allowedMethods" value="*"/>
&lt;/service>
&lt;/deployment> </pre><br /><br />    3、发布服务： <br /><br />    编辑一个deploy.bat，Axis_Lib为axis.jar路径。内容如下： <br /><br /><pre name="code" class="java">set Axis_Lib=D:\workspace\test\WEB-INF\lib
set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%
set Axis_Servlet=http://localhost:8080/test/servlet/AxisServlet 
%Java_Cmd% org.apache.axis.client.AdminClient -l%Axis_Servlet% deploy.wsdd </pre><br /><br />    执行这个批处理文件，这时候，如果提示成功的话，访问http://localhost:8080/test/services 就会显示服务列表。 <br /><br />    4、生成客户端client stub文件 <br /><br />    在浏览器上访问服务器端的服务，可以下载到WSDL文件，通过Axis的相关工具，可以自动从WSDL文件中生成Web Service的客户端代码。 <br /><br />    编写一个WSDL2Java.bat文件，其内容如下： <br /><br /><pre name="code" class="java">set Axis_Lib=D:\workspace\test\WEB-INF\lib
set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%
set Output_Path=D:\workspace\test\src
set Package=server.SayHello
%Java_Cmd% org.apache.axis.wsdl.WSDL2Java -o%Output_Path% -p%Package% SayHello.wsdl </pre><br />    执行这个批处理文件就可以生成client stub. <br /><br />    生成的stub client文件列表为：SayHello.java，SayHelloService.java，SayHelloServiceLocator.java，SayHelloSoapBindingStub.java . <br /><br />    5、编写客户端程序，编译并执行 <br /><br />    下面是一段junit测试客户端代码。 <br /><br /><pre name="code" class="java">import java.net.URL;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class TestWSClient extends TestCase {
public TestWSClient(String string) {
super(string);
}
public void SayHelloClient() throws Exception {
SayHelloService service = new SayHelloServiceLocator();
SayHello_PortType client = service.getSayHello() ;
String retValue = client.getName("clientname");
System.out.println(retValue);
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new TestWSClient("SayHelloClient"));
return suite;
}
} </pre><br /><br />    至此，整个服务器端和客户端的Web Service框架代码就完成了，剩下的就是在里面加入你的业务代码了，怎么样，Web Service并不难开发吧。
          <br/>
          <span style="color:red;">
            <a href="http://pinco.javaeye.com/blog/166922#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>Mon, 03 Mar 2008 14:13:32 +0800</pubDate>
        <link>http://pinco.javaeye.com/blog/166922</link>
        <guid>http://pinco.javaeye.com/blog/166922</guid>
      </item>
      <item>
        <title>portlets 起航</title>
        <author>andyu2008</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://pinco.javaeye.com">andyu2008</a>&nbsp;
          链接：<a href="http://pinco.javaeye.com/blog/163010" style="color:red;">http://pinco.javaeye.com/blog/163010</a>&nbsp;
          发表时间: 2008年02月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Portlets<br />“Portlets 是一种Web组件－就像servlets－是专为将合成页面里的内容聚集在一起而设计的。通常请求一个portal页面会引发多个portlets被调用。每个portlet都会生成标记段，并与别的portlets生成的标记段组合在一起嵌入到portal页面的标记内。”（摘自Portlet规范， JSR 168）<br /><br />本文探讨了以下内容：<br />1.        Portal页面的元素<br />2.        Portal是什么？<br />3.        Portlets是什么？<br />4.        开发“Hello World” Portlet<br />5.        在Pluto上部署HelloWorld Portlet<br />6.        如何创建Portal页面<br />7.        结束语<br />8.        资源<br /><br />　　Portlet规范将portlet定义为一种“基于Java技术的web组件，由处理请求和生成动态内容的portlet容器管理”。这段话听起来是不是有些费解？本文将说明portlets是什么以及能用它们做什么。<br /><br /><br />图1显示了在访问一个portal服务器时浏览器中页面的样子。<br /><br />?????<br />图1 典型的portal服务器的页面（点击查看原图）<br /><br />　　如果仔细查看浏览器里的页面，就会看到页面是由不同的“窗口”组成的。一个窗口用于刷新天气，另一个用于新闻，还有一个用于刷新股价，等等。这里的每一个窗口都代表了一个portlets。如果看得再仔细些，还会发现每个窗口都有一个标题条和一些按钮，包括最小化和最大化按钮。<br /><br />　　在系统里，这些窗口是相互独立开发、各不同的应用。新闻portlet的开发者创建应用并打包成war格式的文件,随后portal服务器的管理员在服务器上部署该war文件并创建页面，接下来每个用户会选择在他的页面里有哪些应用。例如，如果用户对股价不感兴趣而对体育感兴趣，他可以用“体育”窗口替换“股价”窗口。<br /><br />　　Portlet技术需要学习许多新概念，本文不可能全都涵盖，因此本文分为两部分。在第一部分里我们详细说明portals和portlets，并开发一个简单的“Hello World”portlet；在第二部分我们将探讨一些高级主题。<br /><br />　　我们将用Apache的Pluto服务器（Portlet API 1.0规范的参考实现）来测试我们的示例portlets，我们还会花些时间探讨如何安装和使用Pluto服务器。<br /><br />Portal页面的元素<br /><br />图2显示了Portal页面的各种元素。<br /><br />image<br />图2 portal页面的元素<br /><br />　　每个portlet页面由一个或多个portlet窗口组成，每个portlet窗口又分为两部分：一个是外观，它决定了portlet窗口的标题条、控制和边界的样式；另一个是portlet段，它由portlet应用填充。<br /><br />　　Portal服务器决定了portal页面的整体观感，像标识、标题条颜色、控制图标等。通过修改几个JSP和css模板文件就可以改变portal的整个观感。我们将在“如何创建portal页面”部分对此做深入讨论。<br /><br />Portal是什么？<br /><br />　　在了解portlet之前有必要先了解portal。在Portlet规范里是这样讲的：“portal是一种web应用，通常用来提供个性化、单次登录、聚集各个信息源的内容，并作为信息系统表现层的宿主。聚集是指将来自各个信息源的内容集成到一个web页面里的活动”。<br /><br />　　Portal的功能可以分为三个主要方面：<br />1.        Portlet 容器：Portlet容器与servlet容器非常类似，所有的portlet都部署在portlet容器里，portlet容器控制portlet的生命周期并为其提供必要的资源和环境信息。Portlet容器负责初始化和销毁portlets，向portlets传送用户请求并合成响应。<br />2.        内容聚集：Portlet规范中规定portal的主要工作之一是聚集由各种portlet应用生成的内容，我们将在“如何创建Portal页面”部分对此做进一步讨论。<br />3.        公共服务：portlet服务器的一个强项是它所提供的一套公共服务。这些服务并不是portlet规范所要求的，但portal的商业实现版本提供了丰富的公共服务以有别于它们的竞争者。在大部分实现中都有望找到的几个公共服务有：<br />         o 单次登录：只需登录portal服务器一次就可以访问所有其它的应用，这意味着你无需再分别登录每一个应用。例如一旦我登录了我的intranet网站，我就能访问mail应用、IM消息应用和其它的intranet应用，不必再分别登录这些应用。<br />　　Portal服务器会为你分配一个通行证库。你只需要在mail应用里设定一次用户名和密码，这些信息将以加密的方式存储在通行证库中。在你已登录到 intranet网站并要访问mail应用的时候，portal服务器会从通行证库中读取你的通行证替你登录到mail服务器上。你对其它应用的访问也将照此处理。<br />          o个性化：个性化服务的基本实现使用户能从两方面个性化她的页面：第一，用户可以根据她的自身喜好决定标题条的颜色和控制图标。第二，用户可以决定在她的页面上有哪些portlets。例如，如果我是个体育迷，我可能会用一个能提供我钟爱球队最新信息的 portlet来取代股票和新闻portlets。<br />      　　一些在个性化服务方面领先的商业实现版本允许你建立为用户显示什么样的应用所依据的标准（如收入和兴趣）。在这种情况下，可以设定一些像“对任何收入为X的用户显示馈赠商品的portlet”和“对任何收入为X的用户显示打折商品的portlet”这样的商业规则。<br /><br />　　      此外还有一些公共服务，比如机器翻译，是由portal服务器将portlet生成的内容翻译为用户要求的语言。大部分的商业portal服务器都支持手持设备访问并具有针对不同的浏览终端生成不同内容的能力。<br /><br />Portlets是什么？<br /><br />　　与servlets类似，portlets是部署在容器内用来生成动态内容的web组件。从技术角度讲portlet是一个实现了javax.portlet.Portlet接口的类，它被打包成war文件格式部署到portlet容器里。<br /><br />　　Portlets在以下方面与servlets相似：<br />1.        portlets由特定的容器管理。<br />2.        portlets生成动态内容。<br />3.        portlet的生命周期由容器管理。<br />4.        portlets通过请求/响应模式与web客户端交互。<br /><br />　　Portlets在以下方面与servlets相异：<br />1.        portlets只能生成标记段，而不是整个文档。<br />2.        portlets没有可供直接访问的URL地址。不过你还是能够让别人通过URL访问到portlet，你可以把包含该portlet的页面的URL发给他。<br />3.        portlets 不能随意地生成内容，这是因为portlet生成的内容最终要成为portal页面的一部分。如果portal服务器要求的是html/text类型，那么所有的portlets都应生成html/text类型的内容。再比方说，如果portal服务器要求的是WML类型，那么所有的portlets都应生成WML类型的内容。<br /><br />　　portlets还提供了一些附加的功能：<br />1.        设置参数的持久化存储：portlets提供了一个PortletPreferences对象用来保存用户的设置参数。这些参数被存入一个持久化数据库，这样服务器重启后数据依然有效。开发者不必关心这些数据存储的具体实现机制。<br />2.         请求处理：portlets提供了更为细粒度的请求处理。对于用户在portlet上动作时向该portlet发出的请求(一种称为活跃期的状态)，或者因用户在其它portlet上动作而引发的刷新页面请求，Portal服务器提供了两种不同的回调方法来处理。<br />3.        Portlet 模式：portlets用模式的概念来表示用户在做什么。在使用mail应用的时候，你可能会用它来读信、写信或检查信件――这些都是mail应用的预定功能，Portlets通常以VIEW模式提供这些功能。但还有一些活动，像指定刷新时间或（重新）设置用户名和密码，这些活动允许用户定制应用的行为，因此它们用的是EDIT模式。Mail应用的帮助功能用的是HELP模式。<br /><br />　　如果仔细想想其实这里面并没有什么新东西，它们反而大部分都是普通的业务需求。Portlet规范的作用在于它提供了一个抽象层，这才是它对所有与之相关的人－最终用户、开发者和管理员－的价值所在。<br /><br />　　作为一个开发者，我会将所有与VIEW模式有关的业务逻辑放入doView()方法，将与应用配置有关的业务逻辑放入doEdit()方法，将与帮助有关的逻辑放入doHelp()方法<br /><br />　　这就简化了管理员对portlet应用的访问控制管理，因为他只需改变portlet的访问权限就能决定用户能做什么。例如，如果mail应用的一个用户能够在EDIT模式下设定用户名和密码，那么就可以断定他具有EDIT模式访问权限。<br /><br />　　不妨考虑这样一种情形：我是一个intranet网站的管理员，我的公司买了一个能显示新闻信息的第三方portlet应用，该应用允许用户指定跟踪新闻更新的URL地址，我想借助它为用户显示公司的内部新闻。另一个需求是我不想让用户通过该应用来跟踪任何其它的新闻信息来源。作为管理员，我可以为所有的用户指定一个用于内部新闻更新的URL地址，同时通过改变portlet应用的部署描述符来取消其它人修改该地址的权限。<br /><br />　　由于所有的portlet应用都具有相似的UI界面，因此采用portlets可使网站对最终用户更具吸引力。如果她想阅读任何一个应用的帮助信息，她可以点击帮助按钮；她也知道点击编辑按钮能让她进入应用的配置屏。标准化的用户界面使你的portlet应用更引人。<br /><br />4.         窗口状态：窗口状态决定了portal页面上留给portlet生成内容的空间。如果点击最大化按钮，portlet将占据整个屏幕，成为用户唯一可用的 portlet；而在最小化状态，portlet只显示为标题条。作为开发者应当根据可用空间的大小来定做内容。<br /><br />5.        用户信息：通常portlets向发出请求的用户提供个性化的内容，为了能更加行之有效，portlets需要访问用户的属性信息，如姓名、email、电话等。Portlet API为此提供了用户属性的概念，开发者能够用标准的方式访问这些属性，并由管理员负责在这些属性与真实的用户信息数据库（通常是LDAP服务器）之间建立映射关系。<br /><br />　　我们将在本文的第二部分深入讨论这些特点－请求处理、用户信息和portlet模式。<br /><br />开发"Hello World" Portlet<br /><br />　　现在我们就来开发一个简单的HelloWorld portlet。<br />1.        创建一个名为HelloWorld的web项目，它与通常的servlet项目类似，有一个/WEB-INF/web.xml文件作为项目的部署描述符。<br /><br />2.        在build path里加入portlet-api-1.0.jar文件，该jar文件是Pluto发行包的一部分。<br /><br />3.        在Source文件夹中按如下内容创建HelloWorld.java文件：<br /><br />public class HelloWorld extends GenericPortlet{<br />  protected void doView(RenderRequest request,<br />  RenderResponse response) throws<br />  PortletException, IOException {<br />        response.setContentType("text/html");<br />        response.getWriter().println("Hello Portlet");<br />        }<br />}<br /><br /><br /><br />　　每个portlet都要实现Portlet接口，该接口为portlet定义了生命周期方法。由于不想覆盖所有这些方法，我们只对 GenericPortlet类进行扩展，它是一个实现了Portlet接口的适配器类。GenericPortlet类提供了所有生命周期方法的默认实现，所以我们只需实现我们所需要的方法。<br /><br />　　我们在 HelloWorld portlet里要做的只是显示“Hello Portlet”，所以我们将覆盖GenericPortlet类的doView()方法，该方法以PortletRequest 和 PortletResponse作为参数。在doView()方法中首先调用response.setContentType()以通知portlet容器该portlet将要生成何种类型的内容－如果不这样做就会导致IllegalStateException异常。一旦设置了内容的类型，就可以从 response对象中获得PrintWriter并开始写入。<br /><br />4.        每个portlet应用在/WEB-INF文件夹中都有一个portlet.xml文件，它是portlet应用的部署描述符。按以下内容创建portlet.xml文件：<br /><br />&lt;portlet><br />  &lt;description>HelloWorldDescription<br />        &lt;/description><br />    &lt;portlet-name>HelloWorld<br />        &lt;/portlet-name><br />    &lt;display-name>Hello World<br />        &lt;/display-name><br /><br />    &lt;portlet-class>com.test.HelloWorld<br />        &lt;/portlet-class><br />    &lt;expiration-cache>-1<br />        &lt;/expiration-cache><br />        &lt;supports><br />          &lt;mime-type>text/html&lt;/mime-type><br />      &lt;portlet-mode>VIEW<br />          &lt;/portlet-mode><br />        &lt;/supports><br />    &lt;supported-locale>en<br />        &lt;/supported-locale><br /><br />        &lt;portlet-info><br />          &lt;title>Hello World&lt;/title><br />          &lt;short-title>Hello World<br />          &lt;/short-title><br />          &lt;keywords>Hello,pluto&lt;/keywords><br />      &lt;/portlet-info><br />&lt;/portlet><br /><br /><br /><br />　　&lt;portlet-name>元素声明了portlet的名字，&lt;portlet-class>元素指定了portlet的全限定类名，&lt;expiration-cache>元素以秒为单位指定了内容超期的时间。这里面有一点需要注意：你在portlet上的某些动作可能会导致内容刷新，这与缓存时间无关。<br />　　&lt;supports>元素指定对于给定的&lt;mime-type>有哪些模式可供支持。在示例中我们假定HelloWorld只能生成text/html类型的内容，且只有view模式可支持该内容类型。如果要增加对其它内容类型的支持，需要添加新的&lt;support>元素并指定支持该MIME类型的模式有哪些。通常portlet对于text/html类型有 VIEW、EDIT和HELP模式可供支持，而对于WML MIME类型则只有VIEW模式。<br />　　还可以用&lt;supported- locale>元素来指定portlet支持哪些本地化。&lt;title>元素用来指定portlet的标题。如果要对标题做国际化处理，可以用元素&lt;resource-bundle>指定资源（比例properties文件）的文件名。在这种情况下，容器将根据用户所在的地区从适当的properties文件中选择标题。<br /><br />5.        每个portlet应用都是一个web应用，因此除了portlet.xml文件之外还需要有web.xml文件。<br /><br />&lt;web-app><br />  &lt;display-name>Hello World Portlet<br />  &lt;/display-name><br />  &lt;welcome-file-list<br />    &lt;welcome-file>index.jsp<br />        &lt;/welcome-file><br />  &lt;/welcome-file-list><br />&lt;/web-app><br /><br /><br /><br />6.        接下来将这些文件进行编译并打包为war文件。你可以自己完成这些工作，或者下载带有build.xml 的示例代码（参见“资源”部分）来创建war文件。<br />在Pluto上部署HelloWorld Portlet<br /><br />　　Pluto尚处于开发阶段的早期，因此还没有一套易于使用的管理工具。为了能使用Pluto服务器，需要将编译和源代码两个版本都下载。需要注意的是以下说明是针对Windows平台的，Unix用户通过修改斜杠符号和执行sh shell脚本（不是bat批命令文件）会得到类似的结果。<br /><br />1.        创建一个文件夹，比如C:\PlutoInstallation。<br />2.        从Pluto的网站下载pluto-1.0.1-rc1.zip和pluto-src-1.0.1-rc1.zip。<br />3.        将pluto-1.0.1-rc1.zip解压到C:\PlutoInstallation.文件夹，它应被解压到C:\PlutoInstallation\pluto-1.0.1-rc1文件夹下。<br />4.        执行C:\PlutoInstallation\pluto-1.0.1-rc1\bin\startup.bat启动Pluto，现在可以通过地址http://localhost:8080/pluto/portal访问Pluto服务器。<br />5.        将pluto-src-1.0.1-rc1.zip解压到C:\PlutoInstallation\PlutoSrc文件夹。<br />6.         进入C:\PlutoInstallation\PlutoSrc文件夹，执行maven distribute:all.，编译并下载运行常规管理任务所必需的相关资源文件。现在可以将HelloWorldPortlet.war作为 portlet进行安装了。<br />7.        首先将HelloWorldPortlet.war文件拷贝到C:\PlutoInstallation\portlets目录，如果没这个目录就创建它。<br />8.        将C:\PlutoInstallation\plutosrc\build.properties.sample更名为build.properties。<br />9.        编辑build.properties，将maven.tomcat.home指向Pluto编译版的安装位置，在本例中应改为maven.tomcat.home=C:/PlutoInstallation/pluto-1.0.1-rc1。<br />10.         为了安装portlet，进入C:\plutoInstallation\plutosrc\deploy文件夹，执行maven deploy -Ddeploy=c:\PlutoInstallation\portlets\HelloWorldPortlet.war，应能看到“build successful”信息。<br />11.        在C:\PlutoInstallation\pluto-1.0.1-rc1\webapps文件夹下，应该有一个HelloWorldPortlet文件夹。<br />12.        现在进入C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\HelloWorld\WEB-INF\ folder文件夹，打开portlet的web.xml文件，你会发现里面自动多了几行，如下所示：<br /><br />&lt;servlet><br />  &lt;servlet-name>HelloWorld&lt;/servlet-name><br />     &lt;display-name>HelloWorld Wrapper&lt;/display-name><br />      &lt;description>Automated generated<br />      Portlet Wrapper&lt;/description><br />      &lt;servlet-class>org.apache.pluto.core.PortletServlet<br />      &lt;/servlet-class><br />      &lt;init-param><br />         &lt;param-name>portlet-class&lt;/param-name><br />         &lt;param-value>com.test.HelloWorld<br />         &lt;/param-value><br />      &lt;/init-param><br />      &lt;init-param><br />         &lt;param-name>portlet-guid&lt;/param-name><br />         &lt;param-value>HelloPluto.HelloWorld<br />         &lt;/param-value><br />      &lt;/init-param><br />&lt;/servlet><br /><br /><br />13.         接下来我们将该portlet加到页面里。进入C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\pluto \WEB-INF\data文件夹，可以看到有两个XML文件：pageregistry.xml和 portletentityregistry.xml。<br />14.        portletentityregistry.xml包含了portlet的定义，在该文件中加入以下几行：<br /><br /> &lt;application id="5"><br />   &lt;definition-id>HelloWorld&lt;/definition-id><br />     &lt;portlet id="1"><br />       &lt;definition-id>HelloWorld.HelloWorld&lt;/definition-id><br />     &lt;/portlet><br />&lt;/application><br /><br /><br />　　应用的&lt;definition-id>应为web应用所在文件夹的名字，portlet的&lt;definition-id>应与web.xml中生成的portlet-guid相一致。<br />15.        pageregistry.xml定义了页面中包含了哪些portlets，对该文件做如下改动：<br /><br />  &lt;fragment name="p2" type="portlet"><br />    &lt;property name="portlet" value="5.1"/><br />&lt;/fragment><br /><br /><br />16.        执行shutdown命令和startup命令重启Pluto服务器，返回到地址http://localhost:8080/pluto/portal并点击“Test Link”－此时页面中将出现我们的<br /><br />HelloWorld portlet。<br /><br />图3的右侧显示了HelloWorld portlet看上去的样子。<br /><br />image<br />图3 portlet的屏幕截图<br /><br />如何创建Portal页面<br /><br />图4显示了portal容器如何将分离的portlets组装为页面。<br /><br />image<br />图4 创建Portal页面<br /><br />　　大部分的portal服务器基本上都是部署于应用服务器上的web应用，通过servlet来处理访问portal服务器的请求。查看一下Pluto的安装目录就会发现Pluto不过是一个部署于Tomcat服务器上的一个普通web应用，再看看C:\PlutoInstallation\pluto- 1.0.1-rc1\webapps\pluto\WEB-INF\web.xml会发现所有发往Pluto服务器的请求都被映射到 org.apache.pluto.portalImpl.Servlet上。<br /><br />　　在本文开始部分“Portal页面的元素”中，我们提到portal页面由两部分组成。一部分是由页面中的portlets生成的内容，另一部分是由portal服务器生成的内容。<br /><br />　　在Pluto里，只要用户发出请求，就会由servlet进行控制，根据用户所请求的页面来确定需要显示的portlets的列表。一旦生成了列表，servlet就将控制转给这些portlets线程并收集由它们生成的内容。<br /><br />　　对于由portal服务器生成的内容（像portal网站的观感及每个portlet的外观和控制之类）则取决于C:\ PlutoInstallation\pluto-1.0.1-rc1\webapps\pluto\WEB-INF\aggregation文件夹下的 JSP文件。RootFragment.jsp是主JSP文件，它决定了整体的观感和对齐方式；它还包含了Heads以定义在生成的页面中的&lt; HEAD>标签里的内容。TabNavigation.jsp用来选择在banner中该显示什么（默认情况下在banner显示列表中也包扩了 pluto.png图片）。TabNavigation.jsp用来确定portal网站的导航方案。这意味着只需改动该文件夹下少量的几个JSP文件，就能改变整个portal网站的观感。<br /><br />　　Pluto根据pageregistry.xml中的设置确定页面中有多少行，并用 RowFragment.jsp去填充。ColumnFragment.jsp用来填充每个栏目。PortletFragmentHeader.jsp用来填充每个portlet的页头，像标题条及最大化和最小化控制。footer.jsp用来填充JSP的页脚。如果去看一下portal页面的HTML代码就会发现每个portlet窗口无非都是嵌入&lt;TD>标签的内容块。<br /><br />结束语<br /><br />　　任何一种新技术要想获得成功都应具备以下条件：首先，它能提升现有技术；其次，它能解决现有技术遇到的普遍问题；再次，它能提供多于一个的抽象层（有人说，每抽象出一层，问题就解决一半）。<br /><br />　　由于portlet与现有的应用服务器架构兼容，这对Portlet API来说是一次发展servlet技术的好机会。你可以从portlet里调用EJB，或者用它启动和参与由应用服务器控制的全局性事务。换句话说，在以商业逻辑为核心的领域里，portlet完全可以做得和servlet一样好。<br /><br />　　Portlets提供了一个抽象层，现在你不必再担心客户端使用了什么样的HTTP方法，也不必自己编写程序去捕获像点击按钮这样的客户端事件。最后但绝不是最次要的一点是，portlets以提供像单次登录、个性化等服务的方式解决了servlets不能解决的大部分问题。
          <br/>
          <span style="color:red;">
            <a href="http://pinco.javaeye.com/blog/163010#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>Mon, 18 Feb 2008 16:29:00 +0800</pubDate>
        <link>http://pinco.javaeye.com/blog/163010</link>
        <guid>http://pinco.javaeye.com/blog/163010</guid>
      </item>
      <item>
        <title>HttpClient学习</title>
        <author>andyu2008</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://pinco.javaeye.com">andyu2008</a>&nbsp;
          链接：<a href="http://pinco.javaeye.com/blog/162232" style="color:red;">http://pinco.javaeye.com/blog/162232</a>&nbsp;
          发表时间: 2008年02月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          　　今天学习HttpClient对HTTP方法的支持。<br />　　"方法"这个词的含义太丰富了，在学习之前先交待一下。首先，每个类中有方法，与属性相对，可以视作函数，为区分称之”类方法“；HTML语言的表单(FORM)中也定义了方法(method),常见的是GET和POST，用以指明表单中输入的数据上传服务器的方法，称之为”HTML方法“；HTTP协议中也有方法，可视作http客户端向服务器端发送的指令(至于服务器端收到指令后执行不执行或如何执行那是另一码事)，称之为HTTP方法。<br />　　前几篇HttpClient笔记中，我对方法这个词没有根据上下文做细致的说明，估计难为了那些看笔记的朋友了。:)<br /><br /><br />　　HttpClient支持的HTTP方法有8种，下面分述之。<br /><br /><br />1、Options<br /><br />　　HTTP方法Options用来向服务器发送请求，希望获得针对由请求URL(request url)标志的资源在请求/应答的通信过程可以使用的功能选项。通过这个方法，客户端可以在采取具体行动之前，就可对某一资源决定采取什么动作和/或以及一些必要条件，或者了解服务器提供的功能。这个方法最典型的应用，就是用来获取服务器支持哪些HTTP方法。<br />　　HttpClient中有一个类叫OptionsMethod，来支持这个HTTP方法，利用这个类的getAllowedMethods方法，就可以很简单地实现上述的典型应用。<br /><br />OptionsMethod options = new OptionsMethod("http://jakarta.apache.org");<br />// 执行方法并做相应的异常处理<br />...<br />Enumeration allowedMethods = options.getAllowedMethods();<br />options.releaseConnection();<br /><br /><br />2、Get<br /><br />HTTP方法GET用来取回请求URI（request-URI）标志的任何信息（以实体(entity)的形式），"get"这个单词本意就是”获取“的意思。如果请求URI指向的一个数据处理过程，那这个过程生成的数据，在应答中以实体的形式被返回，而不是将这个过程的代码的返回。<br />　　如果HTTP包中含有If-ModifiedSince, If-Unmodified-Since, If-Match, If-None-Match, 或 If-Range等头字段，则GET也就变成了”条件GET“，即只有满足上述字段描述的条件的实体才被取回，这样可以减少一些非必需的网络传输，或者减少为获取某一资源的多次请求（如第一次检查，第二次下载）。（一般的浏览器，都有一个临时目录，用来缓存一些网页信息，当再次浏览某个页面的时候，只下载那些修改过的内容，以加快浏览速度，就是这个道理。至于检查，则常用比GET更好的方法HEAD来实现。）如果HTTP包中含有Range头字段，那么请求URI指定的实体中，只有决定范围条件的那部分才被取回来。（用过多线程下载工具的朋友，可能比较容易理解这一点）<br />　　这个方法的典型应用，用来从web服务器下载文档。HttpClient定义了一个类叫GetMethod来支持这个方法，用GetMethod类中getResponseBody, getResponseBodyAsStream 或 getResponseBodyAsString函数就可以取到应答包包体中的文档（如HTML页面）信息。这这三个函数中，getResponseBodyAsStream通常是最好的方法，主要是因为它可以避免在处理下载的文档之前缓存所有的下载的数据。<br /><br />GetMethod get = new GetMethod("http://jakarta.apache.org");<br />// 执行方法，并处理失败的请求.<br />...<br />InputStream in = get.getResponseBodyAsStream();<br />// 利用输入流来处理信息。<br />get.releaseConnection();<br /><br />　　对GetMethod的最常见的不正确的使用，是没有将全部的应答主体的数据读出来。还有，必须注意要手工明确地将链接释放。<br /><br />3、Head<br /><br />　　HTTP的Head方法，与Get方法完全一致，唯一的差别是服务器不能在应答包中包含主体(message-body)，而且一定不能包含主体。使用这个方法，可以使得客户无需将资源下载回就可就以得到一些关于它的基本信息。这个方法常用来检查超链的可访问性以及资源最近有没有被修改。<br />　　HTTP的head方法最典型的应用，是获取资源的基本信息。HttpClient定义了HeadMethod类支持这个方法，HeadMethod类与其它*Method类一样，用 getResponseHeaders()取回头部信息，而没有自己的特殊方法。<br /><br />HeadMethod head = new HeadMethod("http://jakarta.apache.org");<br />// 执行方法，并处理失败的请求.<br />...<br />// 取回应答包的头字段信息.<br />Header[] headers = head.getResponseHeaders();<br /><br />// 只取回最后修改日期字段的信息.<br />String lastModified = head.getResponseHeader("last-modified").getValue();<br /><br /><br /><br />4、Post<br /><br />　　Post在英文有“派驻”的意思，HTTP方法POST就是要求服务器接受请求包中的实体，并将其作为请求URI的下属资源。从本质上说，这意味着服务器要保存这个实体信息，而且通常由服务器端的程序进行处理。Post方法的设计意图，是要以一种统一的方式实现下列功能：<br />对已有的资源做评注<br /><br />将信息发布到BBS、新闻组、邮件列表，或类似的文章组中<br /><br />将一块数据，提交给数据处理进程<br /><br />通过追加操作，来扩展一个数据库<br />这些都操作期待着在服务器端产生一定的“副作用”，如修改了数据库等。<br />　　HttpClient定义PostMethod类以支持该HTTP方法，在httpclient中，使用post方法有两个基本的步骤：为请求包准备数据，然后读取服务器来的应答包的信息。通过调用 setRequestBody()函数，来为请求包提供数据，它可以接收三类参数：输入流、名值对数组或字符串。至于读取应答包需要调用 getResponseBody* 那一系列的方法，与GET方法处理应答包的方法相同。<br />　　常见问题是，没有将全部应答读取（无论它对程序是否有用），或没有释放链接资源。
          <br/>
          <span style="color:red;">
            <a href="http://pinco.javaeye.com/blog/162232#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, 14 Feb 2008 14:57:02 +0800</pubDate>
        <link>http://pinco.javaeye.com/blog/162232</link>
        <guid>http://pinco.javaeye.com/blog/162232</guid>
      </item>
      <item>
        <title>关于oracle存储过程的若干问题备忘</title>
        <author>andyu2008</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://pinco.javaeye.com">andyu2008</a>&nbsp;
          链接：<a href="http://pinco.javaeye.com/blog/153457" style="color:red;">http://pinco.javaeye.com/blog/153457</a>&nbsp;
          发表时间: 2008年01月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          1.在oracle中，数据表别名不能加as，如：<br /><br /><pre name="code" class="java">select a.appname from appinfo a;-- 正确
select a.appname from appinfo as a;-- 错误</pre>&nbsp;<br /> 也许，是怕和oracle中的存储过程中的关键字as冲突的问题吧<br /><br />2.在存储过程中，select某一字段时，后面必须紧跟into，如果select整个记录，利用游标的话就另当别论了。<br /><br /><pre name="code" class="java">select af.keynode into kn from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;-- 有into，正确编译
select af.keynode from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;-- 没有into，编译报错，提示：Compilation
Error: PLS-00428: an INTO clause is expected in this SELECT statement</pre><p>&nbsp;<br /><br /><br />3.在利用select...into...语法时，必须先确保数据库中有该条记录，否则会报出&quot;no data found&quot;异常。<br /><br />   可以在该语法之前，先利用</p><pre name="code" class="java">select count(*) from</pre><p>&nbsp;</p><p>查看数据库中是否存在该记录，如果存在，再利用select...into...<br /><br />4.在存储过程中，别名不能和字段名称相同，否则虽然编译可以通过，但在运行阶段会报错<br /></p><pre name="code" class="java">select keynode into kn from APPFOUNDATION where appid=aid and foundationid=fid;-- 正确运行
select af.keynode into kn from APPFOUNDATION af where af.appid=appid and af.foundationid=foundationid;-- 运行阶段报错，提示
ORA-01422:exact fetch returns more than requested number of rows</pre>&nbsp;<p><br />5.在存储过程中，关于出现null的问题<br /><br />假设有一个表A，定义如下：</p><pre name="code" class="java">create table A(
id varchar2(50) primary key not null,
vcount number(8) not null,
bid varchar2(50) not null -- 外键
);</pre>&nbsp;<br /><p>如果在存储过程中，使用如下语句：</p><pre name="code" class="java">select sum(vcount) into fcount from A where bid='xxxxxx';</pre>&nbsp;<br /><p>如果A表中不存在bid=&quot;xxxxxx&quot;的记录，则fcount=null(即使fcount定义时设置了默认值，如：fcount number(8):=0依然无效，fcount还是会变成null)，这样以后使用fcount时就可能有问题，所以在这里最好先判断一下：</p><pre name="code" class="java">if fcount is null then
fcount:=0;
end if;</pre>&nbsp;<br /><p>这样就一切ok了。<br /><br />6.Hibernate调用oracle存储过程<br /></p><pre name="code" class="java">this.pnumberManager.getHibernateTemplate().execute(
new HibernateCallback() ...{
public Object doInHibernate(Session session)
throws HibernateException, SQLException ...{
CallableStatement cs = session
.connection()
.prepareCall(&quot;{call modifyapppnumber_remain(?)}&quot;);
cs.setString(1, foundationid);
cs.execute();
return null;
}
});</pre>&nbsp;<p>&nbsp;</p><p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://pinco.javaeye.com/blog/153457#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>Sun, 06 Jan 2008 10:59:05 +0800</pubDate>
        <link>http://pinco.javaeye.com/blog/153457</link>
        <guid>http://pinco.javaeye.com/blog/153457</guid>
      </item>
      <item>
        <title>EJB3.0 消息驱动</title>
        <author>andyu2008</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://pinco.javaeye.com">andyu2008</a>&nbsp;
          链接：<a href="http://pinco.javaeye.com/blog/151689" style="color:red;">http://pinco.javaeye.com/blog/151689</a>&nbsp;
          发表时间: 2007年12月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font color="#ff0000">Java消息服务(JMS Java Message Services)</font>提供了点对点模式(Point-to-Point　Queue)和发布-订阅模式(Publish-Subscribe　Topics).</p>
<p>Queue仅允许一个消息传送给一个客户（一对一）:<br />
消息的接收者和发送者之间不存在时间上的依赖关系。不论发送者发送消息时接收者是否在运行，接收者都可以提取信息。接收者对于成功处理的消息给出回执。</p>
<p>Topics可以有多个客户端（一对多，多对多）:<br />
向某个话题订阅的客户程序只能收到那些在它订阅之后发布的消息。为了接收到消息，订阅者必须保持活动状态。因此，发布者和订阅者之间存在时间上的依赖关系。</p>
<p>点对点消息模式通过一个消息队列(Queue)实现，消息的生产者向队列写入消息，消息的订阅者从队列提取消息。发布-订阅消息模式通过一个话题（Topic）节点构成的层次结构实现，消息的生产者向这个层次结构发布消息，消息的订阅者向这个结构订阅消息。 </p>
<p><font color="#ff0000">消息驱动的Bean只有一个Bean类</font>。从某些方面看，消息驱动的Bean类似于无状态会话Bean：消息驱动的Bean不为特定的客户保留数据或对话状态。 </p>
<p>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span class="annotation">@MessageDriven</span><span>(activationConfig={&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="annotation">@ActivationConfigProperty</span><span>(propertyName=</span><span class="string">&quot;destinationType&quot;</span><span>,propertyValue=</span><span class="string">&quot;javax.jms.Queue&quot;</span><span>),&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;<span class="annotation">@ActivationConfigProperty</span><span>(propertyName=</span><span class="string">&quot;destination&quot;</span><span>,propertyValue=</span><span class="string">&quot;queue/Msg&quot;</span><span>)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>})&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
@MessageDriven注释指明这是一个消息驱动Bean，并使用@ActivationConfigProperty注释配置消息的各种属性，其中<font color="#ff0000">destinationType属性指定消息的类型，消息有两种类型topics 和queues</font>，下面是这两种消息类型的介绍：<br />
Topics 可以有多个客户端。用topic发布允许一对多，或多对多通讯通道。消息的产生者被叫做publisher, 消息接<br />
受者叫做subscriber。destinationType属性对应值：javax.jms.Topic</p>
<p>Queue 仅仅允许一个消息传送给一个客户。一个发送者将消息放入消息队列，接受者从队列中抽取并得到消息，消息就会在队列中消失。第一个接受者抽取并得到消息后，其他人就不能再得到它。destinationType属性对应值：javax.jms.Queue<br />
destination属性用作指定消息路径，消息驱动Bean在发布时，如果路径不存在，容器会自动创建该路径，当容器关闭时该路径会自动被删除</p>
<p>当一个消息到达queue/Msg队列时，就会触发<font color="#ff0000">onMessage</font>方法，消息作为一个参数传入.</p>
<p><br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="keyword">package</span><span>&nbsp;ejb;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.jms.Message;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">import</span><span>&nbsp;javax.jms.MessageListener;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.ejb.MessageDriven;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">import</span><span>&nbsp;javax.jms.TextMessage;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.jms.JMSException;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">import</span><span>&nbsp;javax.ejb.ActivationConfigProperty;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="annotation">@MessageDriven</span><span>(activationConfig={&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;<span class="annotation">@ActivationConfigProperty</span><span>(propertyName=</span><span class="string">&quot;destinationType&quot;</span><span>,propertyValue=</span><span class="string">&quot;javax.jms.Queue&quot;</span><span>),&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="annotation">@ActivationConfigProperty</span><span>(propertyName=</span><span class="string">&quot;destination&quot;</span><span>,propertyValue=</span><span class="string">&quot;queue/Msg&quot;</span><span>)&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>})&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;Msg&nbsp;</span><span class="keyword">implements</span><span>&nbsp;MessageListener&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onMessage(Message&nbsp;msg)&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;<span class="comment">//&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;TextMessage&nbsp;tmsg&nbsp;=&nbsp;(TextMessage)&nbsp;msg;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;<span class="keyword">try</span><span>{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;System.out.println(tmsg.getText());&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;}<span class="keyword">catch</span><span>(JMSException&nbsp;e){&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
&nbsp;
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span class="keyword">package</span><span>&nbsp;test;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.jms.QueueConnection;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">import</span><span>&nbsp;javax.jms.QueueConnectionFactory;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.jms.JMSException;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">import</span><span>&nbsp;javax.jms.QueueSession;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.jms.Queue;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">import</span><span>&nbsp;javax.jms.TextMessage;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.jms.QueueSender;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">import</span><span>&nbsp;javax.naming.*;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;MsgTest&nbsp;{&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args){&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;QueueConnection&nbsp;conn;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;QueueSession&nbsp;ssn;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;Queue&nbsp;queue;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;QueueSender&nbsp;sender;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;TextMessage&nbsp;msg;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;<span class="keyword">try</span><span>{&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;InitialContext&nbsp;ctx&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;InitialContext();&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;QueueConnectionFactory&nbsp;qcf&nbsp;=(QueueConnectionFactory)&nbsp;ctx.lookup(<span class="string">&quot;ConnectionFactory&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;conn&nbsp;=&nbsp;qcf.createQueueConnection();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;ssn&nbsp;=&nbsp;conn.createQueueSession(<span class="keyword">false</span><span>,&nbsp;QueueSession.AUTO_ACKNOWLEDGE);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;queue&nbsp;=(Queue)&nbsp;ctx.lookup(<span class="string">&quot;queue/Msg&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;msg&nbsp;=&nbsp;ssn.createTextMessage(<span class="string">&quot;HELLO&nbsp;WORLD！&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;sender&nbsp;=&nbsp;ssn.createSender(queue);&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;sender.send(msg);&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;sender.close();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;}<span class="keyword">catch</span><span>(NamingException&nbsp;e){&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;}<span class="keyword">catch</span><span>(JMSException&nbsp;e1){&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;e1.printStackTrace();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</p>
<p><br />
(1) 得到一个JNDI初始化上下文(Context)；<br />
例子对应代码：<br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span>Properties&nbsp;props&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Properties();&nbsp;&nbsp;</span></span></li>
    <li class=""><span>props.setProperty(<span class="string">&quot;java.naming.factory.initial&quot;</span><span>,&nbsp;</span><span class="string">&quot;org.jnp.interfaces.NamingContextFactory&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>props.setProperty(<span class="string">&quot;java.naming.provider.url&quot;</span><span>,&nbsp;</span><span class="string">&quot;localhost:1099&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>props.setProperty(<span class="string">&quot;java.naming.factory.url.pkgs&quot;</span><span>,&nbsp;</span><span class="string">&quot;org.jboss.naming&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>InitialContext&nbsp;ctx&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;InitialContext(props);&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br />
</p>
<p>(2) 根据上下文来查找一个连接工厂TopicConnectFactory/ QueueConnectionFactory (有两种连接工厂，根据是topic/queue来使用相应的类型)；<br />
例子对应代码：<br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span>QueueConnectionFactory&nbsp;qcf&nbsp;=(QueueConnectionFactory)&nbsp;ctx.lookup(</span><span class="string">&quot;ConnectionFactory&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br />
</p>
<p>(3) 从连接工厂得到一个连接(Connect 有两种[TopicConnection/ QueueConnection]);<br />
例子对应代码：conn = qcf.createQueueConnection();</p>
<p>(4) 通过连接来建立一个会话(Session);<br />
例子对应代码：ssn = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);<br />
这句代码意思是：建立不需要事务的并且能自动接收消息收条的会话，在非事务Session 中，消息传递的方式有三种：<br />
Session.AUTO_ACKNOWLEDGE ：当客户机调用的receive方法成功返回，或当MessageListenser 成功处理了消息，session将会自动接收消息的收条。</p>
<p>Session.CLIENT_ACKNOWLEDGE ：客户机通过调用消息的acknowledge方法来接收消息。接收发生在session层。接收到一个被消费的消息时，将自动接收该session已经 消费的所有消息。例如：如果消息的消费者消费了10条消息，然后接收15 个被传递的消息，则前面的10 个消息的收据都会在这15 个消息中被接收。</p>
<p>Session.DUPS_ACKNOWLEDGE ：指示session缓慢接收消息。</p>
<p>(5) 查找目的地(Topic/ Queue);<br />
例子对应代码：queue =(Queue) ctx.lookup(&quot;queue/Msg&quot;);</p>
<p>(6) 根据会话以及目的地来建立消息制造者(TopicPublisher/QueueSender)和消费者(TopicSubscriber/QueueReceiver).<br />
例子对应代码：<br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span>msg&nbsp;=&nbsp;ssn.createTextMessage(</span><span class="string">&quot;HELLO&nbsp;WORLD！&quot;</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>sender&nbsp;=&nbsp;ssn.createSender(queue);&nbsp;&nbsp;</span></li>
    <li class="alt"><span>sender.send(msg);&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
</p>
          <br/>
          <span style="color:red;">
            <a href="http://pinco.javaeye.com/blog/151689#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>Sat, 29 Dec 2007 09:55:45 +0800</pubDate>
        <link>http://pinco.javaeye.com/blog/151689</link>
        <guid>http://pinco.javaeye.com/blog/151689</guid>
      </item>
      <item>
        <title>Struts2学习之旅（一）</title>
        <author>andyu2008</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://pinco.javaeye.com">andyu2008</a>&nbsp;
          链接：<a href="http://pinco.javaeye.com/blog/150733" style="color:red;">http://pinco.javaeye.com/blog/150733</a>&nbsp;
          发表时间: 2007年12月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一、Struts2配置文件<br />Struts2相关的配置文件有web.xml，struts.xml，struts.properties，<br />struts-default.xml，velocity.properties，struts-default.vm。其中web.xml，struts.xml是必须的，其它的配置文件可选择。它们在web应用中的功能如下：<br />web.xml：包含所有必须的框架组件的web部署描述符。<br />Struts.xml:配置包含result/view类型、action映射、拦截器等的Struts2的主要配置文件。<br />Struts.properties：配置struts2的框架属性。<br />Struts-default.xml：在文件在struts-action-x.x.jar中，该文件是应该被包含在struts.xml中的缺省配置。<br />Welocity.properties：重写了velocity的配置文件。<br />Struts-default.vm：相对于velocity的缺省配置。<br /><br />二、Struts2配置元素<br />Struts2核心的配置文件是缺省的struts.xml。<br />必要的时候，缺省的配置文件可以包含其它的配置文件；struts文件可以放入jar中，并自动插入应用程序，这样每个模块可以包含自己的配置文件并自动配置。在Freemarker和Velocity模块中，模板也能从classpath中加载，所以整个模块可以作为一个简单的jar文件被包含。<br />Struts.xml配置文件可以包含Interceptor、Action类和Results。<br />Struts.xml配置元素说明：<br /><br />1、Packages<br />Packages:packages把actions、results、results types、interceptors<br />和interceptor-stacks组装到一个逻辑单元中，从概念上讲，packages就像一个对象，可以被其它子包从写，而且可以拥有自己独立的部分。<br />Name属性是packages的必填元素，它作为一个关键字被后边的包引用；extends元素是可选的，它允许包扩展一个和多个前边定义的包。注意，<br />struts.xml文件是至上而下处理的，所有被扩展的包，需要在扩展包前定义。<br />Abstract元素是可选的，它可以申明一个不包含actions的配置文件。<br /><br />2、Namespace<br />Namespace元素把actions细分到逻辑模块，每一个namespace都有自己的<br />前缀（prefix），namespace避免了action之间的名字冲突，当前缀出现在URI中时，这些标签都是名字空间感知的（“namespace aware”），所以这些namespace prefix不必嵌入到表单或连接中。<br />Default的namespace是一个空字符串“”，如果在指定的配置文件中，没有找到action，缺省的namespace也会被查找。 Local/global策略允许应用程序在action “extends”元素层次结构之外，有全局的action配置。缺省的namespace也可以不在package中申明。<br />Namespace prefix可以注册为java的申明式安全，以确保授权的用户才能访问namespace的资源。<br />Root namespace(“/”)也被支持，root就是当直接请求context path的时候的namespace。<br /><br />[个人理解：namespace的用法就像struts1.x中的path一样，只不过它在package中什么路径，而在action中申明action名子罢了]<br /><br />3、Include<br />Include元素使得框架能应用“divide and conquer”来配置文件。被include<br />的每个配置文件必须和struts.xml有一样的格式，一个大的项目可以采用这样方式来组织程序模块。<br />Include元素也可以和package交替出现，框架将按照顺序加载配置文件。<br /><br />4、Interceptor configuration<br />Interceptor允许应用程序在Action方法执行前后定义执行代码，<br />Interceptor在应用程序开发中十分重要，对于Interceptor有许多用例，如validation, property population, security, logging, 和profiling。<br />Interceptor被定义为一个Java类，Interceptor也可以组装成Interceptor-stack，他们将按照定义的顺序执行。<br />在struts-default.xml中定义了一些缺省的Interceptor-stack,以便框架能很好地运行。<br /><br />5、Action<br />Action是框架的“工作单元”。Action可以指定一个Interceptor-stack、<br />一序列的return type和一序列的异常处理，但只有name属性是必须的。
          <br/>
          <span style="color:red;">
            <a href="http://pinco.javaeye.com/blog/150733#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, 25 Dec 2007 16:03:44 +0800</pubDate>
        <link>http://pinco.javaeye.com/blog/150733</link>
        <guid>http://pinco.javaeye.com/blog/150733</guid>
      </item>
      <item>
        <title>Hibernate出现Could not find datasource错误</title>
        <author>andyu2008</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://pinco.javaeye.com">andyu2008</a>&nbsp;
          链接：<a href="http://pinco.javaeye.com/blog/145773" style="color:red;">http://pinco.javaeye.com/blog/145773</a>&nbsp;
          发表时间: 2007年12月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="color: indigo">Hibernate版本3.1<br />开发环境Eclipse3.2.1+MyEclipse5+HibernateTools3.1<br /><br />前几天还好好的程序，今天突然出现Could not find datasource错误。<br />郁闷了一下午，终于找到了罪魁祸首。<br /><br />可以正常运行的hibernate.cfg.xml文件：</span><br />    &lt;session-factory><br />	&lt;property name="show_sql">false&lt;/property><br />	&lt;property name="connection.datasource">java:comp/env/jdbc/myconn&lt;/property><br />	&lt;property name="dialect">org.hibernate.dialect.SQLServerDialect&lt;/property><br />	&lt;mapping resource="org/hibernate/Do/Table49.hbm.xml" /><br />    &lt;/session-factory><br /><br /><span style="color: indigo">出现错误的hibernate.cfg.xml文件(MyEclipse5自动生成)：</span><br />    &lt;session-factory><br />       &lt;property name="show_sql">false&lt;/property><br />       &lt;property name="connection.datasource">java:comp/env/jdbc/myconn&lt;/property><br />       &lt;property name="dialect">org.hibernate.dialect.SQLServerDialect&lt;/property><br />       &lt;property name="jndi.class">&lt;/property><br />       &lt;property name="connection.password">&lt;/property><br />       &lt;property name="connection.username">&lt;/property><br />       &lt;property name="jndi.url">&lt;/property><br />       &lt;mapping resource="org/hibernate/Do/Table49.hbm.xml" /><br />    &lt;/session-factory><br /><br /><span style="color: indigo"><span style="font-size: 18pt">附上TOMCAT(5.016)的连接池配置文件,我的工程名称叫"CMJ2EE",将此文件保存到%TOMCAT_HOME%\conf\Catalina\localhost\,文件名称：CMJ2EE.xml</span></span><br />&lt;?xml version="1.0" encoding="UTF-8"?><br />&lt;Context docBase="CMJ2EE" path="/CMJ2EE" debug="0" reloadable="true" crossContext="true"><br />  &lt;Resource name="jdbc/myconn" type="javax.sql.DataSource"/><br />  &lt;ResourceParams name="jdbc/myconn"><br />    &lt;parameter><br />      &lt;name>maxWait&lt;/name><br />      &lt;value>5&lt;/value><br />    &lt;/parameter><br />    &lt;parameter><br />      &lt;name>maxActive&lt;/name><br />      &lt;value>100&lt;/value><br />    &lt;/parameter><br />    &lt;parameter><br />      &lt;name>password&lt;/name><br />      &lt;value>&lt;/value><br />    &lt;/parameter><br />    &lt;parameter><br />      &lt;name>url&lt;/name><br />      &lt;value>jdbc:jtds:sqlserver://127.0.0.1:1433/pinco&lt;/value><br />    &lt;/parameter><br />    &lt;parameter><br />      &lt;name>driverClassName&lt;/name><br />      &lt;value>net.sourceforge.jtds.jdbc.Driver&lt;/value><br />    &lt;/parameter><br />    &lt;parameter><br />      &lt;name>maxIdle&lt;/name><br />      &lt;value>30&lt;/value><br />    &lt;/parameter><br />    &lt;parameter><br />        &lt;name>removeAbandoned&lt;/name><br />        &lt;value>true&lt;/value><br />     &lt;/parameter><br />     &lt;parameter>       <br />      &lt;name>removeAbandonedTimeout&lt;/name><br />        &lt;value>60&lt;/value><br />      &lt;/parameter><br />    &lt;parameter><br />      &lt;name>username&lt;/name><br />      &lt;value>sa&lt;/value><br />    &lt;/parameter><br />  &lt;/ResourceParams><br />&lt;/Context>
          <br/>
          <span style="color:red;">
            <a href="http://pinco.javaeye.com/blog/145773#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, 04 Dec 2007 10:29:32 +0800</pubDate>
        <link>http://pinco.javaeye.com/blog/145773</link>
        <guid>http://pinco.javaeye.com/blog/145773</guid>
      </item>
      <item>
        <title>卡巴斯基6.0-7.0免费激活</title>
        <author>andyu2008</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://pinco.javaeye.com">andyu2008</a>&nbsp;
          链接：<a href="http://pinco.javaeye.com/blog/145758" style="color:red;">http://pinco.javaeye.com/blog/145758</a>&nbsp;
          发表时间: 2007年12月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          我记得以前很久之前看到这样的说法，就是下载试用版本的卡巴斯基，然后到了时间后，删除几个注册项，就又可以用30天。<br /><br />      以前我试过，是可以的，今天又看到了这样的文章，感兴趣的朋友可以试试。<br /><br />      先关掉卡巴斯基，再删除以下的项(删除Key)：<br /><br />      HKEY_LOCAL_MACHINESOFTWAREKasperskyLabLicStorage<br />      HKEY_LOCAL_MACHINESOFTWAREMicrosoftCryptographyRNG <br />      HKEY_LOCAL_MACHINESOFTWAREMicrosoftSystemCertificatesSPCCertificates<br /><br />     这样就可以了，大家试试吧！！！
          <br/>
          <span style="color:red;">
            <a href="http://pinco.javaeye.com/blog/145758#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, 04 Dec 2007 09:53:29 +0800</pubDate>
        <link>http://pinco.javaeye.com/blog/145758</link>
        <guid>http://pinco.javaeye.com/blog/145758</guid>
      </item>
      <item>
        <title> 在Eclipse中使用JUnit4进行单元测试&lt;高级&gt;  </title>
        <author>andyu2008</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://pinco.javaeye.com">andyu2008</a>&nbsp;
          链接：<a href="http://pinco.javaeye.com/blog/143955" style="color:red;">http://pinco.javaeye.com/blog/143955</a>&nbsp;
          发表时间: 2007年11月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p class="MsoNormal" align="left" style="text-align: left; text-indent: 36pt;"><span style="font-size: 14pt; font-family: 宋体;">通过前</span><span lang="EN-US" style="font-size: 14pt;">2</span><span style="font-size: 14pt; font-family: 宋体;">篇文章，您一定对</span><span lang="EN-US" style="font-size: 14pt;">JUnit</span><span style="font-size: 14pt; font-family: 宋体;">有了一个基本的了解，下面我们来探讨一下</span><span lang="EN-US" style="font-size: 14pt;">JUnit4</span><span style="font-size: 14pt; font-family: 宋体;">中一些高级特性。</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="margin-left: 36pt; text-align: left; text-indent: -36pt;"><!--[if !supportLists]--><span lang="EN-US" style="font-size: 14pt; color: rgb(255, 0, 0); font-weight: bold;"><span style="">一、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]--><span style="font-size: 14pt; font-family: 宋体; color: rgb(255, 0, 0); font-weight: bold;">高级</span><span lang="EN-US" style="font-size: 14pt;"><span style="color: rgb(255, 0, 0); font-weight: bold;">Fixture</span><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="text-align: left; text-indent: 36pt;"><span style="font-size: 14pt; font-family: 宋体;">上一篇文章中我们介绍了两个</span><span lang="EN-US" style="font-size: 14pt;">Fixture</span><span style="font-size: 14pt; font-family: 宋体;">标注，分别是</span><span lang="EN-US" style="font-size: 14pt;">@Before</span><span style="font-size: 14pt; font-family: 宋体;">和</span><span lang="EN-US" style="font-size: 14pt;">@After</span><span style="font-size: 14pt; font-family: 宋体;">，我们来看看他们是否适合完成如下功能：有一个类是负责对大文件（超过</span><span lang="EN-US" style="font-size: 14pt;">500</span><span style="font-size: 14pt; font-family: 宋体;">兆）进行读写，他的每一个方法都是对文件进行操作。换句话说，在调用每一个方法之前，我们都要打开一个大文件并读入文件内容，这绝对是一个非常耗费时间的操作。如果我们使用</span><span lang="EN-US" style="font-size: 14pt;">@Before</span><span style="font-size: 14pt; font-family: 宋体;">和</span><span lang="EN-US" style="font-size: 14pt;">@After</span><span style="font-size: 14pt; font-family: 宋体;">，那么每次测试都要读取一次文件，效率及其低下。这里我们所希望的是在所有测试一开始读一次文件，所有测试结束之后释放文件，而不是每次测试都读文件。</span><span lang="EN-US" style="font-size: 14pt;">JUnit</span><span style="font-size: 14pt; font-family: 宋体;">的作者显然也考虑到了这个问题，它给出了</span><span lang="EN-US" style="font-size: 14pt;">@BeforeClass </span><span style="font-size: 14pt; font-family: 宋体;">和</span><span lang="EN-US" style="font-size: 14pt;"> @AfterClass</span><span style="font-size: 14pt; font-family: 宋体;">两个</span><span lang="EN-US" style="font-size: 14pt;">Fixture</span><span style="font-size: 14pt; font-family: 宋体;">来帮我们实现这个功能。从名字上就可以看出，用这两个</span><span lang="EN-US" style="font-size: 14pt;">Fixture</span><span style="font-size: 14pt; font-family: 宋体;">标注的函数，只在测试用例初始化时执行</span><span lang="EN-US" style="font-size: 14pt;">@BeforeClass</span><span style="font-size: 14pt; font-family: 宋体;">方法，当所有测试执行完毕之后，执行</span><span lang="EN-US" style="font-size: 14pt;">@AfterClass</span><span style="font-size: 14pt; font-family: 宋体;">进行收尾工作。在这里要注意一下，每个测试类只能有一个方法被标注为</span><span lang="EN-US" style="font-size: 14pt;">@BeforeClass </span><span style="font-size: 14pt; font-family: 宋体;">或</span><span lang="EN-US" style="font-size: 14pt;"> @AfterClass</span><span style="font-size: 14pt; font-family: 宋体;">，并且该方法必须是</span><span lang="EN-US" style="font-size: 14pt;">Public</span><span style="font-size: 14pt; font-family: 宋体;">和</span><span lang="EN-US" style="font-size: 14pt;">Static</span><span style="font-size: 14pt; font-family: 宋体;">的。</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="margin-left: 36pt; text-align: left; text-indent: -36pt;"><!--[if !supportLists]--><span lang="EN-US" style="font-size: 14pt; font-weight: bold; color: rgb(255, 0, 0);"><span style="">二、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]--><span style="font-size: 14pt; font-family: 宋体; font-weight: bold; color: rgb(255, 0, 0);">限时测试。</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="text-align: left; text-indent: 36pt;"><span style="font-size: 14pt; font-family: 宋体;">还记得我在初级篇中给出的例子吗，那个求平方根的函数有</span><span lang="EN-US" style="font-size: 14pt;">Bug</span><span style="font-size: 14pt; font-family: 宋体;">，是个死循环：</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="text-align: left;"><span lang="EN-US" style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"><span style=""></span></span></p>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: rgb(230, 230, 230) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" id="_34_90_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_34_90_Open_Text').style.display='none'; document.getElementById('_34_90_Closed_Image').style.display='inline'; document.getElementById('_34_90_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" id="_34_90_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_34_90_Closed_Text').style.display='none'; document.getElementById('_34_90_Open_Image').style.display='inline'; document.getElementById('_34_90_Open_Text').style.display='inline';" alt="" style="display: none;" /><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;squareRoot(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;n)&nbsp;</span><span id="_34_90_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_34_90_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;(;&nbsp;;)&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">Bug&nbsp;:&nbsp;死循环</span><span style="color: rgb(0, 128, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span></div>
</div>
<p class="MsoNormal" align="left" style="text-align: left;"><span lang="EN-US" style="font-size: 10pt; font-family: &quot;Courier New&quot;; color: black;"><span lang="EN-US" style="font-size: 10pt; font-family: &quot;Courier New&quot;;"><o:p></o:p></span></span></p>
<p class="MsoNormal" align="left" style="text-align: left;"><span style="font-size: 14pt; font-family: 宋体;">如 果测试的时候遇到死循环，你的脸上绝对不会露出笑容。因此，对于那些逻辑很复杂，循环嵌套比较深的程序，很有可能出现死循环，因此一定要采取一些预防措 施。限时测试是一个很好的解决方案。我们给这些测试函数设定一个执行时间，超过了这个时间，他们就会被系统强行终止，并且系统还会向你汇报该函数结束的原 因是因为超时，这样你就可以发现这些</span><span lang="EN-US" style="font-size: 14pt;">Bug</span><span style="font-size: 14pt; font-family: 宋体;">了。要实现这一功能，只需要给</span><span lang="EN-US" style="font-size: 14pt;">@Test</span><span style="font-size: 14pt; font-family: 宋体;">标注加一个参数即可，代码如下：</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<pre><code><span lang="EN-US"><span style=""></span></span></code></pre>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: rgb(230, 230, 230) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;@Test(timeout&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">1000</span><span style="color: rgb(0, 0, 0);">)<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" id="_56_151_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_56_151_Open_Text').style.display='none'; document.getElementById('_56_151_Closed_Image').style.display='inline'; document.getElementById('_56_151_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" id="_56_151_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_56_151_Closed_Text').style.display='none'; document.getElementById('_56_151_Open_Image').style.display='inline'; document.getElementById('_56_151_Open_Text').style.display='inline';" alt="" style="display: none;" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;squareRoot()&nbsp;</span><span id="_56_151_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_56_151_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calculator.squareRoot(</span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">);<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">,&nbsp;calculator.getResult());<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span></div>
</div>
<pre><code><span lang="EN-US"></span></code></pre>
<p class="MsoNormal" align="left" style="text-align: left;"><span lang="EN-US" style="font-size: 14pt;">Timeout</span><span style="font-size: 14pt; font-family: 宋体;">参数表明了你要设定的时间，单位为毫秒，因此</span><span lang="EN-US" style="font-size: 14pt;">1000</span><span style="font-size: 14pt; font-family: 宋体;">就代表</span><span lang="EN-US" style="font-size: 14pt;">1</span><span style="font-size: 14pt; font-family: 宋体;">秒。</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="margin-left: 36pt; text-align: left; text-indent: -36pt;"><!--[if !supportLists]--><span lang="EN-US" style="font-size: 14pt; font-weight: bold; color: rgb(255, 0, 0);"><span style="">三、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]--><span style="font-size: 14pt; font-family: 宋体; font-weight: bold; color: rgb(255, 0, 0);">测试异常</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="text-align: left; text-indent: 36pt;"><span lang="EN-US" style="font-size: 14pt;">JAVA</span><span style="font-size: 14pt; font-family: 宋体;">中的异常处理也是一个重点，因此你经常会编写一些需要抛出异常的函数。那么，如果你觉得一个函数应该抛出异常，但是它没抛出，这算不算</span><span lang="EN-US" style="font-size: 14pt;">Bug</span><span style="font-size: 14pt; font-family: 宋体;">呢？这当然是</span><span lang="EN-US" style="font-size: 14pt;">Bug</span><span style="font-size: 14pt; font-family: 宋体;">，并</span><span lang="EN-US" style="font-size: 14pt;">JUnit</span><span style="font-size: 14pt; font-family: 宋体;">也考虑到了这一点，来帮助我们找到这种</span><span lang="EN-US" style="font-size: 14pt;">Bug</span><span style="font-size: 14pt; font-family: 宋体;">。例如，我们写的计算器类有除法功能，如果除数是一个</span><span lang="EN-US" style="font-size: 14pt;">0</span><span style="font-size: 14pt; font-family: 宋体;">，那么必然要抛出&ldquo;除</span><span lang="EN-US" style="font-size: 14pt;">0</span><span style="font-size: 14pt; font-family: 宋体;">异常&rdquo;。因此，我们很有必要对这些进行测试。代码如下：</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<pre><code><span lang="EN-US"><span style=""></span></span></code></pre>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: rgb(230, 230, 230) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;@Test(expected&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;ArithmeticException.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">)<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" id="_76_105_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_76_105_Open_Text').style.display='none'; document.getElementById('_76_105_Closed_Image').style.display='inline'; document.getElementById('_76_105_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" id="_76_105_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_76_105_Closed_Text').style.display='none'; document.getElementById('_76_105_Open_Image').style.display='inline'; document.getElementById('_76_105_Open_Text').style.display='inline';" alt="" style="display: none;" />&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;divideByZero()&nbsp;</span><span id="_76_105_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_76_105_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />calculator.divide(</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">);&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span></div>
</div>
<pre style="text-indent: 24pt;"><code><span lang="EN-US"><o:p></o:p></span></code></pre>
<pre><font size="4"><code>如上述代码所示，我们需要使用</code><span lang="EN-US" style="font-size: 14pt;">@Test</span></font><span style="font-size: 14pt;"><font size="4">标注的<span lang="EN-US">expected</span>属性，将我们要检验的</font>异常传递给他，这样<span lang="EN-US">JUnit</span>框架就能自动帮我们检测是否抛出了我们指定的异常。</span></pre>
<p class="MsoNormal" align="left" style="margin-left: 36pt; text-align: left; text-indent: -36pt;"><!--[if !supportLists]--><!--[endif]--><span lang="EN-US" style="font-size: 14pt; font-weight: bold; color: rgb(255, 0, 0);"><span style="">四、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp; </span></span>Runner (</span><span style="font-size: 14pt; font-family: 宋体; font-weight: bold; color: rgb(255, 0, 0);">运行器</span><span lang="EN-US" style="font-size: 14pt;"><span style="font-weight: bold; color: rgb(255, 0, 0);">)</span><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="text-align: left; text-indent: 36pt;"><span style="font-size: 14pt; font-family: 宋体;">大家有没有想过这个问题，当你把测试代码提交给</span><span lang="EN-US" style="font-size: 14pt;">JUnit</span><span style="font-size: 14pt; font-family: 宋体;">框架后，框架如何来运行你的代码呢？答案就是&mdash;&mdash;</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">。在</span><span lang="EN-US" style="font-size: 14pt;">JUnit</span><span style="font-size: 14pt; font-family: 宋体;">中有很多个</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">，他们负责调用你的测试代码，每一个</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">都有各自的特殊功能，你要根据需要选择不同的</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">来运行你的测试代码。可能你会觉得奇怪，前面我们写了那么多测试，并没有明确指定一个</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">啊？这是因为</span><span lang="EN-US" style="font-size: 14pt;">JUnit</span><span style="font-size: 14pt; font-family: 宋体;">中有一个默认</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">，如果你没有指定，那么系统自动使用默认</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">来运行你的代码。换句话说，下面两段代码含义是完全一样的：</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<pre><code><span lang="EN-US"></span></code></pre>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: rgb(230, 230, 230) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.internal.runners.TestClassRunner;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.runner.RunWith;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">使用了系统默认的TestClassRunner，与下面代码完全一样</span><span style="color: rgb(0, 128, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" id="_154_162_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_154_162_Open_Text').style.display='none'; document.getElementById('_154_162_Closed_Image').style.display='inline'; document.getElementById('_154_162_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" id="_154_162_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_154_162_Closed_Text').style.display='none'; document.getElementById('_154_162_Open_Image').style.display='inline'; document.getElementById('_154_162_Open_Text').style.display='inline';" alt="" style="display: none;" /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;CalculatorTest&nbsp;</span><span id="_154_162_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_154_162_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />...<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" />@RunWith(TestClassRunner.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">)<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" id="_232_240_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_232_240_Open_Text').style.display='none'; document.getElementById('_232_240_Closed_Image').style.display='inline'; document.getElementById('_232_240_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" id="_232_240_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_232_240_Closed_Text').style.display='none'; document.getElementById('_232_240_Open_Image').style.display='inline'; document.getElementById('_232_240_Open_Text').style.display='inline';" alt="" style="display: none;" /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;CalculatorTest&nbsp;</span><span id="_232_240_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_232_240_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />...<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span></div>
</div>
<pre><code><span lang="EN-US"></span></code></pre>
<p class="MsoNormal" align="left" style="text-align: left; text-indent: 36pt;"><span style="font-size: 14pt; font-family: 宋体;">从上述例子可以看出，要想指定一个</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">，需要使用</span><span lang="EN-US" style="font-size: 14pt;">@RunWith</span><span style="font-size: 14pt; font-family: 宋体;">标注，并且把你所指定的</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">作为参数传递给它。另外一个要注意的是，</span><span lang="EN-US" style="font-size: 14pt;">@RunWith</span><span style="font-size: 14pt; font-family: 宋体;">是用来修饰类的，而不是用来修饰函数的。只要对一个类指定了</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">，那么这个类中的所有函数都被这个</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">来调用。最后，不要忘了包含相应的</span><span lang="EN-US" style="font-size: 14pt;">Package</span><span style="font-size: 14pt; font-family: 宋体;">哦，上面的例子对这一点写的很清楚了。接下来，我会向你们展示其他</span><span lang="EN-US" style="font-size: 14pt;">Runner</span><span style="font-size: 14pt; font-family: 宋体;">的特有功能。</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="margin-left: 36pt; text-align: left; text-indent: -36pt;"><!--[if !supportLists]--><span lang="EN-US" style="font-size: 14pt; font-weight: bold; color: rgb(255, 0, 0);"><span style="">五、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]--><span style="font-size: 14pt; font-family: 宋体; font-weight: bold; color: rgb(255, 0, 0);">参数化测试。</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<p class="MsoNormal" align="left" style="text-align: left; text-indent: 36pt;"><span style="font-size: 14pt; font-family: 宋体;">你可能遇到过这样的函数，它的参数有许多特殊值，或者说他的参数分为很多个区域。比如，一个对考试分数进行评价的函数，返回值分别为&ldquo;优秀，良好，一般，及格，不及格&rdquo;，因此你在编写测试的时候，至少要写</span><span lang="EN-US" style="font-size: 14pt;">5</span><span style="font-size: 14pt; font-family: 宋体;">个测试，把这</span><span lang="EN-US" style="font-size: 14pt;">5</span><span style="font-size: 14pt; font-family: 宋体;">中情况都包含了，这确实是一件很麻烦的事情。我们还使用我们先前的例子，测试一下&ldquo;计算一个数的平方&rdquo;这个函数，暂且分三类：正数、</span><span lang="EN-US" style="font-size: 14pt;">0</span><span style="font-size: 14pt; font-family: 宋体;">、负数。测试代码如下：</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<pre><code><span lang="EN-US"></span></code></pre>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: rgb(230, 230, 230) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.AfterClass;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.Before;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.BeforeClass;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.Test;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.Assert.</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" id="_175_721_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_175_721_Open_Text').style.display='none'; document.getElementById('_175_721_Closed_Image').style.display='inline'; document.getElementById('_175_721_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" id="_175_721_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_175_721_Closed_Text').style.display='none'; document.getElementById('_175_721_Open_Image').style.display='inline'; document.getElementById('_175_721_Open_Text').style.display='inline';" alt="" style="display: none;" /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;AdvancedTest&nbsp;</span><span id="_175_721_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_175_721_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;Calculator&nbsp;calculator&nbsp;＝&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Calculator();<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;@Before<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" id="_285_321_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_285_321_Open_Text').style.display='none'; document.getElementById('_285_321_Closed_Image').style.display='inline'; document.getElementById('_285_321_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" id="_285_321_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_285_321_Closed_Text').style.display='none'; document.getElementById('_285_321_Open_Image').style.display='inline'; document.getElementById('_285_321_Open_Text').style.display='inline';" alt="" style="display: none;" /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;clearCalculator()&nbsp;</span><span id="_285_321_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_285_321_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calculator.clear();<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;@Test<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" id="_364_452_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_364_452_Open_Text').style.display='none'; document.getElementById('_364_452_Closed_Image').style.display='inline'; document.getElementById('_364_452_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" id="_364_452_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_364_452_Closed_Text').style.display='none'; document.getElementById('_364_452_Open_Image').style.display='inline'; document.getElementById('_364_452_Open_Text').style.display='inline';" alt="" style="display: none;" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;square1()&nbsp;</span><span id="_364_452_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_364_452_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calculator.square(</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">);<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(</span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">,&nbsp;calculator.getResult());<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;@Test<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" id="_495_583_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_495_583_Open_Text').style.display='none'; document.getElementById('_495_583_Closed_Image').style.display='inline'; document.getElementById('_495_583_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" id="_495_583_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_495_583_Closed_Text').style.display='none'; document.getElementById('_495_583_Open_Image').style.display='inline'; document.getElementById('_495_583_Open_Text').style.display='inline';" alt="" style="display: none;" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;square2()&nbsp;</span><span id="_495_583_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_495_583_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calculator.square(</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">);<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,&nbsp;calculator.getResult());<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;@Test<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" id="_626_715_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_626_715_Open_Text').style.display='none'; document.getElementById('_626_715_Closed_Image').style.display='inline'; document.getElementById('_626_715_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" id="_626_715_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_626_715_Closed_Text').style.display='none'; document.getElementById('_626_715_Open_Image').style.display='inline'; document.getElementById('_626_715_Open_Text').style.display='inline';" alt="" style="display: none;" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;square3()&nbsp;</span><span id="_626_715_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_626_715_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calculator.square(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">);<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(</span><span style="color: rgb(0, 0, 0);">9</span><span style="color: rgb(0, 0, 0);">,&nbsp;calculator.getResult());<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span></span><span style="color: rgb(0, 0, 0);"><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span></div>
</div>
<pre><code><span lang="EN-US"></span></code></pre>
<p class="MsoNormal" align="left" style="text-align: left;"><span style="font-size: 14pt; font-family: 宋体;">为了简化类似的测试，</span><span lang="EN-US" style="font-size: 14pt;">JUnit4</span><span style="font-size: 14pt; font-family: 宋体;">提出了&ldquo;参数化测试&rdquo;的概念，只写一个测试函数，把这若干种情况作为参数传递进去，一次性的完成测试。代码如下：</span><span lang="EN-US" style="font-size: 14pt;"><o:p></o:p></span></p>
<pre><code><span lang="EN-US"></span></code></pre>
<div style="border: 0.5pt solid windowtext; padding: 4px 5.4pt; background: rgb(230, 230, 230) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 95%;">
<div><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.Assert.assertEquals;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.Test;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.runner.RunWith;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.runners.Parameterized;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;org.junit.runners.Parameterized.Parameters;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;java.util.Arrays;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;java.util.Collection;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" />@RunWith(Parameterized.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">)<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" id="_314_912_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_314_912_Open_Text').style.display='none'; document.getElementById('_314_912_Closed_Image').style.display='inline'; document.getElementById('_314_912_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" id="_314_912_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_314_912_Closed_Text').style.display='none'; document.getElementById('_314_912_Open_Image').style.display='inline'; document.getElementById('_314_912_Open_Text').style.display='inline';" alt="" style="display: none;" /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;SquareTest&nbsp;</span><span id="_314_912_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_314_912_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;Calculator&nbsp;calculator&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Calculator();<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;param;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;result;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;@Parameters<br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br />
<img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" id="_487_629_Open_Image" align="top" onclick="this.style.display='none'; document.getElementById('_487_629_Open_Text').style.display='none'; document.getElementById('_487_629_Closed_Image').style.display='inline'; document.getElementById('_487_629_Closed_Text').style.display='inline';" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" id="_487_629_Closed_Image" align="top" onclick="this.style.display='none'; document.getElementById('_487_629_Closed_Text').style.display='none'; document.getElementById('_487_629_Open_Image').style.display='inline'; document.getElementById('_487_629_Open_Text').style.display='inline';" alt="" style="display: none;" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;Collection&nbsp;data()&nbsp;</span><span id="_487_629_Closed_Text" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255); display: none;">...</span><span id="_487_629_Open_Text"><span style="color: rgb(0, 0, 0);">{<br />
<img src="http://images.csdn