﻿<?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/jasonwbd/category/34741.html</link><description>First know how, Second know why !</description><language>zh-cn</language><lastBuildDate>Mon, 22 Sep 2008 20:14:43 GMT</lastBuildDate><pubDate>Mon, 22 Sep 2008 20:14:43 GMT</pubDate><ttl>60</ttl><item><title>使用 JFreeChart来创建基于web的图表</title><link>http://www.blogjava.net/jasonwbd/articles/230261.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sun, 21 Sep 2008 07:00:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230261.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230261.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230261.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230261.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230261.html</trackback:ping><description><![CDATA[<br />
<a href="http://www.ibm.com/developerworks/cn/java/l-jfreechart/index.html">http://www.ibm.com/developerworks/cn/java/l-jfreechart/index.html</a><br />
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="100%">
            <h1><span style="color: #808000">使用 JFreeChart来创建基于web的图表</span></h1>
            <span style="color: #808000"><img class="display-img" height="6" alt="" src="http://www.ibm.com/i/c.gif" width="1" /></span></td>
            <td class="no-print" width="192"><span style="color: #808000"><img height="18" alt="developerWorks" src="http://www.ibm.com/developerworks/i/dw.gif" width="192" /></span></td>
        </tr>
    </tbody>
</table>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="10"><span style="color: #808000"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></span></td>
            <td width="100%">
            <table class="no-print" cellspacing="0" cellpadding="0" width="160" align="right" border="0">
                <tbody>
                    <tr>
                        <td width="10"><span style="color: #808000"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></span></td>
                        <td>
                        <table cellspacing="0" cellpadding="0" width="150" border="0">
                            <tbody>
                                <tr>
                                    <td class="v14-header-1-small"><span style="color: #808000">文档选项</span></td>
                                </tr>
                            </tbody>
                        </table>
                        <table class="v14-gray-table-border" cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td class="no-padding" width="150">
                                    <table cellspacing="0" cellpadding="0" width="143" border="0">
                                        <script language="JavaScript" type="text/javascript">
<!-- document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt="" /></td><td width="16"><img alt="将打印机的版面设置成横向打印模式" height="16" src="//www.ibm.com/i/v14/icons/printer.gif" width="16" vspace="3"  /></td><td width="122"><p><strong><a class="smallplainlink" href="javascript:print()">打印本页</a></strong></p></td></tr>');
//-->
</script>
                                        <tbody>
                                            <tr valign="top">
                                                <td width="8"><span style="color: #808000"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></span></td>
                                                <td width="16"><span style="color: #808000"><img height="16" alt="将打印机的版面设置成横向打印模式" src="http://www.ibm.com/i/v14/icons/printer.gif" width="16" vspace="3" /></span></td>
                                                <td width="122">
                                                <p><strong><a class="smallplainlink" href="javascript:print()" cmimpressionsent="1"><span style="color: #808000">打印本页</span></a></strong></p>
                                                </td>
                                            </tr>
                                            <noscript></noscript>
                                            <form name="email" action="https://www.ibm.com/developerworks/secure/email-it.jsp" cm1="1">
                                                <input type="hidden" value="WWW的发展使得基于因特网的应用程序不再局限于静态或者简单的动态内容提供。传统的一些以软件包形式发布应用程序例如报表系统等都在逐渐搬到因特网上。但是这两者之间有着天壤之别，虽然对于数据获取、业务处理等方面基本类似，但是最大的差别在于用户界面。为了能在web浏览器上显示要求用户界面使用HTML以及图片的方式来展现数据，而传统的一些利用操作系统本身的控件来开发的用户界面无法适应琳琅满目的客户端，因此在这里也变得无能为力。回到本文的题目上来，为了创建一个可以在web浏览器上查看到图表一般有两种做法：第一种就是使用applet利用java本身对图形的支持来显示一个图表；第二种就是直接在web服务器端生成好图表图片文件后发送给浏览器。第一种方式显然对于客户端要求太高，随着现在主流浏览器放弃对JAVA的支持后，这种方式只适合一些局域网的应用，而对于因特网的环境就显得不太适合。因此我们下面将介绍一个JAVA的图表引擎JFreeChart用来产生基于WEB的图表。" name="body" cM3 cm1="1" cm2="0" /><input type="hidden" value="使用 JFreeChart来创建基于web的图表" name="subject" cM3 cm1="1" cm2="1" /><input type="hidden" value="cn" name="lang" cM3 cm1="1" cm2="2" /><span style="color: #808000"> <script language="JavaScript" type="text/javascript">
<!-- document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt="" /></td><td width="16"><img src="//www.ibm.com/i/v14/icons/em.gif" height="16" width="16" vspace="3" alt="将此页作为电子邮件发送"  /></td><td width="122"><p><a class="smallplainlink" href="javascript:document.email.submit();"><strong>将此页作为电子邮件发送</strong></a></p></td></tr>');
//-->
</script></span>
                                                <tr valign="top">
                                                    <td width="8"><span style="color: #808000"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></span></td>
                                                    <td width="16"><span style="color: #808000"><img height="16" alt="将此页作为电子邮件发送" src="http://www.ibm.com/i/v14/icons/em.gif" width="16" vspace="3" /></span></td>
                                                    <td width="122">
                                                    <p><a class="smallplainlink" href="javascript:document.email.submit();" cmimpressionsent="1"><strong><span style="color: #808000">将此页作为电子邮件发送</span></strong></a></p>
                                                    </td>
                                                </tr>
                                                <noscript></noscript>
                                            </form>
                                        </tbody>
                                    </table>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas --><!--end RESERVED FOR FUTURE USE INCLUDE FILES--><br />
                        </td>
                    </tr>
                </tbody>
            </table>
            <p><span style="color: #808000">级别： 初级</span></p>
            <p><a href="http://www.ibm.com/developerworks/cn/java/l-jfreechart/index.html#author" cmimpressionsent="1"><span style="color: #808000">刘冬</span></a><span style="color: #808000"> (</span><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#119;&#105;&#110;&#116;&#101;&#114;&#46;&#108;&#97;&#117;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;&#63;&#115;&#117;&#98;&#106;&#101;&#99;&#116;&#61;&#20351;&#29992;&#32;&#74;&#70;&#114;&#101;&#101;&#67;&#104;&#97;&#114;&#116;&#26469;&#21019;&#24314;&#22522;&#20110;&#119;&#101;&#98;&#30340;&#22270;&#34920;&#38;&#97;&#109;&#112;&#59;&#97;&#109;&#112;&#59;&#99;&#99;&#61;&#119;&#105;&#110;&#116;&#101;&#114;&#46;&#108;&#97;&#117;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;" cmimpressionsent="1"><span style="color: #808000">winter.lau@163.com</span></a><span style="color: #808000">), 软件工程师, 珠海市创我科技发展有限公司<br />
            </span></p>
            <p><span style="color: #808000">2003 年 9 月 08 日</span></p>
            <blockquote><span style="color: #808000">WWW的发展使得基于因特网的应用程序不再局限于静态或者简单的动态内容提供。传统的一些以软件包形式发布应用程序例如报表系统等都在逐渐搬到因特网上。但是这两者之间有着天壤之别，虽然对于数据获取、业务处理等方面基本类似，但是最大的差别在于用户界面。为了能在web浏览器上显示要求用户界面使用HTML以及图片的方式来展现数据，而传统的一些利用操作系统本身的控件来开发的用户界面无法适应琳琅满目的客户端，因此在这里也变得无能为力。回到本文的题目上来，为了创建一个可以在web浏览器上查看到图表一般有两种做法：第一种就是使用applet利用java本身对图形的支持来显示一个图表；第二种就是直接在web服务器端生成好图表图片文件后发送给浏览器。第一种方式显然对于客户端要求太高，随着现在主流浏览器放弃对JAVA的支持后，这种方式只适合一些局域网的应用，而对于因特网的环境就显得不太适合。因此我们下面将介绍一个JAVA的图表引擎JFreeChart用来产生基于WEB的图表。</span></blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
            <p><a name="1"><span class="atitle"><span style="color: #808000">JFreeChart项目简介</span></span></a></p>
            <p><span style="color: #808000">JFreeChart是开放源代码站点SourceForge.net上的一个JAVA项目，它主要用来各种各样的图表，这些图表包括：饼图、柱状图(普通柱状图以及堆栈柱状图)、线图、区域图、分布图、混合图、甘特图以及一些仪表盘等等。这些不同式样的图表基本上可以满足目前的要求。为了减少篇幅本文主要介绍前面三种类型的图表，读者可以触类旁通去开发其他样式的图表。下面几个是JFreeChart产生的这三种类型图表的结果： </span></p>
            <br />
            <a name="N10049"><strong><span style="color: #808000">图1</span></strong></a><br />
            <span style="color: #808000"><img alt="" src="http://www.ibm.com/developerworks/cn/java/l-jfreechart/images/image001.gif" /> <br />
            <br />
            </span><a name="N10056"><strong><span style="color: #808000">图2</span></strong></a><br />
            <span style="color: #808000"><img alt="" src="http://www.ibm.com/developerworks/cn/java/l-jfreechart/images/image002.gif" /> <br />
            <br />
            </span><a name="N10063"><strong><span style="color: #808000">图3</span></strong></a><br />
            <span style="color: #808000"><img alt="" src="http://www.ibm.com/developerworks/cn/java/l-jfreechart/images/image003.gif" /> <br />
            </span>
            <p><span style="color: #808000">上面的三个图都是表示四个季度的某个产品的销量信息。在继续下面小节之前必须先准备好开发环境，因为是基于WEB浏览器的图表展现，因此需要一个Servlet引擎或者是J2EE应用服务器（例如WebSphere，Tomcat等）。WEB环境的搭建就不累赘了，读者根据喜好自行安装。JFreeChart引擎本身需要到SourceForge.net上下载，地址如下： </span></p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode"><span style="color: #808000">JFreeChart主页：
                        </span><a href="http://www.jfree.org/jfreechart/index.html" cmimpressionsent="1"><span style="color: #808000">http://www.jfree.org/jfreechart/index.html</span></a>
                        <span style="color: #808000">JFreeChart下载页面：
                        </span><a href="http://sourceforge.net/projects/jfreechart/" cmimpressionsent="1"><span style="color: #808000">http://sourceforge.net/projects/jfreechart/</span></a>
                        <span style="color: #808000">
                        </span></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p><span style="color: #808000">下载的时候需要注意的是必须下载两个文件：JFreeChart以及Jcommon。目前最新配套版本是：JFreeChart 0.9.11 Jcommon 0.8.6 </span></p>
            <p><span style="color: #808000">这里有点笔者在开发中遇见的问题需要注意的是：在使用Eclipse开发的时候会报一个莫名其妙的错误，错误可能指向某个类文件的第一行。遇到这样的问题一般是因为没有把Jcommon的jar包设置到项目的类路径中的缘故。具体的原因不祥。 </span></p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><span style="color: #808000"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></span></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><span style="color: #808000"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </span>
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><span style="color: #808000"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </span></td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/l-jfreechart/index.html#main" cmimpressionsent="1"><strong><span style="color: #808000">回页首</span></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="2"><span class="atitle"><span style="color: #808000">解读JFreeChart的源码结构</span></span></a></p>
            <p><span style="color: #808000">在开始使用JFreeChart之前我们有必要先大概了解一下JFreeChart本身的结构以及它所带一些例子程序，这样有助于我们下一步自行开发。下载JFreeChart包后已经带有非常丰富的例子，因为JFreeChart这个项目本身的使用文档非常少，因此学习它最好的办法就是学习它所带的例子源码。在包org.jfree.chart.demo中有几十个文件用于展示JFreeChart所能支持的所有图表的结果。如果你的JDK是比较新的情况下可能在运行这些例子时会有问题，现象如下： </span></p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode"><span style="color: #808000">java.lang.UnsatisfiedLinkError: initDDraw
                        at sun.awt.windows.Win32OffScreenSurfaceData.initDDraw(Native Method)
                        at sun.awt.windows.Win32OffScreenSurfaceData.&lt;clinit&gt;(Win32OffScreenSurfaceData.java:141)
                        <!-- code sample is too wide -->	at sun.awt.Win32GraphicsDevice.&lt;clinit&gt;(Win32GraphicsDevice.java:58)
                        at sun.awt.Win32GraphicsEnvironment.makeScreenDevice(Win32GraphicsEnvironment.java:168)
                        <!-- code sample is too wide -->	at sun.java2d.SunGraphicsEnvironment.getScreenDevices(SunGraphicsEnvironment.java:240)
                        <!-- code sample is too wide -->	at sun.awt.Win32GraphicsEnvironment.getDefaultScreenDevice(Win32GraphicsEnvironment.java:61)
                        <!-- code sample is too wide -->	at java.awt.Window.init(Window.java:224)
                        at java.awt.Window.&lt;init&gt;(Window.java:268)
                        at java.awt.Frame.&lt;init&gt;(Frame.java:398)
                        at javax.swing.JFrame.&lt;init&gt;(JFrame.java:198)
                        at org.jfree.chart.demo.JFreeChartDemo.&lt;init&gt;(JFreeChartDemo.java:148)
                        at org.jfree.chart.demo.JFreeChartDemo.main(JFreeChartDemo.java:285)
                        Exception in thread "main"
                        </span></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p><span style="color: #808000">这个错误是由于新版的Swing大量的使用了微软的DirectDraw的技术来提高画图的性能，而可能你的显卡在这时候会跟你闹点情绪或者显卡本身并不支持这样的一个技术。难道就没有办法了嘛？要解决这个问题也非常简单，我们可以屏蔽掉DirectDraw，不让Swing使用该技术就可以了。在运行这些代码时给虚拟机指定参数-Dsun.java2d.noddraw即可。 </span></p>
            <p><span style="color: #808000">这时可能你又该纳闷了，不说是基于Web的图表嘛，怎么又扯到Swing上了？这是因为为了使开发者容易上手，无需配置任何运行环境，所以这些例子都是基于GUI方式的用于展现给开发者如果生成一个图表，我们要学习的也就是如何利用这个引擎生成图表而不是怎么来显示一个图表。当我们把生成的图表对象Export到一个图像文件即可在Web上发布。 </span></p>
            <p><span style="color: #808000">下面我们来介绍JFreeChart中几个核心的对象类：</span></p>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr bgcolor="#99ccff">
                        <td width="30%"><span style="color: #808000">类名</span></td>
                        <td width="70%"><span style="color: #808000">类的作用以及简单描述</span></td>
                    </tr>
                    <tr>
                        <td><span style="color: #808000">JFreeChart</span></td>
                        <td><span style="color: #808000">图表对象，任何类型的图表的最终表现形式都是在该对象进行一些属性的定制。JFreeChart引擎本身提供了一个工厂类用于创建不同类型的图表对象</span></td>
                    </tr>
                    <tr>
                        <td><span style="color: #808000">XXXXXDataset</span></td>
                        <td><span style="color: #808000">数据集对象，用于提供显示图表所用的数据。根据不同类型的图表对应着很多类型的数据集对象类</span></td>
                    </tr>
                    <tr>
                        <td><span style="color: #808000">XXXXXPlot</span></td>
                        <td><span style="color: #808000">图表区域对象，基本上这个对象决定着什么样式的图表，创建该对象的时候需要Axis、Renderer以及数据集对象的支持</span></td>
                    </tr>
                    <tr>
                        <td><span style="color: #808000">XXXXXAxis</span></td>
                        <td><span style="color: #808000">用于处理图表的两个轴：纵轴和横轴</span></td>
                    </tr>
                    <tr>
                        <td><span style="color: #808000">XXXXXRenderer</span></td>
                        <td><span style="color: #808000">负责如何显示一个图表对象</span></td>
                    </tr>
                    <tr>
                        <td><span style="color: #808000">XXXXXURLGenerator</span></td>
                        <td><span style="color: #808000">用于生成Web图表中每个项目的鼠标点击链接</span></td>
                    </tr>
                    <tr>
                        <td><span style="color: #808000">XXXXXToolTipGenerator</span></td>
                        <td><span style="color: #808000">用于生成图象的帮助提示，不同类型图表对应不同类型的工具提示类</span></td>
                    </tr>
                </tbody>
            </table>
            <p><span style="color: #808000">基本上我认为JFreeChart项目本身的类结构的设计并不是很好，首先在创建图表的时候用到了大量的工厂方法，这样做虽然可以简化创建图表对象的代码，但是对项目本身或者开发人员来讲自行扩展一种新的图表都仍然是一件很麻烦的事情；其次除图表对象本身外其余的类过于复杂，使用者必须去了解每个类型的图表对象应该对应哪些Axis、Plot、Renderer类，并且必须非常熟悉这些类的构造函数中每个参数的具体含义。这些问题都大大困扰很多初学者。不过，虽然存在很多问题，但是JFreeChart本身仍不失为一个非常优秀的图表引擎，况且项目本身也在逐渐的发展中。 </span></p>
            <p><span style="color: #808000">在非常简略的介绍了JFreeChart本身的代码结构后，下面我们开始动手试验几个常用的图表并把他们放到web上。 </span></p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><span style="color: #808000"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></span></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><span style="color: #808000"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </span>
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><span style="color: #808000"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </span></td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/l-jfreechart/index.html#main" cmimpressionsent="1"><strong><span style="color: #808000">回页首</span></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="3"><span class="atitle"><span style="color: #808000">使用JFreeChart生成各种样式的图表</span></span></a></p>
            <p><span style="color: #808000">限于篇幅的问题我们在这里只实现两种常用的图表，其他类型图表读者可以触类旁通。我们先给出柱状图的实现，饼图的实现再来跟柱状图进行比较。 </span></p>
            <p><a name="N100FA"><span class="smalltitle"><span style="color: #808000">1 柱状图</span></span></a></p>
            <p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode"><span style="color: #808000">package lius.chart.demo;
                        import java.io.*;
                        import org.jfree.data.*;
                        import org.jfree.chart.*;
                        import org.jfree.chart.plot.*;
                        /**
                        * 该类用于演示最简单的柱状图生成
                        * @author Winter Lau
                        */
                        public class BarChartDemo {
                        public static void main(String[] args) throws IOException{
                        CategoryDataset dataset = getDataSet2();
                        JFreeChart chart = ChartFactory.createBarChart3D(
                        "水果产量图", // 图表标题
                        "水果", // 目录轴的显示标签
                        "产量", // 数值轴的显示标签
                        dataset, // 数据集
                        PlotOrientation.VERTICAL, // 图表方向：水平、垂直
                        <!-- code sample is too wide -->							true, 	// 是否显示图例(对于简单的柱状图必须是false)
                        <!-- code sample is too wide -->							false, 	// 是否生成工具
                        false 	// 是否生成URL链接
                        );
                        FileOutputStream fos_jpg = null;
                        try {
                        fos_jpg = new FileOutputStream("D:\\fruit.jpg");
                        ChartUtilities.writeChartAsJPEG(fos_jpg,100,chart,400,300,null);
                        } finally {
                        try {
                        fos_jpg.close();
                        } catch (Exception e) {}
                        }
                        }
                        /**
                        * 获取一个演示用的简单数据集对象
                        * @return
                        */
                        private static CategoryDataset getDataSet() {
                        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
                        dataset.addValue(100, null, "苹果");
                        dataset.addValue(200, null, "梨子");
                        dataset.addValue(300, null, "葡萄");
                        dataset.addValue(400, null, "香蕉");
                        dataset.addValue(500, null, "荔枝");
                        return dataset;
                        }
                        /**
                        * 获取一个演示用的组合数据集对象
                        * @return
                        */
                        private static CategoryDataset getDataSet2() {
                        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
                        dataset.addValue(100, "北京", "苹果");
                        dataset.addValue(100, "上海", "苹果");
                        dataset.addValue(100, "广州", "苹果");
                        dataset.addValue(200, "北京", "梨子");
                        dataset.addValue(200, "上海", "梨子");
                        dataset.addValue(200, "广州", "梨子");
                        dataset.addValue(300, "北京", "葡萄");
                        dataset.addValue(300, "上海", "葡萄");
                        dataset.addValue(300, "广州", "葡萄");
                        dataset.addValue(400, "北京", "香蕉");
                        dataset.addValue(400, "上海", "香蕉");
                        dataset.addValue(400, "广州", "香蕉");
                        dataset.addValue(500, "北京", "荔枝");
                        dataset.addValue(500, "上海", "荔枝");
                        dataset.addValue(500, "广州", "荔枝");
                        return dataset;
                        }
                        }
                        </span></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p><span style="color: #808000">程序运行结束后生成的图片文件效果如下图所示：</span></p>
            <br />
            <a name="N1010B"><strong><span style="color: #808000">图4</span></strong></a><br />
            <span style="color: #808000"><img alt="" src="http://www.ibm.com/developerworks/cn/java/l-jfreechart/images/image004.gif" /> <br />
            </span>
            <p><span style="color: #808000">如果是使用简单的数据即使用getDataSet方法获取数据集时产生的图片文件如下：</span></p>
            <br />
            <a name="N1011B"><strong><span style="color: #808000">图5</span></strong></a><br />
            <span style="color: #808000"><img alt="" src="http://www.ibm.com/developerworks/cn/java/l-jfreechart/images/image005.gif" /> <br />
            </span>
            <p><a name="N10126"><span class="smalltitle"><span style="color: #808000">2 饼图</span></span></a></p>
            <p>
            <p><span style="color: #808000">对于饼图而言，数据集的获取用的不是同一个数据集类，另外饼图不支持同一个类别的项目中还有子项目这样的数据。我们只给出创建饼图的代码，至于写图表到一个文件则与柱状图一致，无需重复。 </span></p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode"><span style="color: #808000">package lius.chart.demo;
                        import java.io.*;
                        import org.jfree.data.*;
                        import org.jfree.chart.*;
                        /**
                        * 用于演示饼图的生成
                        * @author Winter Lau
                        */
                        public class PieChartDemo {
                        public static void main(String[] args) throws IOException{
                        DefaultPieDataset data = getDataSet();
                        JFreeChart chart = ChartFactory.createPie3DChart("水果产量图",  // 图表标题
                        data,
                        true, // 是否显示图例
                        false,
                        false
                        );
                        //写图表对象到文件，参照柱状图生成源码
                        }
                        /**
                        * 获取一个演示用的简单数据集对象
                        * @return
                        */
                        private static DefaultPieDataset getDataSet() {
                        DefaultPieDataset dataset = new DefaultPieDataset();
                        dataset.setValue("苹果",100);
                        dataset.setValue("梨子",200);
                        dataset.setValue("葡萄",300);
                        dataset.setValue("香蕉",400);
                        dataset.setValue("荔枝",500);
                        return dataset;
                        }
                        }
                        </span></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p><span style="color: #808000">生成的饼图文件效果如下： </span></p>
            <br />
            <a name="N1013A"><strong><span style="color: #808000">图6</span></strong></a><br />
            <span style="color: #808000"><img alt="" src="http://www.ibm.com/developerworks/cn/java/l-jfreechart/images/image006.gif" /> <br />
            <br />
            </span>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><span style="color: #808000"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></span></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><span style="color: #808000"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </span>
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><span style="color: #808000"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </span></td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/l-jfreechart/index.html#main" cmimpressionsent="1"><strong><span style="color: #808000">回页首</span></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="4"><span class="atitle"><span style="color: #808000">将生成的图表移到浏览器上</span></span></a></p>
            <p><span style="color: #808000">为了将生成的图表直接传给客户端浏览器，只需要将前面两个例子中的文件流换成是通过HttpServletResponse对象获取到的输出流，详细代码清单如下： </span></p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode"><span style="color: #808000">package lius.chart.demo;
                        import java.io.IOException;
                        import javax.servlet.*;
                        import javax.servlet.http.HttpServlet;
                        import org.jfree.data.*;
                        import org.jfree.chart.*;
                        /**
                        * 演示通过servlet直接输出图表
                        * @author Winter Lau
                        */
                        public class ChartDemoServlet extends HttpServlet {
                        public void service(ServletRequest req, ServletResponse res)
                        throws ServletException, IOException
                        {
                        res.setContentType("image/jpeg");
                        DefaultPieDataset data = getDataSet();
                        JFreeChart chart = ChartFactory.createPie3DChart("水果产量图",
                        data,
                        true,
                        false,
                        false
                        );
                        ChartUtilities.writeChartAsJPEG(res.getOutputStream(),
                        100,chart,400,300,null);
                        }
                        /**
                        * 获取一个演示用的简单数据集对象
                        * @return
                        */
                        private static DefaultPieDataset getDataSet() {
                        DefaultPieDataset dataset = new DefaultPieDataset();
                        dataset.setValue("苹果",100);
                        dataset.setValue("梨子",200);
                        dataset.setValue("葡萄",300);
                        dataset.setValue("香蕉",400);
                        dataset.setValue("荔枝",500);
                        return dataset;
                        }
                        }
                        </span></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><span style="color: #808000"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></span></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><span style="color: #808000"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </span>
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><span style="color: #808000"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </span></td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/l-jfreechart/index.html#main" cmimpressionsent="1"><strong><span style="color: #808000">回页首</span></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="5"><span class="atitle"><span style="color: #808000">高级主题</span></span></a></p>
            <p><span style="color: #808000">很多情况我们不仅仅要求可以在浏览器上显示一个图表，我们更需要客户可以直接在图表上做一下交互的操作，例如获取信息提示，点击图表某个部分进行更详细信息的展示等等。例如前面生成的简单柱状图，用户需要在看到柱状图后点击某种水果例如是苹果即可看到各个地区苹果产量的情况。为此就要求该图形具有交互操作的功能。在HTML中为了让一个图像具有可交互的功能就必须给该图像定义一个Map对象。下表节选一段具有该功能的HTML代码 </span></p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode"><span style="color: #808000">&lt;MAP NAME="chartMap"&gt;
                        &lt;AREA SHAPE="RECT" COORDS="81,15,126,254" href="?series=0&amp;category=100" title="100 = 7,048"
                        <!-- code sample is too wide -->	onclick="javascript:clickChart('100');return false;"&gt;
                        &lt;AREA SHAPE="RECT" COORDS="143,27,188,255" href="?series=0&amp;category=200" title="200 = 6,721"
                        <!-- code sample is too wide -->	onclick="javascript: clickChart ('200');return false;"&gt;
                        &lt;AREA SHAPE="RECT" COORDS="205,54,250,255" href="?series=0&amp;category=300" title="300 = 5,929"
                        <!-- code sample is too wide -->	onclick="javascript: clickChart ('300');return false;"&gt;
                        &lt;AREA SHAPE="RECT" COORDS="267,85,312,255" href="?series=0&amp;category=400" title="400 = 5,005"
                        <!-- code sample is too wide -->	onclick="javascript: clickChart ('400');return false;"&gt;
                        &lt;AREA SHAPE="RECT" COORDS="329,17,374,255" href="?series=0&amp;category=Diet" title="Diet = 7,017" onclick="javascript:
                        <!-- code sample is too wide -->	clickChart ('Diet');return false;"&gt;
                        &lt;/MAP&gt;
                        </span></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p><span style="color: #808000">由此就产生了一个问题：如果根据一个图像来生成对应的MAP对象。我们回头看看刚才的代码，在创建一个图表对象时候有两个参数，我们举柱状图的例子来讲这两个参数就是ChartFactory. createBarChart3D方法中的最后两个参数，这两个参数的类型都是布尔值。这两个参数意思分别是：是否创建工具提示(tooltip)以及是否生成URL。这两个参数分别对应着MAP中一个AREA的title属性以及href属性。 </span></p>
            <p><span style="color: #808000">可是我想知道的是怎么来产生这个MAP啊！哈哈，不要着急，JFreeChart已经帮我们做好生成MAP对象的功能。为了生成MAP对象就要引入另外一个对象：ChartRenderingInfo。因为JFreeChart没有直接的方法利用一个图表对象直接生成MAP数据，它需要一个中间对象来过渡，这个对象就是ChartRenderingInfo。下图是生成MAP数据的流程图： </span></p>
            <br />
            <a name="N10167"><strong><span style="color: #808000">图7</span></strong></a><br />
            <span style="color: #808000"><img alt="" src="http://www.ibm.com/developerworks/cn/java/l-jfreechart/images/image007.gif" /> <br />
            </span>
            <p><span style="color: #808000">如上图所示，ChartUtilities类是整个流程的核心，它周围的对象都是一些例如数据对象或者是文件等。这个流程简单描述如下：首先创建一个ChartRenderingInfo对象并在调用ChartUtilities的writeChartAsJPEG时作为最后一个参数传递进去。调用该方法结束后将产生一个图像文件以及一个填充好MAP数据的ChartRenderingInfo对象，有了这个对象我们还是没有办法获取具体的MAP数据，我们还必须借助于ChartUtilities的writeImageMap方法来将ChartRenderingInfo对象读取出来，获取MAP数据的代码片断如下： </span></p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode"><span style="color: #808000">		PrintWriter w = null;
                        FileOutputStream fos_jpg = null;
                        FileOutputStream fos_cri = null;
                        try{
                        //根据不同类型的图表使用不同类，以下是针对饼图的操作
                        PiePlot plot = (PiePlot) chart.getPlot();
                        plot.setURLGenerator(new StandardPieURLGenerator(url));
                        //设置工具提示
                        plot.setToolTipGenerator(new StandardPieToolTipGenerator());
                        fos_jpg = new FileOutputStream(&#8220;d:\\fruit.jpg&#8221;);
                        ChartUtilities.writeChartAsJPEG(
                        fos_jpg,
                        100,
                        chart,
                        400,
                        300,
                        info);
                        fos_cri = new FileOutputStream(__d:\\fruit.map__);
                        w = new PrintWriter(fos_cri);
                        ChartUtilities.writeImageMap(w, __mapname__, info);
                        w.flush();
                        }finally{
                        try{
                        w.close();
                        }catch(Exception e){}
                        try{
                        fos_cri.close();
                        }catch(Exception e){}
                        try{
                        fos_jpg.close();
                        }catch(Exception e){}
                        }
                        </span></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p><span style="color: #808000">打开文件D:\fruit.map，文件的内容就是要写到页面上的MAP数据。把生成的图像文件以及MAP数据文件写到页面上即可完成热点图表的功能。至于怎么结合两者之间的关系例如图像的useMap属性值必须与MAP对象的名称结合起来，必须根据实际的应用情况进行相应的处理。笔者建议把二者通过标签库封装起来，图像文件的名称以及MAP对象的名称由标签库统一进行控制，这样可以保证二者的一致性。 </span></p>
            <br />
            <br />
            <p><a name="resources"><span class="atitle"><span style="color: #808000">参考资料 </span></span></a></p>
            <ul>
                <li><a href="http://www.jfree.org/jfreechart/index.html" cmimpressionsent="1"><span style="color: #808000">JFreeChart图表引擎首页</span></a><span style="color: #808000"> <br />
                <br />
                </span>
                <li><a href="http://cewolf.sourceforge.net/" cmimpressionsent="1"><span style="color: #808000">Cewolf自定义图表标签库</span></a><span style="color: #808000"> <br />
                </span></li>
            </ul>
            <br />
            <br />
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230261.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-21 15:00 <a href="http://www.blogjava.net/jasonwbd/articles/230261.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘要] JAVA反射机制是在运行状态中，对于任意一个类，都能够知道这个类的所有属性和方法；对于任意一个对象，都能够调用它的任意一个方法...</title><link>http://www.blogjava.net/jasonwbd/articles/230086.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 01:13:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230086.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230086.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230086.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230086.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230086.html</trackback:ping><description><![CDATA[<div class="ciodigest"><span style="color: #808000"><strong>[摘要] </strong>Enum作为Sun全新引进的一个关键字，看起来很象是特殊的class, 它也可以有自己的变量，可以定义自己的方法，可以实现一个或者多个接口。 <br />
<strong></strong>[关键字] </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=JAVA&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">JAVA</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=JDK&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">JDK</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=%C3%B6%BE%D9&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">枚举</span></a><span style="color: #808000"> </span></div>
<div class="contenttxt"><span style="color: #808000">　　Enum作为Sun全新引进的一个关键字，看起来很象是特殊的class, 它也可以有自己的变量，可以定义自己的方法，可以实现一个或者多个接口。 当我们在声明一个enum类型时，我们应该注意到enum类型有如下的一些特征。 <br />
<br />
　　1．它不能有public的构造函数，这样做可以保证客户代码没有办法新建一个enum的实例。 <br />
<br />
　　2．所有枚举值都是public , static , final的。注意这一点只是针对于枚举值，我们可以和在普通类里面定义 变量一样定义其它任何类型的非枚举变量，这些变量可以用任何你想用的修饰符。 <br />
<br />
　　3．Enum默认实现了java.lang.Comparable接口。 <br />
<br />
　　4．Enum覆载了了toString方法，因此我们如果调用Color.Blue.toString()默认返回字符串&#8221;Blue&#8221;. <br />
<br />
　　5．Enum提供了一个valueOf方法，这个方法和toString方法是相对应的。调用valueOf(&#8220;Blue&#8221;)将返回Color.Blue.因此我们在自己重写toString方法的时候就要注意到这一点，一把来说应该相对应地重写valueOf方法。 <br />
<br />
　　6．Enum还提供了values方法，这个方法使你能够方便的遍历所有的枚举值。 <br />
<br />
　　7．Enum还有一个oridinal的方法，这个方法返回枚举值在枚举类种的顺序，这个顺序根据枚举值声明的顺序而定，这里Color.Red.ordinal()返回0。 <br />
<br />
　　了解了这些基本特性，我们来看看如何使用它们。 <br />
<br />
　　1．遍历所有有枚举值. 知道了有values方法，我们可以轻车熟路地用ForEach循环来遍历了枚举值了。 <br />
<br />
　　for (Color c: Color.values()) <br />
<br />
　　System.out.println(&#8220;find value:&#8221; + c); <br />
<br />
　　2．在enum中定义方法和变量，比如我们可以为Color增加一个方法随机返回一个颜色。 <br />
<br />
　　public enum Color { <br />
<br />
　　Red, <br />
<br />
　　Green, <br />
<br />
　　Blue; <br />
<br />
　　/* <br />
<br />
　　*定义一个变量表示枚举值的数目。 <br />
<br />
　　*(我有点奇怪为什么sun没有给enum直接提供一个size方法). <br />
<br />
　　*/ <br />
<br />
　　private static int number = Color.values().length ; <br />
<br />
　　/** <br />
<br />
　　* 随机返回一个枚举值 <br />
<br />
　　@return a random enum value. <br />
<br />
　　*/ <br />
<br />
　　public static Color getRandomColor(){ <br />
<br />
　　long random = System.currentTimeMillis() % number; <br />
<br />
　　switch ((int) random){ <br />
<br />
　　case 0: <br />
<br />
　　return Color.Red; <br />
<br />
　　case 1: <br />
<br />
　　return Color.Green; <br />
<br />
　　case 2: <br />
<br />
　　return Color.Blue; <br />
<br />
　　default : return Color.Red; <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　可以看出这在枚举类型里定义变量和方法和在普通类里面定义方法和变量没有什么区别。唯一要注意的只是变量和方法定义必须放在所有枚举值定义的后面，否则编译器会给出一个错误。 <br />
<br />
　　3．覆载(Override)toString, valueOf方法 <br />
<br />
　　前面我们已经知道enum提供了toString,valueOf等方法，很多时候我们都需要覆载默认的toString方法，那么对于enum我们怎么做呢。其实这和覆载一个普通class的toString方法没有什么区别。 <br />
<br />
　　&#8230;. <br />
<br />
　　public String toString(){ <br />
<br />
　　switch (this){ <br />
<br />
　　case Red: <br />
<br />
　　return "Color.Red"; <br />
<br />
　　case Green: <br />
<br />
　　return "Color.Green"; <br />
<br />
　　case Blue: <br />
<br />
　　return "Color.Blue"; <br />
<br />
　　default: <br />
<br />
　　return "Unknow Color"; <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　&#8230;. <br />
<br />
　　这时我们可以看到，此时再用前面的遍历代码打印出来的是 <br />
<br />
　　Color.Red <br />
<br />
　　Color.Green <br />
<br />
　　Color.Blue <br />
<br />
　　而不是 <br />
<br />
　　Red <br />
<br />
　　Green <br />
<br />
　　Blue. <br />
<br />
　　可以看到toString确实是被覆载了。一般来说在覆载toString的时候我们同时也应该覆载valueOf方法，以保持它们相互的一致性。 <br />
<br />
　　4．使用构造函数 <br />
<br />
　　虽然enum不可以有public的构造函数，但是我们还是可以定义private的构造函数，在enum内部使用。还是用Color这个例子。 <br />
<br />
　　public enum Color { <br />
<br />
　　Red("This is Red"), <br />
<br />
　　Green("This is Green"), <br />
<br />
　　Blue("This is Blue"); <br />
<br />
　　private String desc; <br />
<br />
　　Color(String desc){ <br />
<br />
　　this.desc = desc; <br />
<br />
　　} <br />
<br />
　　public String getDesc(){ <br />
<br />
　　return this.desc; <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　这里我们为每一个颜色提供了一个说明信息, 然后定义了一个构造函数接受这个说明信息。 <br />
<br />
　　要注意这里构造函数不能为public或者protected, 从而保证构造函数只能在内部使用，客户代码不能new一个枚举值的实例出来。这也是完全符合情理的，因为我们知道枚举值是public static final的常量而已。 <br />
<br />
　　5．实现特定的接口 <br />
<br />
　　我们已经知道enum可以定义变量和方法，它要实现一个接口也和普通class实现一个接口一样，这里就不作示例了。 <br />
<br />
　　6．定义枚举值自己的方法。 <br />
<br />
　　前面我们看到可以为enum定义一些方法，其实我们甚至可以为每一个枚举值定义方法。这样，我们前面覆载 toString的例子可以被改写成这样。 <br />
<br />
　　public enum Color { <br />
<br />
　　Red { <br />
<br />
　　public String toString(){ <br />
<br />
　　return "Color.Red"; <br />
<br />
　　} <br />
<br />
　　}, <br />
<br />
　　Green { <br />
<br />
　　public String toString(){ <br />
<br />
　　return "Color.Green"; <br />
<br />
　　} <br />
<br />
　　}, <br />
<br />
　　Blue{ <br />
<br />
　　public String toString(){ <br />
<br />
　　return "Color.Blue"; <br />
<br />
　　} <br />
<br />
　　}; <br />
<br />
　　} <br />
<br />
　　从逻辑上来说这样比原先提供一个&#8220;全局&#8220;的toString方法要清晰一些。 <br />
<br />
　　总的来说，enum作为一个全新定义的类型，是希望能够帮助程序员写出的代码更加简单易懂，个人觉得一般也不需要过多的使用enum的一些高级特性，否则就和简单易懂的初衷想违背了。</span><a href="http://www.enet.com.cn/"><span style="color: #808000"><img height="11" src="http://images.enet.com.cn/end.gif" width="11" align="absMiddle" border="0" target="_blank"  alt="" /></span></a></div>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230086.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 09:13 <a href="http://www.blogjava.net/jasonwbd/articles/230086.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘要] 在开发中，经常遇到诸如省、市，大类、小类的级联select 下拉框。常常，这些类别或地区的内容，又存在数据库中。这里建议，通过IO，将类别生成js文件，然后在页面中引入这个js文件，这样即提高的程序的运用速度，又精简了的代码书写量。</title><link>http://www.blogjava.net/jasonwbd/articles/230085.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 01:12:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230085.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230085.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230085.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230085.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230085.html</trackback:ping><description><![CDATA[<div class="ciodigest"><span style="color: #808000"><strong>[摘要] </strong>JAVA反射机制是在运行状态中，对于任意一个类，都能够知道这个类的所有属性和方法；对于任意一个对象，都能够调用它的任意一个方法...<br />
<strong></strong>[关键字] </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=JAVA&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">JAVA</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=%B7%B4%C9%E4%BB%FA%D6%C6&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">反射机制</span></a><span style="color: #808000"> </span></div>
<div class="contenttxt"><span style="color: #808000">　　JAVA反射机制 <br />
<br />
　　JAVA反射机制是在运行状态中，对于任意一个类，都能够知道这个类的所有属性和方法；对于任意一个对象，都能够调用它的任意一个方法；这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 <br />
<br />
　　Java反射机制主要提供了以下功能： 在运行时判断任意一个对象所属的类；在运行时构造任意一个类的对象；在运行时判断任意一个类所具有的成员变量和方法；在运行时调用任意一个对象的方法；生成动态代理。 <br />
<br />
　　1. 得到某个对象的属性 <br />
<br />
　　1 public Object getProperty(Object owner, String fieldName) throws Exception { <br />
<br />
　　2 Class ownerClass = owner.getClass(); <br />
<br />
　　3 <br />
<br />
　　4 Field field = ownerClass.getField(fieldName); <br />
<br />
　　5 <br />
<br />
　　6 Object property = field.get(owner); <br />
<br />
　　7 <br />
<br />
　　8 return property; <br />
<br />
　　9 } <br />
<br />
　　Class ownerClass = owner.getClass()：得到该对象的Class。 <br />
<br />
　　Field field = ownerClass.getField(fieldName)：通过Class得到类声明的属性。 <br />
<br />
　　Object property = field.get(owner)：通过对象得到该属性的实例，如果这个属性是非公有的，这里会报IllegalAccessException。 <br />
<br />
　　2. 得到某个类的静态属性 <br />
<br />
　　1 public Object getStaticProperty(String className, String fieldName) <br />
<br />
　　2 throws Exception { <br />
<br />
　　3 Class ownerClass = Class.forName(className); <br />
<br />
　　4 <br />
<br />
　　5 Field field = ownerClass.getField(fieldName); <br />
<br />
　　6 <br />
<br />
　　7 Object property = field.get(ownerClass); <br />
<br />
　　8 <br />
<br />
　　9 return property; <br />
<br />
　　10 } <br />
<br />
　　Class ownerClass = Class.forName(className) ：首先得到这个类的Class。 <br />
<br />
　　Field field = ownerClass.getField(fieldName)：和上面一样，通过Class得到类声明的属性。 <br />
<br />
　　Object property = field.get(ownerClass) ：这里和上面有些不同，因为该属性是静态的，所以直接从类的Class里取。 <br />
<br />
　　3. 执行某对象的方法 <br />
<br />
　　1 public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception { <br />
<br />
　　2 <br />
<br />
　　3 Class ownerClass = owner.getClass(); <br />
<br />
　　4 <br />
<br />
　　5 Class[] argsClass = new Class[args.length]; <br />
<br />
　　6 <br />
<br />
　　7 for (int i = 0, j = args.length; i &lt; j; i++) { <br />
<br />
　　8 argsClass[i] = args[i].getClass(); <br />
<br />
　　9 } <br />
<br />
　　10 <br />
<br />
　　11 Method method = ownerClass.getMethod(methodName, argsClass); <br />
<br />
　　12 <br />
<br />
　　13 return method.invoke(owner, args); <br />
<br />
　　14 } <br />
<br />
　　Class owner_class = owner.getClass() ：首先还是必须得到这个对象的Class。 <br />
<br />
　　5～9行：配置参数的Class数组，作为寻找Method的条件。 <br />
<br />
　　Method method = ownerClass.getMethod(methodName, argsClass)：通过Method名和参数的Class数组得到要执行的Method。 <br />
<br />
　　method.invoke(owner, args)：执行该Method，invoke方法的参数是执行这个方法的对象，和参数数组。返回值是Object，也既是该方法的返回值。 <br />
<br />
　　4. 执行某个类的静态方法 <br />
<br />
　　1 public Object invokeStaticMethod(String className, String methodName, <br />
<br />
　　2 Object[] args) throws Exception { <br />
<br />
　　3 Class ownerClass = Class.forName(className); <br />
<br />
　　4 <br />
<br />
　　5 Class[] argsClass = new Class[args.length]; <br />
<br />
　　6 <br />
<br />
　　7 for (int i = 0, j = args.length; i &lt; j; i++) { <br />
<br />
　　8 argsClass[i] = args[i].getClass(); <br />
<br />
　　9 } <br />
<br />
　　10 <br />
<br />
　　11 Method method = ownerClass.getMethod(methodName, argsClass); <br />
<br />
　　12 <br />
<br />
　　13 return method.invoke(null, args); <br />
<br />
　　14 } <br />
<br />
　　基本的原理和实例3相同，不同点是最后一行，invoke的一个参数是null，因为这是静态方法，不需要借助实例运行。 <br />
<br />
　　5. 新建实例 <br />
<br />
　　1 <br />
<br />
　　2 public Object newInstance(String className, Object[] args) throws Exception { <br />
<br />
　　3 Class newoneClass = Class.forName(className); <br />
<br />
　　4 <br />
<br />
　　5 Class[] argsClass = new Class[args.length]; <br />
<br />
　　6 <br />
<br />
　　7 for (int i = 0, j = args.length; i &lt; j; i++) { <br />
<br />
　　8 argsClass[i] = args[i].getClass(); <br />
<br />
　　9 } <br />
<br />
　　10 <br />
<br />
　　11 Constructor cons = newoneClass.getConstructor(argsClass); <br />
<br />
　　12 <br />
<br />
　　13 return cons.newInstance(args); <br />
<br />
　　14 <br />
<br />
　　15 } <br />
<br />
　　这里说的方法是执行带参数的构造函数来新建实例的方法。如果不需要参数，可以直接使用newoneClass.newInstance()来实现。 <br />
<br />
　　Class newoneClass = Class.forName(className)：第一步，得到要构造的实例的Class。 <br />
<br />
　　第5～第9行：得到参数的Class数组。 <br />
<br />
　　Constructor cons = newoneClass.getConstructor(argsClass)：得到构造子。 <br />
<br />
　　cons.newInstance(args)：新建实例。 <br />
<br />
　　6. 判断是否为某个类的实例 <br />
<br />
　　1 public boolean isInstance(Object obj, Class cls) { <br />
<br />
　　2 return cls.isInstance(obj); <br />
<br />
　　3 } <br />
<br />
　　7. 得到数组中的某个元素 <br />
<br />
　　1 public Object getByArray(Object array, int index) { <br />
<br />
　　2 return Array.get(array,index); <br />
<br />
　　3 }</span><a href="http://www.enet.com.cn/"><span style="color: #808000"><img height="11" src="http://images.enet.com.cn/end.gif" width="11" align="absMiddle" border="0" target="_blank"  alt="" /></span></a><br />
</div>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230085.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 09:12 <a href="http://www.blogjava.net/jasonwbd/articles/230085.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java版通用JS级联</title><link>http://www.blogjava.net/jasonwbd/articles/230084.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 01:11:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230084.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230084.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230084.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230084.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230084.html</trackback:ping><description><![CDATA[<br />
<div class="ciodigest"><span style="color: #808000"><strong>[摘要] </strong>在开发中，经常遇到诸如省、市，大类、小类的级联select 下拉框。常常，这些类别或地区的内容，又存在数据库中。这里建议，通过IO，将类别生成js文件，然后在页面中引入这个js文件，这样即提高的程序的运用速度，又精简了的代码书写量。<br />
<strong></strong>[关键字] </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=Java&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">Java</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=JS&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">JS</span></a><span style="color: #808000"> </span></div>
<div class="contenttxt"><span style="color: #808000">　　在开发中，经常遇到诸如省、市，大类、小类的级联select 下拉框。常常，这些类别或地区的内容，又存在数据库中。因为用户希望，一切都是可控制的。那么，如果涉及到这种级联的地方，每次都人从库中读取，在JSP中要写很多代码去读表。另外，这种级联在修改数据的时候，应设置的选中项为库中所载，这也是需要写一些代码的。 <br />
<br />
</span></div>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230084.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 09:11 <a href="http://www.blogjava.net/jasonwbd/articles/230084.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java操作MySQL的中文处理方法</title><link>http://www.blogjava.net/jasonwbd/articles/230083.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 01:10:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230083.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230083.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230083.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230083.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230083.html</trackback:ping><description><![CDATA[<br />
<div class="ciodigest"><span style="color: #808000"><strong>[摘要] </strong>作者介绍了一种较为实用的Java操作MySQL的中文处理方法。<br />
<strong></strong>[关键字] </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=Java&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">Java</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=MySQL&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">MySQL</span></a><span style="color: #808000"> </span></div>
<div class="contenttxt"><span style="color: #808000">　　这是很头痛的问题，一直都是在困扰着我们。我有一个不算简单也不算难的方法，这是我一直在用的方式。 <br />
<br />
　　1、建立一个类，包括一个格式将中文转换为ISO8859-1编码的方法： <br />
<br />
　　publicclass Format2Chinese { <br />
<br />
　　public Format2Chinese() { <br />
<br />
　　} <br />
<br />
　　public String format2IS08859(String str) { <br />
<br />
　　try { <br />
<br />
　　if (str == null 　　 str.trim().equals("")) <br />
<br />
　　str = ""; <br />
<br />
　　else <br />
<br />
　　str = new String(str.getBytes("ISO8859-1")); <br />
<br />
　　 <br />
<br />
　　} catch (Exception e) { <br />
<br />
　　e.printStackTrace(); <br />
<br />
　　} <br />
<br />
　　return str; <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　2、你的bean里面这时就要加一些东西了，如下面这个简单的bean: <br />
<br />
　　publicclass Leavemsg <br />
<br />
　　{ <br />
<br />
　　public Leavemsg() { </span></div>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230083.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 09:10 <a href="http://www.blogjava.net/jasonwbd/articles/230083.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaClassLoader与Package机制</title><link>http://www.blogjava.net/jasonwbd/articles/230082.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230082.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230082.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230082.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230082.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230082.html</trackback:ping><description><![CDATA[<br />
<div class="ciodigest"><span style="color: #808000"><strong>[摘要] </strong>Java语言规定，在同一个包中的class，如果没有修饰符，默认为Package权限，包内的class都可以访问。但是这还不够准确。确切的说，只有由同一个ClassLoader装载的class才具有以上的Package权限。<br />
<strong></strong>[关键字] </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=JavaClassLoader&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">JavaClassLoader</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=Package&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">Package</span></a><span style="color: #808000"> </span></div>
<div class="contenttxt"><span style="color: #808000">　　为了深入了解Java的ClassLoader机制，我们先来做以下实验： <br />
<br />
　　package java.lang; <br />
<br />
　　public class Test { <br />
<br />
　　public static void main(String[] args) { <br />
<br />
　　char[] c = "1234567890".toCharArray(); <br />
<br />
　　String s = new String(0, 10, c); <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　String类有一个Package权限的构造函数String(int offset, int length, char[] array)，按照默认的访问权限，由于Test属于java.lang包，因此理论上应该可以访问String的这个构造函数。编译通过！执行时结果如下： <br />
<br />
　　Exception in thread "main" java.lang.SecurityException: Prohibited package name: <br />
<br />
　　java.lang <br />
<br />
　　at java.lang.ClassLoader.defineClass(Unknown Source) <br />
<br />
　　at java.security.SecureClassLoader.defineClass(Unknown Source) <br />
<br />
　　at java.net.URLClassLoader.defineClass(Unknown Source) <br />
<br />
　　at java.net.URLClassLoader.access$100(Unknown Source) <br />
<br />
　　at java.net.URLClassLoader$1.run(Unknown Source) <br />
<br />
　　at java.security.AccessController.doPrivileged(Native Method) <br />
<br />
　　at java.net.URLClassLoader.findClass(Unknown Source) <br />
<br />
　　at java.lang.ClassLoader.loadClass(Unknown Source) <br />
<br />
　　at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) <br />
<br />
　　at java.lang.ClassLoader.loadClass(Unknown Source) <br />
<br />
　　at java.lang.ClassLoader.loadClassInternal(Unknown Source) <br />
<br />
　　奇怪吧？要弄清为什么会有SecurityException，就必须搞清楚ClassLoader的机制。 <br />
<br />
　　Java的ClassLoader就是用来动态装载class的，ClassLoader对一个class只会装载一次，JVM使用的ClassLoader一共有4种： <br />
<br />
　　启动类装载器，标准扩展类装载器，类路径装载器和网络类装载器。 <br />
<br />
　　这4种ClassLoader的优先级依次从高到低，使用所谓的&#8220;双亲委派模型&#8221;。确切地说，如果一个网络类装载器被请求装载一个java.lang.Integer，它会首先把请求发送给上一级的类路径装载器，如果返回已装载，则网络类装载器将不会装载这个java.lang.Integer，如果上一级的类路径装载器返回未装载，它才会装载java.lang.Integer。 <br />
<br />
　　类似的，类路径装载器收到请求后（无论是直接请求装载还是下一级的ClassLoader上传的请求），它也会先把请求发送到上一级的标准扩展类装载器，这样一层一层上传，于是启动类装载器优先级最高，如果它按照自己的方式找到了java.lang.Integer，则下面的ClassLoader 都不能再装载java.lang.Integer，尽管你自己写了一个java.lang.Integer，试图取代核心库的java.lang.Integer是不可能的，因为自己写的这个类根本无法被下层的ClassLoader装载。 <br />
<br />
　　再说说Package权限。Java语言规定，在同一个包中的class，如果没有修饰符，默认为Package权限，包内的class都可以访问。但是这还不够准确。确切的说，只有由同一个ClassLoader装载的class才具有以上的Package权限。比如启动类装载器装载了java.lang.String，类路径装载器装载了我们自己写的java.lang.Test，它们不能互相访问对方具有Package权限的方法。这样就阻止了恶意代码访问核心类的Package权限方法。</span><a href="http://www.enet.com.cn/"><span style="color: #808000"><img height="11" src="http://images.enet.com.cn/end.gif" width="11" align="absMiddle" border="0" target="_blank"  alt="" /></span></a><br />
</div>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230082.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 09:09 <a href="http://www.blogjava.net/jasonwbd/articles/230082.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 处理事务精要</title><link>http://www.blogjava.net/jasonwbd/articles/230081.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 01:08:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230081.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230081.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230081.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230081.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230081.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<h1><span style="color: #808000">Java 处理事务精要</span></h1>
<p><span style="color: #808000">&nbsp;&nbsp;&nbsp;&nbsp;</span></p>
<div class="ciodigest"><span style="color: #808000"><strong>[摘要] </strong>有一个订单库存管理系统，每一次生成订单的同时我们都要消减库存。通常来说订单和库存在数据库里是分两张表来保存的：订单表，库存表。每一次追加一个订单实际上需要两步操作：在订单表中插入一条数据，同时修改库存的数据。<br />
<strong></strong>[关键字] </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=Java&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">Java</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=%CA%C2%CE%F1&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">事务</span></a><span style="color: #808000"> </span></div>
<div class="contenttxt"><span style="color: #808000">　　简单事务的概念 <br />
<br />
　　我不想从原理上说明什么是事务，应为那太枯燥了。我只想从一个简单的例子来说明什么是事务。 <br />
<br />
　　例如我们有一个订单库存管理系统，每一次生成订单的同时我们都要消减库存。通常来说订单和库存在数据库里是分两张表来保存的：订单表，库存表。每一次我们追加一个订单实际上需要两步操作：在订单表中插入一条数据，同时修改库存的数据。 <br />
<br />
　　这样问题来了，例如我们需要一个单位为10的订单，库存中有30件，理想的操作是我们在订单表中插入了一条单位为10的订单，之后将库存表中的数据修改为20。但是有些时候事情并不是总是按照你的想法发生，例如：在你修改库存的时候，数据库突然由于莫名其妙的原因无法连接上了。也就是说库存更新失败了。但是订单已经产生了，那么怎么办呢？没办法，只有手动的修改。所以最好的方式是将订单插入的操作和库存修改的操作绑定在一起，必须同时成功或者什么都不做。这就是事务。 <br />
<br />
　　Java如何处理事务呢？ <br />
<br />
　　我们从java.sql.Connection说起，Connection表示了一个和数据库的链接，可以通过Connection来对数据库操作。在通常情况是Connection的属性是自动提交的，也就是说每次的操作真的更新了数据库，真的无法回退了。针对上述的例子，一旦库存更新失败了，订单无法回退，因为订单真的插入到了数据库中。这并不是我们希望的。 <br />
<br />
　　我们希望的是：看起来成功了，但是没有真的操作数据库，知道我想让他真的发生。可以通过Connection的setAutoCommit（false）让Connection不自动提交你的数据，除非你真的想提交。那么如何让操作真的发生呢？可以使用Connection的commit方法。如何让操作回退呢？使用rollback方法。 <br />
<br />
　　例如： <br />
<br />
　　try{ <br />
<br />
　　Connection conn = getConnection（）; // 不管如何我们得到了链接 <br />
<br />
　　conn.setAutoCommit(false); <br />
<br />
　　// 插入订单 <br />
<br />
　　// 修改库存 <br />
<br />
　　conn.commit(); // 成功的情况下，提交更新。 <br />
<br />
　　} catch(SQLException ex) { <br />
<br />
　　conn.rollback(); // 失败的情况下，回滚所有的操作 <br />
<br />
　　} finally { <br />
<br />
　　conn.close(); <br />
<br />
　　} <br />
<br />
　　这里有一点非常重要，事务是基于数据库链接的。所以在但数据库的情况下，事务操作很简单。 <br />
<br />
　　那么如果表分布在两个不同的数据库中呢？ <br />
<br />
　　例如订单表在订单库中，库存表在库存库中，那么我们如何处理这样的事务呢？ <br />
<br />
　　需要注意，提交也可以遇到错误呀！ <br />
<br />
　　try{ <br />
<br />
　　Connection conn1 = getConnection1(); <br />
<br />
　　Connection conn2 = getConnection2(); <br />
<br />
　　// 基于conn1做插入操作 <br />
<br />
　　// 基于conn2做更新操作 <br />
<br />
　　try{ <br />
<br />
　　conn1.commit（） <br />
<br />
　　} catch(SQLExcetion ) { <br />
<br />
　　conn1.rollback(); <br />
<br />
　　} <br />
<br />
　　try { <br />
<br />
　　conn2.commit(); <br />
<br />
　　} catch(SQLException ) { <br />
<br />
　　conn2.rollbakc(); <br />
<br />
　　// 保证肯定删除刚才插入的订单。 <br />
<br />
　　} <br />
<br />
　　} catch(SQLException ex) { <br />
<br />
　　// 如果插入失败，conn1.rollback <br />
<br />
　　// 如果更新失败，conn1.rollback &amp;&amp; conn2.rollback <br />
<br />
　　} finally { <br />
<br />
　　conn1.close(); <br />
<br />
　　conn2.close(); <br />
<br />
　　} <br />
<br />
　　看看上述的代码就知道，其实操作非常的复杂，甚至：保证肯定删除刚才插入的订单根本无法保证。 <br />
<br />
　　在上述情况下的事务可以称之为分布式事务，通过上述的代码中事务同时提交处理的部分我们可以得出，要想处理分布式事务，必须有独立于数据库的第三方的事务处理组件。 <br />
<br />
　　幸运的是通常情况下，JavaEE兼容的应用服务器，例如：Weblogic，Websphere，JBoss，Glassfish等都有这种分布式事务处理的组件。 <br />
<br />
　　如何使用应用服务器的分布式事务管理器处理分布式事务？ <br />
<br />
　　以galssfish为例 <br />
<br />
　　1 建立对应两个数据库的XA（javax.sql.XADataSource）类型的数据源。 <br />
<br />
　　2 使用UserTransaction来保证分布式事务。 <br />
<br />
　　try{ <br />
<br />
　　Connection conn1 = datasource1.getConnection(); <br />
<br />
　　Connection conn2 = datasource2.getConnection(); <br />
<br />
　　UserTransaction ut = getUserTransaction(); <br />
<br />
　　ut.begin(); <br />
<br />
　　// 插入订单 <br />
<br />
　　// 修改库存 <br />
<br />
　　ut.commit(); // 成功的情况下，提交更新。 <br />
<br />
　　} catch(SQLException ex) { <br />
<br />
　　ut.rollback(); // 失败的情况下，回滚所有的操作 <br />
<br />
　　} finally { <br />
<br />
　　conn.close(); <br />
<br />
　　} <br />
<br />
　　如何获取UserTransaction呢？可以使用如下方法 <br />
<br />
　　UserTransaction tx = (UserTransaction) <br />
<br />
　　ctx.lookup("jndi/UserTransaction"); </span><a href="http://www.enet.com.cn/"><span style="color: #808000"><img height="11" src="http://images.enet.com.cn/end.gif" width="11" align="absMiddle" border="0" target="_blank"  alt="" /></span></a><br />
</div>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230081.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 09:08 <a href="http://www.blogjava.net/jasonwbd/articles/230081.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何为Java程序中添加播放MIDI音乐功能</title><link>http://www.blogjava.net/jasonwbd/articles/230080.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 01:05:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230080.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230080.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230080.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230080.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230080.html</trackback:ping><description><![CDATA[<div class="ciodigest"><strong>[摘要] </strong>Java在多媒体处理方面的确优势不大，但是我们在程序中有些时候又需要一些音乐做为点缀，如果播放的音乐是wav等波形音频文件,又挺大,所以背景音乐最好就是MIDI了。<br />
<strong></strong>[关键字] <a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=Java&amp;ACondtion=keyword&amp;siteid=security" target="_blank">Java</a> <a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=%B2%A5%B7%C5&amp;ACondtion=keyword&amp;siteid=security" target="_blank">播放</a> <a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=MIDI&amp;ACondtion=keyword&amp;siteid=security" target="_blank">MIDI</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.enet.com.cn/article/2007/1015/A20071015868395.shtml">http://www.enet.com.cn/article/2007/1015/A20071015868395.shtml</a></div>
<div class="contenttxt">　　Java在多媒体处理方面的确优势不大，但是我们在程序中有些时候又需要一些音乐做为点缀，如果播放的音乐是wav等波形音频文件,又挺大,所以背景音乐最好就是MIDI了，可是网上很多播放MIDI的教程都是简单的几句话的例子，并且没有考虑资源的释放问题，如果程序长久运行的话,就会出现内存越耗越多的情况，以至于最后抛出一个java.lang.OutOfMemoryError，整个程序就挂了。 <br />
<br />
　　在MIDI的播放中，一个类是比较重要的，那就是MidiSystem类，它负责整个MIDI播放设备等的管理，其实就是Seqencer，它就是一个MIDI播放设置，用于播放MIDI序列的，还有一个类叫Seqence，它就是MIDI的序列,MIDI的序列可以自己由程序生成，也可以从文件中或者URL中读取。 <br />
<br />
　　下面是一个播放MIDI音乐功能实例： <br />
<br />
　　
<center><img height="575" alt="1" src="http://myarticle.enet.com.cn/images/2007/1015/1192408109630.jpg" width="537" border="0" /></center></div>
<center>&nbsp;</center>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230080.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 09:05 <a href="http://www.blogjava.net/jasonwbd/articles/230080.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>详细讲述Java中的克隆</title><link>http://www.blogjava.net/jasonwbd/articles/230079.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 01:01:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230079.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230079.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230079.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230079.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230079.html</trackback:ping><description><![CDATA[<br />
<div class="ciodigest"><span style="color: #808000"><strong>[摘要] </strong>经常听到有人说java中没有指针。事实如此吗？no，java是有指针的，只不过换了个名字而已，也就是我们经常提到的引用。<br />
<strong></strong>[关键字] </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=Java&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">Java</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=%BF%CB%C2%A1&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">克隆</span></a><span style="color: #808000"> </span></div>
<div class="contenttxt"><span style="color: #808000">　　经常听到有人说java中没有指针。事实如此吗？no，java是有指针的，只不过换了个名字而已，也就是我们经常提到的引用。我们知道，在java中一切都是对象，那么我们如何操控对象？如何在成千上万的对象中找到我们所需的那个对象呢？又是如何让对象按照我们的意思来完成任务的呢？ <br />
<br />
　　Object o = new Object()； <br />
<br />
　　这是java中最常见的语句了，在这句话中做了三件事。首先声明一个Object类型的变量o，在内存中为对象划分一块地址new Object（），将声明的变量指向内存中的对象。如此一来，我们就可以通过o来操纵对象了。就好像孩子们玩的遥控飞机，在空中飞行的是飞机，而使它做出优美动作的却是孩子们手中的摇控器。 <br />
<br />
　　"克隆"是如今听到的较多的词汇，听说已经将某只羊克隆了好几份了。但愿这种技术不要在人身上实验。java中也有"克隆"，与现实世界的克隆一样，将一个实际存在的对象拷贝几份。如下： <br />
<br />
　　//倒霉的羊 <br />
<br />
　　public class Sheep implements Cloneable{ <br />
<br />
　　private String name; <br />
<br />
　　public void setName(String arg) { <br />
<br />
　　name = arg; <br />
<br />
　　} <br />
<br />
　　public String getName() { <br />
<br />
　　return name; <br />
<br />
　　} <br />
<br />
　　public Object clone() throws CloneNotSupportedException { <br />
<br />
　　return super.clone(); <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　//克隆 <br />
<br />
　　public class Main { <br />
<br />
　　public static void main(String[] args) throws CloneNotSupportedException { <br />
<br />
　　Sheep sheep = new Sheep(); //先得到那只羊的实例 <br />
<br />
　　sheep.setName("我是真的"); //给它做个记号 <br />
<br />
　　System.out.println("sheep.getName() = " + sheep.getName()); <br />
<br />
　　Sheep sheepClone = (Sheep)sheep.clone(); //开始克隆 <br />
<br />
　　System.out.println("sheepClone.getName() = " + sheepClone.getName()); <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　运行程序结果为： <br />
<br />
　　sheep.getName() = 我是真的 <br />
<br />
　　sheepClone.getName() = 我是真的</span><a href="http://www.enet.com.cn/"><span style="color: #808000"><img height="11" src="http://images.enet.com.cn/end.gif" width="11" align="absMiddle" border="0" target="_blank"  alt="" /></span></a><br />
</div>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230079.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 09:01 <a href="http://www.blogjava.net/jasonwbd/articles/230079.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用缓冲IO提高Java程序性能</title><link>http://www.blogjava.net/jasonwbd/articles/230077.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 00:59:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230077.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230077.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230077.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230077.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230077.html</trackback:ping><description><![CDATA[<br />
<div class="ciodigest"><span style="color: #808000"><strong>[摘要] </strong>Java 输入/输出(IO)的性能可以使用标准的缓冲类提升，就像操作系统通过缓冲请求提高它的速度一样。<br />
<strong></strong>[关键字] </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=%BB%BA%B3%E5IO&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">缓冲IO</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=Java&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">Java</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=%D0%D4%C4%DC&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">性能</span></a><span style="color: #808000"> </span></div>
<div class="contenttxt"><span style="color: #808000">　　Java 输入/输出(IO)的性能可以使用标准的缓冲类提升，就像操作系统通过缓冲请求提高它的速度一样。例如，如果一段代码要求从磁盘上读取数据，它会试图读取内存中已有的数据；如果代码希望向磁盘写一些东西，它可能在完成写操作前将输出在内存中存放一段时间以等待更多的数据。 <br />
<br />
　　在Java的IO系统中，将一个字符写入内存比写到磁盘上快得多，例如： <br />
<br />
　　// 这段代码会抛出 IOException <br />
<br />
　　Writer writer = new FileWriter( new File( "file.txt" ) ); <br />
<br />
　　for(int i=0; i&lt;1000; i++) { <br />
<br />
　　writer.write(""+i); <br />
<br />
　　writer.write("\n"); <br />
<br />
　　} <br />
<br />
　　writer.close( ); <br />
<br />
　　在这个范例代码中，FileWriter 一次输出一个数字，在Apple Powerbook 上测量消耗的时间，第一次是180毫秒，以后是90毫秒，这个不同可能是JVM的即时（just-in-time）编译导致的。 <br />
<br />
　　给这段代码添加缓冲功能就是在FileWriter上创建一个BufferedWriter 对象。 <br />
<br />
　　//这段代码会抛出IOException <br />
<br />
　　Writer writer = new BufferedWriter(new FileWriter( <br />
<br />
　　new File( "file.txt" ) <br />
<br />
　　) ); <br />
<br />
　　for(int i=0; i&lt;1000; i++) { <br />
<br />
　　writer.write(""+i); <br />
<br />
　　writer.write("\n"); <br />
<br />
　　} <br />
<br />
　　writer.close( ); <br />
<br />
　　现在BufferedWriter 会决定以什么频率向FileWriter发送写调用。可以使用flush( )方法强制发出写调用。增加了BufferedWriter 后，代码的运行时间是63毫秒。如果是有很多小量的输出，那么BufferedWriter 在缺省条件下的性能提升是非常显著的。 <br />
<br />
　　除了BufferedWriter 外，BufferedOutputStream 也具有相同的品质，对于输入就是BufferedReader 和BufferedInputStream。 <br />
<br />
　　需要注意的是缓冲类不光是在文件系统上起作用，任何的Reader/Writer都能进行缓冲以提高字符输入/输出的速度，同样任何OutputStream/InputStream都能进行缓冲以提高字节IO的速度。</span><a href="http://www.enet.com.cn/"><span style="color: #808000"><img height="11" src="http://images.enet.com.cn/end.gif" width="11" align="absMiddle" border="0" target="_blank"  alt="" /></span></a><br />
<br />
</div>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 08:59 <a href="http://www.blogjava.net/jasonwbd/articles/230077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java进阶:基于Socket的Java网络编程集粹</title><link>http://www.blogjava.net/jasonwbd/articles/230075.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 00:57:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230075.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230075.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230075.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230075.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230075.html</trackback:ping><description><![CDATA[<br />
<div class="ciodigest"><span style="color: #808000"><strong>[摘要] </strong>其实,简单的分析一下，就可以看出客户和服务通讯的主要通道就是Socket本身，而服务器通过accept方法就是同意和客户建立通讯.这样当客户建立Socket的同时。服务器也会使用这一根连线来先后通讯，那么既然如此只要我们存在多条连线就可以了。<br />
<strong></strong>[关键字] </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=Socket&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">Socket</span></a><span style="color: #808000"> </span><a class="cyewunder" href="http://www.enet.com.cn/tech/inforcenter/search.jsp?keyword=%CD%F8%C2%E7%B1%E0%B3%CC&amp;ACondtion=keyword&amp;siteid=security" target="_blank"><span style="color: #808000">网络编程</span></a><span style="color: #808000"> </span></div>
<div class="contenttxt"><span style="color: #808000">其实,简单的分析一下，就可以看出客户和服务通讯的主要通道就是Socket本身，而服务器通过accept方法就是同意和客户建立通讯.这样当客户建立Socket的同时。服务器也会使用这一根连线来先后通讯，那么既然如此只要我们存在多条连线就可以了。那么我们的程序可以变为如下: <br />
那么下面的问题是如何使用线程.首先要做的事情是创建线程并使得其可以和网络连线取得联系。然后由线程来执行刚才的操作，要创建线程要么直接继承Thread要么实现Runnable接口，要建立和Socket的联系只要传递引用就可以了.而要执行线程就必须重写run方法，而run方法所做的事情就是刚才单线程版本main所做的事情，因此我们的程序变成了这样: <br />
<br />
import java.net.*; <br />
import java.io.*; <br />
<br />
public class MultiUser extends Thread{ <br />
　　private Socket client; <br />
<br />
　　public MultiUser(Socket c){ <br />
　　 this.client=c; <br />
　　} <br />
<br />
　　public void run(){ <br />
try{ <br />
　　　 BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream())); <br />
　　　 PrintWriter out=new PrintWriter(client.getOutputStream()); <br />
　　　 //Mutil User but can parallel <br />
　　　 while(true){ <br />
　　　　 String str=in.readLine(); <br />
　　　　 System.out.println(str); <br />
　　　　 out.println("has receive...."); <br />
　　　　 out.flush(); <br />
　　　　 if(str.equals("end")) <br />
　　　　　 break; <br />
} <br />
　　　 client.close(); <br />
}catch(IOException ex){ <br />
}finally{ <br />
　　 } <br />
　　} <br />
<br />
　　public static void main(String[] args)throws IOException{ <br />
　　 ServerSocket server=new ServerSocket(5678); <br />
　　 while(true){ <br />
　　 //transfer location change Single User or Multi User <br />
　　 MultiUser mu=new MultiUser(server.accept()); <br />
　　 mu.start(); <br />
　　 } <br />
　　} <br />
} <br />
<br />
<br />
<br />
客户端代码: <br />
<br />
import Java.net.*; <br />
import Java.io.*; <br />
<br />
public class Client{ <br />
static Socket Server; <br />
<br />
public static void main(String[] args) throws Exception <br />
{ <br />
Server=new Socket (InetAddress.getLocalHost(),5678); <br />
BufferedReader in=new BufferedReader(new InputStreamReader(Server.getInputStream())); <br />
PrintWriter out=new PrintWriter(Server.getOutputStream()); <br />
BufferedReader wt=new BufferedReader(new InputStreamReader(System.in)); <br />
while(true) <br />
{ <br />
String str=wt.readLine(); <br />
out.println(str); <br />
out.flush(); <br />
if(str.equals("end")) <br />
{ <br />
break; <br />
} <br />
System.out.println(in.readLine()); <br />
} <br />
Server.close(); <br />
} <br />
} <br />
<br />
这段程序是接受客户的键盘输入，并把信息输出到服务端。并把"end"作为退出的命令 <br />
<br />
以上程序完成了两台计算机的简单通信。 <br />
<br />
</span></div>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230075.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 08:57 <a href="http://www.blogjava.net/jasonwbd/articles/230075.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2SE综合--对于log4j的深层次的理解</title><link>http://www.blogjava.net/jasonwbd/articles/230074.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 00:56:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230074.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230074.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230074.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230074.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230074.html</trackback:ping><description><![CDATA[<span style="color: #808000"><br />
　　log4j的好处在于： <br />
<br />
　　1.通过修改配置文件，就可以决定log信息输出到何处(console,文件,...),是否输出。 <br />
<br />
　　这样，在系统开发阶段可以打印详细的log信息以跟踪系统运行情况,而在系统稳定后可以关闭log输出,从而在能跟踪系统运行情况的同时,又减少了垃圾代码(System.out.println(...)等)。 <br />
<br />
　　2.使用log4j，需要整个系统有一个统一的log机制，有利于系统的规划。 <br />
<br />
　　log4j的使用本身很简单。但合理地规划一个系统的统一log机制需要周全的考虑。 <br />
<br />
　　其他关于log4j的信息参看log4j自带的文档。 <br />
<br />
　　PART II 配置文件详细解释 <br />
<br />
　　先看一个配置文件的例子: <br />
<br />
　　1.配置文件的例子 <br />
<br />
　　log4j.rootLogger=DEBUG <br />
<br />
　　#将DAO层log记录到DAOLog,allLog中 <br />
<br />
　　log4j.logger.DAO=DEBUG,A2,A4 <br />
<br />
　　#将逻辑层log记录到BusinessLog,allLog中 <br />
<br />
　　log4j.logger.Businesslog=DEBUG,A3,A4 <br />
<br />
　　#A1--打印到屏幕上 <br />
<br />
　　log4j.appender.A1=org.apache.log4j.ConsoleAppender <br />
<br />
　　log4j.appender.A1.layout=org.apache.log4j.PatternLayout <br />
<br />
　　log4j.appender.A1.layout.ConversionPattern=%-5p [%t] %37c %3x - %m%n <br />
<br />
　　#A2--打印到文件DAOLog中--专门为DAO层服务log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender <br />
<br />
　　log4j.appender.A2.file=DAOLog <br />
<br />
　　log4j.appender.A2.DatePattern='.'yyyy-MM-dd <br />
<br />
　　log4j.appender.A2.layout=org.apache.log4j.PatternLayout <br />
<br />
　　log4j.appender.A2.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n <br />
<br />
　　#A3--打印到文件BusinessLog中--专门记录逻辑处理层服务log信息log4j.appender.A3=org.apache.log4j.DailyRollingFileAppender <br />
<br />
　　log4j.appender.A3.file=BusinessLog <br />
<br />
　　log4j.appender.A3.DatePattern='.'yyyy-MM-dd <br />
<br />
　　log4j.appender.A3.layout=org.apache.log4j.PatternLayout <br />
<br />
　　log4j.appender.A3.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n <br />
<br />
　　#A4--打印到文件alllog中--记录所有log信息log4j.appender.A4=org.apache.log4j.DailyRollingFileAppender <br />
<br />
　　log4j.appender.A4.file=alllog <br />
<br />
　　log4j.appender.A4.DatePattern='.'yyyy-MM-dd <br />
<br />
　　log4j.appender.A4.layout=org.apache.log4j.PatternLayout <br />
<br />
　　log4j.appender.A4.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n <br />
<br />
　　2.Appender的使用 <br />
<br />
　　一个Appender代表log信息要写向的一个地方。log4j可使用的Appender有很多类型,这里只考虑3种:ConsoleAppender,FileAppender,DailyRollFileAppender <br />
<br />
　　2.1 ConsoleAppender <br />
<br />
　　如果使用ConsoleAppender，那么log信息将写到Console。就是直接把信息打印到System.out上了。 <br />
<br />
　　2.2 FileAppender <br />
<br />
　　使用FileAppender，那么log信息将写到指定的文件中。这应该是比较经常使用到的情况。 <br />
<br />
　　相应地，在配置文件中应该指定log输出的文件名。如下配置指定了log文件名为demo.txt <br />
<br />
　　log4j.appender.A2.File=demo.txt <br />
<br />
　　注意将A2替换为具体配置中Appender的别名。 <br />
<br />
　　2.DailyRollingAppender <br />
<br />
　　使用FileAppender可以将log信息输出到文件中，但是如果文件太大了读起来就不方便了。这时就可以使用DailyRollingAppender。DailyRollingAppender可以把Log信息输出到按照日期来区分的文件中。如下配置文件就会每天产生一个log文件，每个log文件只记录当天的log信息： <br />
<br />
　　log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender <br />
<br />
　　log4j.appender.A2.file=demo <br />
<br />
　　log4j.appender.A2.DatePattern='.'yyyy-MM-dd <br />
<br />
　　log4j.appender.A2.layout=org.apache.log4j.PatternLayout <br />
<br />
　　log4j.appender.A2.layout.ConversionPattern=%m%n&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;　　3. Layout的配置 <br />
<br />
　　Layout指定了log信息输出的样式。 <br />
<br />
　　详细信息请查看PatternLayout的javadoc。 <br />
<br />
　　例子1：显示日期和log信息 <br />
<br />
　　log4j.appender.A2.layout=org.apache.log4j.PatternLayout <br />
<br />
　　log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %m%n <br />
<br />
　　打印的信息是： <br />
<br />
　　2002-11-12 11:49:42,866 SELECT * FROM Role WHERE 1=1 order by createDate desc <br />
<br />
　　例子2：显示日期，log发生地方和log信息 <br />
<br />
　　log4j.appender.A2.layout=org.apache.log4j.PatternLayout <br />
<br />
　　log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %l "#" %m%n <br />
<br />
　　2002-11-12 11:51:46,313 cn.net.unet.weboa.system.dao.RoleDAO.select(RoleDAO.java:409) "#" SELECT * FROM Role WHERE 1=1 order by createDate desc <br />
<br />
　　例子3：显示log级别,时间,调用方法,log信息 <br />
<br />
　　log4j.appender.A2.layout=org.apache.log4j.PatternLayout <br />
<br />
　　log4j.appender.A2.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%nlog信息:[DEBUG] 2002-11-12 12:00:57,376 method:cn.net.unet.weboa.system.dao.RoleDAO.select(RoleDAO.java:409) <br />
<br />
　　SELECT * FROM Role WHERE 1=1 order by createDate desc <br />
<br />
　　PART 3 log4j的使用 <br />
<br />
　　log4j使用步骤有3个： <br />
<br />
　　3.1 .根据配置文件初始化log4j <br />
<br />
　　配置文件如PART 2所叙述。现在讲的是如何在程序中配置log4j。 <br />
<br />
　　log4j可以使用3中配置器来初始化：BasicConfigurator,DOMConfigurator,PropertyConfigurator <br />
<br />
　　这里用的是PropertyConfigurator。使用PropertyConfigurator适用于所有的系统。 <br />
<br />
　　如下的语句 <br />
<br />
　　PropertyConfigurator.configure("log4j.properties"); <br />
<br />
　　就以log4j.properties为配置文件初始化好了log4j环境。 <br />
<br />
　　注意一点：这个语句只需要在系统启动的时候执行一次。例如:在unet webOA项目中可以这么用: <br />
<br />
　　在ActionServlet的init()方法中调用一次。 <br />
<br />
　　public class ActionServlet extends HttpServlet{ <br />
<br />
　　/*** Initialize global variables*/ <br />
<br />
　　public void init() throws ServletException { <br />
<br />
　　// 初始化Action资源 <br />
<br />
　　try{initLog4j();...} <br />
<br />
　　catch(IOException e) <br />
<br />
　　{throw new ServletException("Load ActionRes is Error");}} <br />
<br />
　　protected void initLog4j(){PropertyConfigurator.configure("log4j.properties");} <br />
<br />
　　} <br />
<br />
　　//end class ActionServlet <br />
<br />
　　3.2 在需要使用log4j的地方获取Logger实例 <br />
　　如下是RoleDAO类中的使用例子: <br />
<br />
　　static Logger log = Logger.getLogger("DAO"); <br />
<br />
　　注意这里使用"DAO"标识符，那么对应的在配置文件中对应的配置信息如下： <br />
<br />
　　#定义DAO Logger <br />
<br />
　　log4j.logger.DAO=DEBUG,A2 <br />
<br />
　　#设置Appender A2的属性 <br />
<br />
　　log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender <br />
<br />
　　log4j.appender.A2.file=demolog4j.appender.A2.DatePattern='.'yyyy-MM-ddlog4j.appender.A2.layout=org.apache.log4j.PatternLayout <br />
<br />
　　log4j.appender.A2.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %l%n%m%n <br />
<br />
　　public class RoleDAO extends BaseDBObject{...static Logger log = Logger.getLogger("DAO"); <br />
<br />
　　public BeanCollection selectAll() throws SQLException{ <br />
<br />
　　StringBuffer sql = new StringBuffer(SQLBUF_LEN);sql.append("SELECT * FROM " + tableName + " order by roldId"); <br />
<br />
　　//System.out.println(sql.toString());log.debug(sql); <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　3.3 使用Logger对象的debug,info,fatal...方法 <br />
<br />
　　log.debug("it is the debug info"); <br />
<br />
　　附件1：log4j的一个bug <br />
<br />
　　当这样使用时，DailyRollingFileAppender不能正确使用： <br />
<br />
　　public Class RoleDAO(){ <br />
<br />
　　static Logger log = Logger.getLogger("DAO"); <br />
<br />
　　//在每一次new RoleDAO对象的时候都执行一次configure()操作 <br />
<br />
　　public RoleDAO(TransactionManager transMgr) throws SQLException{...PropertyConfigurator.configure("log4j.properties");} <br />
<br />
　　public void select(){...//使用log4j进行log记录log.debug("..."); <br />
<br />
　　} <br />
<br />
　　} <a href="http://www.enet.com.cn/"><img height="11" src="http://images.enet.com.cn/end.gif" width="11" align="absMiddle" border="0" target="_blank"  alt="" /></a><br />
<br />
</span>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230074.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 08:56 <a href="http://www.blogjava.net/jasonwbd/articles/230074.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初学者如何开发高质量的J2EE系统</title><link>http://www.blogjava.net/jasonwbd/articles/230073.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 00:53:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230073.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230073.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230073.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230073.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230073.html</trackback:ping><description><![CDATA[<br />
J2EE学习者越来越多，J2EE本身技术不断在发展，涌现出各种概念，本文章试图从一种容易理解的角度对这些概念向初学者进行解释，以便掌握学习J2EE学习方向。 <br />
<br />
　　首先我们需要知道Java和J2EE是两个不同概念，Java不只是指一种语言，已经代表与微软不同的另外一个巨大阵营，所以Java有时是指一种软件系统的流派，当然目前主要是.NET和Java两大主流体系。 <br />
<br />
　　J2EE可以说指Java在数据库信息系统上实现，数据库信息系统从早期的dBase、到Delphi/VB等C/S结构，发展到B/S（Browser浏览器/Server<a class="article" href="http://product.enet.com.cn/price/plist70.shtml" target="_blank">服务器</a>）结构，而J2EE主要是指B/S结构的实现。 <br />
<br />
　　J2EE又是一种框架和标准，框架类似API、库的概念，但是要超出它们。如果需要详细了解框架，可先从设计模式开始学习。 <br />
<br />
　　J2EE是一个虚的大的概念，J2EE标准主要有三种子技术标准：WEB技术、EJB技术和JMS，谈到J2EE应该说最终要落实到这三个子概念上。 <br />
<br />
　　这三种技术的每个技术在应用时都涉及两个部分：容器部分和应用部分，Web容器也是指Jsp/Servlet容器，你如果要开发一个Web应用，无论是编译或运行，都必须要有Jsp/Servlet库或API支持（除了JDK/J2SE以外）。 <br />
<br />
　　Web技术中除了Jsp/Servlet技术外，还需要JavaBeans或Java Class实现一些功能或者包装携带数据，所以Web技术最初裸体简称为Jsp/Servlet+JavaBeans系统。 <br />
<br />
　　谈到JavaBeans技术，就涉及到组件构件技术（component），这是Java的核心基础部分，很多软件设计概念（设计模式）都是通过JavaBeans实现的。 <br />
<br />
　　JavaBeans不属于J2EE概念范畴中，如果一个JavaBeans对象被Web技术（也就是Jsp/Servlet）调用，那么JavaBeans就运行在J2EE的Web容器中；如果它被EJB调用，它就运行在EJB容器中。 <br />
<br />
　　EJB（企业JavaBeans）是普通JavaBeans的一种提升和规范，因为企业信息系统开发中需要一个可伸缩的性能和事务、安全机制，这样能保证企业系统平滑发展，而不是发展到一种规模重新更换一套软件系统。 <br />
<br />
　　至此，JavaBeans组件发展到EJB后，并不是说以前的那种JavaBeans形式就消失了，这就自然形成了两种JavaBeans技术：EJB和POJO，POJO完全不同于EJB概念，指的是普通JavaBeans，而且这个JavaBeans不依附某种框架，或者干脆可以说：这个JavaBeans是你为这个应用程序单独开发创建的。 <br />
<br />
　　J2EE应用系统开发工具有很多：如JBuilder、Eclipse等，这些IDE首先是Java开发工具，也就是说，它们首要基本功能是可以开发出JavaBeans或Java class，但是如果要开发出J2EE系统，就要落实到要么是Web技术或EJB技术，那么就有可能要一些专门模块功能(如eclipse需要lomboz插件)，最重要的是，因为J2EE系统区分为容器和应用两个部分，所以，在任何开发工具中开发J2EE都需要指定J2EE容器。 <br />
<br />
　　J2EE容器分为WEB容器和EJB容器，Tomcat/Resin是Web容器；JBoss是EJB容器+Web容器等，其中Web容器直接使用Tomcat实现的。所以你开发的Web应用程序可以在上面两种容器运行，而你开发的Web+EJB应用则只可以在JBoss服务器上运行，商业产品Websphere/Weblogic等和JBoss属于同一种性质。 <br />
<br />
J2EE容器也称为J2EE<a class="article" href="http://www.enet.com.cn/server/" target="_blank">服务器</a>，大部分时它们概念是一致的。 <br />
<br />
　　如果你的J2EE应用系统的数据库连接是通过JNDI获得，也就是说是从容器中获得，那么你的J2EE应用系统基本与数据库无关，如果你在你的J2EE应用系统耦合了数据库JDBC驱动的配置，那么你的J2EE应用系统就有数据库概念色彩，作为一个成熟需要推广的J2EE应用系统，不推荐和具体数据库耦合，当然这其中如何保证J2EE应用系统运行性能又是体现你的设计水平了。 <br />
<br />
　　衡量J2EE应用系统设计开发水平高低的标准就是：解耦性；你的应用系统各个功能是否能够彻底脱离？是否不相互依赖，也只有这样，才能体现可维护性、可拓展性的软件设计目标。 <br />
<br />
　　为了达到这个目的，诞生各种框架概念，J2EE框架标准将一个系统划分为WEB和EJB主要部分，当然我们有时不是以这个具体技术区分，而是从设计上抽象为表现层、服务层和持久层，这三个层次从一个高度将J2EE分离开来，实现解耦目的。 <br />
<br />
　　因此，我们实际编程中，也要将自己的功能向这三个层次上靠，做到大方向清楚，泾渭分明，但是没有技术上约束限制要做到这点是很不容易的，因此我们还是必须借助J2EE具体技术来实现，这时，你可以使用EJB规范实现服务层和持久层，Web技术实现表现层； <br />
<br />
　　EJB为什么能将服务层从Jsp/Servlet手中分离出来，因为它对JavaBeans编码有强制的约束，现在有一种对JavaBeans弱约束，使用Ioc模式实现的（当然EJB 3.0也采取这种方式），在Ioc模式诞生前，一般都是通过工厂模式来对JavaBeans约束，形成一个服务层，这也是是Jive这样开源论坛设计原理之一。 <br />
<br />
　　由此，将服务层从表现层中分离出来目前有两种可选架构选择：管理普通JavaBeans（POJO）框架(如Spring、JdonFramework)以及管理EJB的EJB框架，因为EJB不只是框架，还是标准，而标准可以扩展发展，所以，这两种区别将来是可能模糊，被纳入同一个标准了。　但是，个人认为：标准制定是为某个目的服务的，总要牺牲一些换取另外一些，所以，这两种架构会长时间并存。 <br />
<br />
　　这两种架构分歧也曾经诞生一个新名词：完全POJO的系统也称为轻量级系统(lightweight)，其实这个名词本身就没有一个严格定义，更多是一个吸引人的招牌，轻量是指容易学习容易使用吗？按照这个定义，其实轻量Spring等系统并不容易学习；而且EJB 3.0（依然叫EJB）以后的系统是否可称为轻量级了呢？ <br />
<br />
　　前面谈了服务层框架，使用服务层框架可以将JavaBeans从Jsp/Servlet中分离出来，而使用表现层框架则可以将Jsp中剩余的JavaBeans完全分离，这部分JavaBeans主要负责显示相关，一般是通过标签库（taglib）实现，不同框架有不同自己的标签库，Struts是应用比较广泛的一种表现层框架。 <br />
<br />
　　这样，表现层和服务层的分离是通过两种框架达到目的，剩余的就是持久层框架了，通过持久层的框架将数据库存储从服务层中分离出来是其目的，持久层框架有两种方向：直接自己编写JDBC等SQL语句（如iBatis）；使用O/R Mapping技术实现的Hibernate和JDO技术；当然还有EJB中的实体Bean技术。 <br />
<br />
　　持久层框架目前呈现百花齐放，各有优缺点的现状，所以正如表现层框架一样，目前没有一个框架被指定为标准框架，当然，表现层框架现在又出来了一个JSF，它代表的页面组件概念是一个新的发展方向，但是复杂的实现让人有些忘而却步。 <br />
<br />
　　在所有这些J2EE技术中，虽然SUN公司发挥了很大的作用，不过总体来说：网络上有这样一个评价：SUN的理论天下无敌；SUN的产品用起来撞墙；对于初学者，特别是那些试图通过或已经通过SUN认证的初学者，赶快摆脱SUN的阴影，立即开溜，使用开源领域的产品来实现自己的应用系统。 <br />
<br />
　　最后，你的J2EE应用系统如果采取上面提到的表现层、服务层和持久层的框架实现，基本你也可以在无需深刻掌握设计模式的情况下开发出一个高质量的应用系统了。 <br />
<br />
　　还要注意的是: 开发出一个高质量的J2EE系统还需要正确的业务需求理解，那么域建模提供了一种比较切实可行的正确理解业务需求的方法，相关详细知识可从UML角度结合理解。 <br />
<br />
　　当然，如果你想设计自己的行业框架，那么第一步从设计模式开始吧，因为设计模式提供你一个实现JavaBeans或类之间解耦参考实现方法，当你学会了系统基本单元JavaBean或类之间解耦时，那么系统模块之间的解耦你就可能掌握，进而你就可以实现行业框架的提炼了，这又是另外一个发展方向了。 <br />
<br />
　　以上理念可以总结为一句话： <br />
<br />
　　J2EE开发三件宝: Domain Model（域建模）、patterns（模式）和framework（框架）。 <br />
<br />
　　推荐一套高质量的J2EE开源系统： JPestore <br />
<br />
　　如果初学者没有理解，欢迎继续讨论，大胆提出你心中的疑问。 <br />
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230073.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 08:53 <a href="http://www.blogjava.net/jasonwbd/articles/230073.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Java中相对路径和绝对路径问题总结</title><link>http://www.blogjava.net/jasonwbd/articles/230072.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 00:52:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230072.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230072.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230072.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230072.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230072.html</trackback:ping><description><![CDATA[<span style="color: #808000"><br />
1.基本概念的理解 <br />
<br />
　　绝对路径：绝对路径就是你的主页上的文件或目录在硬盘上真正的路径，(URL和物理路径)例如： C:\xyz\test.txt 代表了test.txt文件的绝对路径。http://www.sun.com/index.htm也代表了一个 URL绝对路径。 <br />
<br />
　　相对路径：相对与某个基准目录的路径。包含Web的相对路径（HTML中的相对目录），例如：在 Servlet中，"/"代表Web应用的跟目录。和物理路径的相对表示。例如："./" 代表当前目录, "../"代表上级目录。这种类似的表示，也是属于相对路径。 另外关于URI，URL,URN等内容，请参考RFC相关文档标准。 RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax, (http://www.ietf.org/rfc/rfc2396.txt) <br />
<br />
　　2.关于JSP/Servlet中的相对路径和绝对路径。 <br />
<br />
　　2.1<a class="article" href="http://product.enet.com.cn/price/plist70.shtml" target="_blank">服务器</a>端的地址 <br />
<br />
　　服务器端的相对地址指的是相对于你的web应用的地址，这个地址是在服务器端解析的 （不同于html和javascript中的相对地址，他们是由客户端浏览器解析的）也就是说这时候 在jsp和servlet中的相对地址应该是相对于你的web应用，即相对于http://192.168.0.1/webapp/的。 <br />
<br />
　　其用到的地方有： forward：servlet中的request.getRequestDispatcher(address);这个address是 在服务器端解析的，所以，你要forward到a.jsp应该这么写： request.getRequestDispatcher(&#8220;/user/a.jsp&#8221;)这个/相对于当前的web应用webapp， 其绝对地址就是：http://192.168.0.1/webapp/user/a.jsp。 sendRedirect：在jsp中 <br />
<br />
　　2.2、客户端的地址 所有的html页面中的相对地址都是相对于服务器根目录(http://192.168.0.1/)的， 而不是(跟目录下的该Web应用的目录)http://192.168.0.1/webapp/的。 Html中的form表单的action属性的地址应该是相对于服务器根目录(http://192.168.0.1/)的， 所以，如果提交到a.jsp为：action＝"/webapp/user/a.jsp"或action=""/user/a.jsp； <br />
<br />
　　提交到servlet为actiom＝"/webapp/handleservlet" <br />
<br />
　　Javascript也是在客户端解析的，所以其相对路径和form表单一样。 <br />
<br />
　　因此，一般情况下，在JSP/HTML页面等引用的CSS,Javascript.Action等属性前面最好都加上 ,以确保所引用的文件都属于Web应用中的目录。 另外，应该尽量避免使用类似".","./","../../"等类似的相对该文件位置的相对路径，这样 当文件移动时，很容易出问题。<br />
<br />
3. JSP/Servlet中获得当前应用的相对路径和绝对路径 <br />
<br />
　　3.1 JSP中获得当前应用的相对路径和绝对路径 根目录所对应的绝对路径:request.getRequestURI() 文件的绝对路径 　:application.getRealPath(request.getRequestURI()); <br />
<br />
　　当前web应用的绝对路径 :application.getRealPath("/"); <br />
<br />
　　取得请求文件的上层目录:new File(application.getRealPath(request.getRequestURI())).getParent() <br />
<br />
　　3.2 Servlet中获得当前应用的相对路径和绝对路径 根目录所对应的绝对路径:request.getServletPath(); <br />
<br />
　　文件的绝对路径 :request.getSession().getServletContext().getRealPath (request.getRequestURI()) <br />
<br />
　　当前web应用的绝对路径 :servletConfig.getServletContext().getRealPath("/"); <br />
<br />
　　(ServletContext对象获得几种方式： javax.servlet.http.HttpSession.getServletContext() javax.servlet.jsp.PageContext.getServletContext() javax.servlet.ServletConfig.getServletContext() ) <br />
<br />
　　4.java 的Class中获得相对路径，绝对路径的方法 <br />
<br />
　　4.1单独的Java类中获得绝对路径 <br />
<br />
　　根据java.io.File的Doc文挡，可知: 默认情况下new File("/")代表的目录为： <br />
<br />
　　System.getProperty("user.dir")。 一下程序获得执行类的当前路径 <br />
<br />
　　package org.cheng.file; <br />
<br />
　　import java.io.File; <br />
<br />
　　public class FileTest { <br />
<br />
　　public static void main(String[] args) throws Exception { System.out.println(Thread.currentThread().getContextClassLoader().getResource("")); System.out.println(FileTest.class.getClassLoader().getResource("")); 　　System.out.println(ClassLoader.getSystemResource("")); System.out.println(FileTest.class.getResource("")); <br />
<br />
　　System.out.println(FileTest.class.getResource("/")); <br />
<br />
　　//Class文件所在路径 <br />
<br />
　　System.out.println(new File("/").getAbsolutePath()); <br />
<br />
　　System.out.println(System.getProperty("user.dir")); <br />
<br />
　　} <br />
<br />
　　} <br />
<br />
　　4.2<a class="article" href="http://product.enet.com.cn/price/plist70.shtml" target="_blank">服务器</a>中的Java类获得当前路径（来自网络） <br />
<br />
　　(1).Weblogic WebApplication的系统文件根目录是你的weblogic安装所在根目录。 例如：如果你的weblogic安装在c:\bea\weblogic700..... 那么，你的文件根路径就是c:\. 所以，有两种方式能够让你访问你的服务器端的文件： <br />
<br />
　　a.使用绝对路径： 比如将你的参数文件放在c:\yourconfig\yourconf.properties， 直接使用 new FileInputStream("yourconfig/yourconf.properties"); <br />
<br />
　　b.使用相对路径： 相对路径的根目录就是你的webapplication的根路径，即WEB-INF的上一级目录，将你的参数文件放 在yourwebapp\yourconfig\yourconf.properties， 这样使用： new FileInputStream("./yourconfig/yourconf.properties"); 这两种方式均可，自己选择。 <br />
<br />
　　(2).Tomcat 在类中输出System.getProperty("user.dir");显示的是%Tomcat_Home%/bin <br />
<br />
　　(3).Resin 不是你的JSP放的相对路径,是JSP引擎执行这个JSP编译成SERVLET 的路径为根.比如用新建文件法测试File f = new File("a.htm"); 这个a.htm在resin的安装目录下 (4).如何读相对路径哪？ 在Java文件中getResource或getResourceAsStream均可 例：getClass().getResourceAsStream(filePath);//filePath可以是"/filename",这里的/代表web 发布根路径下WEB-INF/classes 默认使用该方法的路径是：WEB-INF/classes。已经在Tomcat中测试。 <br />
<br />
　　5.读取文件时的相对路径，避免硬编码和绝对路径的使用。</span>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230072.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 08:52 <a href="http://www.blogjava.net/jasonwbd/articles/230072.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于JDK5.0一些collection类的使用总结</title><link>http://www.blogjava.net/jasonwbd/articles/230071.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 00:51:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230071.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230071.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230071.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230071.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230071.html</trackback:ping><description><![CDATA[<span style="color: #808000"><br />
　在5.0中，collection最大的一个改变就是可以指定它的具体类型： <br />
<br />
　　List&lt; String&gt; list=new List&lt; String&gt;; <br />
<br />
　　两个最基本的接口： <br />
<br />
　　public interface Collection&lt; E&gt; <br />
<br />
　　{ <br />
<br />
　　boolean add(E element); <br />
<br />
　　Iterator&lt; E&gt; iterator(); <br />
<br />
　　. . . <br />
<br />
　　} <br />
<br />
　　public interface Iterator&lt; E&gt; <br />
<br />
　　{ <br />
<br />
　　E next(); <br />
<br />
　　boolean hasNext(); <br />
<br />
　　void remove(); <br />
<br />
　　} <br />
<br />
　　在5.0以前，常用的形式就是： <br />
<br />
　　Collection&lt; String&gt; c = . . .; <br />
<br />
　　Iterator&lt; String&gt; iter = c.iterator(); <br />
<br />
　　while (iter.hasNext()) <br />
<br />
　　{ <br />
<br />
　　String element = iter.next(); <br />
<br />
　　do something with element <br />
<br />
　　} <br />
<br />
　　但是在5.0中加入另外一种循环方式，类似于for each： <br />
<br />
　　for (String element : c) <br />
<br />
　　{ <br />
<br />
　　do something with element <br />
<br />
　　} <br />
<br />
　　这种方式对任何实现了Iterable接口的类都适用。 <br />
<br />
　　在使用remove的时候特别要注意的一点是，在调用remove之前必须先调用一次next方法，因为next就像是在移动一个指针，remove删掉的就是指针刚刚跳过去的东西。即使是你想连续删掉两个相邻的东西，也必须在每次删除之前调用next。 <br />
<br />
　　对collection排序和查找 <br />
<br />
　　Collections类的sort方法可以对任何实现了List接口的类进行排序。在排序过程中，他默认这些类实现了Comparable接口，如果想用其他方法排序，可以在调用sort方法的时候提供一个Comparator对象： <br />
<br />
　　Comparator&lt; Item&gt; itemComparator = new <br />
<br />
　　Comparator&lt; Item&gt;() <br />
<br />
　　{ <br />
<br />
　　public int compare(Item a, Item b) <br />
<br />
　　{ <br />
<br />
　　return a.partNumber - b.partNumber; <br />
<br />
　　} <br />
<br />
　　}); <br />
<br />
　　反向排序： <br />
<br />
　　Collections.sort(items, itemComparator); <br />
<br />
　　Collections.sort(items, Collections.reverseOrder(itemComparator))； <br />
<br />
　　查找一个对象： <br />
<br />
　　i = Collections.binarySearch(c, element); <br />
<br />
　　i = Collections.binarySearch(c, element, comparator); <br />
<br />
　　但是这些list必须是已经排好序了。而且要注意的是这个算法需要随机访问collection，如果不支持随机访问那么这个算法的效率可能会很低。 <br />
<br />
　　几种常用Collection: <br />
<br />
　　ArrayList <br />
<br />
　　An indexed sequence that grows and shrinks dynamically <br />
<br />
　　可以随机访问，但是如果要从中间删除一个对象会影响效率，因为有些未删除的对象要相应的调整位置。非线程安全，但效率会比Vector要高，如果在单线程下，选它而不是Vector。 <br />
<br />
　　LinkedList <br />
<br />
　　An ordered sequence that allows efficient insertions and removal at any location <br />
<br />
　　只能按顺序访问，添加删除很方便。虽然提供了get(n)方法，但实际上还是顺序访问的，如果发现在LinkedList里面使用了这个方法，要考虑这个List类型是否选的合适 <br />
<br />
　　HashSet <br />
<br />
　　An unordered collection that rejects duplicates <br />
<br />
　　以hashcode为索引，适用于不知道所存对象位置而想寻找某个对象的情况。不可重复 <br />
<br />
　　TreeSet <br />
<br />
　　A sorted set <br />
<br />
　　与HashSet类似，但是所存对象是排了序的 <br />
<br />
　　LinkedHashSet <br />
<br />
　　A set that remembers the order in which elements were inserted <br />
<br />
　　PriorityQueue <br />
<br />
　　A collection that allows efficient removal of the smallest element <br />
<br />
　　加入Queue的时候会给与一个优先级，从queue中取出的时候先取出优先级最低的 <br />
<br />
　　HashMap <br />
<br />
　　A data structure that stores key/value associations <br />
<br />
　　存储key/value对,非线程安全，与HashTable相比效率要高些 <br />
<br />
　　treeMap <br />
<br />
　　A map in which the keys are sorted <br />
<br />
　　排序的HashMap <br />
<br />
　　LinkedHashMap <br />
<br />
　　A map that remembers the order in which entries were added</span>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230071.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 08:51 <a href="http://www.blogjava.net/jasonwbd/articles/230071.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Java编程中的“模式思想”与框架关系</title><link>http://www.blogjava.net/jasonwbd/articles/230070.html</link><dc:creator>鱼跃于渊</dc:creator><author>鱼跃于渊</author><pubDate>Sat, 20 Sep 2008 00:48:00 GMT</pubDate><guid>http://www.blogjava.net/jasonwbd/articles/230070.html</guid><wfw:comment>http://www.blogjava.net/jasonwbd/comments/230070.html</wfw:comment><comments>http://www.blogjava.net/jasonwbd/articles/230070.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasonwbd/comments/commentRss/230070.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasonwbd/services/trackbacks/230070.html</trackback:ping><description><![CDATA[<span style="color: #808000"><br />
目前在开发领域中各种框架越来越多；模式使用机会性似乎减少了，那么是不是意味着我们就不必掌握模式了呢？其实，学习模式实际为了培养模式思维，模式思维有助于了解和使用框架。 <br />
<br />
　　例如如何我们在使用表现层哪个框架，都是MVC模式实现，那么进行编程步骤时，我们脑海里就浮现一个步骤V/C/M以及C和V的转发关系，进而感觉struts-config.xml配置就不是多余或复杂，而是必须的。 <br />
<br />
　　现在有人觉得好像Java世界框架特别多，异常复杂，其实这可能是他从封闭世界走向开放自由世界产生的错觉，当你具备模式思维时，实际你就具备了挑选各种各样框架的能力，打个比喻：以选择轿车为例子，过去，只有一种&#8220;红旗&#8221;轿车供选择，你就只有接受这个轿车；但是现在轿车多了，选择多了，你就必须了解轿车的通用概念，进而你就可以在各种轿车之间选择和衡量，了解轿车的通用概念这个过程就如同我们学习模式，具备通用编程的模式思维，有了模式思维，就会发现有这么多选择产品，不再嫌复杂，而是变得兴奋了；所以，没有复杂的东西，只有是否原意学习的头脑；PC电脑对于一些人很复杂，可是对于我们会复杂吗？不会，因为我们已经掌握通用电脑的模型、模式。 <br />
<br />
　　所以，有人觉得Java软件很多配置复杂，甚至产生配置恐惧症，那是因为他没有模式思维，在模式思维指导下的编程工作，就象在写一篇生动的小说一样，你脑海展现的生动模式实现步骤，而无论代码或配置都是实现你模式思维的文字工具，模式思维考虑到哪里，就想起什么配置，配置对具备模式思维的你来说是很自然的表达。 <br />
<br />
　　在模式思维下的Java编程，编码阶段code completion可能花费2/3时间，但是调试测试时间只需要1/3甚至不到，大多数情况下是一步到位的调试成功；这比以前1/3编程时间，2/3调试时间要高效多，关键是：你无论花费多少时间在调试上，实际上是在做一个修修补补的工作，是在做维修工，头疼医头，永远是机修工，无法成为设计师。 <br />
<br />
　　下面从模式思维角度谈谈几个认识误区，仅仅参考讨论： <br />
<br />
　　<strong>游戏软件比企业软件复杂？</strong> <br />
<br />
　　为什么说企业软件时复杂的？因为企业软件是为应付需求而变，与游戏软件等软件相比，虽然一个游戏软件在代码数量级别上比企业软件复杂，但是游戏软件不必考虑跟随游戏用户需求变化，是游戏用户服务游戏设计规则；但是企业软件和其用户则相反，企业软件必须服从用户的变化，打个不是很确切的比喻：企业软件则类似市场经济中的市场人员，需要&#8220;看客户脸色&#8221;行事。而游戏软件则相反，类似以前朝南坐的政府人员； <br />
<br />
　　因此，企业软件在动态概念上是随时间变化而变化，是由生命的，因为计划赶不上变化，所以企业软件制作时总是使用模式为将来变化预留余地，这种面向未来变化考虑方式无疑是最复杂的思维，就象股票变化将这种未来变化的残酷推向极致，我们都想计划未来，但是总是计划不了未来，这就是企业软件的复杂所在。<br />
<br />
<strong>Class.forName神秘吗？</strong> <br />
<br />
　　有人觉得Class.forName很神秘，神秘不在于本身，就是打开其编码研究到二进制也不能达到目的，它的神秘之处是因为应用在一个恰当之处，就象一块普通布没什么，但是如果从后面变出花了，你觉得这块布神奇了，Class.forName神奇之处在于其隐藏了对象创建，也一种是工厂模式实现。 <br />
<br />
　　同样，对于Collection，本来就是那几个种类List和Map，但是发现使用起来神奇得很，有人甚至研究过Collection的二进制，这和研究魔术师中一块普通布没有什么区别。Collection用于容器，作为对象集合；以及和单例结合实现缓存等，可以实现多种模式。 <br />
<br />
　　<strong>仅会算法就做企业软件吗？</strong> <br />
<br />
　　在实践中，通常表示一个树形关系通过编码实现，例如1122334455表示是代号为11类别下代号为22类别下的代号为33类别下的....然后，在软件各处通过分析这个类别编码获得树形关系，这种将将具体数据和业务耦合在一起做法是受到抨击的。 <br />
<br />
　　那么如果我们要对树形关系的数据进行访问如何实现呢？首先我们将树形关系的访问分为两个部分：树形关系＋功能实现。我们已经知晓树形结构的遍历，但是仅仅知道树形结构遍历还是不够的，我们还需要模式来解决树形关系访问这个通用问题，使用Composite模式可以方便客户端对树形结构访问，使得客户端不至于因为树形结构变化而变化不定；而访问者模式则不会总可能新增的新访问功能，导致树形结构中对象代码变化不定。 <br />
<br />
　　这两种模式协同发力，可以综合解决树形结构中对象群的访问。 <br />
<br />
　　<strong>GoF模式打开的新境界</strong> <br />
<br />
　　没有知晓GoF模式之前，我们总是以为编码就是写一些代码，然后运行，复杂吗？如果我们来分析一下GoF模式三个类型，你会发现平时熟视无睹的代码中隐藏如此多考虑方面。 <br />
<br />
　　GOF模式三种类型：结构型模式、创建型模式和行为型模式其实函括了OO编码的三个方面：静态类关系、类创建成为运行时对象实例；运行时的对象运行行为，也就是说，我们在编码阶段不但考虑现阶段各个类之间静态解耦关系，而且还要考虑这些代码激活后，运行时的情况。 <br />
<br />
　　而以往过程化编程中，编码状况=运行状况，如何先后编码，这些编码运行时就按照这些先后编码顺序执行，两者是统一的，不可能出现运行时可能和编码时预想不一样，更何况需要我们还要在进行类编码时，考虑这些类运行时是如何实现的，有如何对这些类运行时的关系进行解耦和分离呢？所以，我们&#8220;天生&#8221;就无法理解设计模式，因为我们从来就认为软件就是实现功能，哪里还会考虑到实现同样功能会涉及各种考量了呢？ <br />
<br />
　　如果说设计模式是程序员的圣经，那么不掌握设计模式可能就是异教徒，从此教徒和异教徒两者之间就缺乏沟通对话平台，就象鸡对鸭讲话了。 <br />
<br />
　　非模式思维的惩罚 <br />
<br />
　　面向对象软件体系是和面向过程体系格格不入的，面向对象的各种技术如单元测试　性能缓存等等都是OO体系，如果我们没有具备模式思维来编程，由此而诞生的软件架构必然失败，失败在哪里？通过性能惩罚你。最近碰到一个台湾的钢铁架构，它虽然包含一个简单的MVC框架，但是其Controller实际又是Service，该框架配置将下面几个元素耦合在一起：页面流程；控制类；Dao与VO，这实际是将表现层和持久层直接结合一起，这样的框架迫使程序员没有空间做中间领域模型层和服务层，进而整个体系变成一个两层耦合结构，这和传统的C/S没有区别，在Java中使用传统概念编程：如面向过程、面向数据表以及两层耦合导致结果是性能缓慢，很多大型项目就是这样最后是毁在性能上，<a class="article" href="http://product.enet.com.cn/price/plist70.shtml" target="_blank">服务器</a>需要经常启动，一旦并发用户就很慢，服务器经常死机。 <br />
<br />
　　有人可能奇怪：非模式思维属于设计问题，怎么会对性能影响，这是将设计和性能对立起来，性能也是一种设计，池模式以及缓存也是属于模式啊，但是缓存的高效率应用是建立良好的对象设计基础上，或者说是良好的领域建模上，否则就是使用缓存，也会导致粒度或动态机制不准确，无法发挥缓存效率，甚至无法使用缓存。</span>
<img src ="http://www.blogjava.net/jasonwbd/aggbug/230070.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasonwbd/" target="_blank">鱼跃于渊</a> 2008-09-20 08:48 <a href="http://www.blogjava.net/jasonwbd/articles/230070.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>