﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-多读点书,少上会网-随笔分类-JAVA空间</title><link>http://www.blogjava.net/aspirin/category/9106.html</link><description>JAVA_HOME</description><language>zh-cn</language><lastBuildDate>Tue, 19 Jun 2007 09:16:45 GMT</lastBuildDate><pubDate>Tue, 19 Jun 2007 09:16:45 GMT</pubDate><ttl>60</ttl><item><title>mysql事务</title><link>http://www.blogjava.net/aspirin/archive/2007/06/18/124946.html</link><dc:creator>aspirin</dc:creator><author>aspirin</author><pubDate>Mon, 18 Jun 2007 07:03:00 GMT</pubDate><guid>http://www.blogjava.net/aspirin/archive/2007/06/18/124946.html</guid><wfw:comment>http://www.blogjava.net/aspirin/comments/124946.html</wfw:comment><comments>http://www.blogjava.net/aspirin/archive/2007/06/18/124946.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aspirin/comments/commentRss/124946.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aspirin/services/trackbacks/124946.html</trackback:ping><description><![CDATA[这两天装了ubuntu系统，然后把整个开发环境都装到上面了 。<br />但发现一个很奇怪的问题，hibernate的事务无法会滚，这个问题困扰我好几天，今天终于解决了，原来mysql有配置有问题。mysql总共有4种存储方式，<code class="literal">MyISAM</code> 是默认存储方式，但是不支持事务，所以导致了我的问题，只要把默认设置成<code class="literal">default-storage-engine=innodb就可以了，当然也可以在每个table创建的时候指定。<br />希望对碰到此类问题的朋友有所帮助。<br /></code><img src ="http://www.blogjava.net/aspirin/aggbug/124946.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aspirin/" target="_blank">aspirin</a> 2007-06-18 15:03 <a href="http://www.blogjava.net/aspirin/archive/2007/06/18/124946.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初探Quartz的扩展</title><link>http://www.blogjava.net/aspirin/archive/2006/05/19/47034.html</link><dc:creator>aspirin</dc:creator><author>aspirin</author><pubDate>Fri, 19 May 2006 04:49:00 GMT</pubDate><guid>http://www.blogjava.net/aspirin/archive/2006/05/19/47034.html</guid><wfw:comment>http://www.blogjava.net/aspirin/comments/47034.html</wfw:comment><comments>http://www.blogjava.net/aspirin/archive/2006/05/19/47034.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aspirin/comments/commentRss/47034.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aspirin/services/trackbacks/47034.html</trackback:ping><description><![CDATA[   
Quartz作为一个开源的作业调度框架，已经广泛应用于j2ee中。因为项目需要一个任务管理模块，所以选择了Quartz这个强大的框架，并对其进行
了扩展以适应项目的要求。首先介绍一下我们的系统构架，采用webwork，spring，hibernate整合架构，我的任务是无缝的把Quartz
加入到系统，提供一个界面，提供一些操作，使最终用户能够自己定义在什么时间对什么东西做哪些事情，“哪些事情”是预先定义的，提供给客户选择，这是客户
需求，系统地要求是能够容易的扩展，对增加一个新的任务定义提供一些简单的接口。这里不对Quartz作介绍了，想了解的人参考官方网站：http:
//www.opensymphony.com/quartz/，由于涉及的东西比较多，有些细节就带过了，我就大致的介绍一下总体的设计。<br />
    作业调度框架，主要要解决的问题是在某个时间对某些对象作某些动作。<br />
   
对于某个时间，Quarta提供一个字符表达式来表示，这方面要做的是提供一个方便的界面，直观的对其进行设置，不能让最终客户看那些对客户没意义的字符
串。这个工作需要解析那些字符，做起来还是有点意思的，也是比较麻烦的，有兴趣的话可以自己去试试。<br />
   
对于某些对象作和某些动作，Quartz都交给程序员自己去定义，它提供一个Job接口,对我们来说增加任务是比较简单的一件事情.既然Quartz提供
这么简单的接口,我为什么还要对其进行扩展呢?这就要来看"某些对象"了.在一般的系统来"某个动作"所操纵的对象是固定的,比如定期删除日至,定期检查
库存等.由于系统地特殊性,我们"某个动作"对哪些对象是不确定的,"哪些对象"由我提供一个界面,由最终客户去决定对一个或多个对象进行操作.<br />
   
这样就引入了一个范围的概念,"某个动作"是作用在一定范围内的,这个范围就不仅仅是哪些对象了,也可能是时间范围,比如删除几天前的日志信息.到这里对
任务的定义有所改变了,一个任务包括一些范围也可以说是条件,这个条件不包括触发点这个条件),一个动作.所以系统中定义了一个IRange接口,范围的
表示都保存在一个XML字符串,XML字符串的结构和怎么解析都交给具体的子对象,这样就给了子类的灵活性.<br />
public interface IRange {<br />
    public Map saveToMap(String strMap);//保存范围参数<br />
    public List getResult(Map map);//解析范围参数,并返回操作对象线程列表<br />
    public List getViewInfo();取得页面表示方式,结合了webwork<br />
}<br />
一个任务对应一个IRange的子类,IRange的子类对任务的各种参数范围,动作进行了实现.接着还加入一个IRangeManager接口,<br />
public interface IRangeManager {<br />
    public void saveDataMap(Long jobId, String strMap)throws SchedulerException;//保存范围参数<br />
    public List getObjects(Map map);//取得对象列表,其中包括了对参数的解析<br />
    public List getViews(Map map);<br />
}<br />
    实现的功能是对范围进行管理,包括对Quartz的操作,主要一些保存数据库等的操作,这样对于增加一个新的Range子类就可以不用知道Quartz了.<br />
    这样因为很多东西都是可配置的,增加了灵活性,对以后任务的添加定义了一些接口,考虑到了扩展性.在设计这个模块的时候,总的思路是把那些不变的东西都封装起来,把能变得东西都交给具体的任务了.<br />
上面我只是大致讲了一下,由于水平有限,可能讲的不是清楚,比较乱,我没有提供具体的例子,只是提供了一个思路,希望对大家有所帮助,或者你还有更好的设计,请与我联系.<br /><br /><img src ="http://www.blogjava.net/aspirin/aggbug/47034.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aspirin/" target="_blank">aspirin</a> 2006-05-19 12:49 <a href="http://www.blogjava.net/aspirin/archive/2006/05/19/47034.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Quartz与Hibernate在数据库的连接方面的结合</title><link>http://www.blogjava.net/aspirin/archive/2006/05/19/47033.html</link><dc:creator>aspirin</dc:creator><author>aspirin</author><pubDate>Fri, 19 May 2006 04:47:00 GMT</pubDate><guid>http://www.blogjava.net/aspirin/archive/2006/05/19/47033.html</guid><wfw:comment>http://www.blogjava.net/aspirin/comments/47033.html</wfw:comment><comments>http://www.blogjava.net/aspirin/archive/2006/05/19/47033.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aspirin/comments/commentRss/47033.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aspirin/services/trackbacks/47033.html</trackback:ping><description><![CDATA[   
首先介绍一下我们的系统构架，采用webwork，spring，hibernate整合架构,现在引入Quartz框架,Quartz和
hibernate各自拥有的自己数据库配置和连接池的配置,现在的任务是把两者用同一套配置.<br />
先谈谈Quartz,我用的版本是1.5.1,后面的版本我没去看了,没时间,接下来说的都以这个版本为准.Quartz虽然在提供一个
ConnectionProvider接口,提供给程序扩展,但是看它的StdSchedulerFactory实现类,要对它进行扩展还是一件比较麻烦
一件事情,所以我就直接修改了StdSchedulerFactory类,以达到的我的需求.<br />
接下来的问题是既然要结合,那么让Quartz来提供连接池配置呢还是有Hibernate提供.研究了两者的连接池方面的源代码,发现
Hibernate的连接池设计远远好于Quartz,Quartz目前只提供一个连接池提供类PoolingConnectionProvider,而
且使用的连接池是dbcp,这个连接池听说问题多多,相反hibernate提供了更加灵活的配置,所以连接池由Hibernate提供.<br />
    首先实现一个Quartz中ConnectionProvider子类HibernateConnectionProvider<br />
public class HibernateConnectionProvider implements ConnectionProvider {<br />
    private Connection con = null;<br />
    protected static ThreadLocal hibernateHolder = new ThreadLocal();<br />
    public Connection getConnection() throws SQLException {<br />
        con = null;<br />
        SessionFactoryImpl sessionFactory = null;<br />
        sessionFactory = (SessionFactoryImpl) Global.getSessionFacotry();<br />
        con = sessionFactory.getConnectionProvider().getConnection();<br />
    return con;<br />
}<br />
public void shutdown() throws SQLException {<br />
    // FIXME Auto-generated method stub<br />
}<br />
}<br />
,然后修改StdSchedulerFactory,在不破坏其本来的逻辑和可配置性下进行了相应的修改.修改的是private Scheduler
instantiate() throws SchedulerException方法,找到//Set up any
DataSources段进行修改,代码如下:<br />
String[] dsNames = cfg.getPropertyGroups(PROP_DATASOURCE_PREFIX);<br />
        for (int i = 0; i &lt; dsNames.length; i++) {<br />
            PropertiesParser pp = new PropertiesParser(cfg.getPropertyGroup(<br />
           
        PROP_DATASOURCE_PREFIX + "." +
dsNames[i], true));<br /><br />
            String dsDriver = pp<br />
           
       
.getStringProperty(PROP_DATASOURCE_DRIVER, null);<br />
            String dsURL = pp.getStringProperty(PROP_DATASOURCE_URL, null);<br />
            boolean dsAlwaysLookup = pp.getBooleanProperty(<br />
           
       
PROP_DATASOURCE_JNDI_ALWAYS_LOOKUP, false);<br />
            String dsUser = pp.getStringProperty(PROP_DATASOURCE_USER, "");<br />
            String dsPass = pp.getStringProperty(PROP_DATASOURCE_PASSWORD, "");<br />
            int dsCnt = pp.getIntProperty(PROP_DATASOURCE_MAX_CONNECTIONS, 3);<br />
            String providerClass = pp.getStringProperty(<br />
           
        PROP_DATASOURCE_PROVIDER_CLASS,
null);<br />
            String dsJndi = pp<br />
           
       
.getStringProperty(PROP_DATASOURCE_JNDI_URL, null);<br />
            String dsJndiInitial = pp.getStringProperty(<br />
           
        PROP_DATASOURCE_JNDI_INITIAL,
null);<br />
            String dsJndiProvider = pp.getStringProperty(<br />
           
        PROP_DATASOURCE_JNDI_PROVDER,
null);<br />
            String dsJndiPrincipal = pp.getStringProperty(<br />
           
        PROP_DATASOURCE_JNDI_PRINCIPAL,
null);<br />
            String dsJndiCredentials = pp.getStringProperty(<br />
           
        PROP_DATASOURCE_JNDI_CREDENTIALS,
null);<br />
            String dsValidation = pp.getStringProperty(<br />
           
        PROP_DATASOURCE_VALIDATION_QUERY,
null);<br />
            if (providerClass == null<br />
                    || providerClass.equals("")<br />
                    || providerClass<br />
           
           
   
.equals("org.quartz.utils.PoolingConnectionProvider")) {<br />
                if (dsDriver == null) {<br />
           
        initException = new
SchedulerException(<br />
           
           
    "Driver not specified for DataSource: "<br />
           
           
            + dsNames[i]);<br />
                    throw initException;<br />
                }<br />
                if (dsURL == null) {<br />
           
        initException = new
SchedulerException(<br />
           
           
    "DB URL not specified for DataSource: "<br />
           
           
            + dsNames[i]);<br />
                    throw initException;<br />
                }<br />
                try {<br />
           
        PoolingConnectionProvider cp =
new PoolingConnectionProvider(<br />
           
           
    dsDriver, dsURL, dsUser, dsPass, dsCnt,<br />
           
           
    dsValidation);<br />
           
        dbMgr =
DBConnectionManager.getInstance();<br />
           
       
dbMgr.addConnectionProvider(dsNames[i], cp);<br />
                } catch (SQLException sqle) {<br />
           
        initException = new
SchedulerException(<br />
           
           
    "Could not initialize DataSource: " + dsNames[i],<br />
           
           
    sqle);<br />
                    throw initException;<br />
                }<br />
            } else if (providerClass<br />
           
       
.equals("org.quartz.utils.JNDIConnectionProvider")) {<br />
                Properties props = null;<br />
                if (null != dsJndiInitial || null != dsJndiProvider<br />
           
            || null !=
dsJndiPrincipal || null != dsJndiCredentials) {<br />
                    props = new Properties();<br />
                    if (dsJndiInitial != null)<br />
           
           
props.put(PROP_DATASOURCE_JNDI_INITIAL, dsJndiInitial);<br />
                    if (dsJndiProvider != null)<br />
           
           
props.put(PROP_DATASOURCE_JNDI_PROVDER, dsJndiProvider);<br />
                    if (dsJndiPrincipal != null)<br />
           
           
props.put(PROP_DATASOURCE_JNDI_PRINCIPAL,<br />
           
           
        dsJndiPrincipal);<br />
                    if (dsJndiCredentials != null)<br />
           
           
props.put(PROP_DATASOURCE_JNDI_CREDENTIALS,<br />
           
           
        dsJndiCredentials);<br />
                }<br />
           
    JNDIConnectionProvider cp = new
JNDIConnectionProvider(dsJndi,<br />
           
            props,
dsAlwaysLookup);<br />
                dbMgr = DBConnectionManager.getInstance();<br />
                dbMgr.addConnectionProvider(dsNames[i], cp);<br />
            } else if (providerClass<br />
           
       
.equals("org.quartz.utils.HibernateConnectionProvider")) {<br />
           
    HibernateConnectionProvider cp = new
HibernateConnectionProvider();<br />
                dbMgr = DBConnectionManager.getInstance();<br />
                dbMgr.addConnectionProvider(dsNames[i], cp);<br />
            } else {<br />
                initException = new SchedulerException(<br />
           
           
"Provider_Class not Supported: " + providerClass);<br />
                throw initException;<br />
            }<br /><br />
        }<br />
    最后就是修改配置文件quartz.properties,加入<br />
#org.quartz.dataSource.myDS.provider_class = org.quartz.utils.JNDIConnectionProvider<br />
#org.quartz.dataSource.myDS.provider_class = org.quartz.utils.PoolingConnectionProvider<br />
org.quartz.dataSource.myDS.provider_class = org.quartz.utils.HibernateConnectionProvider加#的供参考.<br />
    经过测试,需要对hibernate连接池的一些参数进行微调,这样就完成了Quartz与Hibernate在数据库的连接方面的结合,如果有更好的解决方案,请联系我.<br /><br /><img src ="http://www.blogjava.net/aspirin/aggbug/47033.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aspirin/" target="_blank">aspirin</a> 2006-05-19 12:47 <a href="http://www.blogjava.net/aspirin/archive/2006/05/19/47033.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log的作用</title><link>http://www.blogjava.net/aspirin/archive/2006/03/28/37904.html</link><dc:creator>aspirin</dc:creator><author>aspirin</author><pubDate>Tue, 28 Mar 2006 14:26:00 GMT</pubDate><guid>http://www.blogjava.net/aspirin/archive/2006/03/28/37904.html</guid><wfw:comment>http://www.blogjava.net/aspirin/comments/37904.html</wfw:comment><comments>http://www.blogjava.net/aspirin/archive/2006/03/28/37904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aspirin/comments/commentRss/37904.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aspirin/services/trackbacks/37904.html</trackback:ping><description><![CDATA[
       最近同事在碰到一个棘手的问题,用了一天还是调试不出到底哪里出错了,郁闷中时老大过来就说了一个很好的解决方法,用日志跟踪.没过半小时,问题就找到了,定位很准确.这让我看到日志的重要性了.<br />
      
一开始我还是写一些log的,但是那时候觉得好像没什么必要,后来就从来没有写过,因为我想不出他的好处.现在在知道日志真正的作用,而且也是一个很强大
的工具.平时在写代码的时候,花个几秒钟写个log,也许会觉得很烦,但是我觉得还是值得的.<br />
       这也是一个习惯的问题,好的程序员之所以是个好的程序员是因为他有好的习惯,这些好的习惯带来的好处也是很多的.写日志只是其中一个好习惯,我也要慢慢留意一些好的习惯,慢慢总结.<img src ="http://www.blogjava.net/aspirin/aggbug/37904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aspirin/" target="_blank">aspirin</a> 2006-03-28 22:26 <a href="http://www.blogjava.net/aspirin/archive/2006/03/28/37904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Quartz的入门资料</title><link>http://www.blogjava.net/aspirin/archive/2006/03/28/37902.html</link><dc:creator>aspirin</dc:creator><author>aspirin</author><pubDate>Tue, 28 Mar 2006 14:24:00 GMT</pubDate><guid>http://www.blogjava.net/aspirin/archive/2006/03/28/37902.html</guid><wfw:comment>http://www.blogjava.net/aspirin/comments/37902.html</wfw:comment><comments>http://www.blogjava.net/aspirin/archive/2006/03/28/37902.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aspirin/comments/commentRss/37902.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aspirin/services/trackbacks/37902.html</trackback:ping><description><![CDATA[
       Quartz作为一个开源的作业调度框架，已经广泛应用于j2ee中，在这里提供一些资料以供参考：<br />
        首先是官方网站：<a href="http://www.opensymphony.com/quartz/">http://www.opensymphony.com/quartz/</a> 这里可以下载源代码，还有论坛，jira等最原始的资料。        <br />
        一个写的不错的介绍Quartz的中文文章：<a href="http://tech.ccidnet.com/art/322/20051122/377733_1.html"><b>详细讲解Quartz如何从入门到精通</b></a>，英文不好的可以参考这个。这篇文章大致的讲了Quartz的框架，很多细节并没有涉及，这也难怪，一篇文章不可能都写上去的。<br />
      
如果你想继续了解Quartz，官方网站有面向开发人员的文档，但是放在不起眼的角落，我以前闲逛时找到，现在一时找不到，什么时候什么找到了在加上去，我在
另外地方找到其中的几章，这两章是其中最重要的两章，可以作为参考，http://javaforge.com/proj/doc.do?doc_id=
1740<br />
        如果你还要继续深入研究，就请自己到cvs去下载最新源码，自己研读了，祝大家成功，我会接下去写一些自己从中学到的东西。<img src ="http://www.blogjava.net/aspirin/aggbug/37902.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aspirin/" target="_blank">aspirin</a> 2006-03-28 22:24 <a href="http://www.blogjava.net/aspirin/archive/2006/03/28/37902.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FC4下JDBC应该注意的问题</title><link>http://www.blogjava.net/aspirin/archive/2006/03/28/37901.html</link><dc:creator>aspirin</dc:creator><author>aspirin</author><pubDate>Tue, 28 Mar 2006 14:22:00 GMT</pubDate><guid>http://www.blogjava.net/aspirin/archive/2006/03/28/37901.html</guid><wfw:comment>http://www.blogjava.net/aspirin/comments/37901.html</wfw:comment><comments>http://www.blogjava.net/aspirin/archive/2006/03/28/37901.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aspirin/comments/commentRss/37901.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aspirin/services/trackbacks/37901.html</trackback:ping><description><![CDATA[
		<p>在完全刚装好的fc4上用jdbc进行数据库操作出现了一下错误：<br /><!--StartFragment --> java.net.SocketException: Invalid argument or cannot assign requested address<br />at java.net.PlainSocketImpl.socketConnect(Native Method)<br />at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:305)<br />at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:171)<br />at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:158)<br />at java.net.Socket.connect(Socket.java:452)<br />at java.net.Socket.connect(Socket.java:402)<br />at java.net.Socket.&lt;init&gt;(Socket.java:309)<br />at java.net.Socket.&lt;init&gt;(Socket.java:124) <br /><!--StartFragment -->       这是IP地址的问题,在FC4中默认的是IPv6 socket,JDK1.4支持的应该是IPv4,具体原因可以查看SUN公司给出的解释.<br />解决办法是在运行JAVA程序时加上 -Djava.net.preferIPv4Stack=true 如:<br /><br />java -Djava.net.preferIPv4Stack=true application. </p>
		<p>但是这个在每次都要加上这句话，另有解决方法是<!--StartFragment --> 修改 /etc/modprobe.conf 文件,增加 <br /><br />alias net-pf-10 off<br />alias ipv6 off<br /><br />这样就不用增加参数 "-Djava.net.preferIPv4Stack=true ",重起即可. </p>
		<p>但是既要ipv6又能解决这个问题的方法还没找到。希望高人指点</p>
<img src ="http://www.blogjava.net/aspirin/aggbug/37901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aspirin/" target="_blank">aspirin</a> 2006-03-28 22:22 <a href="http://www.blogjava.net/aspirin/archive/2006/03/28/37901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>junit with ant(转载)</title><link>http://www.blogjava.net/aspirin/archive/2006/03/28/37900.html</link><dc:creator>aspirin</dc:creator><author>aspirin</author><pubDate>Tue, 28 Mar 2006 14:18:00 GMT</pubDate><guid>http://www.blogjava.net/aspirin/archive/2006/03/28/37900.html</guid><wfw:comment>http://www.blogjava.net/aspirin/comments/37900.html</wfw:comment><comments>http://www.blogjava.net/aspirin/archive/2006/03/28/37900.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aspirin/comments/commentRss/37900.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aspirin/services/trackbacks/37900.html</trackback:ping><description><![CDATA[
		<h2>
				<font size="2">附：最近在弄cc，也找了一些ant资料，顺便转载记录一下</font>
				<br />
		</h2>
		<h2>
				<font size="2">转自http://ant.apache.org/manual/OptionalTasks/junit.html</font>
				<br />
		</h2>
		<h2>
				<a name="junit">JUnit</a>
		</h2>
		<h3>Description</h3>
		<p>This task runs tests from the JUnit testing framework. The latest version of 
the framework can be found at <a href="http://www.junit.org/">http://www.junit.org</a>. This task has been tested 
with JUnit 3.0 up to JUnit 3.8.1; it won't work with versions prior to JUnit 
3.0.</p>
		<p>
				<strong>Note:</strong> This task depends on external libraries not included 
in the Ant distribution. See <a href="http://www.blogchinese.com/user1/57647/archives/install.html#librarydependencies">Library Dependencies</a> for more 
information. </p>
		<p>
				<strong>Note</strong>: You must have <code>junit.jar</code> and the class 
files for the <code>&lt;junit&gt;</code> task in the same classpath. You can do 
one of: 
</p>
		<ol>
				<li>Put both <code>junit.jar</code> and the optional tasks jar file in 
<code>ANT_HOME/lib</code>. 
</li>
				<li>Do not put either in <code>ANT_HOME/lib</code>, and instead include their 
locations in your <code>CLASSPATH</code> environment variable. 
</li>
				<li>Do neither of the above, and instead, specify their locations using a 
<code>&lt;classpath&gt;</code> element in the build file. See <a href="http://www.blogchinese.com/user1/57647/faq.html#delegating-classloader" target="_top">the FAQ</a> for 
details. </li>
		</ol>
		<p>Tests are defined by nested <code>test</code> or <code>batchtest</code> tags 
(see <a href="http://www.blogchinese.com/user1/57647/archives/2006/488126.shtml#nested">nested elements</a>).</p>
		<h3>Parameters</h3>
		<table border="1" cellpadding="2" cellspacing="0">
				<tbody>
						<tr>
								<td valign="top" width="12%">
										<b>Attribute</b>
								</td>
								<td valign="top" width="78%">
										<b>Description</b>
								</td>
								<td valign="top" width="10%">
										<b>Required</b>
								</td>
						</tr>
						<tr>
								<td valign="top">printsummary</td>
								<td valign="top">Print one-line statistics for each testcase. Can take the values 
<code>on</code>, <code>off</code>, and <code>withOutAndErr</code>. 
<code>withOutAndErr</code> is the same as <code>on</code> but also includes the 
output of the test as written to <code>System.out</code> and 
<code>System.err</code>.</td>
								<td align="center" valign="top">No; default is <code>off</code>.</td>
						</tr>
						<tr>
								<td valign="top">fork</td>
								<td valign="top">Run the tests in a separate VM.</td>
								<td align="center" valign="top">No; default is <code>off</code>.</td>
						</tr>
						<tr>
								<td valign="top">forkmode</td>
								<td valign="top">Controls how many Java Virtual Machines get created if you want 
to fork some tests. Possible values are "perTest" (the default), "perBatch" and 
"once". "once" creates only a single Java VM for all tests while "perTest" 
creates a new VM for each TestCase class. "perBatch" creates a VM for each 
nested <code>&lt;batchtest&gt;</code> and one collecting all nested 
<code>&lt;test&gt;</code>s. Note that only tests with the same settings of 
<code>filtertrace</code>, <code>haltonerror</code>, <code>haltonfailure</code>, 
<code>errorproperty</code> and <code>failureproperty</code> can share a VM, so 
even if you set <code>forkmode</code> to "once", Ant may have to create more 
than a single Java VM. This attribute is ignored for tests that don't get forked 
into a new Java VM. <em>since Ant 1.6.2</em></td>
								<td align="center" valign="top">No; default is <code>perTest</code>.</td>
						</tr>
						<tr>
								<td valign="top">haltonerror</td>
								<td valign="top">Stop the build process if an error occurs during the test 
run.</td>
								<td align="center" valign="top">No; default is <code>off</code>.</td>
						</tr>
						<tr>
								<td valign="top">errorproperty</td>
								<td valign="top">The name of a property to set in the event of an error.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">haltonfailure</td>
								<td valign="top">Stop the build process if a test fails (errors are considered 
failures as well).</td>
								<td align="center" valign="top">No; default is <code>off</code>.</td>
						</tr>
						<tr>
								<td valign="top">failureproperty</td>
								<td valign="top">The name of a property to set in the event of a failure (errors 
are considered failures as well).</td>
								<td align="center" valign="top">No.</td>
						</tr>
						<tr>
								<td valign="top">filtertrace</td>
								<td valign="top">Filter out Junit and Ant stack frames from error and failure 
stack traces.</td>
								<td align="center" valign="top">No; default is <code>on</code>.</td>
						</tr>
						<tr>
								<td valign="top">timeout</td>
								<td valign="top">Cancel the individual tests if they don't finish in the given 
time (measured in milliseconds). Ignored if <code>fork</code> is disabled.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">maxmemory</td>
								<td valign="top">Maximum amount of memory to allocate to the forked VM. Ignored if 
<code>fork</code> is disabled.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">jvm</td>
								<td valign="top">The command used to invoke the Java Virtual Machine, default is 
'java'. The command is resolved by <code>java.lang.Runtime.exec()</code>. 
Ignored if <code>fork</code> is disabled.</td>
								<td align="center" valign="top">No; default is <code>java</code>.</td>
						</tr>
						<tr>
								<td valign="top">dir</td>
								<td valign="top">The directory in which to invoke the VM. Ignored if 
<code>fork</code> is disabled.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">newenvironment</td>
								<td valign="top">Do not propagate the old environment when new environment 
variables are specified. Ignored if <code>fork</code> is disabled.</td>
								<td align="center" valign="top">No; default is <code>false</code>.</td>
						</tr>
						<tr>
								<td valign="top">includeantruntime</td>
								<td valign="top">Implicitly add the Ant classes required to run the tests and 
JUnit to the classpath in forked mode. <b>Note:</b> Please read the <a href="http://www.blogchinese.com/user1/57647/faq.html#junit-no-runtime-xml">Ant FAQ</a> if you want to set this 
to <code>false</code> and use the XML formatter at the same time.</td>
								<td align="center" valign="top">No; default is <code>true</code>.</td>
						</tr>
						<tr>
								<td valign="top">showoutput</td>
								<td valign="top">Send any output generated by tests to Ant's logging system as 
well as to the formatters. By default only the formatters receive the 
output.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">tempdir</td>
								<td valign="top">Where Ant should place temporary files. <em>Since Ant 
1.6</em>.</td>
								<td align="center" valign="top">No; default is the project's base 
directory.</td>
						</tr>
						<tr>
								<td valign="top">reloading</td>
								<td valign="top">Whether or not a new classloader should be instantiated for each 
test case.<br />Ignore if <code>fork</code> is set to true. <em>Since Ant 
1.6</em>.</td>
								<td align="center" valign="top">No; default is 
<code>true</code>.</td>
						</tr>
				</tbody>
		</table>
		<p>By using the <code>errorproperty</code> and <code>failureproperty</code> 
attributes, it is possible to perform setup work (such as starting an external 
server), execute the test, clean up, and still fail the build in the event of a 
failure.</p>
		<p>The <code>filtertrace</code> attribute condenses error and failure stack 
traces before reporting them. It works with both the plain and XML formatters. 
It filters out any lines that begin with the following string patterns:</p>
		<pre>   "junit.framework.TestCase"<br />   "junit.framework.TestResult"<br />   "junit.framework.TestSuite"<br />   "junit.framework.Assert."<br />   "junit.swingui.TestRunner"<br />   "junit.awtui.TestRunner"<br />   "junit.textui.TestRunner"<br />   "java.lang.reflect.Method.invoke("<br />   "sun.reflect."<br />   "org.apache.tools.ant."</pre>
		<h3>
				<a name="nested">Nested Elements</a>
		</h3>
		<p>The <code>&lt;junit&gt;</code> task supports a nested 
<code>&lt;classpath&gt;</code> element that represents a <a href="http://www.blogchinese.com/user1/57647/archives/using.html#path">PATH like structure</a>.</p>
		<h4>jvmarg</h4>
		<p>If <code>fork</code> is enabled, additional parameters may be passed to the 
new VM via nested <code>&lt;jvmarg&gt;</code> elements. For example:</p>
		<pre>&lt;junit fork="yes"&gt;<br />  &lt;jvmarg value="/-Djava.compiler=NONE"/&gt;<br />  ...<br />&lt;/junit&gt;<br /></pre>
		<p>would run the test in a VM without JIT.</p>
		<p>
				<code>&lt;jvmarg&gt;</code> allows all attributes described in <a href="http://www.blogchinese.com/user1/57647/archives/using.html#arg">Command-line Arguments</a>.</p>
		<h4>sysproperty</h4>
		<p>Use nested <code>&lt;sysproperty&gt;</code> elements to specify system 
properties required by the class. These properties will be made available to the 
VM during the execution of the test (either ANT's VM or the forked VM, if 
<code>fork</code> is enabled). The attributes for this element are the same as 
for <a href="http://www.blogchinese.com/user1/57647/archives/CoreTasks/exec.html#env">environment variables</a>.</p>
		<pre>&lt;junit fork="no"&gt;<br />  &lt;sysproperty key="basedir" value="${basedir}"/&gt;<br />  ...<br />&lt;/junit&gt;<br /></pre>
		<p>would run the test in ANT's VM and make the <code>basedir</code> property 
available to the test.</p>
		<h4>syspropertyset</h4>
		<p>You can specify a set of properties to be used as system properties with <a href="http://www.blogchinese.com/user1/57647/archives/CoreTypes/propertyset.html">syspropertyset</a>s.</p>
		<p>
				<em>since Ant 1.6</em>.</p>
		<h4>env</h4>
		<p>It is possible to specify environment variables to pass to the forked VM via 
nested <code>&lt;env&gt;</code> elements. For a description of the 
<code>&lt;env&gt;</code> element's attributes, see the description in the <a href="http://www.blogchinese.com/user1/57647/archives/CoreTasks/exec.html#env">exec</a> task.</p>
		<p>Settings will be ignored if <code>fork</code> is disabled.</p>
		<h4>bootclasspath</h4>
		<p>The location of bootstrap class files can be specified using this <a href="http://www.blogchinese.com/user1/57647/archives/using.html#path">PATH like structure</a> - will be ignored if 
<i>fork</i> is not <code>true</code> or the target VM doesn't support it (i.e. 
Java 1.1).</p>
		<p>
				<em>since Ant 1.6</em>.</p>
		<h4>permissions</h4>
		<p>Security permissions can be revoked and granted during the execution of the 
class via a nested <i>permissions</i> element. For more information please see 
<a href="http://www.blogchinese.com/user1/57647/archives/CoreTypes/permissions.html">permissions</a></p>
		<p>Settings will be ignored if fork is enabled.</p>
		<p>
				<em>since Ant 1.6</em>.</p>
		<h4>assertions</h4>
		<p>You can control enablement of Java 1.4 assertions with an <a href="http://www.blogchinese.com/user1/57647/archives/CoreTypes/assertions.html"><tt>&lt;assertions&gt;</tt></a> 
subelement.</p>
		<p>Assertion statements are currently ignored in non-forked mode.</p>
		<p>
				<em>since Ant 1.6.</em>
		</p>
		<h4>formatter</h4>
		<p>The results of the tests can be printed in different formats. Output will 
always be sent to a file, unless you set the <code>usefile</code> attribute to 
<code>false</code>. The name of the file is determined by the name of the test 
and can be set by the <code>outfile</code> attribute of 
<code>&lt;test&gt;</code>.</p>
		<p>There are three predefined formatters - one prints the test results in XML 
format, the other emits plain text. The formatter named <code>brief</code> will 
only print detailed information for testcases that failed, while 
<code>plain</code> gives a little statistics line for all test cases. Custom 
formatters that need to implement 
<code>org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter</code> 
can be specified.</p>
		<p>If you use the XML formatter, it may not include the same output that your 
tests have written as some characters are illegal in XML documents and will be 
dropped.</p>
		<p>
				<b>Note:</b> Please read the <a href="http://www.blogchinese.com/user1/57647/faq.html#junit-no-runtime-xml">Ant FAQ</a> if you want to set the 
fork attribute to <code>true</code>, the includeAntRuntime attribute to 
<code>false</code> and use the XML formatter at the same time.</p>
		<table border="1" cellpadding="2" cellspacing="0">
				<tbody>
						<tr>
								<td valign="top" width="12%">
										<b>Attribute</b>
								</td>
								<td valign="top" width="78%">
										<b>Description</b>
								</td>
								<td valign="top" width="10%">
										<b>Required</b>
								</td>
						</tr>
						<tr>
								<td valign="top">type</td>
								<td valign="top">Use a predefined formatter (either <code>xml</code>, 
<code>plain</code>, or <code>brief</code>).</td>
								<td rowspan="2" align="center">Exactly one of these.</td>
						</tr>
						<tr>
								<td valign="top">classname</td>
								<td valign="top">Name of a custom formatter class.</td>
						</tr>
						<tr>
								<td valign="top">extension</td>
								<td valign="top">Extension to append to the output filename.</td>
								<td align="center">Yes, if <code>classname</code> has been used.</td>
						</tr>
						<tr>
								<td valign="top">usefile</td>
								<td valign="top">Boolean that determines whether output should be sent to a 
file.</td>
								<td align="center">No; default is <code>true</code>.</td>
						</tr>
						<tr>
								<td valign="top">if</td>
								<td valign="top">Only use formatter if the named property is set.</td>
								<td align="center">No; default is <code>true</code>.</td>
						</tr>
						<tr>
								<td valign="top">unless</td>
								<td valign="top">Only use formatter if the named property is <b>not</b> set.</td>
								<td align="center">No; default is <code>true</code>.</td>
						</tr>
				</tbody>
		</table>
		<h4>test</h4>
		<p>Defines a single test class.</p>
		<table border="1" cellpadding="2" cellspacing="0">
				<tbody>
						<tr>
								<td valign="top" width="12%">
										<b>Attribute</b>
								</td>
								<td valign="top" width="78%">
										<b>Description</b>
								</td>
								<td valign="top" width="10%">
										<b>Required</b>
								</td>
						</tr>
						<tr>
								<td valign="top">name</td>
								<td valign="top">Name of the test class.</td>
								<td align="center">Yes</td>
						</tr>
						<tr>
								<td valign="top">fork</td>
								<td valign="top">Run the tests in a separate VM. Overrides value set in 
<code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">haltonerror</td>
								<td valign="top">Stop the build process if an error occurs during the test run. 
Overrides value set in <code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">errorproperty</td>
								<td valign="top">The name of a property to set in the event of an error. Overrides 
value set in <code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">haltonfailure</td>
								<td valign="top">Stop the build process if a test fails (errors are considered 
failures as well). Overrides value set in <code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">failureproperty</td>
								<td valign="top">The name of a property to set in the event of a failure (errors 
are considered failures as well). Overrides value set in 
<code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">filtertrace</td>
								<td valign="top">Filter out Junit and Ant stack frames from error and failure 
stack traces. Overrides value set in <code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No; default is <code>on</code>.</td>
						</tr>
						<tr>
								<td valign="top">todir</td>
								<td valign="top">Directory to write the reports to.</td>
								<td align="center" valign="top">No; default is the current directory.</td>
						</tr>
						<tr>
								<td valign="top">outfile</td>
								<td valign="top">Base name of the test result. The full filename is determined by 
this attribute and the extension of <code>formatter</code>.</td>
								<td align="center" valign="top">No; default is <code>TEST-</code><em>name</em>, 
where <em>name</em> is the name of the test specified in the <code>name</code> 
attribute.</td>
						</tr>
						<tr>
								<td valign="top">if</td>
								<td valign="top">Only run test if the named property is set.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">unless</td>
								<td valign="top">Only run test if the named property is <b>not</b> set.</td>
								<td align="center" valign="top">No</td>
						</tr>
				</tbody>
		</table>
		<p>Tests can define their own formatters via nested 
<code>&lt;formatter&gt;</code> elements.</p>
		<h4>batchtest</h4>
		<p>Define a number of tests based on pattern matching.</p>
		<p>
				<code>batchtest</code> collects the included files from any number of nested 
<a href="http://www.blogchinese.com/user1/57647/archives/CoreTypes/fileset.html"><code>&lt;fileset&gt;</code></a>s. It then 
generates a test class name for each file that ends in <code>.java</code> or 
<code>.class</code>.</p>
		<table border="1" cellpadding="2" cellspacing="0">
				<tbody>
						<tr>
								<td valign="top" width="12%">
										<b>Attribute</b>
								</td>
								<td valign="top" width="78%">
										<b>Description</b>
								</td>
								<td valign="top" width="10%">
										<b>Required</b>
								</td>
						</tr>
						<tr>
								<td valign="top">fork</td>
								<td valign="top">Run the tests in a separate VM. Overrides value set in 
<code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">haltonerror</td>
								<td valign="top">Stop the build process if an error occurs during the test run. 
Overrides value set in <code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">errorproperty</td>
								<td valign="top">The name of a property to set in the event of an error. Overrides 
value set in <code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">haltonfailure</td>
								<td valign="top">Stop the build process if a test fails (errors are considered 
failures as well). Overrides value set in <code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">failureproperty</td>
								<td valign="top">The name of a property to set in the event of a failure (errors 
are considered failures as well). Overrides value set in 
<code>&lt;junit&gt;</code></td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">filtertrace</td>
								<td valign="top">Filter out Junit and Ant stack frames from error and failure 
stack traces. Overrides value set in <code>&lt;junit&gt;</code>.</td>
								<td align="center" valign="top">No; default is <code>on</code>.</td>
						</tr>
						<tr>
								<td valign="top">todir</td>
								<td valign="top">Directory to write the reports to.</td>
								<td align="center" valign="top">No; default is the current directory.</td>
						</tr>
						<tr>
								<td valign="top">if</td>
								<td valign="top">Only run tests if the named property is set.</td>
								<td align="center" valign="top">No</td>
						</tr>
						<tr>
								<td valign="top">unless</td>
								<td valign="top">Only run tests if the named property is <strong>not</strong> 
set.</td>
								<td align="center" valign="top">No</td>
						</tr>
				</tbody>
		</table>
		<p>Batchtests can define their own formatters via nested 
<code>&lt;formatter&gt;</code> elements.</p>
		<h3>Examples</h3>
		<pre>&lt;junit&gt;<br />  &lt;test name="my.test.TestCase"/&gt;<br />&lt;/junit&gt;<br /></pre>
		<p>Runs the test defined in <code>my.test.TestCase</code> in the same VM. No 
output will be generated unless the test fails.</p>
		<pre>&lt;junit printsummary="yes" fork="yes" haltonfailure="yes"&gt;<br />  &lt;formatter type="plain"/&gt;<br />  &lt;test name="my.test.TestCase"/&gt;<br />&lt;/junit&gt;<br /></pre>
		<p>Runs the test defined in <code>my.test.TestCase</code> in a separate VM. At 
the end of the test, a one-line summary will be printed. A detailed report of 
the test can be found in <code>TEST-my.test.TestCase.txt</code>. The build 
process will be stopped if the test fails.</p>
		<pre>&lt;junit printsummary="yes" haltonfailure="yes"&gt;<br />  &lt;classpath&gt;<br />    &lt;pathelement location="${build.tests}"/&gt;<br />    &lt;pathelement path="${java.class.path}"/&gt;<br />  &lt;/classpath&gt;<br /><br />  &lt;formatter type="plain"/&gt;<br /><br />  &lt;test name="my.test.TestCase" haltonfailure="no" outfile="result"&gt;<br />    &lt;formatter type="xml"/&gt;<br />  &lt;/test&gt;<br /><br />  &lt;batchtest fork="yes" todir="${reports.tests}"&gt;<br />    &lt;fileset dir="${src.tests}"&gt;<br />      &lt;include name="**/*Test*.java"/&gt;<br />      &lt;exclude name="**/AllTests.java"/&gt;<br />    &lt;/fileset&gt;<br />  &lt;/batchtest&gt;<br />&lt;/junit&gt;<br /></pre>
		<p>Runs <code>my.test.TestCase</code> in the same VM, ignoring the given 
CLASSPATH; only a warning is printed if this test fails. In addition to the 
plain text test results, for this test a XML result will be output to 
<code>result.xml</code>. Then, for each matching file in the directory defined 
for <code>${src.tests}</code> a test is run in a separate VM. If a test fails, 
the build process is aborted. Results are collected in files named 
<code>TEST-</code><em>name</em><code>.txt</code> and written to 
<code>${reports.tests}</code>.</p>
<img src ="http://www.blogjava.net/aspirin/aggbug/37900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aspirin/" target="_blank">aspirin</a> 2006-03-28 22:18 <a href="http://www.blogjava.net/aspirin/archive/2006/03/28/37900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>