﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-网摘-文章分类-Java</title><link>http://www.blogjava.net/jvict/category/33908.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 22 Apr 2010 03:56:00 GMT</lastBuildDate><pubDate>Thu, 22 Apr 2010 03:56:00 GMT</pubDate><ttl>60</ttl><item><title>Apache Commons DbUtils 快速上手 </title><link>http://www.blogjava.net/jvict/articles/318674.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Sun, 18 Apr 2010 09:30:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/318674.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/318674.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/318674.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/318674.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/318674.html</trackback:ping><description><![CDATA[<div><a href="http://java.chinaitlab.com/advance/796954.html">原文：http://java.chinaitlab.com/advance/796954.html</a><br />
另文：<a href="http://topmanopensource.javaeye.com/blog/348863">http://topmanopensource.javaeye.com/blog/348863</a><br />
Hibernate太复杂，iBatis不好用，JDBC代码太垃圾，DBUtils在简单与优美之间取得了完美平衡。</div>
<div>&nbsp;</div>
<div><strong>一、概述</strong></div>
<div>&nbsp;</div>
<div>DbUtils小巧的<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>数据库操作工具，它在JDBC的基础上做了科学的封装，旨在简化JDBC代码混乱与重复。</div>
<div>&nbsp;</div>
<div>对于JDBC代码，存在很多问题，算是对<a class="channel_keylink" href="http://java.chinaitlab.com/" target="_blank">Java</a>的批判：</div>
<div>1、操作过程复杂，代码操作一个模式，大量的重复。</div>
<div>2、结果集难以处理，拿到一个ResultSet干屁啊，一个一个度，转称JavaBean，后来形成List，太麻烦了。</div>
<div>3、到处都强制检查SQLException，烦不烦啊，影响代码的美观和可读性。</div>
<div>&nbsp;</div>
<div>当然，以上的批判不是说JDBC设计不合理，二是缺乏更高层操作API的支持。因此才产生了众多的开源数据库操作的框架和工具包。</div>
<div>&nbsp;</div>
<div><strong>二、熟悉DBUtils的API</strong></div>
<div>&nbsp;</div>
<div>针对DBUitlsAPI的包，做个简单的翻译，以便迅速掌握API的使用。</div>
<div>
<div style="border-right: #aaaaaa 1px solid; padding-right: 5px; border-top: #aaaaaa 1px solid; padding-left: 5px; padding-bottom: 5px; border-left: #aaaaaa 1px solid; padding-top: 5px; border-bottom: #aaaaaa 1px solid; background-color: #fffafa">
<div>1、------------------------------------<br />
包org.apache.commons.dbutils <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DbUtils是一个为简化JDBC操作的小类库。</div>
<div>接口摘要<br />
ResultSetHandler 将ResultSet转换为别的对象的工具。<br />
RowProcessor 将ResultSet行转换为别的对象的工具。&nbsp; </div>
<div>类摘要<br />
BasicRowProcessor RowProcessor接口的基本实现类。 <br />
BeanProcessor BeanProcessor匹配列明到Bean属性名，并转换结果集列到Bean对象的属性中。<br />
DbUtils 一个JDBC辅助工具集合。 <br />
ProxyFactory 产生JDBC接口的代理实现。 <br />
QueryLoader 属性文件加载器，主要用于加载属性文件中的 SQL 到内存中。 <br />
QueryRunner 使用可插拔的策略执行SQL查询并处理结果集。<br />
ResultSetIterator 包装结果集为一个迭代器。 <br />
&nbsp; <br />
2、------------------------------------<br />
包org.apache.commons.dbutils.handlers <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResultSetHandler接口的实现类 </div>
<div>类摘要<br />
AbstractListHandler 将ResultSet转为List的抽象类<br />
ArrayHandler 将ResultSet转为一个Object[]的ResultSetHandler实现类<br />
ArrayListHandler 将ResultSet转换为List&lt;Object[]&gt;的ResultSetHandler实现类<br />
BeanHandler 将ResultSet行转换为一个JavaBean的ResultSetHandler实现类<br />
BeanListHandler 将ResultSet转换为List&lt;JavaBean&gt;的ResultSetHandler实现类<br />
ColumnListHandler 将ResultSet的一个列转换为List&lt;Object&gt;的ResultSetHandler实现类<br />
KeyedHandler 将ResultSet转换为Map&lt;Map&gt;的ResultSetHandler实现类<br />
MapHandler 将ResultSet的首行转换为一个Map的ResultSetHandler实现类<br />
MapListHandler 将ResultSet转换为List&lt;Map&gt;的ResultSetHandler实现类<br />
ScalarHandler 将ResultSet的一个列到一个对象。</div>
<div>&nbsp;</div>
<div>3、------------------------------------<br />
包org.apache.commons.dbutils.wrappers <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 添加java.sql类中功能包装类。</div>
<div>类摘要<br />
SqlNullCheckedResultSet 在每个getXXX方法上检查SQL NULL值的ResultSet包装类。<br />
StringTrimmedResultSet 取出结果集中字符串左右空格的ResultSet包装类。<br />
</div>
</div>
</div>
<div>&nbsp;</div>
<div><strong>三、环境</strong></div>
<div>&nbsp;</div>
<div>Java5</div>
<div>commons-dbutils-1.2-bin.zip</div>
<div>mysql-noinstall-5.1.40-win32.zip</div>
<div>mysql-connector-java-5.1.10.zip</div>
<div>&nbsp;</div>
<div><a class="channel_keylink" href="http://download.chinaitlab.com/" target="_blank">下载</a>地址：</div>
<div><u>http://apache.freelamp.com/commons/dbutils/binaries/commons-dbutils-1.2-bin.zip</u></div>
<div><u>http://gd.tuwien.ac.at/db/mysql/Downloads/MySQL-5.1/mysql-noinstall-5.1.40-win32.zip</u></div>
<div><u><a href="http://gd.tuwien.ac.at/db/mysql/Downloads/Connector-J/mysql-connector-java-5.1.10.zip">http://gd.tuwien.ac.at/db/mysql/Downloads/Connector-J/mysql-connector-java-5.1.10.zip</a></u></div>
<img src ="http://www.blogjava.net/jvict/aggbug/318674.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-04-18 17:30 <a href="http://www.blogjava.net/jvict/articles/318674.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用JFreeChart增强JSP报表的用户体验</title><link>http://www.blogjava.net/jvict/articles/318222.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Wed, 14 Apr 2010 01:15:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/318222.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/318222.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/318222.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/318222.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/318222.html</trackback:ping><description><![CDATA[<p><a href="http://www.sucai.com/Tech/List4/8746.htm">原文：http://www.sucai.com/Tech/List4/8746.htm</a><br />
<br />
JFreeChart是一组功能强大、灵活易用的Java绘图API，使用它可以生成多种通用性的报表，包括柱状图、饼图、曲线图、甘特图等。它能够用在Swing和Web等中制作自定义的图表或报表，并且得到广泛的应用。本文将通过引领读者学习在JFreeChart中饼图、柱状图和曲线图的进阶应用，来达到熟练使用JFreeChart的目的。</p>
<p>一．&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下载与环境配置<br />
1. 下载JFreeChart<br />
JFreeChart是开放源代码的免费软件，但是它的支持文档需要付费才能得到。其下载地址为：http://sourceforge.net/project/showfiles.php?group_id=15494，当前最新版本为1.0.6。笔者下载的是1.0.6最新版。<br />
说明：1）source目录：为jfreechart的源码目录；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）lib目录：为包目录，我们需要关注的包为jfreechart-1.0.6.jar、gnujaxp.jar和jcommon-1.0.10.jar这三个包；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）根目录下的jfreechart-1.0.6-demo.jar是例子程序，大家双击后可看到其中有很多例子的运行结果。<br />
2. 环境配置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 笔者的开发环境如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JDK：1.5<br />
MyEclipse：5.1.1 GA<br />
Tomcat：5.5.28<br />
为了后续的&#8220;用JFreeChart创建基于Web的图表&#8221;的一个例子的展示，我们在MyEclipse中创建一个名为jfreechart的Web工程。将下载的JFreeChart1.0.6下lib目录下的jar包拷贝到WebRoot/WEB-INF/lib目录下。另外还需要在web.xml文件中增加如下配置：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;DisplayChart&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;org.jfree.chart.servlet.DisplayChart&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;DisplayChart&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/DisplayChart&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
二．&nbsp;&nbsp; 柱状图</p>
<p>在WebRoot目录下建立bar目录，用来存放柱状图的各个例子。首先在该目录下建立一个sample1.jsp文件，让我们来看一个简单的柱状图的例子，修改后的sample1.jsp的内容如下所示：</p>
<p>&lt;%@ page contentType="text/html;charset=GBK"%&gt; &lt;%@ page import="org.jfree.chart.ChartFactory, org.jfree.chart.JFreeChart, org.jfree.chart.plot.PlotOrientation, org.jfree.chart.servlet.ServletUtilities, org.jfree.data.category.DefaultCategoryDataset"%&gt; &lt;% DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(610, "广州", "猪肉"); dataset.addValue(220, "广州", "牛肉"); dataset.addValue(530, "广州", "鸡肉"); dataset.addValue(340, "广州", "鱼肉"); JFreeChart chart = ChartFactory.createBarChart3D("肉类销量统计图", "肉类", "销量", dataset, PlotOrientation.VERTICAL, false, false, false); String filename = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, session); String graphURL = request.getContextPath() + "/DisplayChart?filename=" + filename; %&gt; &lt;img src="&lt;%= graphURL %&gt;" width=500 height=300 border=0 usemap="#&lt;%= filename %&gt;"&gt; </p>
<p>在浏览器中输入地址：http://localhost:8080/jfreechart/bar/sample1.jsp，可看到如下柱状图：</p>
<div style="text-indent: 21pt"><br />
<br />
<p align="center"><img height="294" alt="用JFreeChart增强JSP报表的用户体验（图一）" src="http://www.sucai.com/tech/newsfile/12000-12999/12619/080410212563410.jpg" width="504" border="0" /></p>
</div>
<div style="text-indent: 21pt"><br />
<br />
&nbsp;</div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt">上面的这个柱状图比较简单，稍显单调，在有些情况下，我们需要用不同颜色来表示不同的种类，或者在种类上标上具体数值，亦或需要加上3D水晶效果。下面让我们来做更深一步的探讨。接下来让我们看一个用不同颜色来表示不通种类的例子。在WebRoot的bar目录下新建sample2.jsp页面，将其代码修改如下：<br />
<br />
</div>
<div style="scrollbar-highlight-color: buttonhighlight; overflow: auto; width: 500px">
<pre style="border-right: black 1px solid; padding-right: 4px; border-top: black 1px solid; padding-left: 4px; padding-bottom: 4px; border-left: black 1px solid; padding-top: 4px; border-bottom: black 1px solid; background-color: #ededed">
<div>&lt;%@ page contentType="text/html;charset=GBK"%&gt;
&lt;%@ page import="org.jfree.chart.ChartFactory,
org.jfree.chart.JFreeChart,
org.jfree.chart.plot.PlotOrientation,
org.jfree.chart.servlet.ServletUtilities,
org.jfree.data.category.CategoryDataset,
org.jfree.data.general.DatasetUtilities"%&gt;
&lt;%
double[][] data = new double[][] {{1310}, {720}, {1130}, {440}};
String[] rowKeys = {"猪肉", "牛肉","鸡肉", "鱼肉"};
String[] columnKeys = {""};
CategoryDataset dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data);
JFreeChart chart = ChartFactory.createBarChart3D("广州肉类销量统计图",
"肉类",
"销量",
dataset,
PlotOrientation.VERTICAL,
true,
false,
false);
String filename = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, session);
String graphURL = request.getContextPath() + "/DisplayChart?filename=" + filename;
%&gt;
&lt;img src="&lt;%= graphURL %&gt;" width=500 height=300 border=0 usemap="#&lt;%= filename %&gt;"&gt;
</div>
</pre>
</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 该页面的运行效果如下图所示：</div>
<div><br />
<br />
<p>&nbsp;</p>
<p align="center"><img height="277" alt="用JFreeChart增强JSP报表的用户体验（图二）" src="http://www.sucai.com/tech/newsfile/12000-12999/12619/080410212563411.jpg" width="464" border="0" /></p>
</div>
<div><br />
<br />
&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; 对比该例与前例，可看出createBarChart3D的倒数第三个参数修改成了true，该参数可用来显示下方的： 。上两例我们显示的只是一个城市的肉类销量，有时候我们有对比显示多个城市的不同肉类，只要将上例稍作修改即可。例如要在图中表示广州、深圳、东莞、佛山四个城市的四个肉类的销售情况，只需要将如下三句稍做修改：<br />
<br />
</div>
<div>
<div style="scrollbar-highlight-color: buttonhighlight; overflow: auto; width: 500px">
<pre style="border-right: black 1px solid; padding-right: 4px; border-top: black 1px solid; padding-left: 4px; padding-bottom: 4px; border-left: black 1px solid; padding-top: 4px; border-bottom: black 1px solid; background-color: #ededed">
<div>double[][] data = new double[][] {{1310}, {720}, {1130}, {440}};
String[] rowKeys = {"猪肉", "牛肉","鸡肉", "鱼肉"};
String[] columnKeys = {""};
例如修改成：
double[][] data = new double[][] {{1310, 1220, 1110, 1000},
{720, 700, 680, 640},
{1130, 1020, 980, 800},
{440, 400, 360, 300}};
String[] rowKeys = {"猪肉", "牛肉","鸡肉", "鱼肉"};
String[] columnKeys = {"广州", "深圳", "东莞", "佛山"};</div>
</pre>
</div>
</div>
<div style="text-indent: 21pt">在运行该jsp页面，可看到如下界面：</div>
<div style="text-indent: 21pt">&nbsp;</div>
<div><br />
</div>
<p>&nbsp;</p>
<p align="center"><img height="301" alt="用JFreeChart增强JSP报表的用户体验（图三）" src="http://www.sucai.com/tech/newsfile/12000-12999/12619/080410212563412.jpg" width="502" border="0" /></p>
<p align="left">&nbsp;在上述几例中，在某个柱子上都没有显示相应的数值，下面让我们为每个柱子都加上它的数值，我们新建一个sample4.jsp页面，其内容如下：</p>
<p align="left">&lt;%@ page contentType="text/html;charset=GBK"%&gt; &lt;%@ page import="org.jfree.chart.ChartFactory, org.jfree.chart.JFreeChart, org.jfree.chart.plot.PlotOrientation, org.jfree.chart.servlet.ServletUtilities, org.jfree.data.category.CategoryDataset, org.jfree.data.general.DatasetUtilities, org.jfree.chart.plot.*, org.jfree.chart.labels.*, org.jfree.chart.renderer.category.BarRenderer3D, java.awt.*, org.jfree.ui.*, org.jfree.chart.axis.AxisLocation"%&gt; &lt;% double[][] data = new double[][] {{1310, 1220, 1110, 1000}, {720, 700, 680, 640}, {1130, 1020, 980, 800}, {440, 400, 360, 300}}; String[] rowKeys = {"猪肉", "牛肉","鸡肉", "鱼肉"}; String[] columnKeys = {"广州", "深圳", "东莞", "佛山"}; CategoryDataset dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data); JFreeChart chart = ChartFactory.createBarChart3D("肉类销量统计图", "肉类", "销量", dataset, PlotOrientation.VERTICAL, true, true, false); CategoryPlot plot = chart.getCategoryPlot(); //设置网格背景颜色 plot.setBackgroundPaint(Color.white); //设置网格竖线颜色 plot.setDomainGridlinePaint(Color.pink); //设置网格横线颜色 plot.setRangeGridlinePaint(Color.pink); //显示每个柱的数值，并修改该数值的字体属性 BarRenderer3D renderer = new BarRenderer3D(); renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator()); renderer.setBaseItemLabelsVisible(true); //默认的数字显示在柱子中，通过如下两句可调整数字的显示 //注意：此句很关键，若无此句，那数字的显示会被覆盖，给人数字没有显示出来的问题 renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_LEFT)); renderer.setItemLabelAnchorOffset(10D); //设置每个地区所包含的平行柱的之间距离 //renderer.setItemMargin(0.3); plot.setRenderer(renderer); //设置地区、销量的显示位置 //将下方的&#8220;肉类&#8221;放到上方 plot.setDomainAxisLocation(AxisLocation.TOP_OR_RIGHT); //将默认放在左边的&#8220;销量&#8221;放到右方 plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT); String filename = ServletUtilities.saveChartAsPNG(chart, 700, 400, null, session); String graphURL = request.getContextPath() + "/DisplayChart?filename=" + filename; %&gt; &lt;img src="&lt;%= graphURL %&gt;" width=700 height=400 border=0 usemap="#&lt;%= filename %&gt;"&gt;</p>
<p align="left">运行效果如下所示：</p>
<p align="left"><img alt="用JFreeChart增强JSP报表的用户体验（图四）" src="http://www.sucai.com/tech/newsfile/12000-12999/12619/080410212563413.jpg" width="590" border="0" /></p>
<p align="left">注意：jfreechart的很多版本不兼容，请大家在运行此例时确认下载了对应的版本。</p>
<p align="left">三．&nbsp; 饼图</p>
<p align="left">在WebRoot目录下建立名为pie的子目录，用来存放本教程中饼图的实例jsp页面。下面让我们来看一个简单的三维饼图。首先在pie目录下建立一个名为sample1.jsp的页面。<br />
在JFreeChart中，与饼图绘制密切相关的类如下：<br />
1）&nbsp; PiePlot<br />
饼图绘制类，可以用来设置饼图的相关属性。例如：<br />
PiePlot pieplot = (PiePlot)jfreechart.getPlot();<br />
pieplot.setLabelFont(new Font("SansSerif", 0, 12));<br />
pieplot.setNoDataMessage("No data available");<br />
pieplot.setCircular(false);<br />
pieplot.setLabelGap(0.02D);<br />
2）&nbsp; DefaultPieDataset<br />
默认的饼图数据集类，用来存储饼图显示的相关数据信息。例如：<br />
DefaultPieDataset dataset = new DefaultPieDataset();<br />
dataset.setValue("品德", new Double(0.2D));<br />
dataset.setValue("体育", new Double(0.2D));<br />
dataset.setValue("音乐", new Double(0.2D));<br />
dataset.setValue("其余成绩", new Double(0.4D));<br />
3）&nbsp; ChartFactory<br />
可利用该制图工厂类createPieChart来创建一个饼图的JFreeChart对象，例如：<br />
JFreeChart jfreechart = ChartFactory.createPieChart("饼图示例", dataset, true, true, false);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面让我们看一个简单的例子，修改sample1.jsp的内容如下：</p>
<p align="left">&lt;%@ page contentType="text/html;charset=GBK"%&gt; &lt;%@ page import="org.jfree.chart.*, org.jfree.chart.plot.PiePlot, org.jfree.data.general.DefaultPieDataset, org.jfree.chart.servlet.ServletUtilities, java.awt.*"%&gt; &lt;% //设置数据集 DefaultPieDataset dataset = new DefaultPieDataset(); dataset.setValue("初中高级程序员", 0.55); dataset.setValue("项目经理", 0.1); dataset.setValue("系统分析师", 0.1); dataset.setValue("软件架构师", 0.1); dataset.setValue("其他", 0.2); //通过工厂类生成JFreeChart对象 JFreeChart chart = ChartFactory.createPieChart3D("IT行业职业分布图", dataset, true, false, false); PiePlot pieplot = (PiePlot) chart.getPlot(); pieplot.setLabelFont(new Font("宋体", 0, 12)); //没有数据的时候显示的内容 pieplot.setNoDataMessage("无数据显示"); pieplot.setCircular(false); pieplot.setLabelGap(0.02D); String filename = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, session); String graphURL = request.getContextPath() + "/DisplayChart?filename=" + filename; %&gt; &lt;img src="&lt;%= graphURL %&gt;" width=500 height=300 border=0 usemap="#&lt;%= filename %&gt;"&gt;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以看出，饼图的绘制与柱状图的绘制类似，该例的运行效果如下：</p>
<p align="left"><img height="303" alt="用JFreeChart增强JSP报表的用户体验（图五）" src="http://www.sucai.com/tech/newsfile/12000-12999/12619/080410212563414.jpg" width="496" border="0" /></p>
<p align="left">有时候我们还想知道某块所占的具体分值，或者需要突出显示某一块。这时候需要对上例进行部分修改：dataset.setValue("其他", 0.2);后的那段改成：<br />
//通过工厂类生成JFreeChart对象<br />
JFreeChart chart = ChartFactory.createPieChart3D("IT行业职业分布图", dataset, true, false, false);<br />
PiePlot pieplot = (PiePlot) chart.getPlot();<br />
pieplot.setLabelFont(new Font("宋体", 0, 12));<br />
//没有数据的时候显示的内容<br />
pieplot.setNoDataMessage("无数据显示");<br />
pieplot.setCircular(false);<br />
setExplodePercent方法很重要，它将Label为某名称的某块挖出来突出显示，而后两句实现的效果是在&#8220;初中高级程序员&#8221;等名称后加上百分比，改成&#8220;初中高级程序员=55%&#8221;等。加上如上的代码后，同时还需要将相关的两个java包：org.jfree.chart.labels.StandardPieSectionLabelGenerator和java.text.NumberFormat引入到该jsp页面中。此时的运行结果如下：</p>
<p align="left"><img height="248" alt="用JFreeChart增强JSP报表的用户体验（图六）" src="http://www.sucai.com/tech/newsfile/12000-12999/12619/080410212563415.jpg" width="416" border="0" /></p>
<p align="left">&nbsp;通过JFreeChart还可以提供漂亮的水晶饼图效果，接着让我们新建一个sample3.jsp页面来体验一下超炫美图吧。修改sample3.jsp页面如下：<br />
&lt;%@ page contentType="text/html;charset=GBK"%&gt;<br />
&lt;%@ page import="org.jfree.chart.*,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.jfree.chart.servlet.ServletUtilities,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.jfree.util.Rotation,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.jfree.data.general.DefaultPieDataset,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.jfree.chart.plot.PiePlot3D"%&gt;<br />
&lt;%<br />
//设置数据集<br />
DefaultPieDataset dataset = new DefaultPieDataset();<br />
dataset.setValue("初中高级程序员", 0.55);<br />
dataset.setValue("项目经理", 0.1);<br />
dataset.setValue("系统分析师", 0.1);<br />
dataset.setValue("软件架构师", 0.1);<br />
dataset.setValue("其他", 0.2);<br />
&nbsp;<br />
//通过工厂类生成JFreeChart对象<br />
JFreeChart chart = ChartFactory.createPieChart3D("IT行业职业分布图", dataset, true, true, false);<br />
//获得3D的水晶饼图对象<br />
PiePlot3D pieplot3d = (PiePlot3D) chart.getPlot();<br />
//设置开始角度<br />
pieplot3d.setStartAngle(150D);<br />
//设置方向为&#8221;顺时针方向&#8220;<br />
pieplot3d.setDirection(Rotation.CLOCKWISE);<br />
//设置透明度，0.5F为半透明，1为不透明，0为全透明<br />
pieplot3d.setForegroundAlpha(0.5F);<br />
pieplot3d.setNoDataMessage("无数据显示");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
String filename = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, session);<br />
String graphURL = request.getContextPath() + "/DisplayChart?filename=" + filename;<br />
%&gt;<br />
&lt;img src="&lt;%= graphURL %&gt;"width=500 height=300 border=0 usemap="#&lt;%= filename %&gt;"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 利用setForegroundAlpha()方法可以设置3D饼图的透明度，利用setStartAngle()可以设置其开始角度，利用setDirection()方法可以设置其方向。该例的运行效果如下图所示：<br />
&nbsp;<img height="302" alt="用JFreeChart增强JSP报表的用户体验（图七）" src="http://www.sucai.com/tech/newsfile/12000-12999/12619/080410212563416.jpg" width="500" border="0" /></p>
 <img src ="http://www.blogjava.net/jvict/aggbug/318222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-04-14 09:15 <a href="http://www.blogjava.net/jvict/articles/318222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FreeBSD 8 mysql apache php java整合</title><link>http://www.blogjava.net/jvict/articles/309446.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 14 Jan 2010 05:47:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/309446.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/309446.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/309446.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/309446.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/309446.html</trackback:ping><description><![CDATA[<strong>1.下载安装FreeBSD 8，ＤＶＤ１<br />
2.安装mysql 5 - 利用ports安装<br />
</strong><font size="2">cd /usr/ports/databases/mysql50-server/ <br />
make install clean # n长的编译过程 <br />
rehash <br />
mysql_install_db --user=mysql <br />
chown -R mysql /var/db/mysql/<br />
chgrp -R mysql /var/db/mysql/<br />
/usr/local/bin/mysqld_safe -user=mysql &amp;<br />
<br />
mysqld_safe－－MySQL服务器启动脚本 <br />
mysqld_safe是在Unix或是NetWare系统推荐使用来启动MySQL服务器的方法。mysqld_safe添加了许多安全的特征，例如，当发生错误时重新启动服务器，并且可以将运行时的信息写入错误日志文件<br />
<br />
<li>The port installation will put a script file mysql-server.sh<br />
in /usr/local/etc/rc.d which will has capability to start MySQL server.<br />
To enable MySQL server to start automatically after every FreeBSD<br />
server reboot, enter the following command in CLI:
<p><span style="color: red">echo &#8216;mysql_enable=&#8221;YES&#8221;&#8216; &gt;&gt; /etc/ rc.conf<br />
</span></p>
<p>mysqladmin -u root password newpassword (改变root帐户密码）<br />
</p>
<li>MySQL 5.0 installation done. <br />
------------------------------------------------------------------------<br />
<strong>3.安装 Apache Web Server 2.2<br />
</strong>Install Apache HTTP Server 2.20 by using FreeBSD Ports Collection: <br />
cd /usr/ports/www/apache22<br />
make install clean<br />
<li>A Apache HTTP Server script apache22.sh is located at<br />
/usr/local/etc/rc.d to provide Apache HTTP Server start and shutdown <font color="#333333">.</font> <br />
service. To enable Apache web server to automatically starts whenever<br />
after server reboots, issue the following command at CLI: <br />
<span style="color: red">echo &#8216;apache22_enable =&#8221;YES&#8221;&#8216; &gt;&gt; /etc/ rc.conf<br />
</span>
<li>To start Apache HTTP web server immediately, use: <br />
/usr/local/sbin/apachectl start<br />
or<br />
/usr/local/etc/rc.d/apache22.sh start<br />
<li>Apache installation finished. <br />
<br />
<strong>4.Installing PHP Hypertext Preprocessor Scripting Language 5 and PHP 5 Extensions<br />
</strong>
<li>Install by enter the following commands on FreeBSD OS command line,<br />
wait for previous command to finish before running the next command: cd /usr/ports/lang/php5<br />
make install clean<br />
<li>If you&#8217;re prompted, select &#8220;use Apache 2.x instead&#8221;. <br />
<li>Continue with the following commands to install PHP5 extensions and modules to enable the support of the modules in Apache: <br />
cd /usr/ports/lang/php5-extensions </font>make config<br />
<li>At Options for php5-extension 1.0 menu, select all PHP<br />
extensions and modules that you may use with Apache webserver. This is<br />
a part of the configuration for PHP, where you need to enable features<br />
of PHP that come in modules, such as ability to manage user sessions,<br />
interface with databases and many others. Default extensions such as<br />
ctype functions support, HASH Message Digest Framework support, session<br />
support and etc have been selected. Other popular extensions that you<br />
most likely to be in used are MySQL database support and GD library<br />
support. Use space bar to select or unselect the extensions and press<br />
Enter when done.
<li>Continue the installation of php5-extensions with the following commands: <br />
make install clean<br />
<li>If there are any message the pops up and prompts you to select<br />
some options or configurations, you can just accept the default<br />
settings by pressing Enter. Some modules that may prompt you for action&nbsp; <br />
include php5-gd, php5-mbstring and php5-sqlite.
<li>Edit the Apache configuration file in order to enable Apache web server to load the PHP modules when initialization: <br />
<li>Go to Apache configuration file location by cd /usr/local/etc/apache2/ <br />
<li>Edit Apache configuration file by vi httpd.conf <br />
<li>Search for LoadModule lines, after the last LoadModule line, but within the same section, add the following 2 lines: <br />
AddType application/x- httpd-php .php<br />
AddType application/x- httpd-php-source .phps<br />
<li>Optionally, copy /usr/local/etc/php.ini-recommended or<br />
/usr/local/etc/php.ini-dist to /usr/local/etc/php.ini (in same<br />
directory), which will enable you to tune and change the default<br />
settings of behaviours of PHP.
<li>Start the Apache HTTP web server by using apachectl start<br />
(or restart Apache HTTP web server by using apachectl restart).<br />
apachectl is located in /usr/local/sbin, if you encounter Command not<br />
found problem, try to change directory to its location.
<li>PHP5 installation done. <font color="#333333">。</font> <br />
A web server has been setup with the FreeBSD with Apache, MySQL and<br />
PHP. The document root of the web server (where you should put your<br />
HTML and PHP files is at /usr/local/www/apache22/data/ and you will<br />
need a SecureFTP (SFTP) client such as WinSCP to upload your files to<br />
web server securely.
<p><br />
<strong>5.安装php后若apache不能启动：<br />
</strong>在 FreeBSD 下安装 apache22 会出现类似的 warming:<br />
No such file or directory: Failed to enable the 'httpready' Accept Filter</p>
<p>解决方案：<br />
#kldload accf_http并在 /boot/defaults/loader.conf 中加入下面 2 行，以便下次启动自动装载模块<br />
accf_data_load="YES"<br />
accf_http_load="YES"<br />
<br />
<strong>问题</strong><br />
[root@freebsd ~]# apachectl -t<br />
httpd: Could not reliably determine the server's fully qualified domain name, using freebsd.web for ServerName</p>
<p>解决方案：<br />
vi /usr/local/etc/apache22/httpd.conf<br />
添加这么一行：<span style="color: red">ServerName 127.0.0.1:80</span></p>
</li>
<img src ="http://www.blogjava.net/jvict/aggbug/309446.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-01-14 13:47 <a href="http://www.blogjava.net/jvict/articles/309446.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Cent OS OpenJava 1.6 Apache 2.x Tomcat 6.x JK-1.2.28(Apache Tomcat Connectors )整合</title><link>http://www.blogjava.net/jvict/articles/309345.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Wed, 13 Jan 2010 10:32:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/309345.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/309345.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/309345.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/309345.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/309345.html</trackback:ping><description><![CDATA[<strong>问题：当从apache 2.2.14换成apache 2.2.3时，已配好的jsp环境无法正常运行，mod_jk.so不能使用<br />
</strong>&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">重新用yum 安装了httpd-devel套件生成了apxs后，重新对tomcat-connector源程序进行make clean,.configurage,make,make install后用新生成的mod_jk.so即可正常。当系统增加虚拟主机后，httpd.conf配置文件也要进行相应改变。下面有详细说明。</span><br />
<strong>1.下载解压&nbsp;Apache安装至 /usr/local/apache<br />
2.下载解压tomcat安装至 /usr/local/tomcat<br />
3.下载JK-1.2.28源文件(Apache Tomcat Connectors ) 在Tomcat官网界面上有相应连接<br />
4. 编译JK-1.2.28<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;进入native目录<br />
　　./configure -with-apxs=/home2/local/apache/bin/apxs<br />
　　make<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cp ./apache-2.0/mod_jk.so /usr/local/apache/modules<br />
<strong>5.修改apache配置文件httpd.conf<br />
</strong>#增加index.jsp&nbsp;&nbsp;&nbsp;&nbsp;<br />
&lt;IfModule dir_module&gt;<br />
&nbsp;&nbsp;&nbsp; DirectoryIndex index.html index.php index.jsp<br />
&lt;/IfModule&gt;<br />
<br />
<p>LoadModule jk_module&nbsp;&nbsp;&nbsp; modules/mod_jk.so<br />
<br />
JkWorkersFile /usr/local/apache/conf/workers.properties<br />
JkLogFile&nbsp;&nbsp;&nbsp;&nbsp; /usr/local/apache/logs/mod_jk.log<br />
JkLogLevel&nbsp;&nbsp;&nbsp; info<br />
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "<br />
JkMount /*.jsp worker1<br />
JkMount /*.do worker1 // 此项为配置servlet, 在web.xml中可自由配置路径如<span style="color: red">：&lt;url-pattern&gt;/servlet/login&lt;/url-pattern&gt;<br />
</span>// 此时不宜配置成/*, 否则将会屏蔽掉php等其它脚本解析。<br />
<br />
# 以下两项可以省略不要<br />
#JkMount /servlet/* worker1<br />
#JkMount&nbsp; /*.do* worker1<br />
<br />
<span style="color: red"><strong>如果存在虚拟主机，需要进行单独配置，如下所示：<br />
</strong><span style="color: #000000">&lt;VirtualHost *:80&gt;<br />
&nbsp;&nbsp;&nbsp; DocumentRoot /var/www/html/<br />
&nbsp;&nbsp;&nbsp; ServerName&nbsp;<a href="http://www.example.com/">www.example.com</a><br />
&nbsp;&nbsp;&nbsp; ServerAlias&nbsp;example.com<br />
&nbsp;<span style="color: #0000ff">&nbsp;&nbsp; &lt;Location "/*.jsp"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JkMount worker1<br />
&nbsp;&nbsp;&nbsp; &lt;/Location&gt;<br />
</span>&lt;/VirtualHost&gt;<br />
</span></span><br />
<br />
<strong>6. 在apache/conf中增加workers.properties</strong><br />
# Define 1 real worker using ajp13<br />
worker.list=worker1</p>
<p># Set properties for worker1 (ajp13)<br />
worker.worker1.type=ajp13<br />
worker.worker1.host=localhost<br />
worker.worker1.port=8009</p>
<strong>7. 修改Tomcat/conf中的server.xml配置文件，在host中增加路径映射<br />
</strong>&lt;Context path="" docBase="/usr/local/apache/htdocs" debug="0" reloadable="true" crossContext="true" /&gt; <br />
<br />
<strong>8.配置tomcat为服务</strong><br />
编写tomcat脚本，chkconfig --list 显示已有服务，chkconfig --add 添加服务 <br />
<br />
<strong>9.自定义访问找不到相应页面时，tomcat的404错误。</strong>400错误设置方法相同<br />
编辑tomcat安装目录中conf中的web.xml在最后加入<br />
&nbsp;&nbsp;&nbsp; &lt;error-page&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;error-code&gt;404&lt;/error-code&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;location&gt;/404.html&lt;/location&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/error-page&gt;<br />
<img src ="http://www.blogjava.net/jvict/aggbug/309345.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-01-13 18:32 <a href="http://www.blogjava.net/jvict/articles/309345.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2EE开发编程规范</title><link>http://www.blogjava.net/jvict/articles/226768.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Wed, 03 Sep 2008 12:45:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/226768.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/226768.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/226768.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/226768.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/226768.html</trackback:ping><description><![CDATA[<table cellspacing="0" cellpadding="0" width="96%" align="center" border="0">
    <tbody>
        <tr>
            <td class="d_font3" valign="bottom" align="center" height="24"></td>
        </tr>
        <tr>
            <td bgcolor="#e3e3e3" height="3"></td>
        </tr>
        <tr>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td class="d_font4">
            <p>J2ee项目一般是大型项目，大型项目都需要团队协作开发。团队协作开发的成功需要一致的开发规范。对软件进行后续的维护成本远远要大于它最初的开发成本，保证开发的系统是可持续工作易于维护就至关重要了。可靠的OO设计原理实践及一个良好的JAVA编程规范在整个J2EE项目生命周期中变得十分重要。在团队开发中，应该保持所有的代码上都乎合- 1 -一个相同的标准，并且代码在风格上应该保持一致。&nbsp;</p>
            <p>JAVA编程标准为什么会显得这么重要呢？我们经常会发生这样的情况：太注重于j2ee的某方面的技术细节，而忽略了良好的程序设计和编程习惯。太多的J2EE项目的失败就是因为在项目中含有太多草率的代码，使得整个系统变得脆弱、不可维护，最终只得放弃整个项目。&nbsp;</p>
            <p>关于编程规范，它是一个巨大的领域。在这里不作详细的阐述。这里只列出了在实际J2EE开发中十分重要的问题进行讨论，同时对这些问题有不同的见解和解决方法。一切都应该以实践为主。&nbsp;</p>
            <p><strong>一、不要去发明自己的标准</strong>&nbsp;</p>
            <p>几乎每一门编程语言都有自己的一套编程标准，但是千万不要去发明自己的编程标准。</p>
            <p>Java是一门简单的语言，我们应该以sun的java编程标准作为准则。在它的基础上进行扩充。比如C++语言使用的匈牙利命名法，并不适合用于在JAVA。也千万不要在一种开发语言中使用另外一种开发语言的编程标准。</p>
            <p><strong>二、java类中代码的组织结构</strong>&nbsp;</p>
            <p>1.按照方法的功能，而不是按照方法的可访问性来组织方法。&nbsp;</p>
            <p>比如：不是把所有的public方法放在private方法的前面，而是把一个private方法放成使用它的那些public方法的附近。</p>
            <p>2.类的组织约定&nbsp;</p>
            <p>◆静态变量和方法<br />
            ◆成员变量<br />
            ◆构造函数<br />
            ◆接口的实现方法，连同支持它们的私用方法 <br />
            ◆该类独有的公有方法（不包括已实现接口的公用方法）<br />
            ◆抽像保护方法 <br />
            ◆提供给子类使用的保护方法 <br />
            ◆与前面任何一组都无关的实现方法</p>
            <p><strong>三、按职责进行分类，做你该做的事情！</strong> </p>
            <p>每一个类应该具有一个明确的职责，不要把它相干和不相干的代码都填进来。那些不相干的代码应该重构为另一个单独的类或者是助手类。如果一个不同概念级别上的代码对相同的对象重复调用，那么它可能需提升为一个父类。而其它对象通过继承这个父类。&nbsp;</p>
            <p>通过把相干的重复代码提取到父类和把不相干的代码重构为一个助手类是解决代码重复的常用方法。这样可以阻止一个类的爆炸式增长，变成一个臃肿的类。一个类，包括Javadoc和内部注释，如果超过了500行代码，它都是需要重构的候选者。因为它可能已经承担了太多的职责。可以运用策略模式来用一个接口把原类与助手类分开，实现助手类在不同的情况可以有不同的实现。来提高系统的灵活性。 </p>
            <p>每一个方法都应该具有一个单一而清晰明确的职责。否则这个方法应该进行重构。同时这也可以防止方法变得很长。 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp;1public String addCounter(CounterDTO counter) throws BusinessException ...{<br />
                        &nbsp;2String buffer ="00000000";<br />
                        &nbsp;3//读取seqence <br />
                        &nbsp;4String sequenceStr= (String) </p>
                        <p>   this.getSqlMapClientTemplate().queryForObject(SqlID.GET_COUNTER_PK,null);<br />
                        &nbsp;5int seqLength ;<br />
                        &nbsp;6seqLength = sequenceStr.length();<br />
                        &nbsp;7String counterNo ="";<br />
                        &nbsp;8String regionCode = counter.getRegionCode();<br />
                        &nbsp;9if(regionCode.length() &gt; 2) ...{<br />
                        10regionCode = regionCode.substring(0,2);<br />
                        11}<br />
                        12counterNo = regionCode + buffer.substring(0,buffer.length() - seqLength)+sequenceStr;<br />
                        13counter.setCounterNo(counterNo);//设置主键 <br />
                        14<br />
                        15sqlMap.insert(SqlID.ADD_COUNTER, counter);//插入柜面数据 <br />
                        16return pk;<br />
                        17<br />
                        18}<br />
                        19</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>上面的方法是新增一个柜面信息，它有三个步骤：&nbsp;</p>
            <p>1.读取指定的sequence,获得一个唯一柜面流水号。</p>
            <p>2.根据柜面的机构代码和流水号产生一个唯一8位的柜面号，柜面号由两位的机构代码+6位的流水号组成。流水号不足6位，在前面以0补充。&nbsp;</p>
            <p>3.设置柜面信息的柜面号为新产生的柜面号，并插入数据库，成功则返回新的柜面号。 </p>
            <p>重构后的代码：</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp;1//读取sequence,获得流水号 <br />
                        &nbsp;2private String getCounterSequenceNo() throws BusinessException ...{<br />
                        &nbsp;3return (String) this.getSqlMapClientTemplate().queryForObject(SqlID.GET_COUNTER_PK,null);<br />
                        &nbsp;4}<br />
                        &nbsp;5<br />
                        &nbsp;6//根据机构代码来生成柜面号 <br />
                        &nbsp;7private String generateCounterNo(String regionCode)throws BusinessException ...{<br />
                        &nbsp;8String buffer ="00000000";<br />
                        &nbsp;9String sequenceStr = this.getCounterSequenceNo();<br />
                        10int seqLength ;<br />
                        11seqLength = sequenceStr.length();<br />
                        12String counterNo ="";<br />
                        13if(regionCode.length() &gt; 2) ...{<br />
                        14regionCode = regionCode.substring(0,2);<br />
                        15}<br />
                        16counterNo = regionCode + buffer.substring(0,buffer.length() - seqLength)+sequenceStr;<br />
                        17return counterNo;<br />
                        18}<br />
                        19<br />
                        20//新增柜面 <br />
                        21public String addCounter(CounterDTO counter) throws BusinessException ...{<br />
                        22String pk=null;<br />
                        23pk = this.generateCounterNo(counter.getRegionCode());//产生主键 <br />
                        24counter.setCounterNo(pk);//设置主键 <br />
                        25sqlMap.insert(SqlID.ADD_COUNTER, counter);//插入柜面数据 <br />
                        26return pk;<br />
                        27}<br />
                        28</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>重构后的代码大大的便于阅读和维护。使方法具有明确的责任。&nbsp;</p>
            <p>注意在重构的时候，通过我们把那些相对独立的任务变成一个私有的方法。 </p>
            <p>关于一个方法应该限制为多长，没有明确的规定。它应该以人的舒服度为主。一个方法包括注释（不含javadoc）的实现代码能够在一屏中可以进行阅读。否则它就应该需要进行重构。一般来说，一个方法的代码控制在30-40行是最佳的。</p>
            <p>#p#</p>
            <p><strong>四、避免重复的代码</strong>&nbsp;</p>
            <p>在一个类中，可能在各个方法中产生了相同的代码块。这就是重复的代码。重复的代码是难以维护和难以理解的。有一个类其中有两个方法如下： </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp;1//发送一个包裹 <br />
                        &nbsp;2public String deliveryWarePack(WarePackDTO warePack)<br />
                        &nbsp;3throws BusinessException ...{<br />
                        &nbsp;4CommonDAOFactory factory = (CommonDAOFactory) this.context<br />
                        &nbsp;5.getBean(CommonDAOFactory.COMMON_DAO_FACTORY_BEAN_NAME);<br />
                        &nbsp;6WarePackDAO warePackDAO = (WarePackDAO) factory<br />
                        &nbsp;7.getDAOByRegionCode(this.WARE_PACK_DAO_NAME, "00");<br />
                        &nbsp;8&#8230;&#8230;&#8230;&#8230;<br />
                        &nbsp;9}<br />
                        10<br />
                        11//根据包号得到包信息 <br />
                        12public WarePackDTO getWarePackByPackNum(String packNum)<br />
                        13throws BusinessException ...{<br />
                        14CommonDAOFactory factory = (CommonDAOFactory) this.context<br />
                        15.getBean(CommonDAOFactory.COMMON_DAO_FACTORY_BEAN_NAME);<br />
                        16WarePackDAO warePackDAO = (WarePackDAO) factory<br />
                        17.getDAOByRegionCode(this.WARE_PACK_DAO_NAME, "00");<br />
                        18&#8230;&#8230;&#8230;<br />
                        19}<br />
                        20</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>这似乎没有任何问题，但是这样的代码重复可能会导致严重的问题。&nbsp;</p>
            <p>1. 太多的代码：如果重构后只用两行就可以了。</p>
            <p>2. 令阅读者迷惑不解，阅读者可能会对开发人员产生怀疑，认为这两处是两个不相同的代码，从而去进行比较，花费更多的时间和精力。&nbsp;</p>
            <p>3. 造成修改的不一致，经常可能发现对一个方法进行了修改，而忘记也应该对另一个方法也进行相同的修改。增加代码的维护量。&nbsp;</p>
            <p>修改后的代码：</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp;1private WarePackDAO warePackDAO= getWarePackDAO();<br />
                        &nbsp;2private CommonDAOFactory getFactory() ...{<br />
                        &nbsp;3CommonDAOFactory factory =<br />
                        &nbsp;4= (CommonDAOFactory) this.context<br />
                        &nbsp;5.getBean(CommonDAOFactory.COMMON_DAO_FACTORY_BEAN_NAME);<br />
                        &nbsp;6return factory;<br />
                        &nbsp;7}<br />
                        &nbsp;8<br />
                        &nbsp;9Private WarePackDAO getWarePackDAO()...{<br />
                        10WarePackDAO dao = (WarePackDAO)this. getFactory(). getDAOByRegionCode(<br />
                        11this.WARE_DAO_NAME, "00");<br />
                        12return dao;<br />
                        13}<br />
                        14<br />
                        15//发送一个包裹 <br />
                        16public String deliveryWarePack(WarePackDTO warePack)<br />
                        17throws BusinessException ...{<br />
                        18String packNumber = this.warePackDAO.insertWarePack(warePack);<br />
                        19}<br />
                        20<br />
                        21//根据包号得到包信息 <br />
                        22public WarePackDTO getWarePackByPackNum(String packNum)<br />
                        23throws BusinessException ...{<br />
                        24WarePackDTO warePack = this.warePackDAO.getWarePack(packNum);<br />
                        25&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;..<br />
                        26}<br />
                        27</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p><strong>五、最小的作用范围和权利</strong> </p>
            <p>成员变量和方法通常应该拥有尽可能小的可见度(包括private ,protected,public和缺省的变量和方法)。变量应该尽可能局部地进行声明。 </p>
            <p>1. 绝不使用public成员变量&nbsp;</p>
            <p>2. 成员变量首先考虑为private。避免使用protected的成员变量，唯一的例外可能是声明为final protected的成员变量。</p>
            <p>成员变量声明为protected final 是可能需要提供给子类使用，但是这样同样也破坏了类的封装性。更好一点的做法是把成员变量声明为private final的。并提供一个protected 的方法供子类调用，在这个方法中返回 private final 的成员变量。&nbsp;</p>
            <p>3. 一个类只应该有它所实现接口的公有方法和必要的成员变量的getter和setter方法以及这个类提供给外部访问的方法声明为public。其它的统统为protected 或private。</p>
            <p>4. 一个类的方法需要提供给子类有不同的实现而进行重写，或者需要把实现交给子类去完成应该声明为protected。其它的统统声明为private 尽可能的把方法隐藏起来，public ,protected ,默认的方法,private; public方法越少这个类就越简洁。就更便于使用，测试和重构。&nbsp;</p>
            <p>虽然方法的调用不像对成员变量的直接访问那样危险。但是尽可能的降低方法的可见度在于：降低了类之间的耦合度。把一个类的外在需求与一个类的实现逻辑分开来是十分有必要的。这既可防止这个类的内部状态遭到意外的破坏，同时也简化开发人员处理这个类的任务。通常只提供他们所需要的方法。&nbsp;</p>
            <p>5. 变量应该尽可能的在使用它的地方声明。 </p>
            <p>作用范围内的变量越少，可阅读性就越高，也更加便于调试。杜绝使用C语言或delphi的变量声明方式（变量在方法的开始处声明）。 </p>
            <p>#p#</p>
            <p><strong>六、this关键字的使用</strong>&nbsp;</p>
            <p>this是一个java中经常使用的关键字，但是我们也经常忘记使用this而使得在访问两个变量时造成意外的错误。下面的方法将会被编译通过，而并没有给成员变量name赋值。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>1private String name;<br />
                        2public void setName(String name)...{<br />
                        3name = name;<br />
                        4}<br />
                        5</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>还有另外的一种形式也会被编译通过(在录入方法参数时候可能输错某个字母)。 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>public void setName(String nme)...{<br />
                        name = name;<br />
                        } </p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>在上面的两种情况中，假如没有什么方法对name进行初始化，那么在运行的时候出现莫名其妙的空指针异常。</p>
            <p>在第一个方法中把方法参数赋给方法参数自身，在第二方法中把成员变量赋给成员变量自身。除了没有达到预期的效果外都还会造成空指针异常。并且这种错误在编译时都能正常通过。 </p>
            <p>建议：采用下面良好的习惯来避免上面出现的错误：&nbsp;</p>
            <p>1. 访问成员变量总是使用this关键字。这样使得我们总是给期望的成员变量进行访问。而解决变量的多议性。 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>1public void setName(String name)...{<br />
                        2this.name = name;<br />
                        3} </p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>2. 给方法参数赋予一个有意义或有区别的名字（不要使用_下划线来命名变量，只有常量才使用下划线.正确的反映参数的用途或代表的意义，并且避免了我们刚才见过的问题。 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>1public void setName (String newName)...{<br />
                        2this.name = newName;<br />
                        3}<br />
                        4</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>3. 局部变量名变该相对短而成员变量名应该相对冗长。例如，I应该是一个变部变量,&nbsp;userInfo应该是一个成员变量。</p>
            <p>通常，成员变量名以一个小写字母开头的接口或类名，而局部变量名应在当前的上下文环境中代表它的含议。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>1private SystemUserInfo systemUserInfo;<br />
                        2public void methodXX()...{<br />
                        3SystemUserInfo newUser = new SystemUserInfo();<br />
                        4}<br />
                        5</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p><strong>七、不要使用字面常量</strong>&nbsp;</p>
            <p>除了一些大家都明白的如0值，空值null,和空串&#8221;&#8221;外，不要在java代码中使用字面常量。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>1if (ware.getWareDetailList() != null<br />
                        2&amp;&amp; ware.getWareDetailList().size() &gt; 100) ...{<br />
                        3request.setAttribute(super.SERVICE_BUSINESS_INFO,<br />
                        4"物品数量超过了上限，请您将物品数量控制在100件以内"); </p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>看上面的例子。无耐的是，我们经常在j2ee项目中大量出现这样的代码。&nbsp;</p>
            <p>1．这样的代码没有明确的意义。必须被迫阅读代码来猜测100的含义。</p>
            <p>2．代码容易出错，我们必须被迫比较不同的字面值来确信它们是相同的，而且我们很容易错误的输入。&nbsp;</p>
            <p>3．修改100这个常数时，可能需要修改多处。 </p>
            <p>比较好的做法是使用一个常数，在JAVA中意味作使用static final的变量。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>1private static final int WARE_COUNT_LIMIT = 100;<br />
                        2if (ware.getWareDetailList() != null<br />
                        3&amp;&amp; ware.getWareDetailList().size() &gt; WARE_COUNT_LIMIT ) ...{<br />
                        4request.setAttribute(super.SERVICE_BUSINESS_INFO, </p>
                        <p>  "物品数量超过了上限，请您将物品数量控制在100件以内");<br />
                        5</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>一般情况下，这已经OK了。但是在有些情况下它仍然不够好，假如对于每次发送的物品数量限制并不是总是相同的，今天的常量，在明天可能就是一个经常变化的变量。&nbsp;</p>
            <p>可能下面的版本会更灵活一些： </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>1private static final int DEFAULT_WARE_COUNT_LIMIT = 100;<br />
                        2protected int wareCountLimit()...{<br />
                        3return DEFAULT_WARE_COUNT_LIMIT;<br />
                        4}<br />
                        5if (ware.getWareDetailList() != null<br />
                        6&amp;&amp; ware.getWareDetailList().size() &gt; wareCountLimit()) ...{<br />
                        7request.setAttribute(super.SERVICE_BUSINESS_INFO, </p>
                        <p>  "物品数量超过了上限，请您将物品数量控制在100件以内");<br />
                        8</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>这样我们可以把对物品数量的控制延迟到子类进行，子类可以通过重写wareCountLimit()方法来灵活控制。 </p>
            <p>#p#</p>
            <p>如何设计一个常量，可以有下面的标准来进行参照： </p>
            <p>1．如果字面常量应该是代码中的一部分，不应该使用常量变量或方法。&nbsp;</p>
            <p>比如：SQL语句。SQL语句本身就应该是代码的一部分，所以不应该再它们声明一个常量。 </p>
            <p>2. 永远都不会变化的常量或者变化的可能性相当少的常量，声明为static final的常量。例如：在所有应用服务器都相同的JNDI名。&nbsp;</p>
            <p>3. 在编译时可能会发生改变的常量，声明子类可以重写的protected的方法。例如：在应用服务器中可能需要变化的JNDI名，如TransactionManager的名称。</p>
            <p>4．在运行时可能会发生改变的常量，声明一个protected方法。例如：物品数量限制。</p>
            <p>5．受国际化影响的常量，声明一个proteced的方法。</p>
            <p>例如：根据不同的Local信息，需要显示不同的错误信息或语言。</p>
            <p>这个protected方法返回一个从ResourceBundle中查找的值。 </p>
            <p><strong>八、内部类和接口</strong> </p>
            <p>在JAVA中使用内部类和接口可以避免命名空间污染，内部类通常用来帮助外部类有一个一致的责任。除非进行Swing编程，尽可能的少用匿名内部类。而使用一个有类名的内部类会带来更多的好处。比如可以使用构造函数。 <br />
            使用内部类不能够实现代码重用。会导致重复代码的产生。在使用的时候要进行权衡。</p>
            <p><strong>九、Final 关键字</strong>&nbsp;</p>
            <p>1. 方法重写与final方法&nbsp;</p>
            <p>方法重写可能违反&#8220;理氏代换原则&#8221;和&#8220;开闭原则&#8221;。使用final方法有助于保证类的完整性。确保一些关键性的方法不让子类去重写。保证系统的安全性。&nbsp;</p>
            <p>比如： DispatchServlet 需要调用一系列的init()方法。而这些方法都是十分重要的。&nbsp;</p>
            <p>任何重写都可能会导致破坏系统的行为。通常的做法声明一个protected onInit()的空方法。没有任何代码。</p>
            <p>在final init()方法的最后调用onInit()这个空方法。&nbsp;而子类可以去重写onInit()这个方法来扩展功能，而又不破坏父类。</p>
            <p>2. final 类&nbsp;</p>
            <p>只有能够保证永远不变的对象才使用final类。&nbsp;</p>
            <p>3. final成员变量&nbsp;</p>
            <p>一个final的成员变量只可以被初始化一次，只能在两个地方进行初始化（声明时，或构造函数），此后就将不能改变。只有常量才使用final。</p>
            <p><strong>十、实现有用的toString方法</strong>&nbsp;</p>
            <p>实现一个有用的toString方法对于我们调试是十分重要的。实现toString方法在java中有专门的规范。在这不作讨论，简单一点说，是应该能够显示一个类的成员变量等关键信息。可以考虑使用辅助类，来实现toString方法。使用ToStringBuilder辅助类的reflectionToString方法,来实现toString方法。</p>
            <p><strong>十一、使用StringBuffer而不是String</strong>&nbsp;</p>
            <p>当需要进行多次字符串操作时优先考虑使用StringBuffer。而不是使用String。&nbsp;</p>
            <p>String 是一个final类。&nbsp;</p>
            <p>使用StringBuffer进行字符串操作，会带来更大的性能提升。</p>
            <p><strong>十二、可恶的空指针异常</strong>&nbsp;</p>
            <p>NullPointException是一个常见的错误，由于NullPointException是non-checked Exception所以它总是隐式的出错，无需要我们人为的去捕获。产生NullPointException，它又没有相关的有用的帮助信息，所以很难以跟踪。我们只能通过一些编程标准来减少它在运行时出现的次数。&nbsp;</p>
            <p>1. 处理空值的原则</p>
            <p>a. 没有充分的依据，永远都不要假设对象在某一时刻不可能为空。 </p>
            <p>b. 假如认为空值是一个错误的代码调用，则应该以文字说明。不要让它简单的抛出NullPointException;而是要记录为业务异常，并有直接的异常说明。 </p>
            <p>c. 通常对方法参数进行空值检查。&nbsp;</p>
            <p>2. 在页面参数传递中正确的对待空值和空串&nbsp;</p>
            <p>Web编程是无状态编程，web页面只能传递字符串给后台。通常后台程序在获取页面参数的时候要进行特殊字符处理，去掉字符串两端的空格，制表格等特殊字符。&nbsp;</p>
            <p>从页面获取的参数如果是空串应该认为它是空值。&nbsp;</p>
            <p>典型的处理如下：</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>1String s = (String)request.getParameter(name);<br />
                        2if(s != null ) ...{<br />
                        3s = s.trim();<br />
                        4}<br />
                        5<br />
                        6if("".equals(s)) ...{<br />
                        7s = null;<br />
                        8}<br />
                        9</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>#p#</p>
            <p>3. 正确处理从页面参数传递后把字符串转换为非字符串类型&nbsp;</p>
            <p>我们通常需要获取页面参数并转换为非字符串类型。一般是数值或日期类型。这需要有两个步骤：&nbsp;</p>
            <p>第一步是从页面获取字符串参数，如果是空串则要变为空值；</p>
            <p>第二步是把字符串转为相应的类型。</p>
            <p>例如：从页面获取一个年龄的参数。&nbsp;</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp;1Stirng ageStr = request.getParameter(&#8220;age&#8221;);<br />
                        &nbsp;2if(ageStr != null)...{<br />
                        &nbsp;3ageStr = ageStr.trim();<br />
                        &nbsp;4}<br />
                        &nbsp;5<br />
                        &nbsp;6if(&#8220;&#8221;.equals(ageStr))...{<br />
                        &nbsp;7ageStr = null;<br />
                        &nbsp;8}<br />
                        &nbsp;9<br />
                        10Int age = Integer. parseInt(ageStr);<br />
                        11</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>在太多的项目中有这样的代码出现，能够正常编译通过。&nbsp;</p>
            <p>但如果页面的age参数是一个录入域，可以由用户随便录入。并且在页面可能没有做相应完整的javascript控制的时候，很容易&nbsp; 就输入了一些不能进行转换为整数的非法字符串。Integer.parseInt()就会抛出NumberFormaterException。同样的情况也会出现在日期转换中。 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp;&nbsp; SimpleDateFormat format = new SimpleDateFormat(&#8220;yyyy-MM-dd&#8221;); <br />
                        &nbsp;&nbsp;&nbsp; format. Parse(dateStr);&nbsp;</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>这也有可能抛出ParseException。</p>
            <p>NumberFormaterException和parseException都是non-checked Exception。都不需强迫用户去处理。不知不觉就会让系统报异常，使得系统十分脆弱。&nbsp;</p>
            <p>象这种异常我们应该手动去处理，处理方法有两种：</p>
            <p>1. 把异常当空值处理，凡是报这种异常我都把它处理为空值。 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp;1Date birthday;<br />
                        &nbsp;2SimpleDateFormat format = new SimpleDateFormat(&#8220;yyyy-MM-dd&#8221;);<br />
                        &nbsp;3try...{<br />
                        &nbsp;4birthday= format.parse(dateStr);<br />
                        &nbsp;5}catch(ParseException e)...{<br />
                        &nbsp;6birthday = null;<br />
                        &nbsp;7}<br />
                        &nbsp;8</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>2. 把异常当输入错误处理，应该把相应的提示信息返回输入页面，要求用户重新输入合法的数据。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp;9Date birthday;<br />
                        10SimpleDateFormat format = new SimpleDateFormat(&#8220;yyyy-MM-dd&#8221;);<br />
                        11String errorMessage = null;<br />
                        12try...{<br />
                        13birthday= format.parse(dateStr);<br />
                        14}catch(ParseException e)...{<br />
                        15errorMessage = &#8220;日期必须为yyyy-MM-dd格式&#8221;<br />
                        16}<br />
                        17ModelAndView mav = null;<br />
                        18if(errorMessage != null)...{<br />
                        19mav = new ModelAndView(&#8220;inputView&#8221;);<br />
                        20mav.addObject(&#8220;error&#8221;,errorMessage);<br />
                        21}<br />
                        22<br />
                        23</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>3. 编写辅助类来处理页面参数 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp;1public class ServletRequestUtils ...{<br />
                        &nbsp;2<br />
                        &nbsp;3public static final String DEFAULT_DATE_FORMAT="MM/dd/yyyy";<br />
                        &nbsp;4<br />
                        &nbsp;5public static String getStringParameter(HttpServletRequest request, </p>
                        <p>    String name) ...{<br />
                        &nbsp;6String s = (String)request.getParameter(name);<br />
                        &nbsp;7if(s != null ) ...{<br />
                        &nbsp;8s = s.trim();<br />
                        &nbsp;9}<br />
                        10<br />
                        11if(s == null || "".equals(s)) ...{<br />
                        12return null;<br />
                        13}...{<br />
                        14return s;<br />
                        15}<br />
                        16}<br />
                        17<br />
                        18public static String getStringParameter(HttpServletRequest request, </p>
                        <p>  String name, String defaultValue) ...{<br />
                        19String s = (String)request.getParameter(name);<br />
                        20if(s != null ) ...{<br />
                        21s = s.trim();<br />
                        22}<br />
                        23<br />
                        24if(s == null || "".equals(s)) ...{<br />
                        25return defaultValue;<br />
                        26}...{<br />
                        27return s;<br />
                        28}<br />
                        29}<br />
                        30<br />
                        31public static Date getDateParameter(HttpServletRequest request, </p>
                        <p>  String name)throws BusinessException ...{<br />
                        32String dateString= getStringParameter(request,name);<br />
                        33SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_FORMAT);<br />
                        34try ...{<br />
                        35if(dateString != null &amp;&amp; !"".equals(dateString)) ...{<br />
                        36return format.parse(dateString);<br />
                        37}else ...{<br />
                        38return null;<br />
                        39}<br />
                        40}catch(ParseException e) ...{<br />
                        41throw new BusinessException("无效的日期输入:格式错误:"+dateString);<br />
                        42}<br />
                        43}<br />
                        44<br />
                        45public static Date getDateParameter(HttpServletRequest request , </p>
                        <p>   String name, String dateFormat)throws BusinessException...{<br />
                        46String dateString= getStringParameter(request,name);<br />
                        47SimpleDateFormat format = new SimpleDateFormat(dateFormat);<br />
                        48try ...{<br />
                        49if(dateString != null &amp;&amp; !"".equals(dateString)) ...{<br />
                        50return format.parse(dateString);<br />
                        51}else ...{<br />
                        52return null;<br />
                        53}<br />
                        54}catch(ParseException e) ...{<br />
                        55throw new BusinessException("无效的日期输入:格式错误:"+dateString);<br />
                        56}<br />
                        57}<br />
                        58<br />
                        59public static Date getDateParameter(String dateStr)throws BusinessException...{<br />
                        60<br />
                        61SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_FORMAT);<br />
                        62try ...{<br />
                        63if(dateStr != null &amp;&amp; !"".equals(dateStr)) ...{<br />
                        64return format.parse(dateStr);<br />
                        65}else ...{<br />
                        66return null;<br />
                        67}<br />
                        68}catch(ParseException e) ...{<br />
                        69throw new BusinessException("无效的日期输入:格式错误:"+dateStr);<br />
                        70}<br />
                        71}<br />
                        72<br />
                        73public static Date getDateParameter(String dateStr,String dateFmt)</p>
                        <p>   throws BusinessException...{<br />
                        74<br />
                        75SimpleDateFormat format = new SimpleDateFormat(dateFmt);<br />
                        76try ...{<br />
                        77if(dateStr != null &amp;&amp; !"".equals(dateStr)) ...{<br />
                        78return format.parse(dateStr);<br />
                        79}else ...{<br />
                        80return null;<br />
                        81}<br />
                        82}catch(ParseException e) ...{<br />
                        83throw new BusinessException("无效的日期输入:格式错误:"+dateStr);<br />
                        84}<br />
                        85}<br />
                        86}<br />
                        87</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>#p#</p>
            <p><strong>十三、正确的进行对象比较</strong>&nbsp;</p>
            <p>1.总是把不为空的对象放在比较的前面。 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>String name = request.getParameter("name");<br />
                        if(name.equals(""))...{<br />
                        &#8230;&#8230;&#8230;&#8230;<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>在j2ee项目中，这样的代码并不少见。name很容易是一个空值。那么在运行时就很容易抛出NullPointException。换成第二种形式： </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>if("".equals(name))...{<br />
                        &#8230;<br />
                        } </p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>这样当name为空值时条件为false,与我们期望相符。而第一种形式则是一种隐患。说不准它什么时候就抛出了空指针异常。 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>if(name == null || "".equals(name)) ...{<br />
                        &#8230;<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>这样的写法也可以，但是没有必要。第二种写法更简单也同样安全。</p>
            <p>2.使用短路计算 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>public void doXX(User user)...{<br />
                        if(user.getAge() &gt; 10)...{<br />
                        &#8230;<br />
                        }<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>在j2ee项目中，这样的代码也是频繁出象，没有做任何判断就调用对象的方法。谁又能保证调用者一定不会传一个空值对象进来呢？ </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>public void doXX(User user)...{<br />
                        if((user != null) &amp;&amp; (user.getAge() &gt; 10))...{<br />
                        &#8230;<br />
                        }<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>当user为空时，第二个测试条件不被执行，这样才是安全的代码！在&amp;&amp;布尔表达式， 当前面的有一个条件为false时，那么结果为假，后面的条件不再进行测试。 </p>
            <p>同样在||布尔表达式中，当前面的有一个条件为true时，结果为真，后面的条件不再进行测试。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>If((user == null) || (user.getAge() &gt; 10))...{<br />
                        &#8230;&#8230;&#8230;&#8230;&#8230;&#8230;..<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>当user 为null时，结果为真，那么后面的条件将不进行测试。</p>
            <p><strong>十四、小心遍历集合对象</strong> </p>
            <p>在对集合进行遍历时，经常是下面的代码：</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>List serviceDepartList = counter.getServiceDepartList();<br />
                        for(int i = 0; i &lt; serviceDepartList.size();i++) ...{<br />
                        ServiceDepartmentDTO serviceDepart = (ServiceDepartmentDTO)serviceDepartList.get(i);<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>当serviceDepartList 为null时，那么它后面的遍历代码就抛出NullPointException.所以在遍历集合时应该总是小心一些。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>for(int i = 0; serviceDepartList != null &amp;&amp; i &lt; serviceDepartList.size();</p>
                        <p>i++) ...{ServiceDepartmentDTO serviceDepart = </p>
                        <p>(ServiceDepartmentDTO)serviceDepartList.get(i);<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>这样的代码是安全的。我们时刻要防止可恶的nullPoint产生。可能有些代码是这样的：</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>if(serviceDepartList != null)...{<br />
                        for(int i = 0; i &lt; serviceDepartList.size();i++) ...{<br />
                        ServiceDepartmentDTO serviceDepart = (ServiceDepartmentDTO)serviceDepartList.get(i);<br />
                        }<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>但我觉得上面的方法更简洁一些，特别是没有理由进行太多的if语句嵌套。嵌套增加了代码的复杂性，更难以阅读和理解。</p>
            <p><strong>十五、对象创建是要付出代价的&nbsp;</strong></p>
            <p>重复的使用一个对象，而不是在每次需要的时候都去创建一个等价的新对象。对象创建是要付出内存消耗和时间代价。特别是当一个对象创建需要初始化外部环境时，比如数据库连接，ejb查找等。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp; String s = new String("hello");//千万别要这样做比 <br />
                        &nbsp;&nbsp;&nbsp; String s = "hello"; </p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>要付出更多的开销。如果第一种形式频繁的使用，那么会创建出成千上万个String变量。而第二种形式则不会，String s = "hello";只使用一个String实例。&nbsp;</p>
            <p>#p#</p>
            <p>1. 应当重用一个已有的对象时，就不要试着去创建新的对象。看看下面的方法： </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>&nbsp; public CounterDAO getCounterDao() ...{<br />
                        &nbsp;&nbsp;&nbsp; CounterDAO counterDao = </p>
                        <p>      (CounterDAO)this.getDaoFactory().getDAOByRegionCode(COUNTER_DAO_BEAN_NAME,&nbsp;&nbsp;&nbsp; </p>
                        <p>         "00");//读中心数据库 <br />
                        &nbsp;&nbsp; return counterDao;<br />
                        &nbsp;&nbsp;&nbsp; }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>这是要根据不同的机构代码去访问不同的数据库，再获得一个DAO对象，每次都会创建一个新的CounterDAO对象。下面的方法会多次调用CounterDAO的方法。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>public void updateCounterRelation(CounterDTO counter) throws BusinessException ...{<br />
                        this.getCounterDao().removeCounterRelation(counter);//删除此柜面所有子柜面信息 <br />
                        List subCounterList = counter.getSubCounterList(); //本柜面的子柜面列表 <br />
                        for(int i = 0; subCounterList != null &amp;&amp; i &lt; subCounterList.size();i++) ...{<br />
                        CounterDTO subCounter = (CounterDTO)subCounterList.get(i);<br />
                        subCounter.setSuperCounterNo(counter.getCounterNo());<br />
                        this.getCounterDao().updateCounterRelation(subCounter);<br />
                        }} </p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            &nbsp;<br />
            特别是在this.getCounterDao().updateCounterRelation(subCounter)这个语句，需要去更新每一个柜员的关系，那么这样就会创建很多个CounterDao对象，而创建CounterDao对象又会每次都去连接数据库，花费大量的内存空间和连接时间。 </p>
            <p>重构后的代码：</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>private CounterDAO counterDao;<br />
                        public CounterDAO getCounterDao() ...{<br />
                        if(counterDao == null)<br />
                        counterDao = </p>
                        <p>  (CounterDAO)this.getDaoFactory().getDAOByRegionCode(COUNTER_DAO_BEAN_NAME, "00")</p>
                        <p>   ;//读中心数据库 <br />
                        return counterDao;<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>这样不管以后调用这个方法多少次，而只去设置数据库一次，不管使用多少次都只有一个CounterDAO对象创建，更节省内存开销和时间。提升系统性能。 </p>
            <p>2. 在真实需要的时候才去创建对象 </p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>List list = new ArrayList();<br />
                        if (relationCounterNoString != null) ...{<br />
                        &#8230;&#8230;.<br />
                        List.add();<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>上面的例子是从页面读取一个带逗号分隔符的字符串，然后把字符串分切为一个list.上面的例子不管要分隔的字符串是否为空，真是返回一个不为空的List，里面没有包括任何数据项的。白白的浪费空间。</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>List list =null;<br />
                        if (relationCounterNoString != null) ...{<br />
                        list = new ArrayList();<br />
                        &#8230;&#8230;&#8230;..<br />
                        list.add();<br />
                        } </p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>这样的代码会更好一些，总之记住，对象创建是有代价的，只有在真正的需要它的时候才去创建它。 </p>
            <p><strong>十八、使用日志系统</strong>&nbsp;</p>
            <p>日志系统提供帮助我们跟踪系统执行情况的功能。日志最重要的是能够帮助我们进行系统调试。在实际的项目中我们不得不考虑下面的问题：&nbsp;</p>
            <p>1. 调试是经常的，而且是可变的。调试会话是短暂的，没有任何系统能够记下我们的调试内容，今天的问题，在明天可能还是问题。&nbsp;</p>
            <p>2. 调试是十分烦琐和费时的，通常搜索一个日志记录要比去遍历代码来得容易。&nbsp;</p>
            <p>3. 记录日志可以让我们在一开始就要思考程序的运行情况，可以管控程序的一些隐患错误。&nbsp;</p>
            <p>4. 没有任何调试工具可以帮我们良好的解决调试的问题，特别是在分布式系统中。&nbsp;</p>
            <p>下面是一些记录日志规范：&nbsp;</p>
            <p>1. 绝不要使用System.out.print()语句来记录日志，控制台的输出无法灵活配置。比如说我们想关闭某个类的日志输出。在一些应用程序器中，控制台大量的输出是严重影响性能的。&nbsp;</p>
            <p>2. 单元测试能够指出一个类出现了什么问题，但是不一定能详细的指出问题出在哪里。日志可以给我们提供更详细的信息，获得更有用的帮助。&nbsp;</p>
            <p>3. 代码生成的日志一定是要可以配置的，否则不能使用于生产环境。&nbsp;</p>
            <p>4. 为不同的日志消息选择不同的级别。&nbsp;</p>
            <p>5. 在输出日志时先进行级别判断。例如：</p>
            <p>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" bgcolor="#e6e6e6">
                        <pre>
                        <p>if(logger.isDebugable()){ <br />
                        logger.debug(&#8220;&#8221;);<br />
                        }</p>
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </p>
            <p>累了，先写这么多，接下来想写写，测试专题，异常处理专题，事务处理专题！</p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/jvict/aggbug/226768.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-09-03 20:45 <a href="http://www.blogjava.net/jvict/articles/226768.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 获取日期时间</title><link>http://www.blogjava.net/jvict/articles/225184.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 28 Aug 2008 01:38:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/225184.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/225184.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/225184.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/225184.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/225184.html</trackback:ping><description><![CDATA[<p>&nbsp;1.基本的获取时间方法<br />
public class TestDate {<br />
&nbsp; public static void main(String args[]) {<br />
&nbsp; java.util.Date utildate=new java.util.Date();<br />
&nbsp; System.out.println(utildate);<br />
&nbsp; }<br />
}<br />
输出结果如下：<br />
Mon Mar 12 17:40:00 CST 2007<br />
2.获取年月日格式的时间<br />
public class TestDate {<br />
&nbsp; public static void main(String args[]) {<br />
&nbsp; java.util.Date utildate=new java.util.Date();<br />
&nbsp; java.sql.Date date=new java.sql.Date(utildate.getTime());<br />
&nbsp; System.out.println(date);<br />
&nbsp; }<br />
}<br />
输出结果如下：<br />
2007-03-12<br />
3.获取时分秒格式的时间<br />
import java.util.*;<br />
import java.text.*;<br />
public class TestDate {<br />
&nbsp; public static void main(String args[]) {<br />
&nbsp; java.util.Date utildate=new java.util.Date();<br />
&nbsp; String str=DateFormat.getTimeInstance().format(utildate);<br />
&nbsp; System.out.println(str);<br />
&nbsp; }<br />
}<br />
输出结果如下：<br />
17:41:21<br />
4.获取时间戳<br />
import java.util.*;<br />
public class TestDate {<br />
&nbsp; public static void main(String args[]) {<br />
&nbsp; java.util.Date utildate=new java.util.Date();<br />
&nbsp; System.out.println(utildate.getTime());<br />
&nbsp; }<br />
}<br />
或者用下面的方法:<br />
public class TestDate {<br />
&nbsp; public static void main(String args[]) {<br />
&nbsp; long time=System.currentTimeMillis();<br />
&nbsp; System.out.println(time);<br />
&nbsp; }<br />
}<br />
输出结果如下：<br />
1173692497326<br />
5.按指定格式获取时间<br />
import java.util.*;<br />
import java.text.*;<br />
public class TestDate {<br />
&nbsp; public static void main(String args[]) {<br />
&nbsp; Date today=new Date();<br />
&nbsp; SimpleDateFormat f=new SimpleDateFormat("yyyy年MM月dd日&nbsp; <br />
&nbsp; hh:mm:ss");<br />
&nbsp; String time=f.format(today);<br />
&nbsp; System.out.println(time);<br />
&nbsp; }<br />
}<br />
格式里的时如果用hh表示用12小时制，HH表示用24小时制。MM必须是大写!<br />
输出结果如下：<br />
2007年03月12日05:42:08 <br />
</p>
<img src ="http://www.blogjava.net/jvict/aggbug/225184.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-08-28 09:38 <a href="http://www.blogjava.net/jvict/articles/225184.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>