﻿<?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-翠湖月色-随笔分类-报表设计与开发</title><link>http://www.blogjava.net/matthew2006/category/11906.html</link><description>No Buddha tree at all,And bright mirror nor.Now nothing at all,How dusts any more ? </description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 22:35:37 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 22:35:37 GMT</pubDate><ttl>60</ttl><item><title>use japerreports step by step－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2007/01/29/96504.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Mon, 29 Jan 2007 06:25:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2007/01/29/96504.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/96504.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2007/01/29/96504.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/96504.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/96504.html</trackback:ping><description><![CDATA[1.下载japerreports：<br />网址：<a href="https://sourceforge.net/projects/jasperreports/">https://sourceforge.net/projects/jasperreports/</a><br />最好下载完整的zip包：jasperreports-1.3.0-project.zip<br />这样可以得到所有的文件，包括src，samples。<br /><br />2.下载到jasperreports-1.3.0-project.zip包后，解压一看，本身是一个project，有.project,.classpath文件等，于是想到可以把它做为一个project导入eclipse中，于是把它拷贝到eclipse的workspace中，然后“import”，即可整个jasperreport工程导入到ecplise了！<br /><br />注意：我刚开始导入时总出错，提示"Invalid project description",无法导入；后来鬼使神差的把解压后的工程名称"jasperreports-1.3.0"改为"jasperreports"就顺利导入了！<br />再后来，想把工程改为别的名称，但是import时指定工程根目录后，压根就无反应，"finish"按钮始终是灰色的，无法导入；<br />最后问了一下wwm，才是知道如果要import a project，则project名称要与.project文件的&lt;name&gt;&lt;/name&gt;中的名称一致，否则无法导入！<br />例如，工程名称（根目录）为jasperreports，那么.project中应为：&lt;name&gt;jasperreports&lt;/name&gt;；<br />前面是凑巧改对了。<br /><br />3.但是导入到eclipse后，它是做为一个java project的，也就方便看源代码而已，到底要怎么才能运行生成报表呢？这就需要ant来执行build.xml。<br /><br />4.如果没有接触过ant，没关系，很简单的，放心吧。推荐看《java 学习笔记》良葛格 附录A Ant简介(网上搜电子版的即可），15分钟即可搞定ant，不要被它挡路了哦:)<br /><br />5.并且，eclipse中就自带ant，如果要运行"demo\samples\barbecue"示例，进入"jasperreports\demo\samples\barbecue",右键"build.xml",选"run as-&gt;ant build.."，把"javac","compile","fill","view"都打上勾,点"run",ant开始运行该build.xml，不一会，哇，看到报表了！好激动！不过这个报表只有表，没有图，即：看不到自己想要的折线图，柱状图，饼图等。<br /><br />6.看了一些"demo\samples"下的所有示例，觉得折线图，柱状图，饼图等应该都是在"charts"示例中，意识运行"charts"示例的build.xml文件，但是不能编译通过，提示错误：<br />javac:<br />    [javac] Compiling 2 source files to E:\jiangcm\workspace-forict-myeclipse\jasperreports\demo\samples\charts<br />    [javac] 注意： E:\jiangcm\workspace-forict-myeclipse\jasperreports\demo\samples\charts\ChartsApp.java 使用了未经检查或不安全的操作。<br />    [javac] 注意： 要了解详细信息，请使用 -Xlint:unchecked 重新编译。<br />compile:通过,略.<br />fill:<br />     <img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> java.sql.SQLException: Connection is broken: Connection refused: connect<br />     <img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> at org.hsqldb.Trace.getError(Unknown Source)<br />     ……<br />view:<br />     <img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> net.sf.jasperreports.engine.JRException: java.io.FileNotFoundException: MultipleAxisChartReport.jrprint<br /><br />7.怎么办呢？上网查jasper的资料，折腾了大半天，还是没有任何进展，网上的资料都只简单的提到“需要ant”执行，唉，真是没办法。只好转向运行"webapp"示例，运行成功了！（详细看运行jasperreport的webapp示例一文）<br /><br />8.实在不知道为什么最重要的charts示例无法运行，还是先踏踏实实看一下jasperreports的原理吧，于是认真看了"jasperreports 教程"，了解到jasperreports的基本原理：<br />调用jasperreports的相应的库函数，把.jrxml编译为.jasper；-&gt;由.jasper生成.jrprint；-&gt;由.jrprint得到各种输出方式的报表。<br /><br />理解到这一点后，自己就没再往下看，因为能够确定charts示例无法运行绝对与jasperreports的原理无关了。<br /><br />9.于是，认真分析了一下编译提示的错误，发现主要就是因为编译无法通过造成的，以至于后面缺少对应的.jrprint文件。而编译不通过的原因是“[javac]要了解详细信息，请使用-xlint:unchecked重新编译”，在build.xml中相应位置加上编译参数：<br />&lt;javac srcdir="src" destdir="${classdir}"&gt;<br />&lt;compilerarg value="-Xlint:unchecked"/&gt; <br /><br />终于编译通过了！！（详细参见“Eclipse中报错"要了解详细信息，请使用-xlint unchecked重新编译"的解决方案”一文）<br /><br />10.这时javac通过了，即ChartsApp.java编译通过了，但是fill和view这两步还是提示原来的错误,如下所示：<br />javac:<br />    [javac] Compiling 2 source files to E:\jiangcm\workspace-forict-myeclipse\jasperreports-1.3.0-project\demo\samples\charts<br />    [javac] E:\jiangcm\workspace-forict-myeclipse\jasperreports-1.3.0-project\demo\samples\charts\ChartsApp.java:115: 警告： [unchecked] 对作为普通类型 java.util.Map 的成员的 put(K,V) 的调用未经检查<br />    [javac] parameters.put("MaxOrderID", new Integer(12500));<br />    [javac] ^<br />    [javac] 1 警告<br />compile:<br />fill:<br />     <img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> java.sql.SQLException: Connection is broken: Connection refused: connect<br />     <img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> at org.hsqldb.Trace.getError(Unknown Source)<br />view:<br />     <img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> net.sf.jasperreports.engine.JRException: java.io.FileNotFoundException: MultipleAxisChartReport.jrprint<br />     <img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> at net.sf.jasperreports.engine.util.JRLoader.loadObject(JRLoader.java:75)<br />其中fill这一步提示的是SQLException的错误，难道是要配置数据源或者是要运行什么东西？<br />再看fill的出错提示："<img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> at org.hsqldb.Trace.getError(Unknown Source)",对了，好像"demo"文件夹里有"hsqldb"文件夹，是不是要先运行"hsqldb"文件夹的内容？？试试。<br /><br />10.于是ant编译"demo\hsqldb"的build.xml；提示:server is running...<br />应该是数据库启动了；<br /><br />11.接着ant编译"demo\samples\charts"的build.xml；顺利fill，耶！看到曲线图、柱状图等报表了！<br /><br />12.备注：关掉报表再直接运行一次charts的build.xml，还能正确看到报表；关掉eclipse再运行，也也还能正确看到报表；看来hsqldb只要运行过一次，以后就都有效了！至于原理就不太明白了，难道是hsqldb运行过之后就永久的把数据导入到工程的报表中了？有待以后学习验证了。<br /><br />13.小结：<br />运行jasperreports示例，关键是要注意和解决三个问题：<br />1）import project时，工程名称要与.project文件中"&lt;name&gt;&lt;/name&gt;"中的名称一致，否则无法导入；<br /><br />2）jdk版本兼容的问题：<br />加入编译参数：&lt;compilerarg value="-Xlint:unchecked"/&gt;<br /><br />3）要先运行一下"demo\hsqldb"下的build.xml，启动数据库导入数据，才能fill报表，运行显示报表；<br />ok！<br /><br />以上步骤重复验证过两三次均无问题，按上述步骤保证就能运行jasperreports提供的charts关键示例了！<br /><img src ="http://www.blogjava.net/matthew2006/aggbug/96504.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2007-01-29 14:25 <a href="http://www.blogjava.net/matthew2006/archive/2007/01/29/96504.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>myeclipse+tomcat 环境下jasperreports sample之webapp例子－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2007/01/29/96501.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Mon, 29 Jan 2007 06:14:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2007/01/29/96501.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/96501.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2007/01/29/96501.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/96501.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/96501.html</trackback:ping><description><![CDATA[一、引子：前期试验工作<br />1.直接在jasperreports-1.3.0-project工程中运行，ant编译"demo\samples\webapp"的build.xml，可以直接看到由webapp中的.jrxml文件定义的报表格式，但是无法显示数据源的数据；<br /><br />2.上述ant编译"demo\samples\webapp"的build.xml时，也出现了"-Xlint:unchecked" 和"- Xlint:deprecation"的版本兼容问题的错误，在build.xml中加入编译参数后，没什么变化，依然只是能看到.jrxml文件定义的报表格式，无法显示数据；<br /><br />3.运行&lt;target name="viewDesign"&gt;时出错，提示：<br />viewDesign:<br />     <img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> net.sf.jasperreports.engine.JRException: java.io.FileNotFoundException: reports\WebappReport.jasper<br />     <img height="20" alt="[java]" src="http://www.javaresearch.org/faces/60.gif" width="20" border="0" /> at net.sf.jasperreports.engine.util.JRLoader.loadObject(JRLoader.java:75)<br /><br />查看了一下"webapp\reports"目录，果然没有编译好的WebappReport.jasper文件，那么是操作问题导致编译出错无法把.jrxml编译成.jasper，还是程序本身就没有调用编译设计文件的代码？<br /><br />4.查看build.xml文件中&lt;target name="viewDesign"&gt;运行的net.sf.jasperreports.view.JasperDesignViewer类的源代码，以及看build.xml中提供的参数，发现JasperDesignViewer类只是根据传入的.jrxml或者.jasper文件的路径显示报表，并不负责编译和填充xml设计文件；<br /><br />5.ok，webapp示例应该就是只提供了在web服务器中跑的支持，并不同时提供直接applet方式显示，简单让它能够根据.jrxml或者.jasper源设计文件看一下报表格式而已。因为applet方式显示报表的示例charts中都有了，也没必要提供支持了。<br /><br />6.所以，如有要显示webapp示例，只能在web服务器中部署运行了。这个示例也正是用来展示web环境下如何使用jasperreports开发报表的！<br /><br />7.部署webapp示例详见下文；<br /><br />二、myeclipse+tomcat部署运行jasperreports的webapp示例step by step<br />1.在eclipse中新建web 工程:"jasperwebappproject"；<br /><br />2.把"jasperreports-1.3.0-project\demo\samples\webapp"下的所有文件拷贝到新建的web工程("jasperwebappproject")的webroot下；<br /><br />注意：<br /> * 此时新工程的webroot目录就与原webapp目录结构对应上了(不要把该webapp文件夹也拷贝过去了，因为新建web工程就默认有webroot根目录了)，拷贝时要覆盖掉新建工程时webroot下的原WEB-INF目录；<br /><br /> *一定要确保webapp\WEB-INF\classes目录的下的三个源代码文件夹(datasource、scriptlets、servlets)和web.xml文件都拷贝过去了！！<br />因为本人操作的时候发现，有时候原WEB-INF文件能够全部拷贝过去，有时候skip掉没有拷贝过去。<br /><br /> *如果没有把该web.xml拷贝过去，将无法运行示例中的servlet samples，并且jsp samples中也无法显示图片！因为web.xml中没有配置ImageServlet：<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;ImageServlet&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;net.sf.jasperreports.j2ee.servlets.ImageServlet&lt;/servlet-class&gt;<br />&lt;/servlet&gt;<br /><br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt;ImageServlet&lt;/servlet-name&gt;<br />&lt;url-pattern&gt;/servlets/image&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br /><br />3.把"jasperreports-1.3.0-project\lib"与"jasperreports-1.3.0-project\dist"下的所有jar包拷贝到新建工程的lib下；<br />注释：其实只需要拷贝webapp中build.xml文件中要include的jar包，不过本人懒得一一去对了，把所有的jar包都加上，图省事；<br /><br />4.右键新建工程"jasperwebappproject"-&gt;"Properties"-&gt;"Java build path"-&gt;"source"-"add folder...",把"jasperwebappproject\webroot\WEB-INF\classes"文件夹打上勾，即：把classes文件夹也设置为source folder；因为classes文件夹下有.java源文件，如果不设置为source folder，就需要手工编译了，并且eclipse还可能因为自动编译把该classes的源文件全部清空，因为src是空的。<br />所以，一定要把classes文件夹设置为source folder；<br /><br />注：<br />"Java build path"-&gt;"source"中有一选项"allow output folders for source folders",按字面理解应该是把该项选上就是把默认的输出路径WEB-INF\classes设置为source folder了，但是我把它选上了，好像没有效果，只是当时把classes加入source树了，但是下次再查看工程properties还是原样，工程中也没有把classes当作source folder，而且还把classes目录清空了。<br />选项"allow output folders for source folders"到底是干什么用的呢？不知道了，期待知道的回答一下，万分感谢！<br /><br />5.此时，我们把webapp下的所有文件和需要的所有jar包都拷贝到新工程了，并且把WEB-INF\classes设置为source folder了；但是如果此时转换到J2EE development视图的话，会发现工程中报了很多错误，主要是.jsp文件和.html文件大量报错。.html文件的错误无关紧要，只是多了一些没有开始标签的结束标签，改不改都不影响运行。但是.jsp文件怎么会报错，提示很多类文件找不到呢？所需要的jar包(包括jasperreports-1.3.0.jar)和数据源等文件(WEB-INF\classes\datasource)都在工程中了呀！<br />解决：<br />根据以往经验，eclipse中如果直接把别人的代码复制粘贴上去，即使所有的类文件和jar包都存在，也会报错，需要把该.java源文件重新"剪切"粘贴一下，这样就不报错了。<br />试了一下，把jsp文件夹下的compile.jsp,fill.jsp,viewer.jsp,html.jsp文件前面部分导入包和类的那些语句(eg.&lt;%@ page import="datasource.*" %&gt;)重新剪切粘贴一下，保存，耶，不提示红×错误了！<br /><br />注：<br />不理会eclipse中这些.jsp文件的报错也没关系，因为部署到tomcat后，运行时肯定是能够找到所需要的类的，因为那些jar包都在工程中了。不过在eclipse中看着那么多的红×错误，还是剪切粘贴一下消除它，心里比较爽。<br /><br />6.把工程部署(deploy)到tomcat中；<br /><br />7.启动tomcat；<br /><br />8.在IE中输入"http://192.168.3.161:9005/jasperSampleWebapp/index.html",正确显示！<br />9.点左边的菜单"compile JRXML",点右边的"jsp examples",-&gt;"execute",提示编译成功！<br />10.点左边的菜单"fill report",点右边的"jsp examples",-&gt;"execute",提示填充数据成功！<br />11.点左边的菜单"export report",分别可以以pdf,html等格式输出报表！耶，革命终于胜利！<br /><br />ok！<br /><br />三、小结：<br />    总结运行jasperreports的webapp示例的关键几个步骤：<br />1.要确保webapp\WEB-INF\classes目录的下的三个源代码文件夹(datasource、scriptlets、servlets)和web.xml文件都拷贝过去了！！<br />2.要把WEB-INF\classes设置为source folder,否则提示找不到数据源,因为该webapp示例的数据源是WEB-INF\classes\datasource\WebappDataSource.java里的二维数组；<br />3.要确保把原web.xml复制到工程中了,否则无法显示图片，也无法运行servlet samples；<br />4.*.jsp文件的报错可通过重新剪切粘贴一下来消除；<br />5.ie中浏览图表时要按照“compile、fill、export”的顺序点击，这样才能顺利看到报表。<br /><br />四、其他相关内容：<br />1.把.jrxml编译成.jasper文件的类是：net.sf.jasperreports.engine.JasperCompileManager<br />方法compileReportToFile：这个方法能够创建一个在整个程序中使用的编译的报告文件(.jasper)。<br /><br />这个类有两个重载函数，一个只有一个参数，指定.jrxml的路径；另一个有两个参数，分别指定.jrxml的路径和.jasper的输出路径；<br />compileReportToFile(String srcdir):   编译.jrxml得到.jasper,但是不输出该.jasper文件；<br />compileReportToFile(String srcdir,String destdir):  编译.jrxml得到.jasper,并且输出该.jasper文件到指定路径；<br /><br />验证：<br />法一：<br />把compile.jsp中的关键的一行代码：<br />JasperCompileManager.compileReportToFile(application.getRealPath("/reports/WebappReport.jrxml"));<br />改为：<br />JasperCompileManager.compileReportToFile(application.getRealPath("/reports/WebappReport.jrxml"),application.getRealPath("/reports/WebappReport.jasper"));<br /><br />重启tomcat，运行该compile.jsp文件，这时可以在tomcat的目录"tomcat5.5.17\webapps\jasperSampleWebapp\reports"下看到新生成的WebappReport.jasper文件！<br /><br />法二：<br />写一个包含main函数的测试类，执行JasperCompileManager.compileReportToFile方法：<br /><br />package test;<br /><br />import net.sf.jasperreports.engine.JRException;<br />import net.sf.jasperreports.engine.JasperCompileManager;<br />import net.sf.jasperreports.engine.design.*;<br /><br />public class testCompileManager{<br />    public static void main(String[] args) {<br />        String sourceFileName="E:\\jiangcm\\workspace-forict-myeclipse\\jasperreports\\demo\\samples\\webapp\\reports\\WebappReport.jrxml";<br />        String destFileName="E:\\jiangcm\\workspace-forict-myeclipse\\jasperreports\\demo\\samples\\webapp\\reports\\WebappReport.jasper";<br />        try {<br />            JasperCompileManager.compileReportToFile(sourceFileName, destFileName);<br />        } catch (JRException e) {<br />            // TODO Auto-generated catch block<br />            e.printStackTrace();<br />        }<br />    }<br />}<br /><br /><img src ="http://www.blogjava.net/matthew2006/aggbug/96501.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2007-01-29 14:14 <a href="http://www.blogjava.net/matthew2006/archive/2007/01/29/96501.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JFree Chart API简介－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/08/14/63475.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Mon, 14 Aug 2006 06:39:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/08/14/63475.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/63475.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/08/14/63475.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/63475.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/63475.html</trackback:ping><description><![CDATA[
		<div>JFreeChart类：<br />void setAntiAlias(boolean flag) 字体模糊边界<br />void setBackgroundImage(Image image) 背景图片<br />void setBackgroundImageAlignment(int alignment) 背景图片对齐方式（参数常量在org.jfree.ui.Align类中定义）<br />void setBackgroundImageAlpha(float alpha) 背景图片透明度（0.0～1.0）<br />void setBackgroundPaint(Paint paint) 背景色<br />void setBorderPaint(Paint paint) 边界线条颜色<br />void setBorderStroke(Stroke stroke) 边界线条笔触<br />void setBorderVisible(boolean visible) 边界线条是否可见</div>
		<p>
				<br />
		</p>
		<div>
				<br />
				<p>———————————————————————————————————–<br /></p>
				<p>TextTitle类：<br />void setFont(Font font) 标题字体<br />void setPaint(Paint paint) 标题字体颜色<br />void setText(String text) 标题内容<br /></p>
				<p>———————————————————————————————————–<br /></p>
				<p>StandardLegend(Legend)类：<br />void setBackgroundPaint(Paint paint) 图示背景色<br />void setTitle(String title) 图示标题内容<br />void setTitleFont(Font font) 图示标题字体<br />void setBoundingBoxArcWidth(int arcWidth) 图示边界圆角宽<br />void setBoundingBoxArcHeight(int arcHeight) 图示边界圆角高<br />void setOutlinePaint(Paint paint) 图示边界线条颜色<br />void setOutlineStroke(Stroke stroke) 图示边界线条笔触<br />void setDisplaySeriesLines(boolean flag) 图示项是否显示横线（折线图有效）<br />void setDisplaySeriesShapes(boolean flag) 图示项是否显示形状（折线图有效）<br />void setItemFont(Font font) 图示项字体<br />void setItemPaint(Paint paint) 图示项字体颜色<br />void setAnchor(int anchor) 图示在图表中的显示位置（参数常量在Legend类中定义）<br /></p>
				<p>———————————————————————————————————–<br /></p>
				<p>Axis类：<br />void setVisible(boolean flag) 坐标轴是否可见<br />void setAxisLinePaint(Paint paint) 坐标轴线条颜色（3D轴无效）<br />void setAxisLineStroke(Stroke stroke) 坐标轴线条笔触（3D轴无效）<br />void setAxisLineVisible(boolean visible) 坐标轴线条是否可见（3D轴无效）<br />void setFixedDimension(double dimension) （用于复合表中对多坐标轴的设置）<br />void setLabel(String label) 坐标轴标题<br />void setLabelFont(Font font) 坐标轴标题字体<br />void setLabelPaint(Paint paint) 坐标轴标题颜色<br />void setLabelAngle(double angle)` 坐标轴标题旋转角度（纵坐标可以旋转）<br />void setTickLabelFont(Font font) 坐标轴标尺值字体<br />void setTickLabelPaint(Paint paint) 坐标轴标尺值颜色<br />void setTickLabelsVisible(boolean flag) 坐标轴标尺值是否显示<br />void setTickMarkPaint(Paint paint) 坐标轴标尺颜色<br />void setTickMarkStroke(Stroke stroke) 坐标轴标尺笔触<br />void setTickMarksVisible(boolean flag) 坐标轴标尺是否显示<br /></p>
				<p>ValueAxis(Axis)类：<br />void setAutoRange(boolean auto) 自动设置数据轴数据范围<br />void setAutoRangeMinimumSize(double size) 自动设置数据轴数据范围时数据范围的最小跨度<br />void setAutoTickUnitSelection(boolean flag) 数据轴的数据标签是否自动确定（默认为true）<br />void setFixedAutoRange(double length) 数据轴固定数据范围（设置100的话就是显示MAXVALUE到MAXVALUE-100那段数据范围）<br />void setInverted(boolean flag) 数据轴是否反向（默认为false）<br />void setLowerMargin(double margin) 数据轴下（左）边距<br />void setUpperMargin(double margin) 数据轴上（右）边距<br />void setLowerBound(double min) 数据轴上的显示最小值<br />void setUpperBound(double max) 数据轴上的显示最大值<br />void setPositiveArrowVisible(boolean visible) 是否显示正向箭头（3D轴无效）<br />void setNegativeArrowVisible(boolean visible) 是否显示反向箭头（3D轴无效）<br />void setVerticalTickLabels(boolean flag) 数据轴数据标签是否旋转到垂直<br />void setStandardTickUnits(TickUnitSource source) 数据轴的数据标签（可以只显示整数标签，需要将AutoTickUnitSelection设false）<br /></p>
				<p>NumberAxis(ValueAxis)类：<br />void setAutoRangeIncludesZero(boolean flag) 是否强制在自动选择的数据范围中包含0<br />void setAutoRangeStickyZero(boolean flag) 是否强制在整个数据轴中包含0，即使0不在数据范围中<br />void setNumberFormatOverride(NumberFormat formatter) 数据轴数据标签的显示格式<br />void setTickUnit(NumberTickUnit unit) 数据轴的数据标签（需要将AutoTickUnitSelection设false）<br /></p>
				<p>DateAxis(ValueAxis)类：<br />void setMaximumDate(Date maximumDate) 日期轴上的最小日期<br />void setMinimumDate(Date minimumDate) 日期轴上的最大日期<br />void setRange(Date lower,Date upper) 日期轴范围<br />void setDateFormatOverride(DateFormat formatter) 日期轴日期标签的显示格式<br />void setTickUnit(DateTickUnit unit) 日期轴的日期标签（需要将AutoTickUnitSelection设false）<br />void setTickMarkPosition(DateTickMarkPosition position) 日期标签位置（参数常量在org.jfree.chart.axis.DateTickMarkPosition类中定义）<br /></p>
				<p>CategoryAxis(Axis)类：<br />void setCategoryMargin(double margin) 分类轴边距<br />void setLowerMargin(double margin) 分类轴下（左）边距<br />void setUpperMargin(double margin) 分类轴上（右）边距<br />void setVerticalCategoryLabels(boolean flag) 分类轴标题是否旋转到垂直<br />void setMaxCategoryLabelWidthRatio(float ratio) 分类轴分类标签的最大宽度<br /></p>
				<p>———————————————————————————————————–<br /></p>
				<p>Plot类：<br />void setBackgroundImage(Image image) 数据区的背景图片<br />void setBackgroundImageAlignment(int alignment) 数据区的背景图片对齐方式（参数常量在org.jfree.ui.Align类中定义）<br />void setBackgroundPaint(Paint paint) 数据区的背景图片背景色<br />void setBackgroundAlpha(float alpha) 数据区的背景透明度（0.0～1.0）<br />void setForegroundAlpha(float alpha) 数据区的前景透明度（0.0～1.0）<br />void setDataAreaRatio(double ratio) 数据区占整个图表区的百分比<br />void setOutLinePaint(Paint paint) 数据区的边界线条颜色<br />void setOutLineStroke(Stroke stroke) 数据区的边界线条笔触<br />void setNoDataMessage(String message) 没有数据时显示的消息<br />void setNoDataMessageFont(Font font) 没有数据时显示的消息字体<br />void setNoDataMessagePaint(Paint paint) 没有数据时显示的消息颜色<br /></p>
				<p>CategoryPlot(Plot)类：<br />void setDataset(CategoryDataset dataset) 数据区的2维数据表<br />void setColumnRenderingOrder(SortOrder order) 数据分类的排序方式<br />void setAxisOffset(Spacer offset) 坐标轴到数据区的间距<br />void setOrientation(PlotOrientation orientation) 数据区的方向（PlotOrientation.HORIZONTAL或PlotOrientation.VERTICAL）<br />void setDomainAxis(CategoryAxis axis) 数据区的分类轴<br />void setDomainAxisLocation(AxisLocation location) 分类轴的位置（参数常量在org.jfree.chart.axis.AxisLocation类中定义）<br />void setDomainGridlinesVisible(boolean visible) 分类轴网格是否可见<br />void setDomainGridlinePaint(Paint paint) 分类轴网格线条颜色<br />void setDomainGridlineStroke(Stroke stroke) 分类轴网格线条笔触<br />void setRangeAxis(ValueAxis axis) 数据区的数据轴<br />void setRangeAxisLocation(AxisLocation location) 数据轴的位置（参数常量在org.jfree.chart.axis.AxisLocation类中定义）<br />void setRangeGridlinesVisible(boolean visible) 数据轴网格是否可见<br />void setRangeGridlinePaint(Paint paint) 数据轴网格线条颜色<br />void setRangeGridlineStroke(Stroke stroke) 数据轴网格线条笔触<br />void setRenderer(CategoryItemRenderer renderer) 数据区的表示者（详见Renderer组）<br />void addAnnotation(CategoryAnnotation annotation) 给数据区加一个注释<br />void addRangeMarker(Marker marker,Layer layer) 给数据区加一个数值范围区域<br /></p>
				<p>PiePlot(Plot)类：<br />void setDataset(PieDataset dataset) 数据区的1维数据表<br />void setIgnoreNullValues(boolean flag) 忽略无值的分类<br />void setCircular(boolean flag) 饼图是否一定是正圆<br />void setStartAngle(double angle) 饼图的初始角度<br />void setDirection(Rotation direction) 饼图的旋转方向<br />void setExplodePercent(int section,double percent) 抽取的那块（1维数据表的分类下标）以及抽取出来的距离（0.0～1.0），3D饼图无效<br />void setLabelBackgroundPaint(Paint paint) 分类标签的底色<br />void setLabelFont(Font font) 分类标签的字体<br />void setLabelPaint(Paint paint) 分类标签的字体颜色<br />void setLabelLinkMargin(double margin) 分类标签与图的连接线边距<br />void setLabelLinkPaint(Paint paint) 分类标签与图的连接线颜色<br />void setLabelLinkStroke(Stroke stroke) 分类标签与图的连接线笔触<br />void setLabelOutlinePaint(Paint paint) 分类标签边框颜色<br />void setLabelOutlineStroke(Paint paint) 分类标签边框笔触<br />void setLabelShadowPaint(Paint paint) 分类标签阴影颜色<br />void setMaximumLabelWidth(double width) 分类标签的最大长度（0.0～1.0）<br />void setPieIndex(int index) 饼图的索引（复合饼图中用到）<br />void setSectionOutlinePaint(int section,Paint paint) 指定分类饼的边框颜色<br />void setSectionOutlineStroke(int section,Stroke stroke) 指定分类饼的边框笔触<br />void setSectionPaint(int section,Paint paint) 指定分类饼的颜色<br />void setShadowPaint(Paint paint) 饼图的阴影颜色<br />void setShadowXOffset(double offset) 饼图的阴影相对图的水平偏移<br />void setShadowYOffset(double offset) 饼图的阴影相对图的垂直偏移<br />void setLabelGenerator(PieSectionLabelGenerator generator) 分类标签的格式，设置成null则整个标签包括连接线都不显示<br />void setToolTipGenerator(PieToolTipGenerator generator) MAP中鼠标移上的显示格式<br />void setURLGenerator(PieURLGenerator generator) MAP中钻取链接格式<br /></p>
				<p>PiePlot3D(PiePlot)类：<br />void setDepthFactor(double factor) 3D饼图的Z轴高度（0.0～1.0）<br /></p>
				<p>MultiplePiePlot(Plot)类：<br />void setLimit(double limit) 每个饼图之间的数据关联（详细比较复杂）<br />void setPieChart(JFreeChart pieChart) 每个饼图的显示方式（见JFreeChart类个PiePlot类）<br /></p>
				<p>———————————————————————————————————–<br /></p>
				<p>AbstractRenderer类：<br />void setItemLabelAnchorOffset(double offset) 数据标签的与数据点的偏移<br />void setItemLabelsVisible(boolean visible) 数据标签是否可见<br />void setItemLabelFont(Font font) 数据标签的字体<br />void setItemLabelPaint(Paint paint) 数据标签的字体颜色<br />void setItemLabelPosition(ItemLabelPosition position) 数据标签位置<br />void setPositiveItemLabelPosition(ItemLabelPosition position) 正数标签位置<br />void setNegativeItemLabelPosition(ItemLabelPosition position) 负数标签位置<br />void setOutLinePaint(Paint paint) 图形边框的线条颜色<br />void setOutLineStroke(Stroke stroke) 图形边框的线条笔触<br />void setPaint(Paint paint) 所有分类图形的颜色<br />void setShape(Shape shape) 所有分类图形的形状（如折线图的点）<br />void setStroke(Stroke stroke) 所有分类图形的笔触（如折线图的线）<br />void setSeriesItemLabelsVisible(int series,boolean visible) 指定分类的数据标签是否可见<br />void setSeriesItemLabelFont(int series,Font font) 指定分类的数据标签的字体<br />void setSeriesItemLabelPaint(int series,Paint paint) 指定分类的数据标签的字体颜色<br />void setSeriesItemLabelPosition(int series,ItemLabelPosition position) 数据标签位置<br />void setSeriesPositiveItemLabelPosition(int series,ItemLabelPosition position) 正数标签位置<br />void setSeriesNegativeItemLabelPosition(int series,ItemLabelPosition position) 负数标签位置<br />void setSeriesOutLinePaint(int series,Paint paint) 指定分类的图形边框的线条颜色<br />void setSeriesOutLineStroke(int series,Stroke stroke) 指定分类的图形边框的线条笔触<br />void setSeriesPaint(int series,Paint paint) 指定分类图形的颜色<br />void setSeriesShape(int series,Shape shape) 指定分类图形的形状（如折线图的点）<br />void setSeriesStroke(int series,Stroke stroke) 指定分类图形的笔触（如折线图的线）<br /></p>
				<p>AbstractCategoryItemRenderer(AbstractRenderer)类：<br />void setLabelGenerator(CategoryLabelGenerator generator) 数据标签的格式<br />void setToolTipGenerator(CategoryToolTipGenerator generator) MAP中鼠标移上的显示格式<br />void setItemURLGenerator(CategoryURLGenerator generator) MAP中钻取链接格式<br />void setSeriesLabelGenerator(int series,CategoryLabelGenerator generator) 指定分类的数据标签的格式<br />void setSeriesToolTipGenerator(int series,CategoryToolTipGenerator generator) 指定分类的MAP中鼠标移上的显示格式<br />void setSeriesItemURLGenerator(int series,CategoryURLGenerator generator) 指定分类的MAP中钻取链接格式<br /></p>
				<p>BarRenderer(AbstractCategoryItemRenderer)类：<br />void setDrawBarOutline(boolean draw) 是否画图形边框<br />void setItemMargin(double percent) 每个BAR之间的间隔<br />void setMaxBarWidth(double percent) 每个BAR的最大宽度<br />void setMinimumBarLength(double min) 最短的BAR长度，避免数值太小而显示不出<br />void setPositiveItemLabelPositionFallback(ItemLabelPosition position) 无法在BAR中显示的正数标签位置<br />void setNegativeItemLabelPositionFallback(ItemLabelPosition position) 无法在BAR中显示的负数标签位置<br /></p>
				<p>BarRenderer3D(BarRenderer)类：<br />void setWallPaint(Paint paint) 3D坐标轴的墙体颜色<br /></p>
				<p>StackedBarRenderer(BarRenderer)类：<br />没有特殊的设置<br /></p>
				<p>StackedBarRenderer3D(BarRenderer3D)类：<br />没有特殊的设置<br /></p>
				<p>GroupedStackedBarRenderer(StackedBarRenderer)类：<br />void setSeriesToGroupMap(KeyToGroupMap map) 将分类自由的映射成若干个组（KeyToGroupMap.mapKeyToGroup(series,group)）<br /></p>
				<p>LayeredBarRenderer(BarRenderer)类：<br />void setSeriesBarWidth(int series,double width) 设定每个分类的宽度（注意设置不要使某分类被覆盖）<br /></p>
				<p>WaterfallBarRenderer(BarRenderer)类：<br />void setFirstBarPaint(Paint paint) 第一个柱图的颜色<br />void setLastBarPaint(Paint paint) 最后一个柱图的颜色<br />void setPositiveBarPaint(Paint paint) 正值柱图的颜色<br />void setNegativeBarPaint(Paint paint) 负值柱图的颜色<br /></p>
				<p>IntervalBarRenderer(BarRenderer)类：<br />需要传IntervalCategoryDataset作为数据源<br /></p>
				<p>GanttBarRenderer(IntervalBarRenderer)类：<br />void setCompletePaint(Paint paint) 完成进度颜色<br />void setIncompletePaint(Paint paint) 未完成进度颜色<br />void setStartPercent(double percent) 设置进度条在整条中的起始位置（0.0～1.0）<br />void setEndPercent(double percent) 设置进度条在整条中的结束位置（0.0～1.0）<br /></p>
				<p>StatisticBarRenderer(BarRenderer)类：<br />需要传StatisticCategoryDataset作为数据源<br /></p>
				<p>LineAndShapeRenderer(AbstractCategoryItemRenderer)类：<br />void setDrawLines(boolean draw) 是否折线的数据点之间用线连<br />void setDrawShapes(boolean draw) 是否折线的数据点根据分类使用不同的形状<br />void setShapesFilled(boolean filled) 所有分类是否填充数据点图形<br />void setSeriesShapesFilled(int series,boolean filled) 指定分类是否填充数据点图形<br />void setUseFillPaintForShapeOutline(boolean use) 指定是否填充数据点的Paint也被用于画数据点形状的边框<br /></p>
				<p>LevelRenderer(AbstractCategoryItemRenderer)类：<br />void setItemMargin(double percent) 每个分类之间的间隔<br />void setMaxItemWidth(double percent) 每个分类的最大宽度<br /></p>
				<p>CategoryStepRenderer(AbstractCategoryItemRenderer)类：<br />void setStagger(boolean shouldStagger) 不同分类的图是否交错<br /></p>
				<p>MinMaxCategoryRenderer(AbstractCategoryItemRenderer)类：<br />void setDrawLines(boolean drawLines) 是否在每个分类线间画连接线<br />void setGroupPaint(Paint groupPaint) 一组图形连接线的颜色<br />void setGroupStroke(Stroke groupStroke) 一组图形连接线的笔触<br />void setMaxIcon(Icon maxIcon) 最大值的ICON<br />void setMinIcon(Icon minIcon) 最小值的ICON<br />void setObjectIcon(Icon objectIcon) 所有值的ICON<br /></p>
				<p>AreaRender(AbstractCategoryItemRenderer)类：<br />没有特殊的设置<br /></p>
				<p>StackedAreaRender(AreaRender)类：<br />没有特殊的设置</p>
		</div>
		<br />
<img src ="http://www.blogjava.net/matthew2006/aggbug/63475.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-08-14 14:39 <a href="http://www.blogjava.net/matthew2006/archive/2006/08/14/63475.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于J2EE的面向对象型数据的报表系统的设计与实现－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/08/14/63473.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Mon, 14 Aug 2006 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/08/14/63473.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/63473.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/08/14/63473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/63473.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/63473.html</trackback:ping><description><![CDATA[
		<span style="FONT-WEIGHT: bold">一、jFreeChart产生图形的流程</span>
		<br />创建一个数据源（dataset）来包含将要在图形中显示的数据?????&gt;&gt;创建一个 JFreeChart 对象来代表要显示的图形<br />??????&gt;&gt;把图形输出<br />重要的类和接口：<br />org.jfree.data.general.Dataset 所有数据源类都要实现的接口<br />org.jfree.chart.ChartFactory 由它来产生 JFreeChart 对象<br />org.jfree.chart.JFreeChart 所有对图形的调整都是通过它噢！！<br />org.jfree.chart.plot.Plot 通过JFreeChart 对象获得它，然后再通过它对图形外部部分（例：坐标轴）调整<br />注意：它有很多子类，一般都下嗍造型到它的子类！<br />org.jfree.chart.renderer.AbstractRenderer 通过JFreeChart 对象获得它，然后再通过它对图形内部部分<br />（例：折线的类型）调整。同样，针对不同类型的报表图，它有<br />着不同的子类实现！在下面我们简称它为 Renderer<br />下面我们结合不同类型的图形来具体分析这个流程。<br /><br /><a id="more-95"></a><span style="FONT-WEIGHT: bold">二、饼图</span><br />饼图的dataset 一般是用PieDataset 接口，具体实现类是 DefaultPieDataset<br />1、创建一个数据源（dataset）：<br />private static PieDataset createDataset()<br />{<br />DefaultPieDataset defaultpiedataset = new DefaultPieDataset(); //注意是DefaultPieDataset！！<br />defaultpiedataset.setValue(”One”, new Double(43.200000000000003D));<br />defaultpiedataset.setValue(”Two”, new Double(10D));<br />defaultpiedataset.setValue(”Three”, new Double(27.5D));<br />defaultpiedataset.setValue(”Four”, new Double(17.5D));<br />return defaultpiedataset;<br />}<br />2、由ChartFactory 产生 JFreeChart 对象<br />private static JFreeChart createChart(PieDataset piedataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createPieChart(”Pie Chart Demo 1″, //图形标题名称<br />piedataset, // dataset<br />true, // legend?<br />true, // tooltips?<br />false); //URLs?<br />PiePlot pieplot = (PiePlot)jfreechart.getPlot(); //通过JFreeChart 对象获得 plot：PiePlot！！<br />pieplot.setNoDataMessage(”No data available”); // 没有数据的时候显示的内容<br />return jfreechart;<br />}<br />一些重要的方法：<br />pieplot.setExplodePercent(0,0.3D) //把Lable 为”One” 的那一块”挖”出来30%<br />3、输出略<br /><br /><span style="FONT-WEIGHT: bold">三、柱状图</span><br />柱状图的dataset 一般是用CatagoryDataset接口(具体实现类是DefaultCategoryDataset),也会用 IntervalXYDataset<br />接口<br />1、创建一个数据源（dataset）：<br />private static CategoryDataset createDataset()<br />{<br />String series1 = “First”;<br />String series2 = “Second”;<br />String series3 = “Third”;<br />String category1 = “Category 1″;<br />String category2 = “Category 2″;<br />String category3 = “Category 3″;<br />String category4 = “Category 4″;<br />String category5 = “Category 5″;<br />DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();<br />defaultcategorydataset.addValue(1.0D, series1, category1);<br />defaultcategorydataset.addValue(4D, series1, category2);<br />defaultcategorydataset.addValue(3D, series1, category3);<br />defaultcategorydataset.addValue(5D, series1, category4);<br />defaultcategorydataset.addValue(5D, series1, category5);<br /><br />defaultcategorydataset.addValue(5D, series2, category1);<br />defaultcategorydataset.addValue(7D, series2, category2);<br />defaultcategorydataset.addValue(6D, series2, category3);<br />defaultcategorydataset.addValue(8D, series2, category4);<br />defaultcategorydataset.addValue(4D, series2, category5);<br /><br />defaultcategorydataset.addValue(4D, series3, category1);<br />defaultcategorydataset.addValue(3D, series3, category2);<br />defaultcategorydataset.addValue(2D, series3, category3);<br />defaultcategorydataset.addValue(3D, series3, category4);<br />defaultcategorydataset.addValue(6D, series3, category5);<br />return defaultcategorydataset;<br />}<br />2、由ChartFactory 产生 JFreeChart 对象<br />private static JFreeChart createChart(CategoryDataset categorydataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createBarChart(”Bar Chart Demo”, //图形标题名称<br />“Category”,//domain 轴 Lable<br />这里先简单理解为横坐标Lable好了<br />“Value”, //range 轴 Lable<br />这里也先简单理解为纵坐标Lable好了<br />categorydataset, // dataset<br />PlotOrientation.VERTICAL, //垂直显示<br />true, // legend?<br />true, // tooltips?<br />false); //URLs?<br />jfreechart.setBackgroundPaint(Color.white); //设定背景色为白色<br />CategoryPlot categoryplot = jfreechart.getCategoryPlot(); //获得 plot：CategoryPlot！！<br />categoryplot.setBackgroundPaint(Color.lightGray); //设定图表数据显示部分背景色<br />categoryplot.setDomainGridlinePaint(Color.white); //横坐标网格线白色<br />categoryplot.setDomainGridlinesVisible(true); //可见<br />categoryplot.setRangeGridlinePaint(Color.white); //纵坐标网格线白色<br />//下面两行使纵坐标的最小单位格为整数<br />NumberAxis numberaxis = (NumberAxis)categoryplot.getRangeAxis();<br />numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());<br />BarRenderer barrenderer = (BarRenderer)categoryplot.getRenderer(); //获得renderer 注意这里是下嗍造型<br />到BarRenderer！！<br />barrenderer.setDrawBarOutline(false); // Bar的外轮廓线不画<br />GradientPaint gradientpaint = new GradientPaint(0.0F, 0.0F, Color.blue,<br />0.0F, 0.0F, new Color(0, 0, 64)); //设定特定颜色<br />GradientPaint gradientpaint1 = new GradientPaint(0.0F, 0.0F, Color.green,<br />0.0F, 0.0F, new Color(0, 64, 0));<br />GradientPaint gradientpaint2 = new GradientPaint(0.0F, 0.0F, Color.red,<br />0.0F, 0.0F, new Color(64, 0, 0));<br />barrenderer.setSeriesPaint(0, gradientpaint); //给series1 Bar设定上面定义的颜色<br />barrenderer.setSeriesPaint(1, gradientpaint1); //给series2 Bar 设定上面定义的颜色<br />barrenderer.setSeriesPaint(2, gradientpaint2); //给series3 Bar 设定上面定义的颜色<br />CategoryAxis categoryaxis = categoryplot.getDomainAxis(); //横轴上的 Lable 45度倾斜<br />categoryaxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);<br />return jfreechart;<br />}<br />一些重要的方法：（增加一块标记）<br />IntervalMarker intervalmarker = new IntervalMarker(4.5D, 7.5D);<br />intervalmarker.setLabel(”Target Range”);<br />intervalmarker.setLabelFont(new Font(”SansSerif”, 2, 11));<br />intervalmarker.setLabelAnchor(RectangleAnchor.LEFT);<br />intervalmarker.setLabelTextAnchor(TextAnchor.CENTER_LEFT);<br />intervalmarker.setPaint(new Color(222, 222, 255, 128));<br />categoryplot.addRangeMarker(intervalmarker, Layer.BACKGROUND);<br /><br /><span style="FONT-WEIGHT: bold">四、折线图</span><br />折线图的dataset 两种CatagoryDataset接口(具体实现类是DefaultCategoryDataset),XYDataset 接口<br />1、CatagoryDataset接口：<br />A、创建一个数据源（dataset）：<br />private static CategoryDataset createDataset()<br />{<br />String series1 = “First”;<br />String series2 = “Second”;<br />String series3 = “Third”;<br />String type1 = “Type 1″;<br />String type2 = “Type 2″;<br />String type3 = “Type 3″;<br />String type4 = “Type 4″;<br />String type5 = “Type 5″;<br />String type6 = “Type 6″;<br />String type7 = “Type 7″;<br />String type8 = “Type 8″;<br />DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();<br />defaultcategorydataset.addValue(1.0D, series1, type1);<br />defaultcategorydataset.addValue(4D, series1, type2);<br />defaultcategorydataset.addValue(3D, series1, type3);<br />defaultcategorydataset.addValue(5D, series1, type4);<br />defaultcategorydataset.addValue(5D, series1, type5);<br />defaultcategorydataset.addValue(7D, series1, type6);<br />defaultcategorydataset.addValue(7D, series1, type7);<br />defaultcategorydataset.addValue(8D, series1, type8);<br /><br />defaultcategorydataset.addValue(5D, series2, type1);<br />defaultcategorydataset.addValue(7D, series2, type2);<br />defaultcategorydataset.addValue(6D, series2, type3);<br />defaultcategorydataset.addValue(8D, series2, type4);<br />defaultcategorydataset.addValue(4D, series2, type5);<br />defaultcategorydataset.addValue(4D, series2, type6);<br />defaultcategorydataset.addValue(2D, series2, type7);<br />defaultcategorydataset.addValue(1.0D, series2, type8);<br /><br />defaultcategorydataset.addValue(4D, series3, type1);<br />defaultcategorydataset.addValue(3D, series3, type2);<br />defaultcategorydataset.addValue(2D, series3, type3);<br />defaultcategorydataset.addValue(3D, series3, type4);<br />defaultcategorydataset.addValue(6D, series3, type5);<br />defaultcategorydataset.addValue(3D, series3, type6);<br />defaultcategorydataset.addValue(4D, series3, type7);<br />defaultcategorydataset.addValue(3D, series3, type8);<br />return defaultcategorydataset;<br />}<br />B、由ChartFactory 产生 JFreeChart 对象 (与上面重复的部分就不再注释）<br />private static JFreeChart createChart(CategoryDataset categorydataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createLineChart(”Line Chart Demo 1″,<br />“Type”,<br />“Value”,<br />categorydataset,<br />PlotOrientation.VERTICAL,<br />true,<br />true,<br />false);<br />jfreechart.setBackgroundPaint(Color.white);<br />CategoryPlot categoryplot = (CategoryPlot)jfreechart.getPlot();<br />categoryplot.setBackgroundPaint(Color.lightGray);<br />categoryplot.setRangeGridlinePaint(Color.white);<br />NumberAxis numberaxis = (NumberAxis)categoryplot.getRangeAxis();<br />numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());<br />numberaxis.setAutoRangeIncludesZero(true);<br />//获得renderer 注意这里是下嗍造型到lineandshaperenderer！！<br />LineAndShapeRenderer lineandshaperenderer = (LineAndShapeRenderer)categoryplot.getRenderer();<br />lineandshaperenderer.setShapesVisible(true); //series 点（即数据点）可见<br />lineandshaperenderer.setSeriesStroke(0, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {<br />10F, 6F<br />}, 0.0F)); //定义series为”First”的（即series1）点之间的连线 ，这里是虚线，默认是直线<br />lineandshaperenderer.setSeriesStroke(1, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {<br />6F, 6F<br />}, 0.0F)); //定义series为”Second”的（即series2）点之间的连线<br />lineandshaperenderer.setSeriesStroke(2, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {<br />2.0F, 6F<br />}, 0.0F)); //定义series为”Third”的（即series3）点之间的连线<br />return jfreechart;<br />}<br />一些重要的方法：<br />lineandshaperenderer.setLineVisible(true) //series 点（即数据点）间有连线可见<br />2、XYDataset 接口：<br />A、创建一个数据源（dataset）：<br />private static XYDataset createDataset()<br />{<br />XYSeries xyseries = new XYSeries(”First”); //先产生XYSeries 对象<br />xyseries.add(1.0D, 1.0D);<br />xyseries.add(2D, 4D);<br />xyseries.add(3D, 3D);<br />xyseries.add(4D, 5D);<br />xyseries.add(5D, 5D);<br />xyseries.add(6D, 7D);<br />xyseries.add(7D, 7D);<br />xyseries.add(8D, 8D);<br /><br />XYSeries xyseries1 = new XYSeries(”Second”);<br />xyseries1.add(1.0D, 5D);<br />xyseries1.add(2D, 7D);<br />xyseries1.add(3D, 6D);<br />xyseries1.add(4D, 8D);<br />xyseries1.add(5D, 4D);<br />xyseries1.add(6D, 4D);<br />xyseries1.add(7D, 2D);<br />xyseries1.add(8D, 1.0D);<br /><br />XYSeries xyseries2 = new XYSeries(”Third”);<br />xyseries2.add(3D, 4D);<br />xyseries2.add(4D, 3D);<br />xyseries2.add(5D, 2D);<br />xyseries2.add(6D, 3D);<br />xyseries2.add(7D, 6D);<br />xyseries2.add(8D, 3D);<br />xyseries2.add(9D, 4D);<br />xyseries2.add(10D, 3D);<br /><br />XYSeriesCollection xyseriescollection = new XYSeriesCollection(); //再用XYSeriesCollection添加入XYSeries 对象<br />xyseriescollection.addSeries(xyseries);<br />xyseriescollection.addSeries(xyseries1);<br />xyseriescollection.addSeries(xyseries2);<br />return xyseriescollection;<br />}<br />B、由ChartFactory 产生 JFreeChart 对象<br />private static JFreeChart createChart(XYDataset xydataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createXYLineChart(”Line Chart Demo 2″,<br />“X”,<br />“Y”,<br />xydataset,<br />PlotOrientation.VERTICAL,<br />true,<br />true,<br />false);<br />jfreechart.setBackgroundPaint(Color.white);<br />XYPlot xyplot = (XYPlot)jfreechart.getPlot(); //获得 plot：XYPlot！！<br />xyplot.setBackgroundPaint(Color.lightGray); //设定图表数据显示部分背景色<br />xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D)); //设定坐标轴与图表数据显示部分距离<br />xyplot.setDomainGridlinePaint(Color.white); //网格线颜色<br />xyplot.setRangeGridlinePaint(Color.white);<br />//获得 renderer 注意这里是XYLineAndShapeRenderer ！！<br />XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyplot.getRenderer();<br />xylineandshaperenderer.setShapesVisible(true); //数据点可见<br />xylineandshaperenderer.setShapesFilled(true); //数据点被填充即不是空心点<br />NumberAxis numberaxis = (NumberAxis)xyplot.getRangeAxis();<br />numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());<br />return jfreechart;<br />}<br />一些重要的方法：<br />XYLineAndShapeRenderer xylineandshaperenderer = new XYLineAndShapeRenderer();<br />xylineandshaperenderer.setSeriesLinesVisible(0, false); //第一个XYSeries数据点间连线不可见<br />xylineandshaperenderer.setSeriesShapesVisible(1, false); //第二个XYSeries数据点不可见<br />xyplot.setRenderer(xylineandshaperenderer);<br /><br /><span style="FONT-WEIGHT: bold">五、时间序列图</span><br />时间序列图和折线图很相似，不同的是它在 domain轴的数据是时间而不是数字。 时间序列图的dataset 是<br />XYDataset 接口，具体实现类是TimeSeriesCollection ，和上面类似，有TimeSeries 对象，它被添加入<br />TimeSeriesCollection 。<br />1、创建一个数据源（dataset）：<br />private static XYDataset createDataset()<br />{<br />TimeSeries timeseries = new TimeSeries(”L&amp;G European Index Trust”,Month.class);<br />timeseries.add(new Month(2, 2001), 181.8D);//这里用的是Month.class，同样还有Day.class Year.class 等等<br />timeseries.add(new Month(3, 2001), 167.3D);<br />timeseries.add(new Month(4, 2001), 153.8D);<br />timeseries.add(new Month(5, 2001), 167.6D);<br />timeseries.add(new Month(6, 2001), 158.8D);<br />timeseries.add(new Month(7, 2001), 148.3D);<br />timeseries.add(new Month(8, 2001), 153.9D);<br />timeseries.add(new Month(9, 2001), 142.7D);<br />timeseries.add(new Month(10, 2001), 123.2D);<br />timeseries.add(new Month(11, 2001), 131.8D);<br />timeseries.add(new Month(12, 2001), 139.6D);<br />timeseries.add(new Month(1, 2002), 142.9D);<br />timeseries.add(new Month(2, 2002), 138.7D);<br />timeseries.add(new Month(3, 2002), 137.3D);<br />timeseries.add(new Month(4, 2002), 143.9D);<br />timeseries.add(new Month(5, 2002), 139.8D);<br />timeseries.add(new Month(6, 2002), 137D);<br />timeseries.add(new Month(7, 2002), 132.8D);<br /><br />TimeSeries timeseries1 = new TimeSeries(”L&amp;G UK Index Trust”,Month.class);<br />timeseries1.add(new Month(2, 2001), 129.6D);<br />timeseries1.add(new Month(3, 2001), 123.2D);<br />timeseries1.add(new Month(4, 2001), 117.2D);<br />timeseries1.add(new Month(5, 2001), 124.1D);<br />timeseries1.add(new Month(6, 2001), 122.6D);<br />timeseries1.add(new Month(7, 2001), 119.2D);<br />timeseries1.add(new Month(8, 2001), 116.5D);<br />timeseries1.add(new Month(9, 2001), 112.7D);<br />timeseries1.add(new Month(10, 2001), 101.5D);<br />timeseries1.add(new Month(11, 2001), 106.1D);<br />timeseries1.add(new Month(12, 2001), 110.3D);<br />timeseries1.add(new Month(1, 2002), 111.7D);<br />timeseries1.add(new Month(2, 2002), 111D);<br />timeseries1.add(new Month(3, 2002), 109.6D);<br />timeseries1.add(new Month(4, 2002), 113.2D);<br />timeseries1.add(new Month(5, 2002), 111.6D);<br />timeseries1.add(new Month(6, 2002), 108.8D);<br />timeseries1.add(new Month(7, 2002), 101.6D);<br />TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();<br />timeseriescollection.addSeries(timeseries);<br />timeseriescollection.addSeries(timeseries1);<br />timeseriescollection.setDomainIsPointsInTime(true); //domain轴上的刻度点代表的是时间点而不是时间段<br />return timeseriescollection;<br />}<br />2、由ChartFactory 产生 JFreeChart 对象<br />private static JFreeChart createChart(XYDataset xydataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(”Legal &amp; General Unit Trust Prices”,<br />“Date”,<br />“Price Per Unit”,<br />xydataset,<br />true,<br />true,<br />false);<br />jfreechart.setBackgroundPaint(Color.white);<br />XYPlot xyplot = (XYPlot)jfreechart.getPlot(); //获得 plot : XYPlot!!<br />xyplot.setBackgroundPaint(Color.lightGray);<br />xyplot.setDomainGridlinePaint(Color.white);<br />xyplot.setRangeGridlinePaint(Color.white);<br />xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));<br />xyplot.setDomainCrosshairVisible(true);<br />xyplot.setRangeCrosshairVisible(true);<br />org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();<br />if(xyitemrenderer instanceof XYLineAndShapeRenderer)<br />{<br />XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyitemrenderer;<br />xylineandshaperenderer.setDefaultShapesVisible(true); //数据点可见<br />xylineandshaperenderer.setDefaultShapesFilled(true); //数据点是实心点<br />}<br />DateAxis dateaxis = (DateAxis)xyplot.getDomainAxis(); //对domain 轴上日期显示格式定义<br />dateaxis.setDateFormatOverride(new SimpleDateFormat(”MMM-yyyy”));<br />return jfreechart;<br />}<br />一些重要的方法：<br />A、增加标记线：<br />xyplot.addRangeMarker(new ValueMarker(550D)); //数值轴<br />Quarter quarter = new Quarter(2, 2002);<br />xyplot.addDomainMarker(new ValueMarker(quarter.getMiddleMillisecond())); //时间轴<br />B、数据点的调整<br />XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyplot.getRenderer();<br />xylineandshaperenderer.setDefaultShapesVisible(true); //数据点可见<br />xylineandshaperenderer.setSeriesFillPaint(0, Color.red); //数据点填充为红色<br />xylineandshaperenderer.setSeriesFillPaint(1, Color.white); //数据点填充为白色<br />xylineandshaperenderer.setUseFillPaint(true); //应用<br />C、平均值曲线<br />这个曲线有什么用呢？很简单的例子，这里有一个以半年每天为单位的数据绘制的曲线，我们想看看以月为单位数据<br />的变化，这时就可以用到它了。<br />TimeSeries timeseries = createEURTimeSeries(); //就是以半年每天为单位的数据<br />TimeSeries timeseries1 = MovingAverage.createMovingAverage(timeseries,<br />“30 day moving average”,<br />30, //30天为一个周期<br />30); //最开始的30天跳过<br />TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();<br />timeseriescollection.addSeries(timeseries);<br />timeseriescollection.addSeries(timeseries1);<br />return timeseriescollection;<br /><br /><span style="FONT-WEIGHT: bold">六、总结一下</span><br />dataset plot renderer<br />饼图 PieDataset（DefaultPieDataset） PiePlot ——<br />柱状图 CatagoryDataset（DefaultCategoryDataset） CategoryPlot BarRenderer<br />折线图 CatagoryDataset（DefaultCategoryDataset） CategoryPlot LineAndShapeRenderer<br />XYDataset（XYSeriesCollection） XYPlot XYLineAndShapeRenderer<br />时间序列图 XYDataset （TimeSeriesCollection） XYPlot XYLineAndShapeRenderer<br />这里只是一些常用的方法，具体还是看API<br /><span style="FONT-WEIGHT: bold">七、Item Lable</span><br />这里以柱状图为例说明，具体来说就是在每个柱状上显示它的数据，具体有下面内容：<br />A、使 Item Lable 可见<br />B、调整 Item Lable 的颜色、字体等<br />C、调整 Item Lable 的位置<br />D、定制 Item Lable 的内容<br />1、分配一个 Lable Generator 给 renderer<br />BarRenderer barrenderer = (BarRenderer)categoryplot.getRenderer();<br />GategoryLableGenerator generator =new StandardGategoryLableGenerator(<br />“{2}”, new DecimalFormat(”0.00″) //调整显示的数字和字符格式<br />);<br />barrenderer.setLableGenerator(generator);<br />2、使 Item Lable 可见<br />barrenderer.setItemLableVisible(true);<br />3、调整 Item Lable 的颜色、字体等<br />barrenderer.setItemLablePaint(Color.red);<br />barrenderer.setItemLableFont(new Font(”SansSerif”,Font.PLAIN,10));<br />4、调整 Item Lable 的位置<br />这里涉及到一个新的对象 ItemLablePosition , ItemLablePosition的构造函数有两个或四个参数<br />public ItemLabelPosition(ItemLabelAnchor itemLabelAnchor,<br />org.jfree.ui.TextAnchor textAnchor,<br />org.jfree.ui.TextAnchor rotationAnchor,<br />double angle)<br />itemLabelAnchor - Item Lable 的位置 （最重要的！！）<br />textAnchor - Item Lable里包含的正文相对于Item Lable 的位置<br />rotationAnchor - Item Lable里包含的正文旋转的位置<br />angle - 旋转的角度<br />ItemLabelPosition itemlabelposition = new ItemLabelPosition(ItemLabelAnchor.INSIDE12,<br />TextAnchor.CENTER_RIGHT,<br />TextAnchor.CENTER_RIGHT,<br />-1.57D);<br />barrenderer.setPositiveItemLabelPosition(itemlabelposition);<br />这样就可以每个柱状上显示它的数据了，当然可以定制 Item Lable 的内容，比如 Item Lable text 超过100的才<br />显示，这样就需要定制自己的类，它要实现GategoryLableGenerator 接口，实现generateItemLable()方法<br /><img src ="http://www.blogjava.net/matthew2006/aggbug/63473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-08-14 14:35 <a href="http://www.blogjava.net/matthew2006/archive/2006/08/14/63473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JFreeChart 初学</title><link>http://www.blogjava.net/matthew2006/archive/2006/07/07/57143.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Fri, 07 Jul 2006 07:26:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/07/07/57143.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/57143.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/07/07/57143.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/57143.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/57143.html</trackback:ping><description><![CDATA[
		<p>由于项目需求原因，上网看了些JfreeChart的例子。自己就试着用了下：<br /><strong>BarCharDemo.jsp</strong><br />&lt;<a href="mailto:%@page">%@page</a> contentType="text/html; charset=GB2312"%&gt;</p>
		<p>&lt;<a href="mailto:%@page">%@page</a> import="java.io.FileNotFoundException"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="java.io.FileOutputStream"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.apache.commons.logging.Log"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="java.io.IOException"%&gt;</p>
		<p>
				<br />&lt;<a href="mailto:%@page">%@page</a> import="org.apache.commons.logging.LogFactory"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.chart.ChartFactory"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.chart.ChartUtilities"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.chart.JFreeChart"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.chart.plot.PlotOrientation"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.data.general.DefaultPieDataset"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.data.general.PieDataset"%&gt;<br />&lt;%<br />DefaultPieDataset  dataset    = new DefaultPieDataset ();<br />  dataset.setValue("苹果",100);  <br />  dataset.setValue("梨",200); <br />  dataset.setValue("香蕉",300); <br />  dataset.setValue("芒果",400);<br />  dataset.setValue("葡萄",500);</p>
		<p>
				<br />   JFreeChart chart      = ChartFactory.createPieChart3D(<br />    "水果产量图",       //图标标题<br />    dataset,       //数据集<br />    true,        //是否显示图例（简单的柱装图必须是fasle）<br />    false,        //是否生成工具<br />    false        //是否生成URL链接<br />    );</p>
		<p>    <br />    ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,640,370);<br />%&gt;<br /><br /><strong>PieChartDemo.jsp</strong><br />&lt;<a href="mailto:%@page">%@page</a> contentType="text/html; charset=GB2312"%&gt;</p>
		<p>&lt;<a href="mailto:%@page">%@page</a> import="java.io.FileNotFoundException"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="java.io.FileOutputStream"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.apache.commons.logging.Log"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="java.io.IOException"%&gt;</p>
		<p>&lt;<a href="mailto:%@page">%@page</a> import="org.apache.commons.logging.LogFactory"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.chart.ChartFactory"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.chart.ChartUtilities"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.chart.JFreeChart"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.chart.plot.PlotOrientation"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.data.category.CategoryDataset"%&gt;<br />&lt;<a href="mailto:%@page">%@page</a> import="org.jfree.data.category.DefaultCategoryDataset"%&gt;<br />&lt;%<br />DefaultCategoryDataset dataset    = new DefaultCategoryDataset();<br /> dataset.addValue(100, "北京", "苹果");<br />  dataset.addValue(130, "上海", "苹果");<br />  dataset.addValue(160, "广州", "苹果");<br />  dataset.addValue(200, "北京", "梨子");<br />  dataset.addValue(230, "上海", "梨子");<br />  dataset.addValue(260, "广州", "梨子");<br />  dataset.addValue(300, "北京", "葡萄");<br />  dataset.addValue(330, "上海", "葡萄");<br />  dataset.addValue(360, "广州", "葡萄");<br />  dataset.addValue(400, "北京", "香蕉");<br />  dataset.addValue(430, "上海", "香蕉");<br />  dataset.addValue(460, "广州", "香蕉");<br />  dataset.addValue(500, "北京", "荔枝");<br />  dataset.addValue(530, "上海", "荔枝");<br />  dataset.addValue(560, "广州", "荔枝");<br />  <br />    JFreeChart chart      = ChartFactory.createBarChart3D(<br />    "水果产量图",       //图标标题<br />    "水果",        //目录轴显示标签 （x轴）<br />    "产量",        //数据轴显示标签 （y轴）<br />    dataset,       //数据集<br />    PlotOrientation.VERTICAL,   //图标方向：水平，垂直<br />    true,        //是否显示图例（简单的柱装图必须是fasle）<br />    false,        //是否生成工具<br />    false        //是否生成URL链接<br />    );<br />    <br />    ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,640,370);<br />%&gt;<br /><br /><strong>TimeSeriesDemo（在页面上显示）<br /></strong>首先配置web.xml<br /><font color="#0000ff"> </font><font color="#000000">&lt;servlet&gt;<br />  &lt;servlet-name&gt;DisplayChart&lt;/servlet-name&gt;<br />  &lt;servlet-class&gt;org.jfree.chart.servlet.DisplayChart&lt;/servlet-class&gt;<br /> &lt;/servlet&gt;<br /> <br /> <br /> &lt;servlet-mapping&gt;<br />  &lt;servlet-name&gt;DisplayChart&lt;/servlet-name&gt;<br />  &lt;url-pattern&gt;/servlet/DisplayChart&lt;/url-pattern&gt;<br /> &lt;/servlet-mapping&gt;</font></p>
		<p>
				<br />
				<strong>
						<font color="#000000">TimeSeriesDemo.java</font>
				</strong>
		</p>
		<p>
				<strong>
						<font color="#000000">package net.neitbe.home.jfreechart.business;</font>
				</strong>
		</p>
		<p>
				<strong>
						<font color="#000000">import java.awt.Color;<br />import java.awt.Font;<br />import java.awt.GradientPaint;<br />import java.io.IOException;</font>
				</strong>
		</p>
		<p>
				<strong>
						<font color="#000000">import javax.servlet.http.HttpSession;</font>
				</strong>
		</p>
		<p>
				<strong>
						<font color="#000000">import org.apache.commons.logging.Log;<br />import org.apache.commons.logging.LogFactory;<br />import org.jfree.chart.ChartFactory;<br />import org.jfree.chart.ChartRenderingInfo;<br />import org.jfree.chart.JFreeChart;<br />import org.jfree.chart.entity.StandardEntityCollection;<br />import org.jfree.chart.servlet.ServletUtilities;<br />import org.jfree.chart.title.TextTitle;<br />import org.jfree.data.time.Day;<br />import org.jfree.data.time.TimeSeries;<br />import org.jfree.data.time.TimeSeriesCollection;<br />import org.jfree.data.time.TimeSeriesDataItem;</font>
				</strong>
		</p>
		<p>
				<strong>
						<font color="#000000">/**<br /> * @author neitbe<br /> */<br />public class TimeSeriesDemo {</font>
				</strong>
		</p>
		<p>
				<strong>
						<font color="#000000"> private static Log log    = LogFactory.getLog(TimeSeriesDemo.class);<br /> <br /> //曲线图标题<br /> private String title    = "趋势分析";<br /> //曲线图X轴提示<br /> private String domain    = "月份走势";<br /> //曲线图Y轴提示<br /> private String range    = "应收余额";<br /> //曲线图自标题<br /> private String subtitleStr   = "2005财年分析";<br /> <br /> //创建时间数据源<br /> //每一个TimeSeries在图上是一条曲线<br /> private TimeSeries yongyou    = new TimeSeries("用友");<br /> private TimeSeries jindie    = new TimeSeries("金碟");<br /> private TimeSeries dongruan    = new TimeSeries("东软");<br /> <br /> //时间曲线数据集合<br /> private static TimeSeriesCollection dataset = new TimeSeriesCollection();</font>
				</strong>
		</p>
		<p>
				<br />
				<strong>
						<font color="#000000"> private void setDataset() {<br />  dataset.removeAllSeries();        //在javaBean中使用此类这个很重要，不然会不停的加入新的TimeSeries;<br />  dataset.addSeries(this.yongyou);<br />  dataset.addSeries(this.jindie);<br />  dataset.addSeries(this.dongruan);<br />  <br /> }</font>
				</strong>
		</p>
		<p>
				<font color="#000000">
				</font>
		</p>
		<p>
				<strong>
						<font color="#000000"> private void setDongruan() {<br />  this.dongruan.clear();     //很重要，不然会报错<br />  /**<br />   * 报错<br />   * org.apache.jasper.JasperException: You are attempting to add an observation for the time period <br />   * 这里是在类属性里声明TimeSeries才用到的<br />   */<br />  for(int i = 1999; i &lt; 2005; i++) {<br />   for(int mon = 0; mon &lt; 12; mon++) {<br />    <br />    this.dongruan.add(new TimeSeriesDataItem(new Day(1,mon+1,i),new Double(300 - Math.random()*100)));<br />   }<br />  }<br /> }</font>
				</strong>
		</p>
		<p>
				<strong>
						<font color="#000000"> private void setJindie() {<br />  <br />  this.jindie.clear();    //很重要，不然会报错<br />  for(int i = 1999; i &lt; 2005; i++) {<br />   for(int mon = 0; mon &lt; 12; mon++) {<br />    this.jindie.add(new TimeSeriesDataItem(new Day(1,mon+1,i),new Double(400 - Math.random()*100)));<br />   }<br />  }<br /> }</font>
				</strong>
		</p>
		<p>
				<font color="#000000">
				</font> </p>
		<p>
				<strong>
						<font color="#000000"> private void setYongyou() {<br />  this.yongyou.clear();   //很重要，不然会报错<br />  for(int i = 1999; i &lt; 2005; i++) {<br />   for(int mon = 0; mon &lt; 12; mon++) {<br />    this.yongyou.add(new TimeSeriesDataItem(new Day(1,mon+1,i),new Double(500 - Math.random()*100)));<br />   }<br />  }<br />  <br /> }</font>
				</strong>
		</p>
		<p>
				<font color="#000000">
				</font>
		</p>
		<p>
				<strong>
						<font color="#000000"> private TimeSeriesCollection getDataset() {<br />  this.setDongruan();<br />  this.setJindie();<br />  this.setYongyou();<br />  this.setDataset();<br />  return dataset;<br /> }<br /> <br /> public String drawPic(HttpSession session) {<br />  String fileName       = null;<br />  JFreeChart chart      = ChartFactory.createTimeSeriesChart(title,domain,range,getDataset(),true,true,false);<br />  TextTitle subTitle      = new TextTitle(subtitleStr,new Font("黑体",Font.BOLD,12));<br />  chart.addSubtitle(subTitle);<br />  chart.setTitle(new TextTitle(title,new Font("隶书",Font.ITALIC,15)));<br />  chart.setBorderPaint(new GradientPaint(0,0,Color.white,0,1000,Color.blue));<br />  //String fileName       = "D:\\fuit2.jpeg";<br />  try {<br />   ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());</font>
				</strong>
		</p>
		<p>
				<br />
				<strong>
						<font color="#000000">   log.debug("准备创建图片……");<br />   fileName       = ServletUtilities.saveChartAsJPEG(chart,600,600,info,session);<br />   log.debug("图片创建成功！");<br />  } catch (IOException e) {<br />   log.error("IO异常：",e);<br />  }<br />  log.debug("返回的文件名为：" + fileName);<br />  return fileName;<br /> }<br /> <br /> /*public static void main(String[] args) {<br />  TimeSeriesDemo timeSeriesDemo   = new TimeSeriesDemo();<br />  timeSeriesDemo.drawPic();<br /> }*/</font>
				</strong>
		</p>
		<p>
				<br />
				<font color="#000000">
						<strong> <br />}</strong>
						<br />
						<br />
				</font>
				<strong>
						<font color="#000000">index.jsp页面：<br /><!--page language="java" contentType="text/html; charset=GBK"<br />&nbsp;&nbsp;&nbsp; pageEncoding="GBK--></font>
				</strong>
				<strong>
						<font color="#000000">&lt;%@ page language="java" contentType="text/html; charset=GBK"<br />    pageEncoding="GBK"%&gt;<br />&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;<br />&lt;html&gt;<br />&lt;head&gt;<br />&lt;meta http-equiv="Content-Type" content="text/html; charset=GBK"&gt;<br />&lt;title&gt;Insert title here&lt;/title&gt;<br />&lt;jsp:useBean id="timeSeries" scope="session" class="net.neitbe.home.jfreechart.business.TimeSeriesDemo"/&gt;<br />&lt;/head&gt;<br />&lt;body&gt;<br />&lt;% <br /> String fileName   = timeSeries.drawPic(request.getSession());<br /> String graphURL   = request.getContextPath()+"/servlet/DisplayChart?filename=" + fileName;<br />%&gt;<br />&lt;%=graphURL%&gt;&lt;br/&gt;<br />&lt;img src="&lt;%= graphURL %&gt;" width="400" height="400" border="1"/&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</font>
				</strong>
		</p>
<img src ="http://www.blogjava.net/matthew2006/aggbug/57143.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-07-07 15:26 <a href="http://www.blogjava.net/matthew2006/archive/2006/07/07/57143.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jasperreport连续打印多个报表模板－原创</title><link>http://www.blogjava.net/matthew2006/archive/2006/07/01/56099.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sat, 01 Jul 2006 08:52:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/07/01/56099.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/56099.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/07/01/56099.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/56099.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/56099.html</trackback:ping><description><![CDATA[Jasperreport连续打印多个报表模板，这个问题一直困扰我很久。网上查了很多资料都没有具体的解决办法，通过查询jasperreport的API发现提供了解决这个问题的方法。以下是我的过程记录：<br /><br /><strong>问题描述</strong>：一般报表设计和打印中，主要是对单个报表模板进行数据填充、打印、导出。但是，也有个别情况需要连续打印多个报表模板。比如，政府机关的上报材料，属于一个完整的文档。如果一个一个模板打印会显得非常麻烦。<br /><br /><strong>问题解决过程：</strong>一般我们导出报表文件是使用这个语句：<br />exporter.setParamete(JRExporterParameter.JASPER_PRINT, jasperprint);但是它是对单个模板进行操作，通过查找jasperreport的API发现还提供了这样一个语句：<br />exporter.setParameter(JRExporterParameter.JASPER_PRINT_LIST, jasperprint);可以连续对多个报表模板操作。它的方法是通过一个list来存储多个JasperPrint对象，从而实现多个报表模板的打印。在我解决问题的过程中发现导出PDF文件格式比较简单，但是导出WORD文档时发现编码格式出现问题，老是出现乱码。即使这样: exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "GB2312");也没有用。后来浏览一篇贴子：“导出excel时出现乱码问题”，和我的问题差不多。终于大功告成！<img src ="http://www.blogjava.net/matthew2006/aggbug/56099.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-07-01 16:52 <a href="http://www.blogjava.net/matthew2006/archive/2006/07/01/56099.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jasper report 使用 hibernate 数据源性能优化</title><link>http://www.blogjava.net/matthew2006/archive/2006/06/29/55810.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Thu, 29 Jun 2006 12:00:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/06/29/55810.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/55810.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/06/29/55810.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/55810.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/55810.html</trackback:ping><description><![CDATA[
		<p>
				<span class="tpc_content">
						<font size="2">（转贴：Autohr John Ferguson Smart ）<br />      注: 使用了 hibernate 的分页功能，对大数据量查询采用分段读入方法，避免了一次读入带来的性能下降，一般在Tomcat 环境下，当List中的 Object &gt; 10000 一般会导致 OutOfMemory。<br /><br /><br /><strong>Introduction</strong><br />In the article, we examine a performance-optimised approach for using Hibernate queries to generate reports with JasperReports.<br /><br />  JasperReports is a powerful and flexible Open Source reporting tool. Combined with the graphical design tool iReport, for example, you get a complete Java Open Source reporting solution. In this article, we will investigate how you can integrate JasperReports reporting with Hibernate data sources in an optimal manner, without sacrificing ease-of-use or performance.<br /><br /><strong>  Basic Hibernate/JasperReports integration</strong><br />To integrate Hibernate and JasperReports, you have to define a JasperReports data source. One simple and intuitive approach is to use the JRBeanCollectionDataSource data source (This approach is presented here) :<br /><br />-------------------------------------------------------------------------------------------------------<br />List results = session.find("from com.acme.Sale");<br /><br />  Map parameters = new HashMap();<br />  parameters.put("Title", "Sales Report");<br /><br />  InputStream reportStream<br />            = this.class.getResourceAsStream("/sales-report.xml");<br />  JasperDesign jasperDesign = JasperManager.loadXmlDesign(reportStream);<br />  JasperReport jasperReport = JasperManager.compileReport(jasperDesign);<br /><br />JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(results);<br />  JasperPrint jasperPrint = JasperManager.fillReport(jasperReport,<br />                                    parameters,<br />                                    ds);<br /><br />  JasperExportManager.exportReportToPdfFile(jasperPrint, "sales-report.pdf");<br /><br />------------------------------------------------------------------------------------------------------------<br /><br />  This approach will work well for small lists. However, for reports involving tens or hundreds of thousands of lines, it is inefficiant, memory-consuming, and slow. Indeed, experience shows that, when running on a standard Tomcat configuration, a list returning as few as 10000 business objects can cause OutOfMemory exceptions. It also wastes time building a bulky list of objects before processing them, and pollutes the Hibernate session (and possibly second-level caches with temporary objects. <br /><br /><strong>Optimised Hibernate/JasperReports integration<br /></strong>We need a way to efficiently read and process Hibernate queries, without creating too many unnecessary temporary objects in memory. One possible way to do this is the following :<br /><br />Define an optimised layer for executing Hibernate queries efficiently <br />Define an abstraction layer for these classes which is compatible with JasperReports <br />Wrap this data access layer in a JasperReports class that can be directly plugged into JasperReports <br />The Hibernate Data Access Layer : The QueryProvider interface and its implementations<br />We start with the optimised Hibernate data access. (you may note that this layer is not actually Hibernate-specific, so other implementations could implement other types of data access without impacting the design). <br /><br />This layer contains two principal classes :<br /><br />The CriteriaSet class <br />The QueryProvider interface <br /><br /><br />  A CriteriaSet is simply a JavaBean which contains parameters which may be passed to the Hibernate query. It is simply a generic way of encapsulating a set of parameters. A QueryProvider provides a generic way of returning an arbitrary subset of the query results set. The essential point is that query results are read in small chunks, not all at once. This allows more efficient memory handling and better performance.<br /><br /><br />------------------------------------------------------------------------------------------------------------<br />/**<br />  * A QueryProvidor provides a generic way of fetching a set of objects.<br />  */<br />  public interface QueryProvider {<br /><br />    /**<br />      * Return a set of objects based on a given criteria set.<br />      * @param firstResult the first result to be returned<br />      * @param maxResults the maximum number of results to be returned<br />      * @return a list of objects<br />      */<br />    List getObjects(CriteriaSet criteria,<br />                int firstResult,<br />                int maxResults) throws HibernateException;<br />  }<br />----------------------------------------------------------------------------------------------------------<br /><br />  A typical implementation of this class simply builds a Hibernate query using the specified criteria set and returns the requested subset of results. For example : <br /><br />-----------------------------------------------------------------------------------------------------------<br /><br />public class ProductQueryProvider implements QueryProvider {<br /><br />    public List getObjects(CriteriaSet criteria,<br />                    int firstResult,<br />                    int maxResults)<br />          throws HibernateException {<br />      //<br />      // Build query criteria<br />      //<br />      Session sess = SessionManager.currentSession();<br />      ProductCriteriaSet productCriteria<br />                      = (ProductCriteriaSet) criteria;<br />      Query query = session.find("from com.acme.Product p "<br />              + "where p.categoryCode = :categoryCode ");<br /><br />      query.setParameter("categoryCode",<br />                    productCriteria.getCategoryCode();<br />      return query.setCacheable(true)<br />              .setFirstResult(firstResult)<br />              .setMaxResults(maxResults)<br />              .setFetchSize(100)<br />              .list();<br />    }<br />  }<br />-------------------------------------------------------------------------------------------------<br /><br />  A more sophisticated implementation is helpful for dynamic queries. We define an abstract BaseQueryProvider class which can be used for dynamic query generation. This is typically useful when the report has to be generated using several parameters, some of which are optionnal.. Each derived class overrides the buildCriteria() method. This method builds a Hibernate Criteria object using the specified Criteria set as appropriate :<br /><br />---------------------------------------------------------------------------------------------------<br /><br />public abstract class BaseQueryProvider implements QueryProvider {<br /><br />    public List getObjects(CriteriaSet criteria, int firstResult, int maxResults)<br />          throws HibernateException {<br /><br />          Session sess = SessionManager.currentSession();<br />          Criteria queryCriteria = buildCriteria(criteria, sess);<br />          return queryCriteria.setCacheable(true)<br />                  .setFirstResult(firstResult)<br />                  .setMaxResults(maxResults)<br />                  .setFetchSize(100)<br />                  .list();<br /><br />    }<br /><br />    protected abstract Criteria buildCriteria(CriteriaSet criteria, Session sess);<br />  }<br />-------------------------------------------------------------------------------------------------<br /><br />A typical implementation is shown here : <br /><br />--------------------------------------------------------------------------------------------------<br /><br />public class SalesQueryProvider extends BaseQueryProvider {<br /><br />    protected Criteria buildCriteria(CriteriaSet criteria,<br />                          Session sess) {<br />      //<br />      // Build query criteria<br />      //<br />      SalesCriteriaSet salesCriteria<br />                  = (SalesCriteriaSet) criteria;<br /><br />      Criteria queryCriteria<br />                  = sess.createCriteria(Sale.class);<br /><br />      if (salesCriteria.getStartDate() != null) {<br />          queryCriteria.add(<br />              Expression.eq("getStartDate",<br />                        salesCriteria.getStartDate()));<br />      }<br />      // etc...<br /><br />      return queryCriteria;<br />    }<br />  }<br />------------------------------------------------------------------------------------------------<br /><br />  Note that a QueryProvider does not need to return Hibernate-persisted objects. Large-volume queries can sometimes be more efficiently implemented by returning custom-made JavaBeans containing just the required columns. HQL allows you to to this quite easily :<br /><br />---------------------------------------------------------------------------------------------------<br />public class CityQueryProvider implements QueryProvider {<br /><br />    public List getObjects(CriteriaSet criteria,<br />                    int firstResult,<br />                    int maxResults)<br />          throws HibernateException {<br />      //<br />      // Build query criteria<br />      //<br />      Session sess = SessionManager.currentSession();<br />      Query query<br />            = session.find(<br />                "select new CityItem(city.id, "<br />              + "             city.name, "<br />              + "         city.electrityCompany.name) "<br />              + " from City city "<br />              + " left join city.electrityCompany");<br /><br />      return query.setCacheable(true)<br />              .setFirstResult(firstResult)<br />              .setMaxResults(maxResults)<br />              .setFetchSize(100)<br />              .list();<br />    }<br />  }<br />-------------------------------------------------------------------------------------------------<br /><br />Hibernate data access abstraction : the ReportDataSource interface<br />Next, we define a level of abstraction between the Hibernate querying and the JasperReport classes. The ReportDataSource does this :<br /><br />--------------------------------------------------------------------------------------------------<br />public interface ReportDataSource extends Serializable {<br />    Object getObject(int index);<br />  }<br /><br /><br />--------------------------------------------------------------------------------------------------<br /><br />  The standard implementation of this interface reads Hibernate objects using a given QueryProvider and returns them to JasperReports one by one. Here is the source code of this class (getters, setters, logging code and error-handling code have been removed for clarty) : <br /><br />---------------------------------------------------------------------------------------------------<br />public class ReportDataSourceImpl implements ReportDataSource {<br /><br />    private CriteriaSet criteriaSet;<br />    private QueryProvider queryProvider;<br />    private List resultPage;<br />    private int pageStart = Integer.MAX_VALUE;<br />    private int pageEnd = Integer.MIN_VALUE;<br />    private static final int PAGE_SIZE = 50;<br /><br />    //<br />    // Getters and setters for criteriaSet and queryProvider<br />    //<br />    ...<br /><br />    public List getObjects(int firstResult,<br />                    int maxResults) {<br /><br />        List queryResults = getQueryProvider()<br />                      .getObjects(getCriteriaSet(),<br />                              firstResult,<br />                              maxResults);<br />        if (resultPage == null) {<br />          resultPage = new ArrayList(queryResults.size());<br />        }<br />        resultPage.clear();<br />        for(int i = 0; i &lt; queryResults.size(); i++) {<br />          resultPage.add(queryResults.get(i));<br />        }<br />        pageStart = firstResult;<br />        pageEnd = firstResult + queryResults.size() - 1;<br />        return resultPage;<br />    }<br />public final Object getObject(int index) {<br />      if ((resultPage == null)<br />          || (index &lt; pageStart)<br />          || (index &gt; pageEnd)) {<br />          resultPage = getObjects(index, PAGE_SIZE);<br />      }<br />      Object result = null;<br />      int pos = index - pageStart;<br />      if ((resultPage != null)<br />          &amp;&amp; (resultPage.size() &gt; pos)) {<br />          result = resultPage.get(pos);<br />      }<br />      return result;<br />    }<br />  }<br /><br />---------------------------------------------------------------------------------------------------<br /><br />Finally, we have to be able to call the Hibernate data source from JasperReports. To do so, we start by looking at the JasperManager fillReport() method, which takes a JRDataSource object as its third parameter and uses it to generate the report :<br /><br />---------------------------------------------------------------------------------------------------<br />JasperPrint jasperPrint = JasperManager.fillReport(jasperReport, parameters, ds);<br /><br />---------------------------------------------------------------------------------------------------<br /><br /><br />To implement our own optimised JRDataSource, we extended the JRAbstractBeanDataSource class. This class is presented here (logging and error-handling code has been removed for clarty). <br /><br />---------------------------------------------------------------------------------------------------<br />public class ReportSource extends JRAbstractBeanDataSource {<br /><br />    private ReportDataSource dataSource;<br />    protected int index = 0;<br />    protected Object bean;<br />    private static Map fieldNameMap = new HashMap();<br /><br />    public ReportSource(ReportDataSource dataSource) {<br />      super(true);<br />      this.dataSource = dataSource;<br />      index = 0;<br />    }<br /><br />    public boolean next() throws JRException {<br />      bean = dataSource.getObject(index++);<br />      return (bean != null);<br />    }<br /><br />    public void moveFirst() throws JRException {<br />      index = 0;<br />      bean = dataSource.getObject(index);<br />    }<br /><br />    public Object getFieldValue(JRField field) throws JRException {<br />      String nameField = getFieldName(field.getName());<br />      return PropertyUtils.getProperty(bean, nameField);<br />    }<br />/**<br />    * Replace the character "_" by a ".".<br />    *<br />    * @param fieldName the name of the field<br />    * @return the value in the cache or make<br />    * the replacement and return this value<br />    */<br />    private String getFieldName(String fieldName) {<br />      String filteredFieldName<br />          = (String) fieldNameMap.get(fieldName);<br />      if (filteredFieldName == null) {<br />          filteredFieldName = fieldName.replace('_','.');<br />          fieldNameMap.put(fieldName,filteredFieldName);<br />      }<br />      return filteredFieldName;<br />    }<br />  }<br /><br />---------------------------------------------------------------------------------------------------<br /><br />This class is basically just a proxy between JasperReports and the Hibernate data source object. The only tricky bit is field name handling. For some reason, JasperReports does not accept field names containing dots (ex. "product.code"). However, when you retrieve a set of Hibernate-persisted business objects, you often need to access object attributes. To get around this, we replace the "." by a "_" in the JasperReport template (ex. "product_code" instead of "product.code"), and convert back to a conventional JavaBean format in the getFieldName() method. <br /><br />Putting it all together<br />So, when you put it all together, you get something like this :<br /><br />---------------------------------------------------------------------------------------------------<br />List results = session.find("from com.acme.Sale");<br /><br />  Map parameters = new HashMap();<br />  parameters.put("Title", "Sales Report");<br /><br />  InputStream reportStream<br />          = this.class.getResourceAsStream("/sales-report.xml");<br />  JasperDesign jasperDesign<br />          = JasperManager.loadXmlDesign(reportStream);<br />  JasperReport jasperReport<br />          = JasperManager.compileReport(jasperDesign);<br />  <br />  ReportDataSource hibernateDataSource<br />          = new ReportDataSourceImpl();<br />  hibernateDataSource.setQueryProvider(new SalesQueryProvider());<br />  hibernateDataSource.setCriteriaSet(salesCriteria);<br />  ReportSource rs = new ReportSource(hibernateDataSource);<br />  <br />  JasperPrint jasperPrint<br />            = JasperManager.fillReport(jasperReport,<br />                              parameters,<br />                              rs);<br />  JasperExportManager.exportReportTsoPdfFile(jasperPrint,<br />                              "sales-report.pdf");<br /><br />---------------------------------------------------------------------------------------------------<br /><br /><strong>Further JasperReports optimisations</strong><br /><br />Compiled Report caching<br />In the previous code, the JasperReport is loaded and compiled before it is run. In a serverside application, for optimal performance, the reports should be loaded and compiled once and then cached. This will save several seconds on each query generation. <br /><br />Optimising Hibernate Queries<br />The first cause of slow report generation is sub-optimal querying. Hibernate is a high-performance persistence library which gives excellent results when correctly used. So you should treate any report which takes an excessive time to generate as suspicious. Common Hibernate optimisation strategies include :<br /><br />Correct use of joins <br />Correct use of lazy associations <br />Reading a subset of columns rather than whole Hibernate-persisted objects <br />Some Hibernate query optimisation techniques are discussed here.</font>
				</span>
				<br />
				<!---->
		</p>
		<h2>Conclusion</h2>
		<p>JasperReports is a powerful and flexible reporting tool. To achieve high-performance Hibernate intergration however, some extra work is needed. One way is by writing optimised data access classes which can be plugged into the JasperReports architecture. Using this approach, you can take advantage of the full power of Hibernate in your JasperReports reporting solutions. </p>
		<!-- <p class="post-info">
    <?php wp_link_pages(); ?>
    </p>-->
		<!--
    <?php trackback_rdf(); ?>
    -->
<img src ="http://www.blogjava.net/matthew2006/aggbug/55810.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-06-29 20:00 <a href="http://www.blogjava.net/matthew2006/archive/2006/06/29/55810.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jasper report 使用 hibernate 数据源(转 hibernate 官方网站提供)</title><link>http://www.blogjava.net/matthew2006/archive/2006/06/29/55808.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Thu, 29 Jun 2006 11:58:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/06/29/55808.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/55808.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/06/29/55808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/55808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/55808.html</trackback:ping><description><![CDATA[
		<p>
				<span class="tpc_content">
						<font size="2">注: 此方法使用简单，但是没有分页读取数据，适合数据量不大情况下的报表<br /><br />原文：</font>
						<a href="http://www.hibernate.org/79.html" target="_blank">
								<font size="2">http://www.hibernate.org/79.html</font>
						</a>
						<br />
						<br />
						<font size="2">Using JasperReports with Hibernate<br />This section will demonstrate a couple of ways to use the results of a Hibernate query as the datasource of a report in JasperReports.<br /><br />When the Hibernate query returns a simple collection of objects, The JRBeanCollectionDataSource class in the JasperReports library will work fine.<br /><br />--------------------------------------------------------------------------------------------------------<br />List cats = session.find("from eg.Cat");<br /><br />Map parameters = new HashMap();<br />parameters.put("Title", "The Cat Report");<br /><br />InputStream reportStream = this.class.getResourceAsStream("/the-cat-report.xml");<br />JasperDesign jasperDesign = JasperManager.loadXmlDesign(reportStream);<br />JasperReport jasperReport = JasperManager.compileReport(jasperDesign);<br /><br />JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(cats);<br />JasperPrint jasperPrint = JasperManager.fillReport(jasperReport, parameters, ds);<br /><br />JasperManager.printReportToPdfFile(jasperPrint, "the-cat-report.pdf");<br /><br />--------------------------------------------------------------------------------------------------------<br /><br />  However, when the Hibernate query returns tuples of objects (each tuple as an array, each array as an element in the returned List), things get a little tricky. Jasper needs a way to reference each object in the array by a field name. This class is a good solution, but at this time you are required to pass an array of field names matching the results of the query.<br /><br />--------------------------------------------------------------------------------------------------------<br />public class HibernateQueryResultDataSource implements JRDataSource { <br /><br />private String[] fields; <br />private Iterator iterator; <br />private Object currentValue; <br /><br />public HibernateQueryResultDataSource(List list, String[] fields) { <br />  this.fields = fields; <br />  this.iterator = list.iterator(); <br />} <br /><br />public Object getFieldValue(JRField field) throws JRException { <br />  Object value = null; <br />  int index = getFieldIndex(field.getName()); <br />  if (index &gt; -1) { <br />    Object[] values = (Object[])currentValue; <br />    value = values[index]; <br />  } <br />  return value; <br />} <br /><br />public boolean next() throws JRException { <br />  currentValue = iterator.hasNext() ? iterator.next() : null; <br />  return (currentValue != null); <br />} <br /><br />private int getFieldIndex(String field) { <br />  int index = -1; <br />  for (int i = 0; i &lt; fields.length; i++) { <br />    if (fields</font>
						<i>
								<font size="2">.equals(field)) { <br />    index = i; <br />    break; <br />    } <br />  } <br />  return index; <br />} <br /><br />}<br /><br />--------------------------------------------------------------------------------------------------------<br /><br />Now running your report would look something like this:<br /><br /><br />--------------------------------------------------------------------------------------------------------<br />List cats = session.find("select cat.type, cat.birthdate, cat.name from eg.DomesticCat cat");<br /><br />Map parameters = new HashMap();<br />parameters.put("Title", "The Cat Report");<br /><br />InputStream reportStream = this.class.getResourceAsStream("/the-cat-report.xml");<br />JasperDesign jasperDesign = JasperManager.loadXmlDesign(reportStream);<br />JasperReport jasperReport = JasperManager.compileReport(jasperDesign);<br /><br />String[] fields = new String[] { "type", "birthdate", "name"};<br />HibernateQueryResultDataSource ds = new HibernateQueryResultDataSource(cats, fields);<br />JasperPrint jasperPrint = JasperManager.fillReport(jasperReport, parameters, ds);<br /><br />JasperManager.printReportToPdfFile(jasperPrint, "the-cat-report.pdf");<br /><br />--------------------------------------------------------------------------------------------------------<br /><br /><br />Another, alternate implementation, from Erik Romson:<br /><br /><br />--------------------------------------------------------------------------------------------------------<br />public class HibernateQueryResultDataSource implements JRDataSource<br />{<br />  private static final transient Logger logger = <br />    Logger.Factory.getInstance(HibernateQueryResultDataSource.class);<br />  protected HashMap fieldsToIdxMap=new HashMap();<br />  protected Iterator iterator;<br />  protected Object currentValue;<br />  List values;<br /><br />  public HibernateQueryResultDataSource(List list, String query)<br />  {<br />    int start =query.indexOf("select ");<br />    int stop =query.indexOf(" from ");<br />    Assertion.assertTrue(<br />      (start!=-1) &amp;&amp; <br />      (stop!=-1),<br />      "The query "+<br />      query+<br />      " must be of the form select x,x from ..."<br />    );<br />    start+="select".length();<br />    String parameters=query.substring(start,stop);<br />    parameters=parameters.trim();<br />    Assertion.assertTrue(<br />        parameters.length()&gt;0,<br />        "The query "+<br />        query+<br />        " seems to be weird"<br />    );<br />    StringTokenizer tokenizer=new StringTokenizer(parameters,",");<br />    int idx=0;<br />    while( tokenizer.hasMoreTokens() )<br />    {<br />        String parameter=tokenizer.nextToken();<br />        fieldsToIdxMap.put( parameter.trim(), new Integer(idx) );<br />        idx++;<br />    }<br />    values=list;<br />    this.iterator = list.iterator();<br />  }<br />public Object getFieldValue(JRField field) throws JRException<br />  {<br />    String fieldName=field.getName().replace('_','.'); <br />    //JasperReports does not allow '.' in field names, so we <br />    //use '_' for nested properties instead and must convert here <br />    //(comment added by kbrown)<br />    Integer idxInt=(Integer) fieldsToIdxMap.get(fieldName);<br />    if (idxInt==null)<br />    {<br />        Assertion.fail(<br />          "The field \""+<br />          fieldName+<br />          "\" did not have an index mapping. Should be one off "+<br />          fieldsToIdxMap.keySet()<br />        );<br />    }<br />    Object[] values = (Object[]) currentValue;<br />    Assertion.assertTrue(<br />        idxInt.intValue()<values.length,><br />        "The index from field "+<br />        fieldName+<br />        " was illegal"<br />    );<br />    Object value= values[ idxInt.intValue() ];<br />    if ( logger.isDebugEnabled() )<br />    {<br />        logger.debug("fetched value "+value+" from field "+fieldName);<br />    }<br />    return value;<br />  }<br /><br />  public boolean next() throws JRException<br />  {<br />    currentValue = iterator.hasNext() ? iterator.next() : null;<br />    return currentValue != null;<br />  }<br /><br />  public List getValues()<br />  {<br />    return values;<br />  }<br />}<br /><br />--------------------------------------------------------------------------------------------------------<br /><br />Using JasperReports with Hibernate<br />This section will demonstrate a couple of ways to use the results of a Hibernate query as the datasource of a report in JasperReports.<br /><br />When the Hibernate query returns a simple collection of objects, The JRBeanCollectionDataSource class in the JasperReports library will work fine.<br /><br />List cats = session.find("from eg.Cat");<br /><br />Map parameters = new HashMap();<br />parameters.put("Title", "The Cat Report");<br /><br />InputStream reportStream = this.class.getResourceAsStream("/the-cat-report.xml");<br />JasperDesign jasperDesign = JasperManager.loadXmlDesign(reportStream);<br />JasperReport jasperReport = JasperManager.compileReport(jasperDesign);<br /><br />JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(cats);<br />JasperPrint jasperPrint = JasperManager.fillReport(jasperReport, parameters, ds);<br /><br />JasperManager.printReportToPdfFile(jasperPrint, "the-cat-report.pdf");<br />However, when the Hibernate query returns tuples of objects (each tuple as an array, each array as an element in the returned List), things get a little tricky. Jasper needs a way to reference each object in the array by a field name. This class is a good solution, but at this time you are required to pass an array of field names matching the results of the query.<br /><br />public class HibernateQueryResultDataSource implements JRDataSource { <br /><br />private String[] fields; <br />private Iterator iterator; <br />private Object currentValue; <br /><br />public HibernateQueryResultDataSource(List list, String[] fields) { <br />  this.fields = fields; <br />  this.iterator = list.iterator(); <br />} <br /><br />public Object getFieldValue(JRField field) throws JRException { <br />  Object value = null; <br />  int index = getFieldIndex(field.getName()); <br />  if (index &gt; -1) { <br />    Object[] values = (Object[])currentValue; <br />    value = values[index]; <br />  } <br />  return value; <br />} <br /><br />public boolean next() throws JRException { <br />  currentValue = iterator.hasNext() ? iterator.next() : null; <br />  return (currentValue != null); <br />} <br /><br />private int getFieldIndex(String field) { <br />  int index = -1; <br />  for (int i = 0; i &lt; fields.length; i++) { <br />    if (fields</values.length,></font>
								<i>
										<font size="2">.equals(field)) { <br />    index = i; <br />    break; <br />    } <br />  } <br />  return index; <br />} <br /><br />}<br />Now running your report would look something like this:<br /><br />List cats = session.find("select cat.type, cat.birthdate, cat.name from eg.DomesticCat cat");<br /><br />Map parameters = new HashMap();<br />parameters.put("Title", "The Cat Report");<br /><br />InputStream reportStream = this.class.getResourceAsStream("/the-cat-report.xml");<br />JasperDesign jasperDesign = JasperManager.loadXmlDesign(reportStream);<br />JasperReport jasperReport = JasperManager.compileReport(jasperDesign);<br /><br />String[] fields = new String[] { "type", "birthdate", "name"};<br />HibernateQueryResultDataSource ds = new HibernateQueryResultDataSource(cats, fields);<br />JasperPrint jasperPrint = JasperManager.fillReport(jasperReport, parameters, ds);<br /><br />JasperManager.printReportToPdfFile(jasperPrint, "the-cat-report.pdf");<br /><br />--------------------------------------------------------------------------------<br /><br />Another, alternate implementation, from Erik Romson:<br /><br />public class HibernateQueryResultDataSource implements JRDataSource<br />{<br />  private static final transient Logger logger = <br />    Logger.Factory.getInstance(HibernateQueryResultDataSource.class);<br />  protected HashMap fieldsToIdxMap=new HashMap();<br />  protected Iterator iterator;<br />  protected Object currentValue;<br />  List values;<br /><br />  public HibernateQueryResultDataSource(List list, String query)<br />  {<br />    int start =query.indexOf("select ");<br />    int stop =query.indexOf(" from ");<br />    Assertion.assertTrue(<br />      (start!=-1) &amp;&amp; <br />      (stop!=-1),<br />      "The query "+<br />      query+<br />      " must be of the form select x,x from ..."<br />    );<br />    start+="select".length();<br />    String parameters=query.substring(start,stop);<br />    parameters=parameters.trim();<br />    Assertion.assertTrue(<br />        parameters.length()&gt;0,<br />        "The query "+<br />        query+<br />        " seems to be weird"<br />    );<br />    StringTokenizer tokenizer=new StringTokenizer(parameters,",");<br />    int idx=0;<br />    while( tokenizer.hasMoreTokens() )<br />    {<br />        String parameter=tokenizer.nextToken();<br />        fieldsToIdxMap.put( parameter.trim(), new Integer(idx) );<br />        idx++;<br />    }<br />    values=list;<br />    this.iterator = list.iterator();<br />  }<br /><br />  public Object getFieldValue(JRField field) throws JRException<br />  {<br />    String fieldName=field.getName().replace('_','.'); <br />    //JasperReports does not allow '.' in field names, so we <br />    //use '_' for nested properties instead and must convert here <br />    //(comment added by kbrown)<br />    Integer idxInt=(Integer) fieldsToIdxMap.get(fieldName);<br />    if (idxInt==null)<br />    {<br />        Assertion.fail(<br />          "The field \""+<br />          fieldName+<br />          "\" did not have an index mapping. Should be one off "+<br />          fieldsToIdxMap.keySet()<br />        );<br />    }<br />    Object[] values = (Object[]) currentValue;<br />    Assertion.assertTrue(<br />        idxInt.intValue()<values.length,><br />        "The index from field "+<br />        fieldName+<br />        " was illegal"<br />    );<br />    Object value= values[ idxInt.intValue() ];<br />    if ( logger.isDebugEnabled() )<br />    {<br />        logger.debug("fetched value "+value+" from field "+fieldName);<br />    }<br />    return value;<br />  }<br /><br />  public boolean next() throws JRException<br />  {<br />    currentValue = iterator.hasNext() ? iterator.next() : null;<br />    return currentValue != null;<br />  }<br /><br />  public List getValues()<br />  {<br />    return values;<br />  }<br />}<br /><br />--------------------------------------------------------------------------------<br /><br />Using the information from this page I've made a patch to JasperReports 0.6.5. You can find the patch at: </values.length,></font>
										<a href="http://www.waltermourao.com.br/JasperReports/jr65_hql.zip" target="_blank">
												<font size="2">http://www.waltermourao.com.br/JasperReports/jr65_hql.zip</font>
										</a>
										<font size="2"> or you can download the full version from: </font>
										<a href="http://www.waltermourao.com.br/JasperReports/jasperreports-hql-0.6.5.zip" target="_blank">
												<font size="2">http://www.waltermourao.com.br/JasperReports/jasperreports-hql-0.6.5.zip</font>
										</a>
								</i>
						</i>
				</span>
				<br />
				<!---->
		</p>
<img src ="http://www.blogjava.net/matthew2006/aggbug/55808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-06-29 19:58 <a href="http://www.blogjava.net/matthew2006/archive/2006/06/29/55808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JasperReport 用户手册－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/06/07/51021.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Wed, 07 Jun 2006 01:30:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/06/07/51021.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/51021.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/06/07/51021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/51021.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/51021.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JasperReport 用户手册的翻译												1 										简介																																																						       JasperReport										是一个强大、灵活的报表生成工具，能够展示丰富的页面内容...&nbsp;&nbsp;<a href='http://www.blogjava.net/matthew2006/archive/2006/06/07/51021.html'>阅读全文</a><img src ="http://www.blogjava.net/matthew2006/aggbug/51021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-06-07 09:30 <a href="http://www.blogjava.net/matthew2006/archive/2006/06/07/51021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jasperreport+ireport报表设计中遇到的问题</title><link>http://www.blogjava.net/matthew2006/archive/2006/06/06/50879.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Tue, 06 Jun 2006 11:43:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/06/06/50879.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/50879.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/06/06/50879.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/50879.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/50879.html</trackback:ping><description><![CDATA[今天是个好日子，200666。把自己这段时间遇到的几个问题记录下来吧。<br />问题1:最常见的问题就是中文问题，不能显示中文或者是乱码。<br />解决办法：在需要显示中文的field里面(包括静态的)设置PDF font name:STSong-Light,PDF encoding:<span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">UniGB-UCS2-H (Chinese Simplified)</span><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">。即可！<br /><br />问题2:设计静态报表模板时，word输出格式问题，预览时总是空白页。<br />解决办法：可以通过设置报表属性中的“当没有数据时的显示方式”为：除detail外的所有地方。<br /><br />问题3:当输出HTML格式报表时总是出现空白页问题。<br />解决办法:原因是我用的jasperreport版本是1.2.2,在这个版本中出现一个小bug，就是编译输出的html源代码为&lt;/title&gt;，IE不能编译。办法是修改源码，或者手工添加代码把&lt;/title&gt;改为&lt;title&gt;&lt;/title&gt;，最后也可以把你的lib目录下的jasperreport的jar包的版本换为1.2.1<br />....待续</span><img src ="http://www.blogjava.net/matthew2006/aggbug/50879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-06-06 19:43 <a href="http://www.blogjava.net/matthew2006/archive/2006/06/06/50879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ireport+Jasperreport报表设计－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/06/06/50873.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Tue, 06 Jun 2006 11:11:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/06/06/50873.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/50873.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/06/06/50873.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/50873.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/50873.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第一部分：使用iReport制作报表的详细过程（Windows环境下）																1				、前言														在网络上可以搜索到很多使用						iReport						和						Jasperreport						配合实现各种报表任务的文章，但是我觉得很少有一篇（几乎没有）做一个比较详细的介绍如何使用...&nbsp;&nbsp;<a href='http://www.blogjava.net/matthew2006/archive/2006/06/06/50873.html'>阅读全文</a><img src ="http://www.blogjava.net/matthew2006/aggbug/50873.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-06-06 19:11 <a href="http://www.blogjava.net/matthew2006/archive/2006/06/06/50873.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Java报表－jasperreport</title><link>http://www.blogjava.net/matthew2006/archive/2006/06/06/50868.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Tue, 06 Jun 2006 10:53:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/06/06/50868.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/50868.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/06/06/50868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/50868.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/50868.html</trackback:ping><description><![CDATA[新开了个Blog,该填点东西进来呵。这段时间由于种种原因在研究B/S架构下的报表设计，也早想写点自己的经验记录自己的学习过程。总的感觉报表是个比较麻烦的东西，算是个细致活。我会在往后的学习中把一些遇到的问题和解决办法记录下来，首先还是贴点别人的文章吧。。。<img src ="http://www.blogjava.net/matthew2006/aggbug/50868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-06-06 18:53 <a href="http://www.blogjava.net/matthew2006/archive/2006/06/06/50868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>