﻿<?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-财哥的地盘-文章分类-J2EE</title><link>http://www.blogjava.net/java-my-love/category/30329.html</link><description>家穷人丑,一米四九</description><language>zh-cn</language><lastBuildDate>Fri, 09 May 2008 00:48:46 GMT</lastBuildDate><pubDate>Fri, 09 May 2008 00:48:46 GMT</pubDate><ttl>60</ttl><item><title>面向对象编程思想(转)</title><link>http://www.blogjava.net/java-my-love/articles/199399.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Fri, 09 May 2008 00:48:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/199399.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/199399.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/199399.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/199399.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/199399.html</trackback:ping><description><![CDATA[<p><font face="Verdana">我是从学习Java编程开始接触OOP(面向对象编程)，刚开始使用Java编写程序的时候感觉很别扭，因为我早以习惯用C来编写程序，很欣赏C的简洁性和高效性，喜欢C简练而表达能力丰富的风格，特别忍受不了Java运行起来慢吞吞的速度，相对冗长的代码，而且一个很简单的事情，要写好多类，一个类调用一个类，心里的抵触情绪很强。</font></p>
<p><font face="Verdana">我对Java的面向对象的特性琢磨良久，自认为有所领悟，也开始有意识的运用OOP风格来写程序，然而还是经常会觉得不知道应该怎样提炼类，面对一个具体的问题的时候，会觉得脑子里千头万绪的，不知道怎么下手，一不小心，又会回到原来的思路上去。</font></p>
<p><font face="Verdana">举个例子，要发广告邮件，广告邮件列表存在数据库里面。倘若用C来写的话，一般会这样思考，先把邮件内容读入，然后连接数据库，循环取邮件地址，调用本机的qmail的sendmail命令发送。</font></p>
<p><font face="Verdana">然后考虑用Java来实现，既然是OOP，就不能什么代码都塞到main过程里面，于是就设计了三个类：</font></p>
<p><font face="Verdana">一个类是负责读取数据库，取邮件地址，调用qmail的sendmail命令发送；<br />
一个类是读邮件内容，MIME编码成HTML格式的，再加上邮件头；<br />
一个主类负责从命令读参数，处理命令行参数，调用发email的类。</font></p>
<p><font face="Verdana">把一件工作按照功能划分为3个模块分别处理，每个类完成一件模块任务。</font></p>
<p><font face="Verdana">仔细的分析一下，就会发现这样的设计完全是从程序员实现程序功能的角度来设计的，或者说，设计类的时候，是自低向上的，从机器的角度到现实世界的角度来分析问题的。因此在设计的时候，就已经把程序编程实现的细节都考虑进去了，企图从底层实现程序这样的出发点来达到满足现实世界的软件需求的目标。</font></p>
<p><font face="Verdana">这样的分析方法其实是不适用于Java这样面向对象的编程语言，因为，如果改用C语言，封装两个C函数，都会比Java实现起来轻松的多，逻辑上也清楚的多。</font></p>
<p><font face="Verdana">我觉得面向对象的精髓在于考虑问题的思路是从现实世界的人类思维习惯出发的，只要领会了这一点，就领会了面向对象的思维方法。</font></p>
<p><font face="Verdana">举一个非常简单的例子：假使现在需要写一个网页计数器，客户访问一次页面，网页计数器加1，计数器是这样来访问的</font></p>
<p><font face="Verdana">http://hostname/count.cgi?id=xxx</font></p>
<p><font face="Verdana">后台有一个数据库表，保存每个id（一个id对应一个被统计访问次数的页面）的计数器当前值，请求页面一次，对应id的计数器的字段加1(这里我们忽略并发更新数据库表，出现的表锁定的问题)。</font></p>
<p><font face="Verdana">如果按照一般从程序实现的角度来分析，我们会这样考虑：首先是从HTTP GET请求取到id，然后按照id查数据库表，获得某id对应的访问计数值，然后加1，更新数据库，最后向页面显示访问计数。</font></p>
<p><font face="Verdana">现在假设一个没有程序设计经验的人，他会怎样来思考这个问题的呢？他会提出什么样的需求呢？他很可能会这样想：</font></p>
<p><font face="Verdana">我需要有一个计数器，这个计数器应该有这样的功能，刷新一次页面，访问量就会加1，另外最好还有一个计数器清0的功能，当然计数器如果有一个可以设为任意值的功能的话，我就可以作弊了。</font></p>
<p><font face="Verdana">做为一个没有程序设计经验的人来说，他完全不会想到对数据库应该如何操作，对于HTTP变量该如何传递，他考虑问题的角度就是我有什么需求，我的业务逻辑是什么，软件应该有什么功能。</font></p>
<p><font face="Verdana">按照这样的思路(请注意，他的思路其实就是我们平时在生活中习惯的思维方式)，我们知道需要有一个计数器类 Counter，有一个必须的和两个可选的方法：</font></p>
<p><font face="Verdana">getCount() // 取计数器值方法<br />
resetCounter() // 计数器清0方法<br />
setCount() // 设计数器为相应的值方法</font></p>
<p><font face="Verdana">把Counter类完整的定义如下：</font></p>
<p><font face="Verdana">public class Counter {<br />
public int getCount(int id) {}<br />
public void resetCounter(int id) {}<br />
public void setCount(int id, int currentCount) {}<br />
}</font></p>
<p><font face="Verdana">解决问题的框架已经有了，来看一下如何使用Counter。 在count.cgi里面调用Counter来计数，程序片断如下：</font></p>
<p><font face="Verdana">// 这里从HTTP环境里面取id值<br />
...<br />
Counter myCounter = new Counter(); // 获得计数器<br />
int currentCount = myCounter.getCount(id); // 从计数器中取计数<br />
// 这里向客户浏览器输出<br />
...</font></p>
<p><font face="Verdana">程序的框架全都写好了，剩下的就是实现Counter类方法里面具体的代码了，此时才去考虑具体的程序语言实现的细节，比如，在getCount()方法里面访问数据库，更新计数值。</font></p>
<p><font face="Verdana">从上面的例子中看到，面向对象的思维方法其实就是我们在现实生活中习惯的思维方式，是从人类考虑问题的角度出发，把人类解决问题的思维方式逐步翻译成程序能够理解的思维方式的过程，在这个翻译的过程中，软件也就逐步被设计好了。</font></p>
<p><font face="Verdana">在运用面向对象的思维方法进行软件设计的过程中，最容易犯的错误就是开始分析的时候，就想到了程序代码实现的细节，因此封装的类完全是基于程序实现逻辑，而不是基于解决问题的业务逻辑。</font></p>
<p><font face="Verdana">学习JDBC编程的经典错误问法是：&#8220;我怎样封装对数据库的select操作？&#8221;</font></p>
<p><font face="Verdana">面向对象的设计是基于解决业务问题的设计，而不是基于具体编程技术的设计。我不会去封装select语句的，我只封装解决问题的业务逻辑，对数据库的读取是在业务逻辑的编码实现阶段才去考虑的问题。</font></p>
<p><font face="Verdana">回过头看上面那个发广告邮件的例子，应该如何应用面向对象的思维方法呢？</font></p>
<p><font face="Verdana">对于一个邮件来说，有邮件头，邮件体，和邮件地址这三个属性，发送邮件，需要一个发送的方法，另外还需要一个能把所有邮件地址列出来的方法。所以应该如下设计：</font></p>
<p><font face="Verdana">类JunkMail</font></p>
<p><font face="Verdana">属性：<br />
head<br />
body<br />
address<br />
方法：<br />
sendMail() // 发送邮件<br />
listAllMail() // 列邮件地址</font></p>
<p><font face="Verdana">用Java来表示：</font></p>
<p><font face="Verdana">public class JunkMail {<br />
private String head;<br />
private String body;<br />
private String address;<br />
public JunkMain() { // 默认的类构造器<br />
// 从外部配置文件读邮件头和邮件体<br />
this.head=...;<br />
this.body=...;<br />
}</font></p>
<p><font face="Verdana">public static boolean sendMail(String address) {<br />
// 调用qmail，发送email<br />
}</font></p>
<p><font face="Verdana">public static Collection listAllMail() {<br />
// 访问数据库，返回一个邮件地址集合<br />
}<br />
}</font></p>
<p><font face="Verdana">当把JunkMail设计好了以后，再调用JunkMail类完成邮件的发送，将是非常轻松的事情。</font></p>
<p><font face="Verdana">如果说传统的面向过程的编程是符合机器运行指令的流程的话，那么面向对象的思维方法就是符合现实生活中人类解决问题的思维过程。</font></p>
<p><font face="Verdana">在面向对象的软件分析和设计的时候，要提醒自己，不要一上来就去想程序代码的实现，应该抛开具体编程语言的束缚，集中精力分析我们要实现的软件的业务逻辑，分析软件的业务流程，思考应该如何去描述和实现软件的业务。毕竟软件只是一个载体，业务才是我们真正要实现的目标。</font></p>
<p><font face="Verdana">但是在设计过程中，心里却往往在担心，如果我完全不去考虑程序代码的实现的话，那么我怎么知道我的设计一定合理呢？我怎么知道我设计的类、接口一定可以实现呢？所以经常可以看到的现象就是：</font></p>
<p><font face="Verdana">在设计过程中，虽然知道不能过早考虑代码实现，但是每设计一个类，一个接口，心里都要不知不觉的用自己熟悉的编程语言大概的评估一下，看看能否编出来，因此，一不小心，就会又回到按照程序功能实现的思路进行设计的老路上去了。</font></p>
<p><font face="Verdana">举个例子来说明，在做Web程序设计的时候，经常要遇到分页显示数据的情况。比如说需要把系统中所有的用户都列出来这样的功能。假设使用User类来表示用户，增加用户addUser()，删除用户deleteUser()，查询所有用户listUsers()方法。而数据库中有一个user表，一条记录是一个用户的信息。下面考虑一下User类的方法的实现：</font></p>
<p><font face="Verdana">addUser()和deleteUser()方法都好实现，就是对数据库增加记录和删除记录。对于listUsers()方法，其实就是对user表的select，取出一个记录集。但是该怎么从listUsers()方法中得到所有用户的列表呢？</font></p>
<p><font face="Verdana">一个方法调用的返回值只有一个，没有多个，所以很多情况下采用的办法就是返回值定义为集合类型，比如Vector。这样就可以在listUsers()方法的具体代码实现的时候，从数据库依次取出一个个记录，插入到Vector里面来。在主程序里面，调用listUsers()方法可以返回一个Vector，然后再对Vector遍历操作，就可以得到用户列表了。</font></p>
<p><font face="Verdana">public class User {</font></p>
<p><font face="Verdana">public static void addUser(...) {<br />
// 数据库insert一条记录<br />
}</font></p>
<p><font face="Verdana">public static void deleteUser(...) {<br />
// 数据库delete一条记录<br />
}</font></p>
<p><font face="Verdana">public Vector listUsers(...) {<br />
// 数据库select结果放到一个集合里面<br />
}<br />
}</font></p>
<p><font face="Verdana">这样的设计基本合理，但是仍然有点小问题。因为在设计的时候，就考虑到了用Java的集合类Vector来实现对不定长数据集的存放，因而违反了面向对象设计的一个原则：在设计的时候不应过早的考虑具体程序语言的实现。所以必须用抽象的方法，和具体实现无关的方法来表达业务逻辑。</font></p>
<p><font face="Verdana">我们知道，通常对具有集合特征的数据结构进行遍历通常可以使用next和hasNext方法，next实现取下一个用户，hasNext判断是否还有元素。 因此我们定义一个接口Iterator，这个接口中定义两个方法next和hasNext：</font></p>
<p><font face="Verdana">public interface Iterator {<br />
public boolean hasNext() {}<br />
public Object next() {}<br />
}</font></p>
<p><font face="Verdana">而User类的listUses方法返回值改为Iterator接口的实现类:</font></p>
<p><font face="Verdana">public class User {<br />
...<br />
public Iterator listUsers() {<br />
}<br />
...<br />
}</font></p>
<p><font face="Verdana">这样就把User类的设计和具体的实现方法分离开了，因为此时任何实现了next()和hasNext()方法的类都可以做为listUsers的返回值，都可以被用来表达&#8220;用户列表&#8221;，而不仅仅可以使用Vector而已。比如，我可以用ArrayList来表达用户列表，因为ArrayList也实现了Iterator，当然我也可以自己专门写一个类来存放用户列表，只要实现next()和hasNext()方法就行了。</font></p>
<p><font face="Verdana">这样在具体的编写代码的时候，程序员具有了最大的灵活性，可以根据具体的情况，采用不同的编程方法来存放用户列表。特别是降低了程序的耦合度，提高了程序的可移植性。对于上面那个JunkMail的listAllMail()方法也同样应该改为接口类型。</font></p>
<p><font face="Verdana">然后，在主程序里面就这样来使用User类的listUsers方法：</font></p>
<p><font face="Verdana">User myUser = new User();<br />
Iterator iterator = myUser.listUsers();<br />
while (iterator.hasNext()) {<br />
iterator.next();<br />
}</font></p>
<p><font face="Verdana">这样就可以完全不用考虑程序代码实现了，从高层次上把功能抽象出来，定义成为接口，同时又可以把系统设计的很合理，完全根据业务的需求来进行设计。</font></p>
<p><font face="Verdana">结语</font></p>
<p><font face="Verdana">通过上面的几个例子的设计说明，使用面向对象的思维方法，其实是一个把业务逻辑从具体的编程技术当中抽象出来的过程，而这个抽象的过程是自上而下的，非常符合人类的思维习惯，也就是先不考虑问题解决的细节，把问题的最主要的方面抽象成为一个简单的框架，集中精力思考如何解决主要矛盾，然后在解决问题的过程中，再把问题的细节分割成一个一个小问题，再专门去解决细节问题。</font></p>
<p><font face="Verdana">因而一旦牢牢的抓住了这一点，你就会发现在软件设计和开发过程中，你自己总是会不知不觉的运用面向对象的思维方法来设计和编写程序，并且程序的设计和开发也变得不再那么枯燥，而一个合理运用面向对象技术进行设计和架构的软件，更是具备了思维的艺术美感。</font></p>
<p><font face="Verdana">最后，愿面向对象的思维方法也能给您的程序设计之路带来创作的乐趣。 </font></p>
<img src ="http://www.blogjava.net/java-my-love/aggbug/199399.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-05-09 08:48 <a href="http://www.blogjava.net/java-my-love/articles/199399.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java项目开发规范(转)</title><link>http://www.blogjava.net/java-my-love/articles/199396.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Fri, 09 May 2008 00:42:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/199396.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/199396.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/199396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/199396.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/199396.html</trackback:ping><description><![CDATA[<div class="postbody">
<p><font face="Verdana">一、目的&nbsp;&nbsp;&nbsp; </font></p>
<p><font face="Verdana">　　对于代码，首要要求是它必须正确，能够按照程序员的真实思想去运行；第二个的要求是代码必须清晰易懂，使别的程序员能够容易理解代码所进行的实际工作。在软件工程领域，源程序的风格统一标志着可维护性、可读性，是软件项目的一个重要组成部分。而目前还没有成文的编码风格文档，以致于很多时候，程序员没有一个共同的标准可以遵守，编码风格各异，程序可维护性差、可读性也很差。通过建立代码编写规范，形成开发小组编码约定，提高程序的可靠性、可读性、可修改性、可维护性、可继承性和一致性，可以保证程序代码的质量，继承软件开发成果，充分利用资源，使开发人员之间的工作成果可以共享。</font></p>
<p><font face="Verdana">&nbsp;&nbsp;&nbsp; 本文在参考业界已有的编码风格的基础上，描述了一个基于 JBuilder 的项目风格，力求一种统一的编程风格，并从整体编码风格、代码文件风格、函数编写风格、变量风格、注释风格等几个方面进行阐述。（这些规范并不是一定要绝对遵守，但是一定要让程序有良好的可读性）</font></p>
<font face="Verdana">
<p><br />
二、整体编码风格</p>
<p>1、缩进</p>
<p>&nbsp;&nbsp;&nbsp; 缩进建议以4个空格为单位。建议在 Tools/Editor Options 中设置 Editor 页面的Block ident为4，Tab Size 为8。预处理语句、全局数据、标题、附加说明、函数说明、标号等均顶格书写。语句块的&amp;quot;{&amp;quot;、&amp;quot;}&amp;quot;配对对齐，并与其前一行对齐，语句块类的语句缩进建议每个&amp;quot;{&amp;quot;、&amp;quot;}&amp;quot;单独占一行，便于匹对。JBuilder 中的默认方式是开始的&amp;quot;{&amp;quot;不是单独一行，建议更改成上述格式（在 Project/Default Project Properties 中设置 Code Style 中选择 Braces 为 Next line）。</p>
<p>2、空格</p>
<p>&nbsp;&nbsp;&nbsp; 原则上变量、类、常量数据和函数在其类型，修饰名称之间适当空格并据情况对齐。关键字原则上空一格，如：if ( ... ) 等。运算符的空格规定如下：&amp;quot;::&amp;quot;、&amp;quot;-&gt;;&amp;quot;、&amp;quot;[&amp;quot;、&amp;quot;]&amp;quot;、&amp;quot;++&amp;quot;、&amp;quot;--&amp;quot;、&amp;quot;~&amp;quot;、&amp;quot;!&amp;quot;、&amp;quot;+&amp;quot;、&amp;quot;-&amp;quot;（指正负号）、&amp;quot;&amp;amp;&amp;quot;（引用）等几个运算符两边不加空格（其中单目运算符系指与操作数相连的一边），其它运算符（包括大多数二目运算符和三目运算符&amp;quot;?:&amp;quot;两边均加一空格，在作函数定义时还可据情况多空或不空格来对齐，但在函数实现时可以不用。&amp;quot;,&amp;quot;运算符只在其后空一格，需对齐时也可不空或多空格。不论是否有括号，对语句行后加的注释应用适当空格与语句隔开并尽可能对齐。个人认为此项可以依照个人习惯决定遵循与否。</p>
<p>3、对齐</p>
<p>&nbsp;&nbsp;&nbsp; 原则上关系密切的行应对齐，对齐包括类型、修饰、名称、参数等各部分对齐。另每一行的长度不应超过屏幕太多，必要时适当换行，换行时尽可能在&amp;quot;,&amp;quot;处或运算符处，换行后最好以运算符打头，并且以下各行均以该语句首行缩进，但该语句仍以首行的缩进为准，即如其下一行为&#8220;{&#8221;应与首行对齐。</p>
<p>&nbsp;&nbsp;&nbsp; 变量定义最好通过添加空格形成对齐，同一类型的变量最好放在一起。如下例所示：<br />
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Value;<br />
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Result;<br />
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Length;<br />
DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Size;<br />
DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufSize;</p>
<p>&nbsp;个人认为此项可以依照个人习惯决定遵循与否。</p>
<p>4、空行</p>
<p>&nbsp;不得存在无规则的空行，比如说连续十个空行。程序文件结构各部分之间空两行，若不必要也可只空一行，各函数实现之间一般空两行，由于每个函数还要有函数说明注释，故通常只需空一行或不空，但对于没有函数说明的情况至少应再空一行。对自己写的函数，建议也加上&#8220;//------&#8221;做分隔。函数内部数据与代码之间应空至少一行，代码中适当处应以空行空开，建议在代码中出现变量声明时，在其前空一行。类中四个&#8220;p&#8221;之间至少空一行，在其中的数据与函数之间也应空行。</p>
<p>5、注释</p>
<p>&nbsp;注释是软件可读性的具体体现。程序注释量一般占程序编码量的20%，软件工程要求不少于20%。程序注释不能用抽象的语言，类似于&amp;quot;处理&amp;quot;、&amp;quot;循环&amp;quot;这样的计算机抽象语言，要精确表达出程序的处理说明。例如：&amp;quot;计算净需求&amp;quot;、&amp;quot;计算第一道工序的加工工时&amp;quot;等。避免每行程序都使用注释，可以在一段程序的前面加一段注释，具有明确的处理逻辑。</p>
<p>&nbsp;注释必不可少，但也不应过多，不要被动的为写注释而写注释。以下是四种必要的注释：<br />
&nbsp;<br />
A. 标题、附加说明。</p>
<p>B. 函数、类等的说明。对几乎每个函数都应有适当的说明，通常加在函数实现之前，在没有函数实现部分的情况下则加在函数原型前，其内容主要是函数的功能、目的、算法等说明，参数说明、返回值说明等，必要时还要有一些如特别的软硬件要求等说明。公用函数、公用类的声明必须由注解说明其使用方法和设计思路，当然选择恰当的命名格式能够帮助你把事情解释得更清楚。</p>
<p>C. 在代码不明晰或不可移植处必须有一定的说明。</p>
<p>D. 及少量的其它注释，如自定义变量的注释、代码书写时间等。</p>
<p>&nbsp; 注释有块注释和行注释两种，分别是指：&amp;quot;/**/&amp;quot;和&amp;quot;//&amp;quot;建议对A用块注释，D用行注释，B、C则视情况而定，但应统一，至少在一个单元中B类注释形式应统一。具体对不同文件、结构的注释会在后面详细说明。</p>
<p>6、代码长度</p>
<p>&nbsp;对于每一个函数建议尽可能控制其代码长度为53行左右，超过53行的代码要重新考虑将其拆分为两个或两个以上的函数。函数拆分规则应该一不破坏原有算法为基础，同时拆分出来的部分应该是可以重复利用的。对于在多个模块或者窗体中都要用到的重复性代码，完全可以将起独立成为一个具备公用性质的函数，放置于一个公用模块中。</p>
<p>7、页宽</p>
<p>&nbsp;页宽应该设置为80字符。源代码一般不会超过这个宽度, 并导致无法完整显示, 但这一设置也可以灵活调整. 在任何情况下, 超长的语句应该在一个逗号或者一个操作符后折行. 一条语句折行后, 应该比原来的语句再缩进2个字符. </p>
<p>8、行数</p>
<p>&nbsp;一般的集成编程环境下，每屏大概只能显示不超过50行的程序，所以这个函数大概要5-6屏显示，在某些环境下要8屏左右才能显示完。这样一来，无论是读程序还是修改程序，都会有困难。因此建议把完成比较独立功能的程序块抽出，单独成为一个函数。把完成相同或相近功能的程序块抽出，独立为一个子函数。可以发现，越是上层的函数越简单，就是调用几个子函数，越是底层的函数完成的越是具体的工作。这是好程序的一个标志。这样，我们就可以在较上层函数里容易控制整个程序的逻辑，而在底层的函数里专注于某方面的功能的实现了。</p>
<p><br />
三、代码文件风格</p>
<p>所有的 Java(*.java) 文件都必须遵守如下的样式规则：</p>
<p>. 文件生成</p>
<p>对于规范的 JAVA 派生类，尽量用 JBuilder 的 Object Gallery 工具来生成文件格式，避免用手工制作的头文件/实现文件。<br />
&nbsp;<br />
. package/import </p>
<p>package 行要在 import 行之前，import 中标准的包名要在本地的包名之前，而且按照字母顺序排列。如果 import 行中包含了同一个包中的不同子目录，则应该用 * 来处理。 </p>
<p>package hotlava.net.stats;</p>
<p>import java.io.*;<br />
import java.util.Observable;<br />
import hotlava.util.Application;&nbsp; <br />
&nbsp;<br />
这里 java.io.* 使用来代替InputStream and OutputStream 的。</p>
<p>. 文件头部注释</p>
<p>文件头部注释主要是表明该文件的一些信息，是程序的总体说明，可以增强程序的可读性和可维护性。文件头部注释一般位于 package/imports 语句之后，Class 描述之前。要求至少写出文件名、创建者、创建时间和内容描述。JBuilder 的 Object Gallery 工具生成的代码中会在类、工程文件中等自动添加注释，我们也要添加一些注释，其格式应该尽量约束如下：</p>
<p>/**<br />
&nbsp;* Title:&nbsp; 确定鼠标位置类<br />
&nbsp;* Description: 确定鼠标当前在哪个作业栏位中并返回作业号<br />
&nbsp;* @Copyright: Copyright (c) 2002<br />
&nbsp;* @Company: HIT<br />
&nbsp;* @author: rivershan<br />
&nbsp;* @version: 1.0<br />
&nbsp;* @time: 2002.10.30<br />
&nbsp;*/<br />
&nbsp;<br />
. Class </p>
<p>接下来的是类的注释，一般是用来解释类的。 </p>
<p>/**<br />
&nbsp;* A class representing a set of packet and byte counters<br />
&nbsp;* It is observable to allow it to be watched, but only<br />
&nbsp;* reports changes when the current set is complete<br />
&nbsp;*/ <br />
&nbsp;<br />
接下来是类定义，包含了在不同的行的 extends 和 implements </p>
<p>public class CounterSet<br />
&nbsp; extends Observable<br />
&nbsp; implements Cloneable </p>
<p>.Class Fields </p>
<p>接下来是类的成员变量： </p>
<p>/**<br />
&nbsp;* Packet counters<br />
&nbsp;*/<br />
&nbsp;<br />
protected int[] packets;<br />
&nbsp;<br />
public 的成员变量必须生成文档（JavaDoc）。proceted、private和 package 定义的成员变量如果名字含义明确的话，可以没有注释。</p>
<p>. 存取方法<br />
&nbsp;<br />
接下来是类变量的存取的方法。它只是简单的用来将类的变量赋值获取值的话，可以简单的写在一行上。（个人认为尽量分行写）</p>
<p>/**<br />
&nbsp;* Get the counters<br />
&nbsp;* @return an array containing the statistical data.&nbsp; This array has been<br />
&nbsp;* freshly allocated and can be modified by the caller.<br />
&nbsp;*/<br />
&nbsp;<br />
public int[] getPackets() <br />
{<br />
&nbsp; return copyArray(packets, offset); <br />
}</p>
<p>public int[] getBytes() <br />
{ <br />
&nbsp;return copyArray(bytes, offset); <br />
}</p>
<p>public int[] getPackets() <br />
{ <br />
&nbsp;return packets; <br />
}</p>
<p>public void setPackets(int[] packets) <br />
{ <br />
&nbsp;this.packets = packets; <br />
}<br />
&nbsp;<br />
其它的方法不要写在一行上</p>
<p>. 构造函数 </p>
<p>接下来是构造函数，它应该用递增的方式写（比如：参数多的写在后面）。 </p>
<p>访问类型(&amp;quot;public&amp;quot;,&amp;quot;private&amp;quot; 等.)和任何&amp;quot;static&amp;quot;,&amp;quot;final&amp;quot;或&amp;quot;synchronized&amp;quot;应该在一行中，并且方法和参数另写一行，这样可以使方法和参数更易读。 </p>
<p>public<br />
CounterSet(int size)<br />
{<br />
&nbsp;&nbsp; this.size = size;<br />
}</p>
<p>. 克隆方法<br />
&nbsp;<br />
如果这个类是可以被克隆的，那么下一步就是 clone 方法： </p>
<p>public<br />
Object clone()<br />
{<br />
&nbsp;try <br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; CounterSet obj = (CounterSet)super.clone();<br />
&nbsp;&nbsp;&nbsp;&nbsp; obj.packets = (int[])packets.clone();<br />
&nbsp;&nbsp;&nbsp;&nbsp; obj.size = size;<br />
&nbsp;&nbsp;&nbsp;&nbsp; return obj;<br />
&nbsp;&nbsp; }&nbsp; <br />
&nbsp;&nbsp; catch(CloneNotSupportedException e) <br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; throw new InternalError(&amp;quot;Unexpected CloneNotSUpportedException: &amp;quot; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + e.getMessage());<br />
&nbsp;&nbsp; }<br />
} </p>
<p>. 类方法 </p>
<p>下面开始写类的方法： </p>
<p>/**<br />
&nbsp;* Set the packet counters<br />
&nbsp;* (such as when restoring from a database)<br />
&nbsp;*/<br />
protected final<br />
void setArray(int[] r1, int[] r2, int[] r3, int[] r4)<br />
&nbsp; throws IllegalArgumentException<br />
{<br />
&nbsp;//<br />
&nbsp;&nbsp; // Ensure the arrays are of equal size<br />
&nbsp;&nbsp; //<br />
&nbsp;&nbsp; if (r1.length != r2.length || r1.length != r3.length || r1.length != r4.length)<br />
&nbsp; throw new IllegalArgumentException(&amp;quot;Arrays must be of the same size&amp;quot;);<br />
&nbsp;&nbsp; System.arraycopy(r1, 0, r3, 0, r1.length);<br />
&nbsp;&nbsp; System.arraycopy(r2, 0, r4, 0, r1.length);<br />
} </p>
<p>. toString 方法 </p>
<p>无论如何，每一个类都应该定义 toString 方法： </p>
<p>public<br />
String toString()<br />
{<br />
&nbsp;String retval = &amp;quot;CounterSet: &amp;quot;;<br />
&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; data.length(); i++) <br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; retval += data.bytes.toString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; retval += data.packets.toString();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return retval;<br />
}</p>
<p>. main 方法 </p>
<p>如果main(String[]) 方法已经定义了, 那么它应该写在类的底部. </p>
<p><br />
四、函数编写风格</p>
<p>. 函数的命名</p>
<p>通常，函数的命名也是以能表达函数的动作意义为原则的，一般是由动词打头，然后跟上表示动作对象的名词，各单词的首字母应该大写。另外，还有一些函数命名的通用规则。如取数，则用Get打头，然后跟上要取的对象的名字；设置数，则用Set打头，然后跟上要设的对象的名字；而对象中为了响应消息进行动作的函数，可以命名为On打头，然后是相应的消息的名称；进行主动动作的函数，可以命名为Do打头，然后是相应的动作名称。类似的规则还有很多，需要程序员多读优秀的程序，逐渐积累经验，才能作出好的函数命名。</p>
<p>. 函数注释</p>
<p>系统自动生成的函数，如鼠标动作响应函数等，不必太多的注释和解释；</p>
<p>对于自行编写的函数，若是系统关键函数，则必须在函数实现部分的上方标明该函数的信息，格式如下：</p>
<p>/**<br />
* 函数名：<br />
* 编写者：<br />
* 参考资料：<br />
* 功&nbsp; 能：<br />
* 输入参数：<br />
* 输出参数：<br />
* 备&nbsp; 注：<br />
*/</p>
<p>希望尽量遵循以上格式。</p>
<p><br />
五、符号风格</p>
<p>. 总体要求</p>
<p>对于各种符号的定义，都有一个共通点，就是应该使用有实际意义的英文单词或英文单词的缩写，不要使用简单但没有意义的字串，尽可能不使用阿拉伯数字，更切忌使用中文拼音的首字母。如这样的名称是不提倡的：Value1,Value2,Value3,Value4 &#8230;。</p>
<p>例如：<br />
file(文件),code(编号),data(数据),pagepoint(页面指针), faxcode(传真号) ,address(地址),bank(开户银行),&#8230;&#8230;</p>
<p>. 变量名称</p>
<p>变量命名由（前缀+修饰语）构成。现在比较流行的是一套由微软的一个匈牙利软件工程师首先使用，并且在微软推广开来，现在被称之为匈牙利命名法的命名规则。匈牙利命名法规定，使用表示标识符所对应的变量类型的英文小写缩写作为标识符的前缀，后面在使用表示变量意义的英文单词或缩写进行命名。下面是匈牙利命名法中的一些命名方式：</p>
<p>（1）生存期修饰：用l(local)表示局域变量，p(public)表示全局变量，s(send)表示参数变量</p>
<p>（2）类型修饰：用s(AnsiString)表示字符串,c(char)表示字符,n(number)数值,i(intger)表示整数,d(double)表示双精度,f(float)浮点型,b(bool)布尔型,d(date)表示日期型.</p>
<p>例如：<br />
li_length表示整形的局域变量,是用来标识长度的.ls_code表示字符型的局域变量,用来标识代码.</p>
<p>. 控件名称</p>
<p>控件命名由（前缀+修饰语）构成。前缀即为控件的名称。</p>
<p>按钮变量&nbsp; Button+Xxxxxxx&nbsp;&nbsp;&nbsp; 例如：ButtonSave,ButtonExit,ButtonPrint等<br />
题标变量&nbsp; Label+Xxxxxxxx&nbsp;&nbsp;&nbsp; 例如：LabelName,LabelSex等<br />
数据表变量 Table+Xxxxxx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例如：TableFile,TableCount等<br />
查询变量&nbsp; Query+Xxxxxx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例如：QueryFile,QueryCeneter等<br />
数据源变量 DataSource+Xxx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例如：DataSourceFile,DataSourceCenter等<br />
。。。。。。。。。。。。。。。。<br />
(注：对于与表有关的控件&#8220;修饰语&#8221;部分最好直接用表名。)</p>
<p>. Package 的命名 </p>
<p>Package 的名字应该都是由一个小写单词组成。 </p>
<p>. Class 的命名 </p>
<p>Class 的名字必须由一个或数个能表达该类的意思的大写字母开头而其它字母都小写的单词或缩写组成，这样能使这个 Class 的名称能更容易被理解。</p>
<p>. Class 变量的命名 </p>
<p>变量的名字必须用一个小写字母开头。后面的单词用大写字母开头。对于类的成员变量，在对其标识符命名时，要加上代表member（成员）的前缀m_。例如一个标识符为m_dwFlag，则它表示的变量是一个类型为双字的成员变量，它是代表一个标志。</p>
<p>. Static Final 变量的命名 </p>
<p>Static Final 变量的名字应该都大写，并且指出完整含义。 </p>
<p>. 参数的命名 </p>
<p>参数的名字必须和变量的命名规范一致。 </p>
<p>. 数组的命名 </p>
<p>数组应该总是用下面的方式来命名：<br />
byte[] buffer;&nbsp; <br />
&nbsp;<br />
而不是： <br />
byte buffer[]; </p>
<p>. 方法的参数<br />
&nbsp;<br />
使用有意义的参数命名，如果可能的话，使用和要赋值的字段一样的名字： </p>
<p>SetCounter(int size)<br />
{<br />
&nbsp;this.size = size;<br />
} </p>
<p>. 神秘的数</p>
<p>首先要说什么是神秘的数。我们在程序里经常会用到一些量，它是有特定的含义的。例如，现在我们写一个薪金统计程序，公司员工有50人，我们在程序里就会用50这个数去进行各种各样的运算。在这里，50就是&amp;quot;神秘的数&amp;quot;。为什么称它为神秘呢？因为别的程序员在程序里看到50这个数，不知道它的含义，只能靠猜了。</p>
<p>在程序里出现&amp;quot;神秘的数&amp;quot;会降低程序的可读性，应该尽量避免。避免的方法是把神秘的数定义为一个常量。注意这个常量的命名应该能表达该数的意义，并且应该全部大写，以与对应于变量的标识符区别开来。例如上面50这个数，我们可以定义为一个名为NUMOFEMPLOYEES的常量来代替。这样，别的程序员在读程序的时候就可以容易理解了。</p>
<p>六、程序编写风格</p>
<p>. exit() </p>
<p>exit 除了在 main 中可以被调用外，其他的地方不应该调用。因为这样做不给任何代码代码机会来截获退出。一个类似后台服务地程序不应该因为某一个库模块决定了要退出就退出。 </p>
<p>. 异常 </p>
<p>申明的错误应该抛出一个RuntimeException或者派生的异常。 <br />
顶层的main()函数应该截获所有的异常，并且打印（或者记录在日志中）在屏幕上。 </p>
<p>. 垃圾收集 </p>
<p>JAVA使用成熟的后台垃圾收集技术来代替引用计数。但是这样会导致一个问题：你必须在使用完对象的实例以后进行清场工作。比如一个prel的程序员可能这么写： </p>
<p>&nbsp;...<br />
&nbsp;{<br />
&nbsp; FileOutputStream fos = new FileOutputStream(projectFile);<br />
&nbsp; project.save(fos, &amp;quot;IDE Project File&amp;quot;); <br />
&nbsp;}<br />
&nbsp;...<br />
&nbsp;<br />
除非输出流一出作用域就关闭，非引用计数的程序语言，比如JAVA，是不能自动完成变量的清场工作的。必须象下面一样写： </p>
<p>&nbsp;FileOutputStream fos = new FileOutputStream(projectFile);<br />
&nbsp;project.save(fos, &amp;quot;IDE Project File&amp;quot;); <br />
&nbsp;fos.close();</p>
<p>. Clone </p>
<p>下面是一种有用的方法： <br />
implements Cloneable</p>
<p>public<br />
Object clone()<br />
{<br />
&nbsp;try <br />
&nbsp;{<br />
&nbsp; ThisClass obj = (ThisClass)super.clone();<br />
&nbsp; obj.field1 = (int[])field1.clone();<br />
&nbsp; obj.field2 = field2;<br />
&nbsp; return obj;<br />
&nbsp;} <br />
&nbsp;catch(CloneNotSupportedException e) <br />
&nbsp;{<br />
&nbsp; throw new InternalError(&amp;quot;Unexpected CloneNotSUpportedException: &amp;quot; + e.getMessage());<br />
&nbsp;}<br />
} </p>
<p>. final 类 </p>
<p>绝对不要因为性能的原因将类定义为 final 的（除非程序的框架要求） <br />
如果一个类还没有准备好被继承，最好在类文档中注明，而不要将她定义为 final 的。这是因为没有人可以保证会不会由于什么原因需要继承她。<br />
&nbsp;<br />
. 访问类的成员变量<br />
&nbsp;<br />
大部分的类成员变量应该定义为 protected 的来防止继承类使用他们。 <br />
注意，要用&amp;quot;int[] packets&amp;quot;，而不是&amp;quot;int packets[]&amp;quot;，后一种永远也不要用。 </p>
<p>public void setPackets(int[] packets) <br />
{ <br />
&nbsp;this.packets = packets; <br />
}<br />
CounterSet(int size)<br />
{<br />
&nbsp;this.size = size;<br />
}</p>
<p>. byte 数组转换到 characters </p>
<p>为了将 byte 数组转换到 characters，你可以这么做： </p>
<p>&amp;quot;Hello world!&amp;quot;.getBytes(); </p>
<p>. Utility 类 </p>
<p>Utility 类（仅仅提供方法的类）应该被申明为抽象的来防止被继承或被初始化。 </p>
<p>. 初始化<br />
&nbsp;<br />
下面的代码是一种很好的初始化数组的方法： </p>
<p>objectArguments = new Object[] <br />
{ <br />
&nbsp;arguments <br />
}; </p>
<p>. 枚举类型<br />
&nbsp;<br />
JAVA 对枚举的支持不好，但是下面的代码是一种很有用的模板： </p>
<p>class Colour <br />
{<br />
&nbsp;&nbsp; public static final Colour BLACK = new Colour(0, 0, 0);<br />
&nbsp;&nbsp; public static final Colour RED = new Colour(0xFF, 0, 0);<br />
&nbsp;&nbsp; public static final Colour GREEN = new Colour(0, 0xFF, 0);<br />
&nbsp;&nbsp; public static final Colour BLUE = new Colour(0, 0, 0xFF);<br />
&nbsp;&nbsp; public static final Colour WHITE = new Colour(0xFF, 0xFF, 0xFF);<br />
}<br />
&nbsp;<br />
这种技术实现了RED, GREEN, BLUE 等可以象其他语言的枚举类型一样使用的常量。 他们可以用 '==' 操作符来比较。 <br />
但是这样使用有一个缺陷：如果一个用户用这样的方法来创建颜色 BLACK </p>
<p>new Colour(0,0,0) </p>
<p>那么这就是另外一个对象，'=='操作符就会产生错误。她的 equal() 方法仍然有效。由于这个原因，这个技术的缺陷最好注明在文档中，或者只在自己的包中使用。</p>
<p>. 混合使用 AWT 和 Swing 组件 </p>
<p>如果要将 AWT 组件和 Swing 组件混合起来使用的话，请小心使用。实际上，尽量不要将他们混合起来使用。 </p>
<p>. 滚动的 AWT 组件 </p>
<p>AWT 组件绝对不要用 JscrollPane 类来实现滚动。滚动 AWT 组件的时候一定要用 AWT ScrollPane 组件来实现。</p>
<p>. 避免在 InternalFrame 组件中使用 AWT 组件<br />
&nbsp;<br />
尽量不要这么做，要不然会出现不可预料的后果。 </p>
<p>. Z-Order 问题 </p>
<p>AWT 组件总是显示在 Swing 组件之上。当使用包含 AWT 组件的 POP-UP 菜单的时候要小心，尽量不要这样使用。 </p>
<p><br />
八、性能 </p>
<p>&nbsp;在写代码的时候，从头至尾都应该考虑性能问题。这不是说时间都应该浪费在优化代码上，而是我们时刻应该提醒自己要注意代码的效率。比如：如果没有时间来实现一个高效的算法，那么我们应该在文档中记录下来，以便在以后有空的时候再来实现她。 </p>
<p>&nbsp;不是所有的人都同意在写代码的时候应该优化性能这个观点的，他们认为性能优化的问题应该在项目的后期再去考虑，也就是在程序的轮廓已经实现了以后。 </p>
<p>. 不必要的对象构造 </p>
<p>不要在循环中构造和释放对象 </p>
<p>. 使用 StringBuffer 对象 </p>
<p>在处理 String 的时候要尽量使用 StringBuffer 类，StringBuffer 类是构成 String 类的基础。String 类将 StringBuffer 类封装了起来，（以花费更多时间为代价）为开发人员提供了一个安全的接口。当我们在构造字符串的时候，我们应该用 StringBuffer 来实现大部分的工作，当工作完成后将 StringBuffer 对象再转换为需要的 String 对象。比如：如果有一个字符串必须不断地在其后添加许多字符来完成构造，那么我们应该使用 StringBuffer 对象和她的 append() 方法。如果我们用 String 对象代替 StringBuffer 对象的话，会花费许多不必要的创建和释放对象的 CPU 时间。 </p>
<p>. 避免太多的使用 synchronized 关键字 </p>
<p>避免不必要的使用关键字 synchronized，应该在必要的时候再使用她，这是一个避免死锁的好方法。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rivershan 原创 </font></p>
</div>
 <img src ="http://www.blogjava.net/java-my-love/aggbug/199396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-05-09 08:42 <a href="http://www.blogjava.net/java-my-love/articles/199396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Hibernate的7个步骤</title><link>http://www.blogjava.net/java-my-love/articles/196968.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Mon, 28 Apr 2008 14:33:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/196968.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/196968.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/196968.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/196968.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/196968.html</trackback:ping><description><![CDATA[<p>面试遇到这个问题,搞了半天就这些东西<br />
Hibernate.cfg.xml文件必须被放在你的classpath里。</p>
<p>在你的程序里使用hibernate必须有下面几个步骤：</p>
<p>1、建立一个Hibernate configuration对象</p>
<p>2、使用Hibernate configuration对象来建立一个Hibernate factory对象。</p>
<p>3、使用Hibernate factory对象来建立一个Hibernate session对象。</p>
<p>4、使用Hibernate session对象来开始一个事务(可选)</p>
<p>5、使用Hibernate session对象来建立、读取、更新、删除数据库里的数据</p>
<p>6、提交事务（可选）</p>
<p>7、关闭session</p>
<p>Hibernate最佳实践是建立和缓存Hibernate factory来提高性能。所以我们最好在第一步和第二步建立一</p>
<p>个Struts plug-in 来在servlet context中缓存Hibernate factory。如List5所示：</p>
<p>Hibernate是一个功能非常强大的产品，还有一些未知的功能留给你们去发现。我们简单的例子只是关于</p>
<p>读这个行为，但是CRUD里的其它功能也是一样的简单。功能性的更新和读取指定对象一样简单，调用</p>
<p>JavaBean setter，调用session的commit方法。Hibernate负责帮你生成SQL语句并且更新数据库。一个删</p>
<p>除也是非常的简单—session.delete(element)便是所有要做的!最后建立只是需要初始化对象，调用</p>
<p>setters方法，然后调用session.save(element)。</p>
<p>Hibernate最佳实践推荐缓存Hibernate factory对象。我们选择通过Struts plug-in来建立并且缓存</p>
<p>factory。你也可以选择使用其它方法在你的类里缓存它。</p>
<p>虽然这个摘录能很好的满足你的需要，它还有其它的一些缺点。第一，我们在Struts Action里使用了</p>
<p>Hibernate。迁移到其它的持久层框架上便将需要我们改变每个使用Hibernate的Action。第二，我们的持</p>
<p>久层紧密的与表示层连接。这种关联使我们在其它表示层机制中没有重新使用持久层逻辑的机会，例如批</p>
<p>处理程序。</p>
<p>虽然有许多改进的空间，当你不需要重用表现层的时候，这个摘录还是很适合的。 <br />
</p>
 <img src ="http://www.blogjava.net/java-my-love/aggbug/196968.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-04-28 22:33 <a href="http://www.blogjava.net/java-my-love/articles/196968.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP知识要点(转)</title><link>http://www.blogjava.net/java-my-love/articles/191030.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Sun, 06 Apr 2008 05:50:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/191030.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/191030.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/191030.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/191030.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/191030.html</trackback:ping><description><![CDATA[Servlet三个要素: <br />
1.必须继承自HttpServlet <br />
2.必须实现doGet()或者doPost() <br />
3.必须在web.xml中配置Servlet <br />
&lt;servlet&gt; <br />
&lt;servlet-name&gt; &lt;/servlet-name&gt; <br />
&lt;servlet-class&gt; &lt;/servlet-class&gt; <br />
&lt;/servlet&gt; <br />
&lt;servlet-mapping&gt; <br />
&lt;servlet-name&gt; &lt;/servlet-name&gt; <br />
&lt;url-pattern&gt; &lt;/url-pattern&gt; <br />
&lt;/servelt-mapping&gt; <br />
<br />
HttpServeltRrequest:请求对象 <br />
getParameter():获得表单元素的值 <br />
getAttribute():获得request范围中的属性值 <br />
setAttribute():设置reqeust范围中的属性值 <br />
setCharacterEncoding():设置字符编码 <br />
<br />
HttpSerletResponse:相应对象 <br />
sendRedirect():外部跳转 <br />
getWriter():获得输出流对象 <br />
setContentType("text/html;&nbsp;charset=utf-8"):设置相应内容格式和编码 <br />
<br />
四种会话跟踪方式: <br />
1.Session <br />
HttpSession&nbsp;session&nbsp;=&nbsp;request.getSession(); <br />
session.setAttribute("name",&nbsp;"zhangsan"); <br />
session.setAttribute("pwd",&nbsp;"aaa"); <br />
String&nbsp;name&nbsp;=&nbsp;(String)&nbsp;session.getAttribute("name"); <br />
<br />
2.cookie: <br />
//创建Cookie <br />
Cookie&nbsp;cookie&nbsp;=&nbsp;new&nbsp;Cookie("name",&nbsp;"zhangsan"); <br />
//设置Cookie的超时时间 <br />
cookie.setMaxAge(24&nbsp;*&nbsp;60&nbsp;*&nbsp;60&nbsp;*60); <br />
//把Cookie发送到客户端 <br />
response.addCookie(cookie); <br />
<br />
//得到客户端发送的Cookie <br />
Cookie&nbsp;[]&nbsp;cookies&nbsp;=&nbsp;request.getCookies(); <br />
for(int&nbsp;i=0;&nbsp;i &lt;cookies.length;&nbsp;i++)&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;Cookie&nbsp;temp&nbsp;=&nbsp;cookies[i]; <br />
&nbsp;&nbsp;&nbsp;String&nbsp;key&nbsp;=&nbsp;temp.getName(); <br />
&nbsp;&nbsp;&nbsp;String&nbsp;value&nbsp;=&nbsp;temp.getValue(); <br />
} <br />
<br />
3.隐藏表单域 <br />
&lt;input&nbsp;type="hidden"&nbsp;name="name"&nbsp;value="zhangsan"&nbsp;/&gt; <br />
request.getParameter("name"); <br />
<br />
4.Url重写 <br />
问号传参 <br />
LoginServlet?username=zhangsan&amp;pwd=123 <br />
String&nbsp;name&nbsp;=&nbsp;request.getParameter("username"); <br />
String&nbsp;pwd&nbsp;=request.getPareameter("pwd"); <br />
<br />
内部跳转: <br />
LoginServlet <br />
request.getRequestDispatcher("index.jsp").forward(request,&nbsp;resposne); <br />
外部跳转: <br />
response.sendRedirect("index.jsp"); <br />
内部跳转是一次请求和一次响应 <br />
外部跳转是两次请求和两次响应 <br />
<br />
ServletContext:Servlet上下文对象 <br />
它是一个公共区域,可以被所有的客户端共享 <br />
setAttribute():向公共区域里放入数据 <br />
getAttribute():从公共区域里取数据 <br />
<br />
二: <br />
三:三个标准范围:request,&nbsp;session,&nbsp;ServletContext <br />
&nbsp;&nbsp;&nbsp;共同点:都有setAttribute(),&nbsp;getAttribute() <br />
&nbsp;&nbsp;&nbsp;区别:范围不同,request&nbsp; &lt;&nbsp;session&nbsp; &lt;&nbsp;servletContext <br />
四:四种会话跟踪方式 <br />
五:服务器上的五大对象 <br />
&nbsp;&nbsp;&nbsp;request,&nbsp;response,&nbsp;servlet,&nbsp;session,&nbsp;servletContext <br />
&nbsp;&nbsp;&nbsp; <br />
Jsp:Java&nbsp;Server&nbsp;Page <br />
页面构成:7种元素 <br />
1.静态内容:html <br />
2.指令:page,&nbsp;include,&nbsp;taglib: <br />
&lt;%@&nbsp;指令名&nbsp;属性1="属性值1"&nbsp;属性2="属性值2"&nbsp;%&gt; <br />
3.表达式: &lt;%=表达式&nbsp;%&gt; <br />
4.Scriptlet &lt;%&nbsp;Java代码&nbsp;%&gt; <br />
5.声明: &lt;%!&nbsp;%&gt;:变量和方法 <br />
6.动作: &lt;jsp:动作名&nbsp;属性="属性值"&gt; &lt;/jsp:动作名&gt; <br />
7.注释: <br />
客户端看不到的: &lt;%--&nbsp;--%&gt; <br />
客户端可以看到的: &lt;!--&nbsp;--&gt; <br />
<br />
<br />
Jsp的执行过程: <br />
1.转译:Jsp---&gt;Servlet <br />
2.编译:Servlet----&gt;.class <br />
3.执行:.class <br />
第一次访问jsp的时候响应速度较慢,后面请求时响应速度快 <br />
<br />
脚本: <br />
表达式: &lt;%=&nbsp;%&gt; <br />
Scriptlet: &lt;%&nbsp;%&gt; <br />
声明: &lt;%!&nbsp;%&gt; <br />
<br />
指令: <br />
page:language,&nbsp;import,&nbsp;errorPage,&nbsp;isErrorpage <br />
include:file <br />
taglib:uri:指定标签库描述符的路径&nbsp;prefix:指定标签的前缀 <br />
<br />
隐式对象: <br />
分类: <br />
1.输入和输出对象:request(HttpServletRequest),&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response(HttpServletResponse),&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out(JspWriter),&nbsp;servlet中的out是PrintWriter <br />
2.作用域通信对象:pageContext,&nbsp;request,&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session(HttpSession), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;application(ServletContext) <br />
3.Servlet对象:page(this),&nbsp;config <br />
4.错误对象:exception <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
JavaBean: <br />
一个标准的JavaBean有三个条件 <br />
1.共有的类 <br />
2.具有不带参数的公共的构造方法 <br />
3.具有set()和get()方法 <br />
4.私有属性 <br />
<br />
Jsp中的标准动作: <br />
1.useBean:创建JavaBean的一个实例 <br />
&lt;jsp:useBean&nbsp;id="stu"&nbsp;class="com.westaccp.test.Student"&nbsp;scope="page/session/application/request"&nbsp;/&gt; <br />
2.setProperty:给JavaBean的属性赋值 <br />
&lt;jsp:setProperty&nbsp;name="stu"&nbsp;property="stuName"&nbsp;value="zhangsan"&nbsp;/&gt; <br />
&lt;jsp:setProperty&nbsp;name="stu"&nbsp;property="stuName"&nbsp;param="txtName"&nbsp;/&gt; <br />
value和param不能同时使用 <br />
偷懒的方法: &lt;jsp:setProperty&nbsp;name="stu"&nbsp;property="*"&nbsp;/&gt; <br />
这个时候需要注意的是,表单元素的名字必须和JavaBean的属性值 <br />
一模一样 <br />
3.getProperty:获得JvaBean的属性值 <br />
&lt;jsp:getProperty&nbsp;name="stu"&nbsp;property="stuName"&nbsp;/&gt; <br />
4.forward:内部跳转,相当于request.getRequestDispatcher().forward(request,&nbsp;response); <br />
&lt;jsp:forward&nbsp;page="index.jsp"&nbsp;/&gt; <br />
5.include:包含 <br />
&lt;jsp:include&nbsp;page="header.jsp"&nbsp;flush="true"&nbsp;/&gt; <br />
<br />
表达式语言: <br />
EL:&nbsp;Expression&nbsp;Language <br />
语法格式:&nbsp;${表达式&nbsp;} <br />
表示式&nbsp;=&nbsp;运算符&nbsp;+&nbsp;操作数 <br />
运算符:跟Java比较,多了一个empty,&nbsp;少了一个赋值运算符 <br />
${empty&nbsp;""}&nbsp;:&nbsp;true <br />
${empty&nbsp;null}&nbsp;:true <br />
操作数: <br />
--&gt;常量:布尔型(true/false),&nbsp;整型,&nbsp;浮点型,&nbsp;字符串(可以用'',&nbsp;还可以用""),&nbsp;Null <br />
--&gt;变量: <br />
&nbsp;&nbsp;&nbsp;&nbsp;1.指的是放在四个标准范围里的属性(page,&nbsp;request,&nbsp;session,&nbsp;application) <br />
&nbsp;&nbsp;&nbsp;&nbsp;2.在编准范围内的搜索顺序:page--&gt;request---&gt;session---&gt;application <br />
&nbsp;&nbsp;&nbsp;&nbsp;3.怎么取得变量值:点运算符.,&nbsp;还以用[] <br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;%&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request.setAttribute("name",&nbsp;"lisi"); <br />
&nbsp;&nbsp;&nbsp;&nbsp;%&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;${requestScope.name} <br />
&nbsp;&nbsp;&nbsp;&nbsp;或者 <br />
&nbsp;&nbsp;&nbsp;&nbsp;${requestScope["name"]} <br />
--&gt;隐式对象 <br />
&nbsp;&nbsp;&nbsp;&nbsp;1.pageContext:通过它可以访问request,&nbsp;session,&nbsp;servletContext <br />
&nbsp;&nbsp;&nbsp;&nbsp;2.跟范围由关的:pageScope,&nbsp;requestScope,&nbsp;sessionScope,&nbsp;applicationScope <br />
&nbsp;&nbsp;&nbsp;&nbsp;3.跟输入有关的:param,&nbsp;paramValues <br />
&nbsp;&nbsp;&nbsp;&nbsp;4.其他的:header,&nbsp;cookie,&nbsp;headervalues, <br />
<br />
EL表达式适用的场合: <br />
1.可以在静态文本中使用 <br />
2.与自定义标签结合使用 <br />
3.和JavaBean结合使用 <br />
&lt;jsp:userBean&nbsp;id="stu"&nbsp;class="com.westaccp.test.Student"&nbsp;scope="session"&nbsp;/&gt; <br />
&lt;jsp:setProperty&nbsp;name="stu"&nbsp;property="stuName"&nbsp;value="hello"&nbsp;/&gt; <br />
${stu.stuName} <br />
<br />
自定义标签: <br />
1.标签处理程序实现 <br />
---&gt;实现:继承自BodyTagSupport或者TagSupport <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一般会重写doStartTag(),&nbsp;doEndTag(),&nbsp;doAfterBody() <br />
---&gt;描述:在标签库描述符文件中描述(.tld) <br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;taglib&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tlib-version&gt;1.0 &lt;/tlib-version&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;jsp-version&gt;2.0 &lt;/jsp-version&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;short-name&gt;simpletag &lt;/short-name&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tag&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;showbody &lt;/name&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tag-class&gt;com.westaccp.test.ShowBodyTag &lt;/tag-class&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;body-content&gt;empty/jsp &lt;/body-content&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;attribute&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;color &lt;/name&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/attribute&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tag&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/taglib&gt; <br />
---&gt;使用: &lt;%@&nbsp;taglib&nbsp;uri="WEB-INF/mytag.tld"&nbsp;prefix="my"&nbsp;%&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;my:showbody&nbsp;/&gt; <br />
2.标签文件 <br />
---&gt;实现和描述 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在.tag文件中实现 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置主体内容: &lt;%@&nbsp;body-content="empty/scriptless"&nbsp;%&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置属性: &lt;%@&nbsp;attribute&nbsp;name="name"&nbsp;required="true"&nbsp;rtexprvalue="true"&nbsp;%&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有主体内容: &lt;jsp:doBody&nbsp;scope="session"&nbsp;var="theBody"&nbsp;/&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;% <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;body&nbsp;=&nbsp;(String)&nbsp;session.getAttribute("theBody"); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%&gt; <br />
---&gt;使用 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WEB-INF/tags/sayhello.tag <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;%@&nbsp;taglib&nbsp;tagdir="/WEB-INF/tags/"&nbsp;prefix="you"&nbsp;%&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;you:sayhello&nbsp;/&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
标准标签库: <br />
1.核心标签库 <br />
--&gt;通用: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set: &lt;c:set&nbsp;var=""&nbsp;value=""&nbsp;scope=""&nbsp;/&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out: &lt;c:out&nbsp;value=""&nbsp;/&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove:&nbsp; &lt;c:remove&nbsp;var=""&nbsp;scope=""&nbsp;/&gt; <br />
--&gt;条件: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if: &lt;c:if&nbsp;test=""&gt;..... &lt;/c:if&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;choose:&nbsp; &lt;c:choose&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;c:when&nbsp;test=""&gt;... &lt;/c:when&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;c:when&nbsp;test=""&gt;... &lt;/c:when&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;c:when&nbsp;test=""&gt;... &lt;/c:when&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..... <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;c:otherwise&gt;... &lt;/otherwise&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/c:choose&gt; <br />
--&gt;迭代: <br />
&nbsp;&nbsp;&nbsp;&nbsp;forEach: &lt;forEach&nbsp;var=""&nbsp;items=""&nbsp;varStatus=""&nbsp;begin=""&nbsp;end=""&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;foTokens: &lt;foTodens&nbsp;var=""&nbsp;items=""&nbsp;delim=",; &#166;"&gt; &lt;/foTodens&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;Java,C#;SQL &#166;C <br />
2.I18N与格式化标签库 <br />
--&gt;setLocale:设置本地区域 <br />
--&gt;bundle:设置资源包 <br />
--&gt;setBundle:设置资源包 <br />
--&gt;message:输出消息 <br />
3.SQL标签库 <br />
--&gt;setDataSource:设置数据源,用于获得与数据库的连接 <br />
--&gt;query:执行查询 <br />
--&gt;update:执行增,删,改 <br />
--&gt;transaction:事务 <br />
--&gt;param:参数 <br />
4.XML标签库 <br />
<br />
过滤器: <br />
生命周期: <br />
1.实例华: <br />
2.初始化:init() <br />
3.过滤:doFilter() <br />
4.销毁:destroy() <br />
5.不可用 <br />
<br />
配置: <br />
&lt;filter&gt; <br />
&lt;filter-name&gt; &lt;/filter-name&gt; <br />
&lt;filter-class&gt; &lt;/filter-class&gt; <br />
&lt;/filter&gt; <br />
&lt;filter-mapping&gt; <br />
&lt;filter-name&gt; &lt;/filter-name&gt; <br />
&lt;url-pattern&gt; &lt;/url-pattern&gt; <br />
&lt;/filter-mapping&gt; <br />
<br />
几个重要的接口: <br />
1.Filter:init(),&nbsp;doFilter(),&nbsp;destroy() <br />
2.FilterChain:&nbsp;doFilter(request,&nbsp;response) <br />
3.FilterConfig:getFilterName(),&nbsp;getInitParameter(), <br />
<br />
过滤器链:---&gt;1---&gt;2---&gt;3---&gt;Servlet&nbsp;请求 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;----1 &lt;---2 &lt;---3 &lt;---&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;响应 <br />
<img src ="http://www.blogjava.net/java-my-love/aggbug/191030.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-04-06 13:50 <a href="http://www.blogjava.net/java-my-love/articles/191030.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库查询优化原则(转)</title><link>http://www.blogjava.net/java-my-love/articles/190371.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Wed, 02 Apr 2008 06:56:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/190371.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/190371.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/190371.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/190371.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/190371.html</trackback:ping><description><![CDATA[1.对查询进行优化，应尽量避免全表扫描，首先应考虑在 where 及 order by 涉及的列上建立索引。
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 2.应尽量避免在 where 子句中对字段进行 null 值判断，否则将导致引擎放弃使用索引而进行全表扫描，如：<br />
&nbsp;&nbsp;&nbsp; select id from t where num is null<br />
&nbsp;&nbsp;&nbsp; 可以在num上设置默认值0，确保表中num列没有null值，然后这样查询：<br />
&nbsp;&nbsp;&nbsp; select id from t where num=0</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 3.应尽量避免在 where 子句中使用!=或&lt;&gt;操作符，否则将引擎放弃使用索引而进行全表扫描。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 4.应尽量避免在 where 子句中使用 or 来连接条件，否则将导致引擎放弃使用索引而进行全表扫描，如：<br />
&nbsp;&nbsp;&nbsp; select id from t where num=10 or num=20<br />
&nbsp;&nbsp;&nbsp; 可以这样查询：<br />
&nbsp;&nbsp;&nbsp; select id from t where num=10<br />
&nbsp;&nbsp;&nbsp; union all<br />
&nbsp;&nbsp;&nbsp; select id from t where num=20</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 5.in 和 not in 也要慎用，否则会导致全表扫描，如：<br />
&nbsp;&nbsp;&nbsp; select id from t where num in(1,2,3)<br />
&nbsp;&nbsp;&nbsp; 对于连续的数值，能用 between 就不要用 in 了：<br />
&nbsp;&nbsp;&nbsp; select id from t where num between 1 and 3</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 6.下面的查询也将导致全表扫描：<br />
&nbsp;&nbsp;&nbsp; select id from t where name like '%abc%'<br />
&nbsp;&nbsp;&nbsp; 若要提高效率，可以考虑全文检索。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 7.如果在 where 子句中使用参数，也会导致全表扫描。因为SQL只有在运行时才会解析局部变量，但优化程序不能将访问计划的选择推迟到运行时；它必须在编译时进行选择。然而，如果在编译时建立访问计划，变量的值还是未知的，因而无法作为索引选择的输入项。如下面语句将进行全表扫描：<br />
&nbsp;&nbsp;&nbsp; select id from t where num=@num<br />
&nbsp;&nbsp;&nbsp; 可以改为强制查询使用索引：<br />
&nbsp;&nbsp;&nbsp; select id from t with(index(索引名)) where num=@num</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 8.应尽量避免在 where 子句中对字段进行表达式操作，这将导致引擎放弃使用索引而进行全表扫描。如：<br />
&nbsp;&nbsp;&nbsp; select id from t where num/2=100<br />
&nbsp;&nbsp;&nbsp; 应改为: <br />
&nbsp;&nbsp;&nbsp; select id from t where num=100*2</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 9.应尽量避免在where子句中对字段进行函数操作，这将导致引擎放弃使用索引而进行全表扫描。如：<br />
&nbsp;&nbsp;&nbsp; select id from t where substring(name,1,3)='abc'--name以abc开头的id<br />
&nbsp;&nbsp;&nbsp; select id from t where datediff(day,createdate,'2005-11-30')=0--&#8216;2005-11-30&#8217;生成的id<br />
&nbsp;&nbsp;&nbsp; 应改为:<br />
&nbsp;&nbsp;&nbsp; select id from t where name like 'abc%'<br />
&nbsp;&nbsp;&nbsp; select id from t where createdate&gt;='2005-11-30' and createdate&lt;'2005-12-1'</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 10.不要在 where 子句中的&#8220;=&#8221;左边进行函数、算术运算或其他表达式运算，否则系统将可能无法正确使用索引。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 11.在使用索引字段作为条件时，如果该索引是复合索引，那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引，否则该索引将不会被使用，并且应尽可能的让字段顺序与索引顺序相一致。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 12.不要写一些没有意义的查询，如需要生成一个空表结构：<br />
&nbsp;&nbsp;&nbsp; select col1,col2 into #t from t where 1=0<br />
&nbsp;&nbsp;&nbsp; 这类代码不会返回任何结果集，但是会消耗系统资源的，应改成这样：<br />
&nbsp;&nbsp;&nbsp; create table #t(...)</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 13.很多时候用 exists 代替 in 是一个好的选择：<br />
&nbsp;&nbsp;&nbsp; select num from a where num in(select num from b)<br />
&nbsp;&nbsp;&nbsp; 用下面的语句替换：<br />
&nbsp;&nbsp;&nbsp; select num from a where exists(select 1 from b where num=a.num)</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 14.并不是所有索引对查询都有效，SQL是根据表中数据来进行查询优化的，当索引列有大量数据重复时，SQL查询可能不会去利用索引，如一表中有字段sex，male、female几乎各一半，那么即使在sex上建了索引也对查询效率起不了作用。<br />
&nbsp;15.索引并不是越多越好，索引固然可以提高相应的 select 的效率，但同时也降低了 insert 及 update 的效率，因为 insert 或 update 时有可能会重建索引，所以怎样建索引需要慎重考虑，视具体情况而定。一个表的索引数最好不要超过6个，若太多则应考虑一些不常使用到的列上建的索引是否有必要。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 16.应尽可能的避免更新 clustered 索引数据列，因为 clustered 索引数据列的顺序就是表记录的物理存储顺序，一旦该列值改变将导致整个表记录的顺序的调整，会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列，那么需要考虑是否应将该索引建为 clustered 索引。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 17.尽量使用数字型字段，若只含数值信息的字段尽量不要设计为字符型，这会降低查询和连接的性能，并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符，而对于数字型而言只需要比较一次就够了。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 18.尽可能的使用 varchar/nvarchar 代替 char/nchar ，因为首先变长字段存储空间小，可以节省存储空间，其次对于查询来说，在一个相对较小的字段内搜索效率显然要高些。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 19.任何地方都不要使用 select * from t ，用具体的字段列表代替&#8220;*&#8221;，不要返回用不到的任何字段。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 20.尽量使用表变量来代替临时表。如果表变量包含大量数据，请注意索引非常有限（只有主键索引）。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 21.避免频繁创建和删除临时表，以减少系统表资源的消耗。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 22.临时表并不是不可使用，适当地使用它们可以使某些例程更有效，例如，当需要重复引用大型表或常用表中的某个数据集时。但是，对于一次性事件，最好使用导出表。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 23.在新建临时表时，如果一次性插入数据量很大，那么可以使用 select into 代替 create table，避免造成大量 log ，以提高速度；如果数据量不大，为了缓和系统表的资源，应先create table，然后insert。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 24.如果使用到了临时表，在存储过程的最后务必将所有的临时表显式删除，先 truncate table ，然后 drop table ，这样可以避免系统表的较长时间锁定。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 25.尽量避免使用游标，因为游标的效率较差，如果游标操作的数据超过1万行，那么就应该考虑改写。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 26.使用基于游标的方法或临时表方法之前，应先寻找基于集的解决方案来解决问题，基于集的方法通常更有效。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 27.与临时表一样，游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法，尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括&#8220;合计&#8221;的例程通常要比使用游标执行的速度快。如果开发时间允许，基于游标的方法和基于集的方法都可以尝试一下，看哪一种方法的效果更好。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ，在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 29.尽量避免大事务操作，提高系统并发能力。</font></p>
<p><font face="Arial">&nbsp;&nbsp;&nbsp; 30.尽量避免向客户端返回大数据量，若数据量过大，应该考虑相应需求是否合理。</font></p>
<img src ="http://www.blogjava.net/java-my-love/aggbug/190371.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-04-02 14:56 <a href="http://www.blogjava.net/java-my-love/articles/190371.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网站设计中43个你应当避免的错误(转)</title><link>http://www.blogjava.net/java-my-love/articles/189692.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Sun, 30 Mar 2008 16:23:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/189692.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/189692.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/189692.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/189692.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/189692.html</trackback:ping><description><![CDATA[1.&nbsp;用户必须在几秒钟知道网站是做什么的。注意力是因特网上最有价值的货币。&nbsp;如果访问者无法在几秒钟之内得知你的网站的方向，他很有可能转而访问其他网站。&nbsp;你必须迅速地告诉访问者为什么要在你的网站上花费时间。&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;让网站易于速读。因特网不是书，因此没必要使用大段的文字。&nbsp;也许我访问你的网站时我正在忙于其他工作，我不得不迅速读完所有内容。&nbsp;项目符号、标题、副标题、列表，这些都能帮助读者迅速找到他想要的内容。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;3.&nbsp;不要使用难于阅读的花哨字体。当然，某些字体可以让网站精彩纷呈。&nbsp;不过它们容易阅读吗？如果你的主要目的是传递信息并让读者阅读，&nbsp;你应该让阅读过程舒服些。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;4.&nbsp;不要用小字体。如上一条所述，你得让读者阅读时感到舒服。&nbsp;虽然我的Firefox有放大功能，但如果必须放大才能看清一个网站的话，&nbsp;我就再也不会去访问它了。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;5.&nbsp;不要打开新浏览器窗口。我的第一个网站曾经经常这么做。&nbsp;原因很简单，在新窗口中打开外部链接，用户就不必离开我的网站。&nbsp;错！让用户决定如何打开链接，否则浏览器上大大的后退按钮就没必要存在了。&nbsp;不用担心用户离开你的网站，在必要的时候他们会回来的。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;6.&nbsp;不要改变用户的浏览器窗口大小。用户有权控制自己的浏览器。&nbsp;如果你改变窗口大小，你会在他们面前失去信用。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;7.&nbsp;不必要时不要让用户注册。直白地讲，我上网是为了获取信息，不是为了别的。&nbsp;不要强迫我注册并留下我的电子邮件以及其他信息，除非特别必要（比如你&nbsp;能提供的消息非常有价值）。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;8.&nbsp;不要在未经访问者同意的情况下为他们订阅电子杂志。&nbsp;不要在访问者注册时自动给他们订阅电子杂志。&nbsp;不请自来的邮件可不是个交朋友的好办法。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;9.&nbsp;不要过多使用Flash。Flash不仅会增加网站的读取时间，&nbsp;过度使用甚至会让访问者感到不快。只有当静态页面无法表达你的意图时&nbsp;才使用Flash。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;10.&nbsp;不要播放音乐。早些年Web开发者都喜欢在网站中集成音乐，结果他们失败了。&nbsp;记住，永远不要使用音乐。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;11.&nbsp;当你必须使用声音时，让用户启动它。有时你必须使用声音文件，&nbsp;比如你要给用户发送一份演讲，或者你的教程包含声音。这没问题，但要让用户来控制，&nbsp;让用户点击&#8220;播放&#8221;按钮，别在打开网页的瞬间播放声音。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;12.&nbsp;不要让标志弄乱你的网站。社交网络和社区的标志会让你的网站看起来十分不专业。&nbsp;就算是奖章和荣誉等标志也应当放到&#8220;关于我们&#8221;页面上。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;13.&nbsp;不要使用&#8220;点击进入&#8221;页面。用户访问到内容的步骤越少越好。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;14.&nbsp;注意要留下联系方式。最差的莫过于网站没有留下联系方式的了。&nbsp;不仅对访问者不友好，而且对你也没好处，你会错过珍贵的反馈信息。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;15.&nbsp;不要影响&#8220;后退&#8221;按钮的动作。这是网站可用性的最基本的理念。&nbsp;在任何情况下都不能影响&#8220;后退&#8221;按钮的动作。比如，打开新窗口会破坏它，&nbsp;某些Javas&nbsp;cript链接也会破坏它。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;16.&nbsp;不要用闪烁的文字。除非你的访问者来自1996年，否则别用闪烁文字。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;17.&nbsp;避免复杂的URL结构。一个简单的基于关键字的URL结构不仅能提高你的搜索引擎排名，&nbsp;还能让访问者在访问之前了解网页内容。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;18.&nbsp;用CSS布局，不要使用表格。HTML表格曾经被用于页面布局，&nbsp;但没有必要拘泥于此，尤其是在CSS诞生之后。CSS更快、更稳定，&nbsp;并能提供更多的特性。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;19.&nbsp;保证用户可以搜索整个网站。搜索引擎带来因特网革命的原因，就是&nbsp;它使得信息查找变得十分容易。别在你的网站上唱反调。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;20.&nbsp;避免使用下拉菜单。用户应当直观地看到所有导航选项。&nbsp;下拉菜单会造成混乱，并且会隐藏访问者真正要找的信息。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;21.&nbsp;使用文字做导航栏。文字导航不仅速度快，而且更稳定。&nbsp;例如，有些用户上网时会关闭图片。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;22.&nbsp;如果需要链接到PDF文档，一定要注明。你一定有过点击链接之后，&nbsp;浏览器就像死掉一样等待Acrobat&nbsp;Reader启动，只为了打开一个（你不想看的）PDF？&nbsp;这是个不小的麻烦，因此一定要在指向PDF的链接旁特别说明，使用户可以采取相应措施。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;23.&nbsp;不要用多种版本让访问者迷惑。你想用哪种带宽？56Kbps？128Kbps？Flash版还是HTML版？&nbsp;嗨，我只想快点看到内容！ <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;24.&nbsp;不要在内容中混合广告。在内容中混合广告（如Adsense）也许会增加短期内的广告点击率，&nbsp;但从长远角度来看，这会减少网站的人气。愤怒的用户会离开的。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;25.&nbsp;使用简单的导航结构。过犹不及。这个规则通常适用于人和选择上。&nbsp;确保你的网站的导航结构单纯简洁。你不想让用户在查找信息时遇到麻烦吧？ <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;26.&nbsp;避免内容介绍。别强迫用户在访问到真正内容之前看某些东西。&nbsp;这很令人愤怒，除非你提供的信息是用户必须的，否则他不会等下去。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;27.&nbsp;不要使用FrontPage。这一点也适用于其他廉价的HTML编辑器。&nbsp;它们让页面设计变得更方便，但其输出结果将会非常低级，不兼容不同的浏览器，&nbsp;并且会包含错误。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;28.&nbsp;保证你的网站兼容大部分浏览器。浏览器并不完全相同，在解释CSS和其他&nbsp;语言的方法也相差甚远。不管你是否愿意，你应当让网站兼容市面上的常用浏览器，&nbsp;否则你会永远地失去部分读者。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;29.&nbsp;保证在链接上添加有意义的文字。以前我经常犯这个错误。告诉人们&#8220;点击这里&#8221;很容易，&nbsp;但这没有效果。要保证链接文字有意义。它使得访问者知道点击链接之后将出现什么，&nbsp;也能为链接指向的外部站点带来SEO效果。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;30.&nbsp;不要在状态栏中隐藏链接。用户还必须能在状态栏中看到链接指向哪里。&nbsp;如果你隐藏了链接（即使是由于其他原因），那么你也会丧失信誉。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;31.&nbsp;使链接可见。访问者应能轻易识别出哪些能点击，哪些不能。&nbsp;确保链接的颜色有强烈的对比（标准的蓝色通常是最好的）。可能的话，&nbsp;最好加上下划线。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;32.&nbsp;不要在普通文本上添加下划线或者颜色。除非特别需要，否则不要为普通文字添加下划线。&nbsp;就像用户需要识别哪些能点击一样，他们不应当将本不能点击的文字误认为能够点击。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;33.&nbsp;改变访问过的链接的颜色。这一点对于提高网站可用性非常重要。&nbsp;改变访问过的链接颜色有助于用户在网站中定位，确保他们不会不经意地&nbsp;访问同一页面两次。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;34.&nbsp;不要使用动态GIF。除非你有需要动画的广告条，否则避免使用动态GIF。&nbsp;它会使网站看上去很业余，并且会分散访问者的注意力。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;35.&nbsp;给图像添加ALT和TITLE属性。ALT和TITLE不仅会带来SEO效果，而且&nbsp;对盲人有很大帮助。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;36.&nbsp;不要用令人不快的颜色。如果用户连续阅读10分钟后觉得头疼，&nbsp;那么你最好选择别的配色方案。根据你的目的决定设计（例如，创造一种氛围&nbsp;使得用户将注意力放在网站内容上，等等）。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;37.&nbsp;不要弹出窗口。这一点涉及任何种类的弹出窗口。即使用户要求使用，&nbsp;弹出窗口也不宜使用，因为它会被弹出窗口拦截功能阻拦。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;38.&nbsp;不要使用Javas&nbsp;cript做链接。远离那些点击之后执行一小段Javas&nbsp;cript的链接，&nbsp;它们经常给用户带来麻烦。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;39.&nbsp;在页面底部放置有意义的链接。访问者在找不到所需信息时通常会滚动到页面最底端。&nbsp;作为最后的手段，你应当在页面底部放一个&#8220;联系我们&#8221;页面的链接。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;40.&nbsp;避免网页过长。如果用户老是需要滚动才能看到内容，他通常会采取的做法是&nbsp;跳过它们。如果你的网站正好如此，那么应当缩短内容并优化导航结构。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;41.&nbsp;禁止使用水平滚动条。虽然垂直滚动条可以接受，但水平滚动条却远非如此。&nbsp;现在的流行分辨率是1024x768，要确保网站能容纳在其中。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;42.&nbsp;禁止出现拼写或语法错误。这不是网站设计的错，但却是影响网站整体质量的重要因素。&nbsp;确保链接和文字中没有拼写或语法错误。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;43.&nbsp;如果你使用图片认证，要保证能看清其字符。有些网站将图片认证作为对抗垃圾评论的方法，&nbsp;或是在注册表单上使用。其中有个问题就是，用户经常需要叫上全家人来讨论图片上到底是什么字母 <br />
<img src ="http://www.blogjava.net/java-my-love/aggbug/189692.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-03-31 00:23 <a href="http://www.blogjava.net/java-my-love/articles/189692.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate数据加载—Session.get()/load()方法异同</title><link>http://www.blogjava.net/java-my-love/articles/189599.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Sun, 30 Mar 2008 05:41:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/189599.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/189599.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/189599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/189599.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/189599.html</trackback:ping><description><![CDATA[Session.load/get方法均可以根据指定的实体类和id从数据库读取记录，并返回与之对应的实体对象。其区别在于：<br />
<br />
如果未能发现符合条件的记录，get方法返回null，而load方法会抛出一个ObjectNotFoundException。 <br />
Load方法可返回实体的代理类实例，而get方法永远直接返回实体类。 <br />
load方法可以充分利用内部缓存和二级缓存中的现有数据，而get方法则仅仅在内部缓存中进行数据查找，如没有发现对应数据，将越过二级缓存，直接调用SQL完成数据读取。 <br />
Session在加载实体对象时，将经过的过程：<br />
<br />
首先，Hibernate中维持了两级缓存。第一级缓存由Session实例维护，其中保持了Session当前所有关联实体的数据，也称为内部缓存。而第二级缓存则存在于SessionFactory层次，由当前所有由本SessionFactory构造的Session实例共享。出于性能考虑，避免无谓的数据库访问，Session在调用数据库查询功能之前，会先在缓存中进行查询。首先在第一级缓存中，通过实体类型和id进行查找，如果第一级缓存查找命中，且数据状态合法，则直接返回。 <br />
之后，Session会在当前&#8220;NonExists&#8221;记录中进行查找，如果&#8220;NonExists&#8221;记录中存在同样的查询条件，则返回null。&#8220;NonExists&#8221;记录了当前Session实例在之前所有查询操作中，未能查询到有效数据的查询条件（相当于一个查询黑名单列表）。如此一来，如果Session中一个无效的查询条件重复出现，即可迅速作出判断，从而获得最佳的性能表现。 <br />
对于load方法而言，如果内部缓存中未发现有效数据，则查询第二级缓存，如果第二级缓存命中，则返回。 <br />
如在缓存中未发现有效数据，则发起数据库查询操作（Select SQL），如经过查询未发现对应记录，则将此次查询的信息在&#8220;NonExists&#8221;中加以记录，并返回null。 <br />
根据映射配置和Select SQL得到的ResultSet，创建对应的数据对象。 <br />
将其数据对象纳入当前Session实体管理容器（一级缓存）。 <br />
执行Interceptor.onLoad方法（如果有对应的Interceptor）。 <br />
将数据对象纳入二级缓存。 <br />
如果数据对象实现了LifeCycle接口，则调用数据对象的onLoad方法。 <br />
返回数据对象。 
<img src ="http://www.blogjava.net/java-my-love/aggbug/189599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-03-30 13:41 <a href="http://www.blogjava.net/java-my-love/articles/189599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA的容器---List Map Set </title><link>http://www.blogjava.net/java-my-love/articles/188848.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Wed, 26 Mar 2008 12:18:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/188848.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/188848.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/188848.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/188848.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/188848.html</trackback:ping><description><![CDATA[<div>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">JAVA</span><span style="font-size: 10pt; font-family: 宋体">的容器---List,Map,Set <br />
Collection<br />
├List<br />
│├LinkedList<br />
│├ArrayList<br />
│└Vector<br />
│　└Stack<br />
└Set<br />
Map<br />
├Hashtable<br />
├HashMap<br />
└WeakHashMap</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">Collection</span><span style="font-size: 10pt; font-family: 宋体">接口<br />
　　Collection是最基本的集合接口，一个Collection代表一组Object，即Collection的元素（Elements）。一些 Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类，Java SDK提供的类都是继承自Collection的&#8220;子接口&#8221;如List和Set。<br />
　　所有实现Collection接口的类都必须提供两个标准的构造函数：无参数的构造函数用于创建一个空的Collection，有一个 Collection参数的构造函数用于创建一个新的Collection，这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。<br />
　　如何遍历Collection中的每一个元素？不论Collection的实际类型如何，它都支持一个iterator()的方法，该方法返回一个迭代子，使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下：<br />
　　　　Iterator it = collection.iterator(); // 获得一个迭代子<br />
　　　　while(it.hasNext()) {<br />
　　　　　　Object obj = it.next(); // 得到下一个元素<br />
　　　　}<br />
　　由Collection接口派生的两个接口是List和Set。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">List</span><span style="font-size: 10pt; font-family: 宋体">接口<br />
　　List是有序的Collection，使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引（元素在List中的位置，类似于数组下标）来访问List中的元素，这类似于Java的数组。<br />
和下面要提到的Set不同，List允许有相同的元素。<br />
　　除了具有Collection接口必备的iterator()方法外，List还提供一个listIterator()方法，返回一个 ListIterator接口，和标准的Iterator接口相比，ListIterator多了一些add()之类的方法，允许添加，删除，设定元素，还能向前或向后遍历。<br />
　　实现List接口的常用类有LinkedList，ArrayList，Vector和Stack。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">LinkedList</span><span style="font-size: 10pt; font-family: 宋体">类<br />
　　LinkedList实现了List接口，允许null元素。此外LinkedList提供额外的get，remove，insert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈（stack），队列（queue）或双向队列（deque）。<br />
　　注意LinkedList没有同步方法。如果多个线程同时访问一个List，则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List：<br />
　　　　List list = Collections.synchronizedList(new LinkedList(...));</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">ArrayList</span><span style="font-size: 10pt; font-family: 宋体">类<br />
　　ArrayList实现了可变大小的数组。它允许所有元素，包括null。ArrayList没有同步。<br />
size，isEmpty，get，set方法运行时间为常数。但是add方法开销为分摊的常数，添加n个元素需要O(n)的时间。其他的方法运行时间为线性。<br />
　　每个ArrayList实例都有一个容量（Capacity），即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加，但是增长算法并没有定义。当需要插入大量元素时，在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。<br />
　　和LinkedList一样，ArrayList也是非同步的（unsynchronized）。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">Vector</span><span style="font-size: 10pt; font-family: 宋体">类<br />
　　Vector非常类似ArrayList，但是Vector是同步的。由Vector创建的Iterator，虽然和ArrayList创建的 Iterator是同一接口，但是，因为Vector是同步的，当一个Iterator被创建而且正在被使用，另一个线程改变了Vector的状态（例如，添加或删除了一些元素），这时调用Iterator的方法时将抛出ConcurrentModificationException，因此必须捕获该异常。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">Stack </span><span style="font-size: 10pt; font-family: 宋体">类<br />
　　Stack继承自Vector，实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop 方法，还有peek方法得到栈顶的元素，empty方法测试堆栈是否为空，search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">Set</span><span style="font-size: 10pt; font-family: 宋体">接口<br />
　　Set是一种不包含重复的元素的Collection，即任意的两个元素e1和e2都有e1.equals(e2)=false，Set最多有一个null元素。<br />
　　很明显，Set的构造函数有一个约束条件，传入的Collection参数不能包含重复的元素。<br />
　　请注意：必须小心操作可变对象（Mutable Object）。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">Map</span><span style="font-size: 10pt; font-family: 宋体">接口<br />
　　请注意，Map没有继承Collection接口，Map提供key到value的映射。一个Map中不能包含相同的key，每个key只能映射一个 value。Map接口提供3种集合的视图，Map的内容可以被当作一组key集合，一组value集合，或者一组key-value映射。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">Hashtable</span><span style="font-size: 10pt; font-family: 宋体">类<br />
　　Hashtable继承Map接口，实现一个key-value映射的哈希表。任何非空（non-null）的对象都可作为key或者value。<br />
　　添加数据使用put(key, value)，取出数据使用get(key)，这两个基本操作的时间开销为常数。<br />
Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大，这会影响像get和put这样的操作。<br />
使用Hashtable的简单示例如下，将1，2，3放到Hashtable中，他们的key分别是&#8221;one&#8221;，&#8221;two&#8221;，&#8221;three&#8221;：<br />
　　　　Hashtable numbers = new Hashtable();<br />
　　　　numbers.put(&#8220;one&#8221;, new Integer(1));<br />
　　　　numbers.put(&#8220;two&#8221;, new Integer(2));<br />
　　　　numbers.put(&#8220;three&#8221;, new Integer(3));<br />
　　要取出一个数，比如2，用相应的key：<br />
　　　　Integer n = (Integer)numbers.get(&#8220;two&#8221;);<br />
　　　　System.out.println(&#8220;two = &#8221; + n);<br />
　　由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置，因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object，如果你用自定义的类当作key的话，要相当小心，按照散列函数的定义，如果两个对象相同，即obj1.equals(obj2)=true，则它们的hashCode必须相同，但如果两个对象不同，则它们的hashCode不一定不同，如果两个不同对象的hashCode相同，这种现象称为冲突，冲突会导致操作哈希表的时间开销增大，所以尽量定义好的hashCode()方法，能加快哈希表的操作。<br />
　　如果相同的对象有不同的hashCode，对哈希表的操作会出现意想不到的结果（期待的get方法返回null），要避免这种问题，只需要牢记一条：要同时复写equals方法和hashCode方法，而不要只写其中一个。<br />
　　Hashtable是同步的。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">HashMap</span><span style="font-size: 10pt; font-family: 宋体">类<br />
　　HashMap和Hashtable类似，不同之处在于HashMap是非同步的，并且允许null，即null value和null key。，但是将HashMap视为Collection时（values()方法可返回Collection），其迭代子操作时间开销和HashMap 的容量成比例。因此，如果迭代操作的性能相当重要的话，不要将HashMap的初始化容量设得过高，或者load factor过低。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">WeakHashMap</span><span style="font-size: 10pt; font-family: 宋体">类<br />
　　WeakHashMap是一种改进的HashMap，它对key实行&#8220;弱引用&#8221;，如果一个key不再被外部所引用，那么该key可以被GC回收。</span></p>
<p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">总结<br />
　　如果涉及到堆栈，队列等操作，应该考虑用List，对于需要快速插入，删除元素，应该使用LinkedList，如果需要快速随机访问元素，应该使用ArrayList。<br />
　　如果程序在单线程环境中，或者访问仅仅在一个线程中进行，考虑非同步的类，其效率较高，如果多个线程可能同时操作一个类，应该使用同步的类。<br />
　　要特别注意对哈希表的操作，作为key的对象要正确复写equals和hashCode方法。<br />
　　尽量返回接口而非实际的类型，如返回List而非ArrayList，这样如果以后需要将ArrayList换成LinkedList时，客户端代码不用改变。这就是针对抽象编程。</span></p>
</div>
<img src ="http://www.blogjava.net/java-my-love/aggbug/188848.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-03-26 20:18 <a href="http://www.blogjava.net/java-my-love/articles/188848.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为什么要用webservice解理文章(转载)</title><link>http://www.blogjava.net/java-my-love/articles/188701.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Wed, 26 Mar 2008 04:44:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/188701.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/188701.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/188701.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/188701.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/188701.html</trackback:ping><description><![CDATA[当前，WebService是一个热门话题。但是，WebService究竟是什么？什么情况下应该用WebService？什么情况下不应该用WebService？是需要我们正确认识的。<br />
<br />
　　实际上，WebService的主要目标是跨平台的可互操作性。为了达到这一目标，WebService完全基于XML（可扩展标记语言）、XSD（XMLSchema）等独立于平台、独立于软件供应商的标准，是创建可互操作的、分布式应用程序的新平台。由此可以看出，在以下三种情况下，使用WebService会带来极大的好处。<br />
<br />
　　长项一：跨防火墙的通信<br />
<br />
　　如果应用程序有成千上万的用户，而且分布在世界各地，那么客户端和服务器之间的通信将是一个棘手的问题。因为客户端和服务器之间通常会有防火墙或者代理服务器。在这种情况下，使用DCOM就不是那么简单，通常也不便于把客户端程序发布到数量如此庞大的每一个用户手中。传统的做法是，选择用浏览器作为客户端，写下一大堆ASP页面，把应用程序的中间层暴露给最终用户。这样做的结果是开发难度大，程序很难维护。<br />
<br />
　　图1通过WebService集成应用程序<br />
<br />
　　举个例子，在应用程序里加入一个新页面，必须先建立好用户界面(Web页面)，并在这个页面后面，包含相应商业逻辑的中间层组件，还要再建立至少一个ASP页面，用来接受用户输入的信息，调用中间层组件，把结果格式化为HTML形式，最后还要把&#8220;结果页&#8221;送回浏览器。要是客户端代码不再如此依赖于HTML表单，客户端的编程就简单多了。<br />
<br />
　　如果中间层组件换成WebService的话，就可以从用户界面直接调用中间层组件，从而省掉建立ASP页面的那一步。要调用WebService，可以直接使用MicrosoftSOAPToolkit或.NET这样的SOAP客户端，也可以使用自己开发的SOAP客户端，然后把它和应用程序连接起来。不仅缩短了开发周期，还减少了代码复杂度，并能够增强应用程序的可维护性。同时，应用程序也不再需要在每次调用中间层组件时，都跳转到相应的&#8220;结果页&#8221;。<br />
<br />
　　从经验来看，在一个用户界面和中间层有较多交互的应用程序中，使用WebService这种结构，可以节省花在用户界面编程上20%的开发时间。另外，这样一个由WebService组成的中间层，完全可以在应用程序集成或其它场合下重用。最后，通过WebService把应用程序的逻辑和数据&#8220;暴露&#8221;出来，还可以让其它平台上的客户重用这些应用程序。<br />
<br />
　　长项二：应用程序集成<br />
<br />
　　企业级的应用程序开发者都知道，企业里经常都要把用不同语言写成的、在不同平台上运行的各种程序集成起来，而这种集成将花费很大的开发力量。应用程序经常需要从运行在IBM主机上的程序中获取数据；或者把数据发送到主机或UNIX应用程序中去。即使在同一个平台上，不同软件厂商生产的各种软件也常常需要集成起来。通过WebService，应用程序可以用标准的方法把功能和数据&#8220;暴露&#8221;出来，供其它应用程序使用。<br />
<br />
　　例如，有一个订单登录程序，用于登录从客户来的新订单，包括客户信息、发货地址、数量、价格和付款方式等内容；还有一个订单执行程序，用于实际货物发送的管理。这两个程序来自不同软件厂商。一份新订单进来之后，订单登录程序需要通知订单执行程序发送货物。通过在订单执行程序上面增加一层WebService，订单执行程序可以把&#8220;AddOrder&#8221;函数&#8220;暴露&#8221;出来。这样，每当有新订单到来时，订单登录程序就可以调用这个函数来发送货物了。<br />
<br />
　　长项三：B2B的集成<br />
<br />
　　用WebService集成应用程序，可以使公司内部的商务处理更加自动化。但当交易跨越供应商和客户、突破公司的界限时会怎么样呢？跨公司的商务交易集成通常叫做B2B集成。<br />
<br />
　　WebService是B2B集成成功的关键。通过WebService，公司可以把关键的商务应用&#8220;暴露&#8221;给指定的供应商和客户。例如，把电子下单系统和电子发票系统&#8220;暴露&#8221;出来，客户就可以以电子的方式发送订单，供应商则可以以电子的方式发送原料采购发票。当然，这并不是一个新的概念，EDI(电子文档交换)早就是这样了。但是，WebService的实现要比EDI简单得多，而且WebService运行在Internet上，在世界任何地方都可轻易实现，其运行成本就相对较低。不过，WebService并不像EDI那样，是文档交换或B2B集成的完整解决方案。WebService只是B2B集成的一个关键部分，还需要许多其它的部分才能实现集成。<br />
<br />
　　用WebService来实现B2B集成的最大好处在于可以轻易实现互操作性。只要把商务逻辑&#8220;暴露&#8221;出来，成为WebService，就可以让任何指定的合作伙伴调用这些商务逻辑，而不管他们的系统在什么平台上运行，使用什么开发语言。这样就大大减少了花在B2B集成上的时间和成本，让许多原本无法承受EDI的中小企业也能实现B2B集成。<br />
<br />
　　长项四：软件和数据重用<br />
<br />
　　软件重用是一个很大的主题，重用的形式很多，重用的程度有大有小。最基本的形式是源代码模块或者类一级的重用，另一种形式是二进制形式的组件重用。<br />
<br />
　　图2用WebService集成各种应用中的功能，为用户提供一个统一的界面<br />
<br />
　　当前，像表格控件或用户界面控件这样的可重用软件组件，在市场上都占有很大的份额。但这类软件的重用有一个很大的限制，就是重用仅限于代码，数据不能重用。原因在于，发布组件甚至源代码都比较容易，但要发布数据就没那么容易，除非是不会经常变化的静态数据。<br />
<br />
　　WebService在允许重用代码的同时，可以重用代码背后的数据。使用WebService，再也不必像以前那样，要先从第三方购买、安装软件组件，再从应用程序中调用这些组件；只需要直接调用远端的WebService就可以了。举个例子，要在应用程序中确认用户输入的地址，只需把这个地址直接发送给相应的WebService，这个WebService就会帮你查阅街道地址、城市、省区和邮政编码等信息，确认这个地址是否在相应的邮政编码区域。WebService的提供商可以按时间或使用次数来对这项服务进行收费。这样的服务要通过组件重用来实现是不可能的，那样的话你必须下载并安装好包含街道地址、城市、省区和邮政编码等信息的数据库，而且这个数据库还是不能实时更新的。<br />
<br />
　　另一种软件重用的情况是，把好几个应用程序的功能集成起来。例如，要建立一个局域网上的门户站点应用，让用户既可以查询联邦快递包裹，查看股市行情，又可以管理自己的日程安排，还可以在线购买电影票。现在Web上有很多应用程序供应商，都在其应用中实现了这些功能。一旦他们把这些功能都通过WebService&#8220;暴露&#8221;出来，就可以非常容易地把所有这些功能都集成到你的门户站点中，为用户提供一个统一的、友好的界面。<br />
<br />
　　将来，许多应用程序都会利用WebService，把当前基于组件的应用程序结构扩展为组件/WebService的混合结构，可以在应用程序中使用第三方的WebService提供的功能，也可以把自己的应用程序功能通过WebService提供给别人。两种情况下，都可以重用代码和代码背后的数据。<br />
<br />
　　从以上论述可以看出，WebService在通过Web进行互操作或远程调用的时候是最有用的。不过，也有一些情况，WebService根本不能带来任何好处。<br />
<br />
　　短处一：单机应用程序<br />
<br />
　　目前，企业和个人还使用着很多桌面应用程序。其中一些只需要与本机上的其它程序通信。在这种情况下，最好就不要用WebService，只要用本地的API就可以了。COM非常适合于在这种情况下工作，因为它既小又快。运行在同一台服务器上的服务器软件也是这样。最好直接用COM或其它本地的API来进行应用程序间的调用。当然WebService也能用在这些场合，但那样不仅消耗太大，而且不会带来任何好处。<br />
<br />
　　短处二：局域网的同构应用程序<br />
<br />
　　在许多应用中，所有的程序都是用VB或VC开发的，都在Windows平台下使用COM，都运行在同一个局域网上。例如，有两个服务器应用程序需要相互通信，或者有一个Win32或WinForm的客户程序要连接局域网上另一个服务器的程序。在这些程序里，使用DCOM会比SOAP/HTTP有效得多。与此相类似，如果一个.NET程序要连接到局域网上的另一个.NET程序，应该使用.NETremoting。有趣的是，在.NETremoting中，也可以指定使用SOAP/HTTP来进行WebService调用。不过最好还是直接通过TCP进行RPC调用，那样会有效得多。<br />
<br />
　　总之，只要从应用程序结构的角度看，有别的方法比WebService更有效、更可行，那就不要用WebService。<img id="paperPicArea1" style="display: none; position: relative" src="http://imgcache.qq.com/qzone_v4/b.gif"  alt="" />
<div class="clear" id="paperBottom"></div>
<img src ="http://www.blogjava.net/java-my-love/aggbug/188701.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-03-26 12:44 <a href="http://www.blogjava.net/java-my-love/articles/188701.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts+Hibernate通用分页</title><link>http://www.blogjava.net/java-my-love/articles/188355.html</link><dc:creator>杨景</dc:creator><author>杨景</author><pubDate>Mon, 24 Mar 2008 13:36:00 GMT</pubDate><guid>http://www.blogjava.net/java-my-love/articles/188355.html</guid><wfw:comment>http://www.blogjava.net/java-my-love/comments/188355.html</wfw:comment><comments>http://www.blogjava.net/java-my-love/articles/188355.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-my-love/comments/commentRss/188355.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-my-love/services/trackbacks/188355.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 自己写个分页,用起来挺爽PageBean类:&nbsp;&nbsp; 封装一切页面元素及结果集,保存在Session里,省略了一切能省略的setter getterpackage&nbsp;com.yls.car.bean.car;//通用Hibernate分页类&nbsp;import&nbsp;java.util.*;import&nbsp;org.hibe...&nbsp;&nbsp;<a href='http://www.blogjava.net/java-my-love/articles/188355.html'>阅读全文</a><img src ="http://www.blogjava.net/java-my-love/aggbug/188355.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-my-love/" target="_blank">杨景</a> 2008-03-24 21:36 <a href="http://www.blogjava.net/java-my-love/articles/188355.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>