﻿<?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-limq</title><link>http://www.blogjava.net/limq/</link><description>rainman</description><language>zh-cn</language><lastBuildDate>Wed, 29 Apr 2026 16:51:14 GMT</lastBuildDate><pubDate>Wed, 29 Apr 2026 16:51:14 GMT</pubDate><ttl>60</ttl><item><title>MUI 上拉加载 完整实例</title><link>http://www.blogjava.net/limq/archive/2018/04/24/433177.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Tue, 24 Apr 2018 07:29:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2018/04/24/433177.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/433177.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2018/04/24/433177.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/433177.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/433177.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;例子是参照网上的MUI豆瓣电影，但是android上有一个问题 上拉后卡主不能动，并且提示&nbsp;Ignored attempt to cancel a touchmove event with cancelable=false查了很多，最后解决的方案是 阻止了冒泡事件。Code highlighting produced by Actipro CodeHighlighter (f...&nbsp;&nbsp;<a href='http://www.blogjava.net/limq/archive/2018/04/24/433177.html'>阅读全文</a><img src ="http://www.blogjava.net/limq/aggbug/433177.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2018-04-24 15:29 <a href="http://www.blogjava.net/limq/archive/2018/04/24/433177.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>动态表单及动态建表实现原理</title><link>http://www.blogjava.net/limq/archive/2009/09/19/295690.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Sat, 19 Sep 2009 13:12:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2009/09/19/295690.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/295690.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2009/09/19/295690.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/295690.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/295690.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.blogjava.net/limq/archive/2009/09/19/295690.html'>阅读全文</a><img src ="http://www.blogjava.net/limq/aggbug/295690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2009-09-19 21:12 <a href="http://www.blogjava.net/limq/archive/2009/09/19/295690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构—利用反射合并函数</title><link>http://www.blogjava.net/limq/archive/2009/02/17/255027.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Tue, 17 Feb 2009 01:49:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2009/02/17/255027.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/255027.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2009/02/17/255027.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/255027.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/255027.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp;&nbsp;先看下重构前的测试用例：public&nbsp;class&nbsp;TestLogin&nbsp;extends&nbsp;TestCase{&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;ButtonManagerIbatis&nbsp;buttonManagerIbatis;&nbsp;&nbsp;&n...&nbsp;&nbsp;<a href='http://www.blogjava.net/limq/archive/2009/02/17/255027.html'>阅读全文</a><img src ="http://www.blogjava.net/limq/aggbug/255027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2009-02-17 09:49 <a href="http://www.blogjava.net/limq/archive/2009/02/17/255027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载- 网页弹出对话框</title><link>http://www.blogjava.net/limq/archive/2008/01/27/178009.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Sun, 27 Jan 2008 05:28:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2008/01/27/178009.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/178009.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2008/01/27/178009.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/178009.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/178009.html</trackback:ping><description><![CDATA[如何利用网页弹出各种形式的窗口，我想大家大多都是知道些的，但那种多种多样的弹出式窗口是怎么搞出来的，我们今天就来学习一下：
<p align="left">　　<strong>1.弹启一个全屏窗口</strong></p>
<p align="left">&lt;html&gt;<br />
&lt;body onload="window.open('http://www.pconline.com.cn','example01','fullscreen');"&gt;;<br />
&lt;b&gt;www.e3i5.com&lt;/b&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p align="left">　　<strong>2.弹启一个被F11化后的窗口</strong></p>
<p align="left">&lt;html&gt;<br />
&lt;body onload="window.open(''http://www.pconline.com.cn','example02','channelmode');"&gt;;<br />
&lt;b&gt;www.e3i5.com&lt;/b&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p align="left">　　<strong>3.弹启一个带有收藏链接工具栏的窗口</strong></p>
<p align="left">&lt;html&gt;<br />
&lt;body onload="window.open('http://www.pconline.com.cn','example03','width=400,height=300,directories');"&gt;<br />
&lt;b&gt;www.e3i5.com&lt;/b&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p align="left">　　<strong>4.网页对话框</strong></p>
<p align="left">&lt;html&gt;<br />
&lt;SCRIPT LANGUAGE="javascript"&gt;<br />
&lt;!--<br />
showModalDialog('http://www.pconline.com.cn','example04','dialogWidth:400px;dialogHeight:300px;<br />
dialogLeft:200px;dialogTop:150px;center:yes;help:yes;resizable:yes;status:yes')<br />
//--&gt;<br />
&lt;/SCRIPT&gt;<br />
&lt;b&gt;www.e3i5.com&lt;/b&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p align="left">&lt;html&gt;<br />
&lt;SCRIPT LANGUAGE="javascript"&gt;<br />
&lt;!--<br />
showModelessDialog('http://www.pconline.com.cn','example05','dialogWidth:400px;dialogHeight:300px;<br />
dialogLeft:200px;dialogTop:150px;center:yes;help:yes;resizable:yes;status:yes')<br />
//--&gt;<br />
&lt;/SCRIPT&gt;<br />
&lt;b&gt;http://www.pconline.com.cn&lt;/b&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p align="left">　　showModalDialog()或是showModelessDialog() 来调用网页对话框，至于showModalDialog()与showModelessDialog()的区别，在于showModalDialog()打开的窗口（简称模式窗口），置在父窗口上，必须关闭才能访问父窗口(建议尽量少用，以免招人反感)；showModelessDialog()（简称无模式窗口），打开后不必关闭也可访问父窗口打开的窗口。 </p>
<p align="left">dialogHeight: iHeight 设置对话框窗口的高度。 <br />
dialogWidth: iWidth 设置对话框窗口的宽度。 　　<br />
dialogLeft: iXPos 设置对话框窗口相对于桌面左上角的left位置。 <br />
dialogTop: iYPos 设置对话框窗口相对于桌面左上角的top位置。 <br />
center: {yes | no | 1 | 0 } 指定是否将对话框在桌面上居中，默认值是&#8220;yes&#8221;。<br />
help: {yes | no | 1 | 0 } 指定对话框窗口中是否显示上下文敏感的帮助图标。默认值是&#8220;yes&#8221;。 　　<br />
resizable: {yes | no | 1 | 0 } 指定是否对话框窗口大小可变。默认值是&#8220;no&#8221;。 <br />
status: {yes | no | 1 | 0 } 指定对话框窗口是否显示状态栏。对于非模式对话框窗口，默认值是&#8220;yes&#8221;；对于模式对话框窗口，默认值是 &#8220;no&#8221;。</p>
<img src ="http://www.blogjava.net/limq/aggbug/178009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2008-01-27 13:28 <a href="http://www.blogjava.net/limq/archive/2008/01/27/178009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4j使用进阶</title><link>http://www.blogjava.net/limq/archive/2006/04/10/40341.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Mon, 10 Apr 2006 15:11:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2006/04/10/40341.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/40341.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2006/04/10/40341.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/40341.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/40341.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" align="right" border="0">
				<tbody>
						<tr>
								<td>
										<table cellspacing="0" cellpadding="0" align="left" border="0">
												<tbody>
														<tr>
																<td>
																		<!-- 这儿显示Google的广告 -->
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>二　动态配置log4j<br />1 配置外部配置文件来配置的基本步骤<br />1.1　一个运用配置文件的实例<br />Log4j之所以能成功的原因之一是它的灵活性。但如果只是简单的调用BasicConfigurator.configure()来进行配置工作，那么所有的配置都是在函数中写死的，以后修改配置就要修改原代码，这就不能体现出log4j的灵活性了，所以基本上不会通过BasicConfigurator.configure()来进行配置工作的。<br />为了增加软件的灵活性，最常用的做法就是使用配置文件，如web.xml之于J2EE，struts-config.xml之于struts一样，log4j也提供了让我们把配置信息从程序转移到配置文件中的方法。Log4j提供了两种方式的配置文件：XML文件和Java的property配置文件。通过把配置信息转移到外部文件中，当我们要修改配置信息时，就可以直接修改配置文件而不用去修改代码了，下面，我们就来完成一个通过配置文件来实现log4j的实例。<br />例2-a：<br />package TestLog4j;<br />import org.apache.log4j.Logger;<br />import org.apache.log4j.BasicConfigurator;<br />import org.apache.log4j.PropertyConfigurator;<br />import org.apache.log4j.Priority; public class TestLog4j <br />{<br />static Logger logger = Logger.getLogger(TestLog4j.class.getName());<br />public TestLog4j(){}<br /><br />public static void main(String[] args)<br />{<br />//通过BasicConfigurator类来初始化<br />//BasicConfigurator.configure();<br />//（1）通过配置文件来初始化<br />PropertyConfigurator.configure("F:\\nepalon\\log4j.properties");<br /><br />logger.debug("Start of the main() in TestLog4j");　//代码（2）<br />logger.info("Just testing a log message with priority set to INFO");<br />logger.warn("Just testing a log message with priority set to WARN");<br />logger.error("Just testing a log message with priority set to ERROR");<br />logger.fatal("Just testing a log message with priority set to FATAL");<br />logger.log(Priority.WARN, "Testing a log message use a alternate form");<br />logger.debug(TestLog4j.class.getName());　//代码（2）<br />}<br />}<br />在这个例子中，我们用PropertyConfigurator.configure("F:\\nepalon\\log4j.properties")代替BasicConfigurator.configure()进行配置。PropertyConfigurator.configure()函数的参数可以是一个properties文件所在路径的String对象，可以是一个properties文件所在路径的URL对象，也可以是一个properties对象。通过PropertyConfigurator.configure()可以通过指定的properties文件来配置信息。如果要用XML文件进行信息配置，可以在代码中调用DOMConfigurator()函数来进行配置工作。在这里，我们只以properties文件来完成例子。接着，我们来看一下log4j.properties文件中都有些什么东西：<br />例2-b：<br />log4j.rootLogger = DEBUG, A1<br />log4j.appender.A1 = org.apache.log4j.ConsoleAppender<br />log4j.appender.A1.layout = org.apache.log4j.PatternLayout<br />log4j.appender.A1.layout.ConversionPattern = %-4r [%t] %-5p %c %x - %m%n<br />运行这个实例，运行结果为<br />0 [main] DEBUG TestLog4j.TestLog4j - Start of the main() in TestLog4j<br />20 [main] INFO TestLog4j.TestLog4j - Just testing a log message with priority set to INFO<br />20 [main] WARN TestLog4j.TestLog4j - Just testing a log message with priority set to WARN<br />20 [main] ERROR TestLog4j.TestLog4j - Just testing a log message with priority set to ERROR<br />20 [main] FATAL TestLog4j.TestLog4j - Just testing a log message with priority set to FATAL<br />180 [main] WARN TestLog4j.TestLog4j - Testing a log message use a alternate form<br />180 [main] DEBUG TestLog4j.TestLog4j - TestLog4j.TestLog4j<br />下面，我们分析一下这个配置文件。<br />1) 由于每一个Logger对旬都有一个级别，文件的第一行就是定义了一个Logger及其级别。在这里定义了一个根记录器（root logger），这涉及到记录器的层次问题，在些暂时不深入讨论，在后面的章节再进行讨论。<br />2) 第二行定义了一个名为A1的输出流，这个流就是控制台，所以通过Logger对象打印的信息会在控制台输出。<br />3) 第三行定义了打印信息的布局。在这里我们用PatternLayout作为此记录器的布局，PatternLayout允许你以灵活的格式来打印信息。<br />4) 第四行指定的打印信息的具体格式，从结果可知，这个实例的打印格式为：当前打印语句所使用的时间 [日志所在的线程] 打印的级别 当前日志所在的类的全名 日志信息。<br />现在我们来修改一下这个记录器的级别，把第一行的DEBUG改为INFO，再运行程序，结果将变为：<br />0 [main] INFO TestLog4j.TestLog4j - Just testing a log message with priority set to INFO<br />10 [main] WARN TestLog4j.TestLog4j - Just testing a log message with priority set to WARN<br />10 [main] ERROR TestLog4j.TestLog4j - Just testing a log message with priority set to ERROR<br />10 [main] FATAL TestLog4j.TestLog4j - Just testing a log message with priority set to FATAL<br />10 [main] WARN TestLog4j.TestLog4j - Testing a log message use a alternate form<br />由于这个Logger的级别变为INFO，而代码（2）是调用debug()函数来输出日志信息时只能当记录器级别为DEBUG时才输出信息，所以代码（2）将不输出信息。<br />1.2　实例原理<br />1.2.1　初始化配置信息<br />如果要通过JAVA的properties文件来配置信息，那么在代码中就要通过PropertyConfigurator.configure()函数从properties文件中加载配置信息，这个函数有三种参数形式：一个properties文件所在路径的String对象，可以是一个properties文件所在路径的URL对象，也可以是一个properties对象。如果要用XML文件来配置信息，则可用类型的<br />DOMConfigurator()函数来从一个XML文件中加载配置信息。<br />1.2.2　输出端Appender<br />在上面的例子中，我们都是简单的把日志信息输出到控制台中。其实在log4j中还可以把日志信息输出到其它的输出端，对于同一个日志信息，我们还可以让它同时输出到多个输出端中，如同时在控制台和文件中进行打印。一个输出端就是一个appender。要在配置文件中定义一个appender有三步：<br />1) 在定义一个记录器的同时定义出该记录器的输出端appender。在例2的配置文件的第一句log4j.rootLogger = DEBUG, A1中，我们定义了一个根记录器，它的级别为DEBUG，它有一个appender名为A1。定义根记录器的格式为log4j.rootLogger = [ level ], appendName1, appendName2, ...appendNameN。同一个记录器可有多个输出端。<br />2) 定义appender的输出目的地。定义一个appender的输出目的地的格式为log4j.appender.appenderName = fully.qualified.name.of.appender.class。log4j提供了以下几种常用的输出目的地：<br />? org.apache.log4j.ConsoleAppender，将日志信息输出到控制台<br />? org.apache.log4j.FileAppender，将日志信息输出到一个文件<br />? org.apache.log4j.DailyRollingFileAppender，将日志信息输出到一个，并且每天输出到一个新的日志文件<br />? org.apache.log4j.RollingFileAppender，将日志信息输出到一个文件，通过指定文件的的尺寸，当文件大小到达指定尺寸的时候会自动把文件改名，如名为example.log的文件会改名为example.log.1，同时产生一个新的example.log文件。如果新的文件再次达到指定尺寸，又会自动把文件改名为example.log.2，同时产生一个example.log文件。依此类推，直到example.log. MaxBackupIndex，MaxBackupIndex的值可在配置文件中定义。<br />? org.apache.log4j.WriterAppender，将日志信息以流格式发送到任意指定的地方。<br />? org.apache.log4j.jdbc.JDBCAppender，通过JDBC把日志信息输出到数据库中。<br />在例2中，log4j.appender.A1 = org.apache.log4j.ConsoleAppender定义了名为A1的appender的输出目的地为控制台，所以日志信息将输出到控制台。<br />3) 定义与所选的输出目的地相关的参数，定义格式为：<br />log4j.appender.appenderName.optionName1 = value1<br />......<br />log4j.appender.appenderName.optionNameN = valueN<br />其中一个最常用的参数layout将在下面介绍。<br />1.2.3　输出格式（布局）layout<br />通过appender可以控制输出的目的地，而如果要控制输出的格式，就可通过log4j的layout组件来实现。通过配置文件定义一个appender的输出格式，也通常需要两个步骤：<br />1) 定义appender的布局模式。定义一个appender的布局模式的格式为log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class。Log4j提供的布局模式有以下几种：<br />? org.apache.log4j.HTMLLayout，以HTML表格形式布局<br />? org.apache.log4j.PatternLayout，可以灵活地指定布局模式<br />? org.apache.log4j.SimpleLayout，包含日志信息的级别和信息字符串<br />在例2　中log4j.appender.A1.layout = org.apache.log4j.PatternLayout定义了名为A1的appender的布局模式为PatternLayout。<br />2) 定义与所选的布局模式相关的设置信息，定义格式为：<br />log4j.appender.appenderName.layout.optionName1 = value1<br />......<br />log4j.appender.appenderName.layout.optionNameN = valueN<br />选择了不同的布局模式可能会有不同的设置信息。实例2所选的布局模式PatternLayout的一个PatternLayout为ConversionPattern ，通过定义这个PatternLayout的值，我们可以指定输出信息的输出格式。在例2的配置文件中的定义如下log4j.appender.A1.layout.ConversionPattern = %-4r [%t] %-5p %c %x - %m%n。在下面，我们将介绍布局模式PatternLayout的参数ConversionPattern的各个值代表的含义。<br />1.2.4　ConversionPattern参数的格式含义<br />格式名 含义<br />%c 输出日志信息所属的类的全名<br />%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyy-MM-dd HH:mm:ss }，输出类似：2002-10-18- 22：10：28<br />%f 输出日志信息所属的类的类名<br />%l 输出日志事件的发生位置，即输出日志信息的语句处于它所在的类的第几行<br />%m 输出代码中指定的信息，如log(message)中的message<br />%n 输出一个回车换行符，Windows平台为"\r\n"，Unix平台为"\n"<br />%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL。如果是调用debug()输出的，则为DEBUG，依此类推<br />%r 输出自应用启动到输出该日志信息所耗费的毫秒数<br />%t 输出产生该日志事件的线程名<br />1.3　定义多个输出目的地的实例<br />从上面的实例原理中我们已经知道，同一个日志信息可以同时输出到多个输出目的地，在这个例子中，我们将实现一个把日志信息同时输出到控制器、一个文件中的实例和数据库中。这个实例的Java代码我们沿用例2中的代码，我们只需修改配置文件即可。这也体现了log4j的灵活性。<br />例3-a：<br />create table log4j(<br />logID int primary key identity,<br />message varchar(1024),<br />priority varchar(10),<br />milliseconds int,<br />category varchar(256),<br />thread varchar(100),<br />NDC varchar(256),<br />createDate datetime,<br />location varchar(256),<br />caller varchar(100),<br />method varchar(100),<br />filename varchar(100),<br />line int<br />)<br />例3-b：<br />#1 定义了两个输出端<br />log4j.rootLogger = INFO, A1, A2,A3<br /><br />#2 定义A1输出到控制器<br />log4j.appender.A1 = org.apache.log4j.ConsoleAppender<br />#3 定义A1的布局模式为PatternLayout<br />log4j.appender.A1.layout = org.apache.log4j.PatternLayout<br />#4 定义A1的输出格式<br />log4j.appender.A1.layout.ConversionPattern = %-4r [%t] %-5p %c - %m%n<br /><br />#5 定义A2输出到文件<br />log4j.appender.A2 = org.apache.log4j.RollingFileAppender<br />#6 定义A2要输出到哪一个文件<br />log4j.appender.A2.File = F:\\nepalon\\classes\\example3.log<br />#7 定义A2的输出文件的最大长度<br />log4j.appender.A2.MaxFileSize = 1KB<br />#8 定义A2的备份文件数<br />log4j.appender.A2.MaxBackupIndex = 3<br />#9 定义A2的布局模式为PatternLayout<br />log4j.appender.A2.layout = org.apache.log4j.PatternLayout<br />#10 定义A2的输出格式<br />log4j.appender.A2.layout.ConversionPattern = %d{yyyy-MM-dd hh:mm:ss}:%p %t %c - %m%n<br /><br />#11区 定义A3输出到数据库<br />log4j.appender.A3 = org.apache.log4j.jdbc.JDBCAppender<br />log4j.appender.A3.BufferSize = 40<br />log4j.appender.A3.Driver = com.microsoft.jdbc.sqlserver.SQLServerDriver<br />log4j.appender.A3.URL = jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=nepalon<br />log4j.appender.A3.User = sa<br />log4j.appender.A3.Password = <br />log4j.appender.A3.layout = org.apache.log4j.PatternLayout<br />log4j.appender.A3.layout.ConversionPattern = INSERT INTO log4j (createDate, thread, priority, category, message) values(getdate(), '%t', '%-5p', '%c', '%m')<br />配置文件中的6、7、8行显示了输出端为RollingFileAppender的特有参数及其运用的方法。11区显示了输出端为JDBCAppender的特有参数及其运用方法。在这着重讲解一下6、7、8行的作用。6行指定日志信息输出到哪个文件，7行指定日志文件的最大长度，最后要详细介绍8行。第8行的参数是设置备份文件的个数的参数，在这里我们设置为3，表示最多有3个备份文件，具体作用为：<br />1) 当example3.log文件的大小超过K时，就把文件改名为example3.log.1，同时生成一个新的example3.log文件<br />2) 当example3.log文件的大小再次超过1K，又把文件改名为example3.log.1。但由于此时example3.log.1已存在，则先把example3.log.1更名为example3.log.2，再把example3.log文件改名为example3.log.1<br />3) 同理，当example3.log文件的大小再次超过1K，先把example3.log.2文件更名为example3.log.3，把example3.log.1文件更名为example3.log.2，再把example3.log文件改名为example3.log.1<br />4) 当example3.log文件的大小再次超过1K，先把example3.log.2文件更名为example3.log.3，旧的example3.log.3文件将被覆盖；把example3.log.1文件更名为example3.log.2，旧的example3.log.2文件被覆盖；最后把example3.log文件改名为example3.log.1并覆盖掉旧的example3.log.1文件。<br />运行结果将分为两部分<br />在控制器中：<br />0 [main] INFO TestLog4j.TestLog4j - Just testing a log message with priority set to INFO<br />11 [main] WARN TestLog4j.TestLog4j - Just testing a log message with priority set to WARN<br />21 [main] ERROR TestLog4j.TestLog4j - Just testing a log message with priority set to ERROR 21 [main] FATAL TestLog4j.TestLog4j - Just testing a log message with priority set to FATAL<br />21 [main] WARN TestLog4j.TestLog4j - Testing a log message use a alternate form<br />在文件example3.log中：<br />2003-12-18 04:23:02:INFO main TestLog4j.TestLog4j - Just testing a log message with priority set to INFO<br />2003-12-18 04:23:02:WARN main TestLog4j.TestLog4j - Just testing a log message with priority set to WARN<br />2003-12-18 04:23:02:ERROR main TestLog4j.TestLog4j - Just testing a log message with priority set to ERROR<br />2003-12-18 04:23:02:FATAL main TestLog4j.TestLog4j - Just testing a log message with priority set to FATAL<br />2003-12-18 04:23:02:WARN main TestLog4j.TestLog4j - Testing a log message use a alternate form<br />1.4　配置log4j的总结<br />这个教程到这里，关于配置log4j的配置文件的基本原理已经讲完了，而且通过例3我们已经可以完成基本的日志工作了。现在，我们就做一个总结。配置一个配置文件的基本步骤如下：<br />1) 定义一个Logger。在定义Logger时指定该Logger的级别级其输出目的地。定义Logger的格式为<br />log4j.rootLogger = [ level ], appendName1, appendName2, ...appendNameN。<br />2) 定义appender的输出目的地。定义一个appender的输出目的地的格式为<br />log4j.appender.appenderName = fully.qualified.name.of.appender.class。<br />log4j提供的输出端有ConsoleAppender、FileAppender 、DailyRollingFileAppender、RollingFileAppender和WriterAppender。<br />3) 定义appender的除布局模式外的其它相关参数，如例3中第6、7、8定义了A2的相关参数。定义格式为<br />log4j.appender.appenderName.optionName1 = value1<br />......<br />log4j.appender.appenderName.optionNameN = valueN<br />如果除了布局模式外不需要定义别的参数，可跳过这一步（如例3中的A1）。<br />4) 定义appender的布局模式。定义一个appender的布局模式的格式为<br />log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class。<br />布局模式其实也是步骤3）中的一个部分，只是布局模式参数是每一个appender必须定义的参数。Log4j提供的布局模式有HTMLLayout、PatternLayout和SimpleLayout。<br />5) 定义与所选的布局模式相关的设置信息，定义格式为<br />og4j.appender.appenderName.layout.optionName1 = value1<br />......<br />log4j.appender.appenderName.layout.optionNameN = valueN<br />2　记录器的层次Logger hierarchy<br />2.1　何为记录器的层次hierarchy<br />首先，我们先看一下何为层次，以我们最熟悉的继承为例，下面是一张类图<br /><br />在这个继承体系中，类B是类C的父类，类A是类C的祖先类，类D是类C的子类。这些类之间就构成一种层次关系。在这些具有层次关系的类中，子类都可继承它的父类的特征，如类B的对象能调用类A中的非private实例变量和函数；而类C由于继承自类B，所以类B的对象可以同时调用类A和类B中的非private实例变量和函数。<br />在log4j中，处于不同层次中的Logger也具有象类这样的继承关系。<br />2.2　记录器的层次<br />如果一个应用中包含了上千个类，那么也几乎需要上千个Logger实例。如何对这上千个Logger实例进行方便地配置，就是一个很重要的问题。Log4J采用了一种树状的继承层次巧妙地解决了这个问题。在Log4J中Logger是具有层次关系的。它有一个共同的根，位于最上层，其它Logger遵循类似包的层次。下面我们将进行介绍。<br />2.2.1　根记录器root logger<br />就象一个Java中的Object类一样，log4j中的logger层次中有一个称之为根记录器的记录器，其它所有的记录器都继承自这个根记录器。根记录器有两个特征：<br />1) 根记录器总是存在。就像Java中的Object类一样，因为用log4j输出日志信息是通过记录器来实现的，所以只要你应用了log4j，根记录器就肯定存在的。<br />2) 根记录器没有名称，所以不能通过名称来取得根记录器。但在Logger类中提供了getRootLogger()的方法来取得根记录器。<br />2.2.2　记录器的层次<br />Logger遵循类似包的层次。如<br />static Logger rootLog = Logger.getRootLogger();<br />static Logger log1 = Logger.getLogger("test4j");<br />static Logger log2 = Logger.getLogger("test4j.test4j2");<br />static Logger log3 = Logger.getLogger("test4j.test4j2.test4j2");<br />那么rootLog是log2的祖先子记录器，log1是log2的父子记录器，log3是log2的子记录器。记录器象Java中的类继承一样，子记录器可以继承父记录器的设置信息，也可以可以覆写相应的信息。<br />首先先看一下记录器层次中的继承有什么用处。假设程序中的每个包都具有一些基本的日志信息，而包中的不同包可能会有些额外的日志信息要输出，这种情况就可以象处理Java中的类一样，运用Logger中的层次关系来达到目的。假设有个名为A的包，我包下的所有类都要把日志信息输出到控制台中；A.B包除了输出到控制台外还要输出到文件中；A.C包除了输出到控制台中还要输出到HTML文档中。这样我们就可以通过定义一个父记录器A，它负责把日志信息输出到控制台中；定义一个A的子记录器A.B，它负责把日志信息输出到文件中；定义一个A的子记录器A.C，它负责把日志信息输出到HTML文档中。<br />记录器遵循的是类似包的层次，这样做为我们带来了大大的方便。Logger类中的getLogger()方法可以取得Logger对象，这个方法有三种参数形式String、Class和URL，其实不论是用哪一种，最终都是通过记录器的名字来取得记录器对象的。如果要取得一个名为A.B的记录器对象，我们可以Logger.getLogger("A.B")。但从上面的例子中，我们都是通过Logger.getLogger(TestLog4j.class.getName())这种方法来取得记录器对象。这是为什么呢？现在我们假设A.B的包下有一个类BClass，那么我们调用BClass.class.getName()得到的是这个类的全名A.B.BClass。所以当调用Logger.getLogger(BClass.class.getName())时，最理想的情况是返回名为A.B.BClass的记录器对象。但是如果不存在名为A.B.BClass的记录器时它会怎样呢？其实通过Logger类的getLogger方法取得记录器时存在下面两种情况：<br />1) 如果存在与所要找的名字完全相同的记录器，则返回相应的记录器对象。<br />当调用Logger.getLogger(BClass.class.getName())时，如果定义了名为A.B.BClass的记录器，它就返回该记录器的对象。<br />2) 但如果找不到，它会尝试返回在记录器层次中与所要找的记录器最接近的记录器对象。<br />当调用Logger.getLogger(BClass.class.getName())时，如果没有定义了名为A.B.BClass的记录器，那会尝试返回名为A.B的记录器的对象；如果又没有定义名为A.B的记录器，它会尝试返回名为A的记录器的对象；如果也没定义名为A的记录器，它就会返回根记录器的对象，而根记录器是必须存在的，所以你总能得到一个记录器对象。<br />好了，现在我们回到前面的问题，我们为什么总要通过Logger.getLogger(BClass.class.getName())这种以类全名作为参数来取得记录器对象呢？其实这是为了管理方便。因为我们在定义设计Logger时也遵循类似包的规则，使设计器的名称与程序中的类包对应。如上面的假设中我们的程序中有A包，A包下有B包和C包，B包下又有类BClass，那么我们就可使设计器的名为A、A.B、A.C、A.B.BClass，以此类推。那么当我们通过类命名来取得设计器对象时，总能取到与所要的设计器最接近的设计器对象。<br />2.3　如何应用记录器的层次<br />2.3.1　如果定义及获取不同层次的记录器<br />任何一个记录器的使用都有两个步骤：<br />1) 在配置文件中定义相应的记录器。<br />在配置文件中定义记录器的格式有两种<br />? 定义根记录器的格式为<br />log4j.rootLogger = [ level ], appendName1, appendName2, ...appendNameN<br />? 定义一个非根记录器的格式为<br />log4j.logger.loggerName1 = [ level ], appendName1,...appendNameN<br />......<br />log4j.logger.loggerNameM = [ level ], appendName1, ...appendNameN<br />我们可以定义任意个非根记录器。<br />2) 在代码中调用Logger类的取得记录器方法取得相应的记录器对象。<br />要取得根记录器对象可通过Logger.getRootLogger()函数，要取得非根记录器可通过Logger.getLogger()函数。<br />理论知道就讲到这里，纸上得来终觉浅，下面，我们来小小演练一下。<br />例4-a：<br />package TestLog4j;<br />import org.apache.log4j.Logger;<br />import org.apache.log4j.PropertyConfigurator;<br />import org.apache.log4j.Priority;<br />import TestLog4j.TestLog4j2.TestLog4j2;<br /><br />public class TestLog4j <br />{<br />static Logger logger = Logger.getLogger(TestLog4j.class.getName());　//（2）<br />public TestLog4j(){}<br /><br />public static void main(String[] args)<br />{<br />//同时输出到控制台和一个文件的实例并实现了Logger的继承<br />PropertyConfigurator.configure("F:\\nepalon\\log4j2.properties");<br /><br />logger.debug("Start of the main() in TestLog4j");<br />logger.info("Just testing a log message with priority set to INFO");<br />logger.warn("Just testing a log message with priority set to WARN");<br />logger.error("Just testing a log message with priority set to ERROR");<br />logger.fatal("Just testing a log message with priority set to FATAL");<br />logger.log(Priority.WARN, "Testing a log message use a alternate form");<br />logger.debug(TestLog4j.class.getName());<br />TestLog4j2 testLog4j2 = new TestLog4j2();　//（1）<br />testLog4j2.testLog();<br />}<br />}<br />在类TestLog4j中我们调用了另一个类TestLog4j2，下面看一下类TestLog4j2的代码。<br />例4-b：<br />package TestLog4j.TestLog4j2;<br />import org.apache.log4j.Logger;<br />import org.apache.log4j.PropertyConfigurator;<br />import org.apache.log4j.Priority;<br /><br />public class TestLog4j2 <br />{<br />static Logger logger = Logger.getLogger(TestLog4j2.class.getName());　//（1）<br />public TestLog4j2(){}<br /><br />public void testLog()<br />{<br />//同时输出到控制台和一个文件的实例<br />PropertyConfigurator.configure("F:\\nepalon\\log4j2.properties");<br />logger.debug("2Start of the main()");<br />logger.info("2Just testing a log message with priority set to INFO");<br />logger.warn("2Just testing a log message with priority set to WARN");<br />logger.error("2Just testing a log message with priority set to ERROR");<br />logger.fatal("2Just testing a log message with priority set to FATAL");<br />logger.log(Priority.DEBUG, "Testing a log message use a alternate form");<br />logger.debug("2End of the main()");<br />}<br />}<br />最后我们来看一下配置文件。<br />例4-c：<br />log4j2.properties文件内容<br />＃1区<br />#### Use two appenders, one to log to console, another to log to a file<br />log4j.rootLogger = debug, stdout<br /><br />#2区<br />#Print only messages of priority WARN or higher for your category<br />log4j.logger.TestLog4j= , R<br />log4j.logger.TestLog4j.TestLog4j2=WARN<br /><br />#3区<br />#### First appender writes to console<br />log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br />log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<br /><br /># Pattern to output the caller's file name and line number.<br />log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n<br /><br />#4区<br />#### Second appender writes to a file<br />log4j.appender.R=org.apache.log4j.RollingFileAppender<br />log4j.appender.R.File=F:\\nepalon\\classes\\TestLog4j\\example.log<br /><br /># Control the maximum log file size<br />log4j.appender.R.MaxFileSize=100KB<br /># Archive log files (one backup file here)<br />log4j.appender.R.MaxBackupIndex=1<br /><br />log4j.appender.R.layout=org.apache.log4j.PatternLayout<br />log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss}:%p %t %c - %m%n<br />先看一下运行结果。<br />在控制台中的结果为：<br />DEBUG [main] (?:?) - Start of the main() in TestLog4j<br />INFO [main] (?:?) - Just testing a log message with priority set to INFO<br />WARN [main] (?:?) - Just testing a log message with priority set to WARN<br />ERROR [main] (?:?) - Just testing a log message with priority set to ERROR<br />FATAL [main] (?:?) - Just testing a log message with priority set to FATAL<br />WARN [main] (?:?) - Testing a log message use a alternate form<br />DEBUG [main] (?:?) - TestLog4j.TestLog4j<br />WARN [main] (?:?) - 2Just testing a log message with priority set to WARN<br />ERROR [main] (?:?) - 2Just testing a log message with priority set to ERROR<br />FATAL [main] (?:?) - 2Just testing a log message with priority set to FATAL<br />输出文件的结果为：<br />2003-12-19 04:19:44:DEBUG main TestLog4j.TestLog4j - Start of the main() in TestLog4j<br />2003-12-19 04:19:44:INFO main TestLog4j.TestLog4j - Just testing a log message with priority set to INFO<br />2003-12-19 04:19:44:WARN main TestLog4j.TestLog4j - Just testing a log message with priority set to WARN<br />2003-12-19 04:19:44:ERROR main TestLog4j.TestLog4j - Just testing a log message with priority set to ERROR<br />2003-12-19 04:19:44:FATAL main TestLog4j.TestLog4j - Just testing a log message with priority set to FATAL<br />2003-12-19 04:19:44:WARN main TestLog4j.TestLog4j - Testing a log message use a alternate form<br />2003-12-19 04:19:44:DEBUG main TestLog4j.TestLog4j - TestLog4j.TestLog4j<br />2003-12-19 04:19:44:WARN main TestLog4j.TestLog4j2.TestLog4j2 - 2Just testing a log message with priority set to WARN<br />2003-12-19 04:19:44:ERROR main TestLog4j.TestLog4j2.TestLog4j2 - 2Just testing a log message with priority set to ERROR<br />2003-12-19 04:19:44:FATAL main TestLog4j.TestLog4j2.TestLog4j2 - 2Just testing a log message with priority set to FATAL<br /><br />首先，先来看一下配置文件都有些什么东西。<br />1) 在1区中定义了一个根记录器。这个根记录器具有DEBUG级别并有一个名称为stdout的输出端appender。<br />2) 2区中的内容是这一节的重点，也是应用到记录器层次的地方，但其实也只有两句，充分体现了log4j的简单性。在这里，我们定义了两个名称分别为TestLog4j和TestLog4j.TestLog4j2设计器。<br />? 在定义TestLog4j记录器时没有指定级别，所以它的级别继承自它的父记录器，即要记录器，所以它的级别也为DEBUG。在定义TestLog4j记录器时又定义了一个名称为R的输出端，所以它的输出端有两个，一个从根记录器继承而来的名为stdout的输出端，另一个为在此定义的名为R的输出端。在此需要注意的是，在定义记录器时必须先定义记录器的级别，然后才是记录器的输出端。如果只想定义输出端而不定义级别，则虽然级别可以为空，但逗号分隔符不能省略。如定义TestLog4j记录器的做法。<br />? 在定义TestLog4j.TestLog4j2记录器时又指定了它的级别，由于一个记录器的级别只能有一个，所以新指定的级别将覆写掉它的父记录器的级别（这就象Java中的多态）。我们没有定义TestLog4j.TestLog4j2记录器的输出端，所以它的输出端将从它的父记录器中继承而来。它的父记录器为estLog4j记录器，所以它和estLog4j记录器一样具有两个名称分别为stdout和R的输出端。<br />3) 剩下的3区和4区分别设置了两个输出端的参数值。<br />接下来，回到我们的代码，看一下是如何取得记录器，在取记录器时又发生了什么。<br />1) 例4-a中的代码（2）中，语句Logger.getLogger()中的参数TestLog4j.class.getName()的值为TestLog4j. TestLog4j，所以此语句的结果是取得一个名为TestLog4j. TestLog4j的记录器的对象。但在配置文件中并没有定义这样的记录器，所以最终将返回与所需的名称TestLog4j. TestLog4j最接近的记录器对象，即名为TestLog4j的记录器的对象。<br />2) 例4-b中的代码（1）的原理与例4-a中的代码（2）相似，期望取得的是名为TestLog4j.TestLog4j2. TestLog4j2的记录器对象，但最终返回的是TestLog4j.TestLog4j2记录器的对象。<br />三　log4j与J2EE的结合<br />到目前为止，这篇文章讲的都是如何在application中应用log4j，而Java现在的应用主流是J2EE和J2ME。现在，我们来看一下要如何在J2EE开发中应用log4j。其实在Web application中应用log4j也很简单，与在application中应用log4j不同之处就是要在所有应用log4j的代码之前对log4j进行初始化。所以，我们在web application中就要把log4j的初始化工作独立出来，把它放在Servlet中。下面，我们看一个例子。<br />例5-a：<br />进行初始化的Servlet：<br />import org.apache.log4j.PropertyConfigurator;<br />import javax.servlet.http.HttpServlet;<br />import javax.servlet.http.HttpServletRequest;<br />import javax.servlet.http.HttpServletResponse;<br /><br />/**<br />* log4j.jar的初始化类，参考web.xml<br />*/<br />public class Log4jInit extends HttpServlet <br />{<br />public void init() <br />{<br />//通过web.xml来动态取得配置文件<br />String prefix = getServletContext().getRealPath("/");<br />String file = getInitParameter("log4j-init-file");<br /><br />// 如果没有给出相应的配置文件，则不进行初始化<br />if(file != null) <br />{<br />PropertyConfigurator.configure(prefix+file);　//（1）<br />}<br />}<br /><br />public void doGet(HttpServletRequest req, HttpServletResponse res) <br />{} <br />}<br />下面来看一下这个Servlet在web.xml中的定义。<br />例5-b：<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;log4j-init&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;TestLog4j.Log4jInit&lt;/servlet-class&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;log4j-init-file&lt;/param-name&gt;<br />&lt;param-value&gt;sort.properties&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />&lt;/servlet&gt;<br />因为log4j的初始化要在所有的log4j调用之前完成，所以在web.xml文件中，我们一定要把对应的Servlet定义的load-on-startup应设为1，以便在Web容器启动时即装入该Servlet。<br />完成了这两个步骤这后，我们就可以象在application开发中一样在web application任何地方应用log4j了。下面是在javabean中的应用的一个例子。<br />例5-c：<br />import org.apache.log4j.Logger;<br /><br />public class InfoForm <br />{<br />static Logger logger = Logger.getLogger(InfoForm.class);<br /><br />protected String title;<br />protected String content;<br /><br />public InfoForm() {}<br /><br />public void setTitle(Object value) <br />{<br />logger.debug("nepalon:title = " + title);<br />title = value;<br />}<br /><br />public String getTitle() <br />{<br />logger.debug("nepalon:title = " + title);<br />return title;<br />}<br /><br />public void setContent(String value) <br />{<br />content = value;<br />logger.debug("nepalon: content() = " + content);<br />}<br /><br />public String getContent() <br />{<br />logger.debug("nepalon: content = \n" + content);<br />return content;<br />}<br />} <img src ="http://www.blogjava.net/limq/aggbug/40341.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2006-04-10 23:11 <a href="http://www.blogjava.net/limq/archive/2006/04/10/40341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【Eclipse资料】]常用的Eclipse 3.0插件（转）</title><link>http://www.blogjava.net/limq/archive/2006/04/10/40329.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Mon, 10 Apr 2006 13:43:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2006/04/10/40329.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/40329.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2006/04/10/40329.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/40329.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/40329.html</trackback:ping><description><![CDATA[1.MyEclipse  J2EE开发插件，支持SERVLET/JSP/EJB/数据库操纵等<br /><a href="http://www.myeclipseide.com/"><font color="#4a664d"><u>www.myeclipseide.com</u></font></a><div><font color="#4a664d"></font> </div><div>2.Properties Editor  编辑java的属性文件，并可以自动存盘为Unicode格式<br /><a href="http://propedit.sourceforge.jp/index_en.html"><font color="#4a664d"><u>http://propedit.sourceforge.jp/index_en.html</u></font></a></div><div><font color="#4a664d"></font> </div><div>3.Colorer Take  为上百种类型的文件按语法着色<br /><a href="http://colorer.sourceforge.net/"><font color="#4a664d"><u>http://colorer.sourceforge.net/</u></font></a></div><div><font color="#4a664d"></font> </div><div>4.XMLBuddy 编辑xml文件<br /><a href="http://www.xmlbuddy.com/"><font color="#4a664d"><u>www.xmlbuddy.com</u></font></a></div><div><font color="#4a664d"></font> </div><div>5.Code Folding  加入多种代码折叠功能（比eclipse自带的更多）<br /><a href="http://www.coffee-bytes.com/servlet/PlatformSupport"><font color="#4a664d"><u>http://www.coffee-bytes.com/servlet/PlatformSupport</u></font></a></div><div><font color="#4a664d"></font> </div><div>6.Easy Explorer  从eclipse中访问选定文件、目录所在的文件夹<br /><a href="http://easystruts.sourceforge.net/"><font color="#4a664d"><u>http://easystruts.sourceforge.net/</u></font></a></div><div><font color="#4a664d"></font> </div><div>7.Fat Jar 打包插件，可以方便的完成各种打包任务，可以包含外部的包等<br /><a href="http://fjep.sourceforge.net/"><font color="#4a664d"><u>http://fjep.sourceforge.net/</u></font></a></div><div><font color="#4a664d"></font> </div><div>8.RegEx Test 测试正则表达式<br /><a href="http://brosinski.com/stephan/archives/000028.php"><font color="#4a664d"><u>http://brosinski.com/stephan/archives/000028.php</u></font></a></div><div><font color="#4a664d"></font> </div><div>9.JasperAssistant 报表插件（强，要钱的）<br /><a href="http://www.jasperassistant.com/"><font color="#4a664d"><u>http://www.jasperassistant.com/</u></font></a></div><div><font color="#4a664d"></font> </div><div>10.Jigloo GUI Builder ＪＡＶＡ的ＧＵＩ编辑插件<br /><a href="http://cloudgarden.com/jigloo/"><font color="#4a664d"><u>http://cloudgarden.com/jigloo/</u></font></a></div><div><font color="#4a664d"></font> </div><div>11.Profiler 性能跟踪、测量工具，能跟踪、测量ＢＳ程序<br /><a href="http://sourceforge.net/projects/eclipsecolorer/"><font color="#4a664d"><u>http://sourceforge.net/projects/eclipsecolorer/</u></font></a></div><div><font color="#4a664d"></font> </div><div>12.AdvanQas 提供对if/else等条件语句的提示和快捷帮助（自动更改结构等）<br /><a href="http://eclipsecolorer.sourceforge.net/advanqas/index.html"><font color="#4a664d"><u>http://eclipsecolorer.sourceforge.net/advanqas/index.html</u></font></a></div><div><font color="#4a664d"></font> </div><div>13.Log4E     Log4j插件，提供各种和Log4j相关的任务，如为方法、类添加一个logger等<br /><a href="http://log4e.jayefem.de/index.php/Main_Page"><font color="#4a664d"><u>http://log4e.jayefem.de/index.php/Main_Page</u></font></a></div><div><font color="#4a664d"></font> </div><div>14.VSSPlugin VSS插件<br /><a href="http://sourceforge.net/projects/vssplugin"><font color="#4a664d"><u>http://sourceforge.net/projects/vssplugin</u></font></a></div><div><font color="#4a664d"></font> </div><div>15.Implementors   提供跳转到一个方法的实现类，而不是接中的功能（实用!）<br /><a href="http://eclipse-tools.sourceforge.net/implementors/"><font color="#4a664d"><u>http://eclipse-tools.sourceforge.net/implementors/</u></font></a></div><div><font color="#4a664d"></font> </div><div>16.Call Hierarchy 显示一个方法的调用层次（被哪些方法调，调了哪些方法）<br /><a href="http://eclipse-tools.sourceforge.net/call-hierarchy/index.html"><font color="#4a664d"><u>http://eclipse-tools.sourceforge.net/call-hierarchy/index.html</u></font></a></div><div><font color="#4a664d"></font> </div><div>17.EclipseTidy 检查和格式化HTML/XML文件<br /><a href="http://eclipsetidy.sourceforge.net/"><font color="#4a664d"><u>http://eclipsetidy.sourceforge.net/</u></font></a></div><div><font color="#4a664d"></font> </div><div>18.Checkclipse 检查代码的风格、写法是否符合规范<br /><a href="http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm"><font color="#4a664d"><u>http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm</u></font></a></div><div><font color="#4a664d"></font> </div><div>19.Hibernate Synchronizer Hibernate插件，自动映射等<br /><a href="http://www.binamics.com/hibernatesync/"><font color="#4a664d"><u>http://www.binamics.com/hibernatesync/</u></font></a></div><div><font color="#4a664d"></font> </div><div>20.VeloEclipse  Velocity插件<br /><a href="http://propsorter.sourceforge.net/"><font color="#4a664d"><u>http://propsorter.sourceforge.net/</u></font></a></div><div><font color="#4a664d"></font> </div><div>21.EditorList   方便的列出所有打开的Editor<br /><a href="http://editorlist.sourceforge.net/"><font color="#4a664d"><u>http://editorlist.sourceforge.net/</u></font></a></div><div><font color="#4a664d"></font> </div><div>22.MemoryManager 内存占用率的监视<br /><a href="http://cloudgarden.com/memorymanager/"><font color="#4a664d"><u>http://cloudgarden.com/memorymanager/</u></font></a></div><div> </div><div><font color="#ff0000">+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</font></div><div><p><strong><font size="2">plug-in网址：</font></strong></p><p><a href="http://www.eclipse-plugins.info/eclipse/index.jsp"><font color="#000080" size="2"><u>http://www.eclipse-plugins.info/eclipse/index.jsp</u></font></a></p><p><a href="http://www.eclipse-workbench.com/jsp/"><font color="#000080" size="2"><u>http://www.eclipse-workbench.com/jsp/</u></font></a></p><p><a href="http://eclipse-plugins.2y.net/eclipse/index.jsp"><font color="#000080" size="2"><u>http://eclipse-plugins.2y.net/eclipse/index.jsp</u></font></a> （非常非常著名的插件更新网站） </p><p><a href="http://www.crionics.com/products/opensource/eclipse/eclipse.jsp"><font color="#000080" size="2"><u>http://www.crionics.com/products/opensource/eclipse/eclipse.jsp</u></font></a> （分类清楚） </p><p><a href="http://www.eclipseplugincentral.com/"><font color="#000080" size="2"><u>http://www.eclipseplugincentral.com/</u></font></a></p><p><strong><font size="2">Preferences无法显示新安装的插件的解决办法</font></strong></p><p><font face="宋体" color="#ff0000" size="4">删除C:\eclipse\configuration\org.eclipse.update下的platform.xml文件，重新启动Eclipse</font></p><p><font face="宋体" color="#ff0000" size="4"></font> </p><p><font face="宋体" color="#ff0000" size="4"><font color="#000000" size="3">perl插件 </font><a href="http://e-p-i-c.sf.net/updates"><font color="#000080" size="2"><u>http://e-p-i-c.sf.net/updates</u></font></a><br /><font color="#000000" size="3">C#插件 </font><a href="http://www.improve-technologies.com/alpha/updates/site.xml"><font color="#000080" size="2"><u>http://www.improve-technologies.com/alpha/updates/site.xml</u></font></a><br /><font color="#000000" size="3">C插件 </font><a href="http://update.eclipse.org/tools/cdt/releases/new"><font color="#000080" size="2"><u>http://update.eclipse.org/tools/cdt/releases/new</u></font></a><br /><font color="#000000" size="3">Hex插件 </font><a href="http://ehep.sourceforge.net/update"><font color="#000080" size="2"><u>http://ehep.sourceforge.net/update</u></font></a></font></p><p><font face="宋体" color="#ff0000" size="4"></font> </p><p><font face="宋体" color="#ff0000" size="4"><strong><font color="#000000"><font size="2">Eclipse加速插件KeepResident</font></font></strong></font></p><p><a href="http://suif.stanford.edu/pub/keepresident/"><font color="#000080"><u>http://suif.stanford.edu/pub/keepresident/</u></font></a></p><p><font color="#000080">原理:利用两个 Windows API - SetProcessWorkingSetSize 与 VirtualLock (适用于 Windows 平台)。</font></p><p><font color="#000080">切换时果然快很多。</font></p><p><font color="#000080">官方建议最小值设定在 100 MB，最大值 250 MB 左右。</font></p></div><div> </div><div> </div><div> </div><div><font color="#800080">Eclipse插件及电子书列表</font></div><div>    近日整理了一下我的软件厂商发布记录，找到了一堆跟Eclipse有关的东东，恩，涵盖的面还非常的广泛有指导学习的书，有插件，有支持工具，自己不敢独享，便拿出来放在这里，跟大家一块儿讨论一下。这个，要声明一下，我只有软件记录，并没有保存，所以找不到列表里面的软件的，不要跟我要，我能做的也只是帮助大家寻找一下而已。所有的软件后面都有链接，但是每次更新列表的时候我的链接都没有拷贝完全，不过，前面有链接里面有软件发布的网站信息，到该网站里面自己搜索就能搞到准确的信息。</div><div><br />2004-12-01<br />Apress.The.Definitive.Guide.to.SWT.and.JFace<br />Apress出版的《The.Definitive.Guide.to.SWT.and.JFace》chm格式电子书，Eclipse平台的两个用户界面工具箱－SWT和JFace的java编程指南。<br /><a href="http://www.amazon.com/exec/obidos/tg/detai...6889430-0550522"><font color="#008000"><u>http://www.amazon.com/exec/obidos/tg/detai...6889430-0550522</u></font></a><br /><a href="http://images.amazon.com/images/P/15905932...SCMZZZZZZZ_.jpg"><font color="#008000"><u>http://images.amazon.com/images/P/15905932...SCMZZZZZZZ_.jpg</u></font></a></div><div>2004-11-29<br />JasperAssistant.v1.4.2<br />JasperAssistant是一款可视化的JasperReports报表设计工具，JasperReports是一个非常流行的开放源码报告引擎。JasperAssistant基于Eclipse的插件程序结构，通过逼真的图形界面方便的创建JasperReports报表定义文件。<br /><a href="http://www.jasperassistant.com/"><font color="#008000"><u>http://www.jasperassistant.com/</u></font></a><br /><a href="http://www.jasperassistant.com/shots/full.png"><font color="#008000"><u>http://www.jasperassistant.com/shots/full.png</u></font></a></div><div>JVider.for.Eclipse.v1.7e1.Java<br />一款为JavaSwing应用程序设计的GUIBuilder工具。在他的帮助下，你可以很简单的为你的Java校应用程序和程序设计图形用户界面。<br /><a href="http://www.jvider.com/"><font color="#008000"><u>http://www.jvider.com/</u></font></a><br /><a href="http://www.jvider.com/jviderscreen.png"><font color="#008000"><u>http://www.jvider.com/jviderscreen.png</u></font></a></div><div>2004-11-28</div><div>RMI.Plugin.for.Eclipse.v1.6.1<br />Eclipse开发平台的RMI（基于Java的分布计算框架）插件，是在JavaSDK平台通过调用RMI编译器自动生成远程对象stub（桩）和skeleton（框架）的简便方法。<br /><a href="http://www.genady.net/rmi/"><font color="#008000"><u>http://www.genady.net/rmi/</u></font></a><br /><a href="http://www.genady.net/rmi/v16/screenshots/...rmi-eclipse.png"><font color="#008000"><u>http://www.genady.net/rmi/v16/screenshots/...rmi-eclipse.png</u></font></a></div><div>2004-11-19</div><div>Addison.Wesley.Professional.SWT.The.Standard.Widget.Toolkit.Volume.1.Jun.2004<br />电子书，Eclipse系列之SWT精解，SWT就是StandardWidgetToolkit，是在java中创建图形界面的类库<br /><a href="http://www.amazon.com/exec/obidos/ASIN/032...8151071-6877408"><font color="#008000"><u>http://www.amazon.com/exec/obidos/ASIN/032...8151071-6877408</u></font></a><br /><a href="http://images.amazon.com/images/P/0321256638.01.LZZZZZZZ.jpg"><font color="#008000"><u>http://images.amazon.com/images/P/0321256638.01.LZZZZZZZ.jpg</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/22338_AddisonWesley.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/22338_AddisonWesley.html</u></font></a></div><div>2004-11-13</div><div>Omondo.Eclipse.UML.Studio.Edition.v1.1.0<br />OmondoEclipseUML是一款可视化的模块设计工具，可以完全集成于Eclipse和CVS。<br /><a href="http://www.omondo.com/"><font color="#008000"><u>http://www.omondo.com</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/21757_OmondoEclipse.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/21757_OmondoEclipse.html</u></font></a></div><div>Omondo.Eclipse.UML.Studio.Edition.v1.1.0<br />OmondoEclipseUML是一款可视化建模工具，可以与Eclipse和CVS无缝集成。</div><div>2004-10-20</div><div>Oxygen.XML.Editor.v5.0.Eclipse.plugin<br />OxygenXMLeditor是一款基于Java的XML编辑器，支持XML,XSL,TXT,XSD,DTD文档，能自行校验XML,XSL,XSD代码，提示脚本错误。Oxygen能自动完成结束标签，代码高亮现实，支持Unicode。<br /><a href="http://www.oxygenxml.com/features/"><font color="#008000"><u>http://www.oxygenxml.com/features/</u></font></a><br /><a href="http://www.oxygenxml.com/img/oxygen-mac.gif"><font color="#008000"><u>http://www.oxygenxml.com/img/oxygen-mac.gif</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/19151_OxygenXMLEdit.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/19151_OxygenXMLEdit.html</u></font></a></div><div>2004-10-19</div><div>Jigloo.GUI.Builder.v3.0.1<br />为EclipseJavaIDE和WebSphereStudio设计的插件，可以用来创建和管理Swing和SWTGUI类。<br /><a href="http://cloudgarden.com/jigloo/"><font color="#008000"><u>http://cloudgarden.com/jigloo/</u></font></a><br /><a href="http://cloudgarden.com/jigloo/images/screenshot4_sm.jpg"><font color="#008000"><u>http://cloudgarden.com/jigloo/images/screenshot4_sm.jpg</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/19038_JiglooGUIBuil.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/19038_JiglooGUIBuil.html</u></font></a></div><div>2004-10-13</div><div>Code.Pro.Studio.3.0.0<br />一款为那些使用IBMwebspherestuodio和eclipse开发环境的开发者设计的软件。能够让java的开发者有效开速的开发高质量的软件。这款软件可以通过许多重复任务来完成软件的开发，同时能够极大的提高用户界面和使开发活动流水线化。此款软件集成了CodeProAdisor，CodeProAgilityandCodeProBuild。<br /><a href="http://www.instantiations.com/codepro/default.htm"><font color="#008000"><u>http://www.instantiations.com/codepro/default.htm</u></font></a><br /><a href="http://www.instantiations.com/codepro/imag...pstudio3-sm.gif"><font color="#008000"><u>http://www.instantiations.com/codepro/imag...pstudio3-sm.gif</u></font></a></div><div>2004-10-10</div><div>Window.Builder.Pro.2.1.1<br />一款基于EclipseSWT技术上的双向javaGui设计软件。具备SWT设计以及Swing设计两个主要功能。该软件会被作为一个插件镶嵌入Eclipse以及其他一些兼容的IDEs中（WSSD,WSAD,WSED等等）。新的2.0版本支持Eclipse3.0。<br /><a href="http://www.windowbuilderpro.com/"><font color="#008000"><u>http://www.windowbuilderpro.com/</u></font></a><br /><a href="http://www.instantiations.com/swt-designer...ts/designer.gif"><font color="#008000"><u>http://www.instantiations.com/swt-designer...ts/designer.gif</u></font></a></div><div>2004-10-04</div><div>Jigloo.GUI.Builder.v3.0.0<br />Jigloo.GUI.Builder是一个为Eclipsejave和WebSphereStudio开发的插件，能够创建出滚动控制和SWTGUI的效果界面。</div><div>Vi.plugin.for.Eclipse3.v1.86<br />ViPlugin可以在vi编辑器上添加一个功能条，这个是用于Eclipse3+的。</div><div>2004-10-03</div><div>Parasoft.JTest.v5.1.71.DC.20040912.WinNT2kXP<br />自动进行JAVA单元测试和代码标准检查来帮助开发人员编写克号的代码的工具。可分析类，然后生成单元测试案例来包括最大的覆盖测试，发现未处理的异常并校验需求。<br />-自动的基本错误预防，包括单元测试和自动代码标准检查<br />-生成并执行单元测试案例<br />-提供了进行黑盒测试、模型测试和系统测试的快速简单的途径<br />-识别并预防未处理的运行时异常，函数错误，内存泄露，性能问题和安全弱点<br />-对群或方案优先作测试和报告<br />-监控测试的覆盖范围<br />-自动回归测试<br />-支持按比例压缩设计<br />-检查超过400个来自JAVA专家的编码规范<br />-改正违反超过200个编码规范的错误<br />-允许用户创建自己的编码规范<br />-可在小组范围内管理共享测试文件<br />-和IBMWebSphere和Eclipse集成<br />-支持Borland？JBuilder？,Together？ControlCenter？,和Ant</div><div>2004-09-23</div><div>Borland.Together.for.Eclipse.v6.3<br />最佳的程序分析设计工具，提供实时的协同工作能力。<br />·支持所有主要的UML图形<br />充分利用UnifiedModelingLanguage(统一建模语言—UML)搭建正确的架构，以便满足你的业务目标。每一个软件项目都需要一个蓝图，以保持整个小组向相同的方向前进并构建正确的软件。通过集成UML能力的方式，Together扩展了开发框架，简化了构建软件的复杂过程。<br />·TogetherLiveSource自动进行模型与代码的同步<br />使用同步的模型与代码，允许进行更加有效的开发小组沟通与协作。同时的同步化让手工更新成为过去，使用相同的信息保持开发小组的信息更新。模型处于灵活的状态，不会过时，这是因为开发小组做出的任何变化总是同时反映在代码与模型之中，让开发小组更加高效、更加有效。<br />·自动文档生成<br />保持开发小组专注于设计与实现，而不是拟制文档。Together提供了强大的、可以定制的文档生成能力，其中包括多种文档格式与定制模板的能力。通过自动生成文档的方式，开发者可以集中精力搞软件开发，而小组领导随时都有所需要的信息。<br />·支持业界标准的模式<br />使用业界领先的模式着手开发工作，改善了架构的质量。Together支持标准的模式，比如GoF与J2EE，并且同时也提供了更改现有模式、创建新模式的能力。广泛的模式支持使得开发小组在将来的项目中复用模式，改善所有项目的架构质量。<br />·使用审计测定软件质量<br />审计为开发小组提供了在软件开发的初期测定质量，强化企业标准的能力—在软件开发的初期，开发小组还在编制软件的代码呢。在分发之前测定质量，开发者可以改善代码的质量，在代码转交QA小组之前，发现并修复自己的错误。审计变量可以被定制并保存，这样开发小组就能制订代码标准，监视代码超出认可规范的问题。审计也被用来改变开发者的个人代码编制风格，以便符合企业的编码标准。<br />·使用度量进行软件开发的量化<br />量度为开发小组提供了测量软件项目复杂程度、质量与规模的能力。通过测量并对信息进行标准检查，管理人员能够知晓开发小组与开发过程的质量与效率，更好地进行当前与未来项目的量化。<br />·重构<br />在Together技术之中的大量重构特性验证所有的系统变化都被正确地传送到整个应用。所得到的结果便是代码不易出错，应用的质量得到改善。<br />·Together与Eclipse的集成<br />Eclipse是一种开放源代码的业界平台，Together技术与Eclipse的集成为Eclipse用户提供了一种熟悉的环境，用来进行软件开发。在Eclipse环境中，开发者可以利用TogetherEditionforEclipse之中的、领先的建模、设计与质量保证功能，快速构建高质量的企业应用。通过在Eclipse本地开发用于TogetherEditionforEclipse的用户接口，用户可受益于紧密的集成，并利用在同一个工具之中两种技术的优势。<br /><a href="http://www.borland.com/together/index.html"><font color="#008000"><u>http://www.borland.com/together/index.html</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/16494_BorlandTogethe.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/16494_BorlandTogethe.html</u></font></a></div><div>2004-08-02</div><div>Clay.Database.Modeling.Pro.for.Eclipse.v1.0.5<br />作为插件运行于Eclipse开发环境的数据库设计工具。通过直观的界面图形化地设计数据库模型。它可以通过逆向设计来根据现存数据库来设计新的数据库模型。更多地，它还能生成适合你的数据库的SQL(DDL)代码。<br /><a href="http://www.azzurri.jp/en/software/clay/index.jsp"><font color="#008000"><u>http://www.azzurri.jp/en/software/clay/index.jsp</u></font></a><br /><a href="http://www.azzurri.jp/en/software/clay/ima...y_eclipse_1.png"><font color="#008000"><u>http://www.azzurri.jp/en/software/clay/ima...y_eclipse_1.png</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/11208_ClayDatabaseM.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/11208_ClayDatabaseM.html</u></font></a></div><div>2004-07-28</div><div>Oxygen.XML.Editor.v4.2.Eclipse.plugin<br />OxygenXMLeditor是一款基于Java的XML编辑器，支持XML,XSL,TXT,XSD,DTD文档，能自行校验XML,XSL,XSD代码，提示脚本错误。Oxygen能自动完成结束标签，代码高亮现实，支持Unicode。<br /><a href="http://www.oxygenxml.com/features/"><font color="#008000"><u>http://www.oxygenxml.com/features/</u></font></a><br /><a href="http://www.oxygenxml.com/img/oxygen-mac.gif"><font color="#008000"><u>http://www.oxygenxml.com/img/oxygen-mac.gif</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/10689_OxygenXMLEdit.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/10689_OxygenXMLEdit.html</u></font></a></div><div>2004-07-26</div><div>MC.Press.Eclipse.Step.by.Step<br />MCPress出版的《Eclipse循序渐近》(Eclipse:StepbyStep)电子版，Eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言，它只是一个框架和一组服务，用于通过插件组件构建开发环境。幸运的是，Eclipse附带了一个标准的插件集，包括Java开发工具（JavaDevelopmentTools，JDT）。该书包括了Eclipse平台开发的方方面面，可以手把手帮助你编写完整的可用的程序，并更好的立即各种基本概念<br /><a href="http://www.amazon.com/exec/obidos/tg/detail/-/1583470441/"><font color="#008000"><u>http://www.amazon.com/exec/obidos/tg/detail/-/1583470441/</u></font></a><br /><a href="http://images.amazon.com/images/P/15834704...SCMZZZZZZZ_.jpg"><font color="#008000"><u>http://images.amazon.com/images/P/15834704...SCMZZZZZZZ_.jpg</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/10486_MCPressEclips.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/10486_MCPressEclips.html</u></font></a></div><div>2004-07-24</div><div>Window.Builder.Pro.v2.0.1<br />一款基于EclipseSWT技术上的双向JavaGui设计软件。具备SWT设计以及Swing设计两个主要功能。该软件会被作为一个插件镶嵌入Eclipse以及其他一些兼容的IDEs中（WSSD,WSAD,WSED等等）。新的2.0版本支持Eclipse3.0。<br /><a href="http://www.windowbuilderpro.com/"><font color="#008000"><u>http://www.windowbuilderpro.com/</u></font></a><br /><a href="http://www.instantiations.com/swt-designer...ts/designer.gif"><font color="#008000"><u>http://www.instantiations.com/swt-designer...ts/designer.gif</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/10310_WindowBuilder.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/10310_WindowBuilder.html</u></font></a></div><div>2004-07-20</div><div>XMLBuddy.PRO.v2.0.11<br />Eclipse插件，提供XML编辑功能，支持XML,DTD,XMLSchema,RELAXNG,RELAXNGcompactsyntax,XSLT<br /><a href="http://xmlbuddy.com/"><font color="#008000"><u>http://xmlbuddy.com/</u></font></a><br /><a href="http://xmlbuddy.com/2.0/screen.jpg"><font color="#008000"><u>http://xmlbuddy.com/2.0/screen.jpg</u></font></a><br /><a href="http://0daycheck.eastgame.net/0day/archives/9848_XMLBuddyPROv2.html"><font color="#008000"><u>http://0daycheck.eastgame.net/0day/archives/9848_XMLBuddyPROv2.html</u></font></a></div><div>2004-07-09</div><div>Compuware.DevPartner.Java.Edition.v3.0.3<br />快速高质量的开发java程序的开发工具箱，增强组件和软件的可靠性。可以针对个人定制不同的浏览数据窗口和调试工具。<br />新的3.03版本具有如下更新：<br />-具有Eclipse插件<br />-可以在系统，开发环境和应用程序之间交互切换<br />-还有其他更新等。</div><div>2004-05-09</div><div>Manning.Publications.Company.Eclipse.in.Action.A.Guide.for.the.Java.Developer<br />电子书-Eclipse实践：java开发人员指南。<br /><a href="http://www.amazon.com/exec/obidos/tg/detail/-/1930110960/"><font color="#008000"><u>http://www.amazon.com/exec/obidos/tg/detail/-/1930110960/</u></font></a><br />PE32_PIdp-schmoo2,TopRight,7,-26_SCMZZZZZZZ.jpg"&gt;http://images.amazon.com/images/P/1930110960.01.&lt;u&gt;PE32_PIdp-schmoo2,TopRight,7,-26_SCMZZZZZZZ&lt;/u&gt;.jpg</div><div>Manning.Publications.Company.Eclipse.in.Action.A.Guide.for.the.Java.Developer<br />电子书《jave开发指南》<br /><a href="http://www.amazon.com/exec/obidos/tg/detail/-/1930110960/"><font color="#008000"><u>http://www.amazon.com/exec/obidos/tg/detail/-/1930110960/</u></font></a><br /><a href="http://images.amazon.com/images/P/19301109...SCMZZZZZZZ_.jpg"><font color="#008000"><u>http://images.amazon.com/images/P/19301109...SCMZZZZZZZ_.jpg</u></font></a></div><div>2004-05-06</div><div>SignSoft_intelliBO_v3.6.2<br />一个中间件的应用，不仅仅执行JavaDataObjects标准(JDO)（现在支持JDO标准1.0.1），而且实现智能的数据访问，所以称作：“intelligentBusinessObjects”。可集成于Eclipse及IBMWebsphereApllicationDeveloperIDE。</div><div>2004-04-27</div><div>OReilly.Eclipse.A.Java.Developers.Guide.eBook<br />《Java开发者指南》</div><div>2004-04-21</div><div>IBM.Redbooks.Eclipse.Development.Using.the.Graphical.Editing.Framework.and.the.Eclipse.Modeling.Framework.eBook<br />电子书，提供给那些具备良好知识基础以及丰富经验的使用EclipseSDK来开发插件代码的程序员,用以校验插件的工作性能。<br /><a href="http://publib-b.boulder.ibm.com/Redbooks.n...s/sg246302.html"><font color="#008000"><u>http://publib-b.boulder.ibm.com/Redbooks.n...s/sg246302.html</u></font></a></div><div>IBM.Redbooks.Eclipse.Development.Using.the.Graphical.Editing.Framework.and.the.Eclipse.Modeling.Framework.eBook<br />书名：《使用Graphical.Editing.Framework和Eclipse.Modeling.Framework进行Eclipse开发》<br />作者：BillMooreetal.<br />出版社：IBMRedbooks<br />格式：CHM<br />分类：计算机/软件开发<br />ISBN：0738453161<br />内容简介：<br />一本介绍使用GraphicalEditingFramework(GEF)和EclipseModelingFramework(EMF).进行Eclipseplugin开发的书。</div><div>2004-04-06</div><div>Rational.XDE.v2003.Developer.Plus.NET.Edition.Retail<br />RationalXDEDeveloper是一个十分完善的可视化设计和开发的环境，它可以结合Rational支持的集成开发环境（IDE）来使用，比如Eclipseplatform,IBMWebSphereStudioApplicationDeveloper,MicrosoftVisualStudio.NET等。RationalXDEDeveloper可以在构建企业应用和Web为中心的解决方案上开发人员提供支持。通过结合使用RationalXDEDeveloper的多种特性（比如，代码的双向工程，自动和按需的对代码和模型进行同步，模式引擎支持，多模型的支持，将数据库资产逆向工程为数据模型，团队协作，可选择的过程指南）可以减轻一些被需要的代码开发和设计的工作。这个是VisualStudio.NET版本的License。<br /><a href="http://www.rational.com/products/xde/index.jsp"><font color="#008000"><u>http://www.rational.com/products/xde/index.jsp</u></font></a></div><div>2003-12-29</div><div>Addison.Wesley.Contributing.To.Eclipse.Principles.Patterns.And.Plug-Ins.eBook---1<br />讲述在Eclipse(一种正在兴起的软件开发环境)下进行插件开发的电子图书</div><div>2003-12-28</div><div>Addison.Wesley.Contributing.To.Eclipse.Principles.Patterns.And.Plug-Ins.eBook---2<br />出版：Addison-WesleyPubCo；作者：ErichGamma,KentBeck；ISBN：0321205758。<br />一本关于Eclipse的书。这本书不仅仅教你怎么做而且使你完全理解Eclipse。<br /><a href="http://www.amazon.com/exec/obidos/tg/detai...l/-/0321205758/"><font color="#008000"><u>http://www.amazon.com/exec/obidos/tg/detai...l/-/0321205758/</u></font></a></div><div>2003-11-14</div><div>Addison.Wesley.Eclipse.Modeling.Framework.A.Developers.Guide.eBook<br />电子书，EclipseModelingFramework模型构架可以使Java,XML,和UML语言开发者统一起来使用令人惊讶的模板快速构建健康的应用程序,是一本软件开发人员指导书<br /><a href="http://www.amazon.com/exec/obidos/ASIN/013...1308053-5737658"><font color="#008000"><u>http://www.amazon.com/exec/obidos/ASIN/013...1308053-5737658</u></font></a></div><img src ="http://www.blogjava.net/limq/aggbug/40329.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2006-04-10 21:43 <a href="http://www.blogjava.net/limq/archive/2006/04/10/40329.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4J 最佳实践之全能配置文件(转）</title><link>http://www.blogjava.net/limq/archive/2006/04/10/40328.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Mon, 10 Apr 2006 13:41:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2006/04/10/40328.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/40328.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2006/04/10/40328.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/40328.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/40328.html</trackback:ping><description><![CDATA[LOG4J的配置之简单使它遍及于越来越多的应用中了：Log4J配置文件实现了输出到控制台、文件、回滚文件、发送日志邮件、输出到数据库日志表、自定义标签等全套功能。择其一二使用就够用了， <br /><br /><br /><br />log4j.rootLogger=DEBUG,CONSOLE,A1,im <br />log4j.addivity.org.apache=true <br /><br /><br /><br /># 应用于控制台 <br /><br />log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender <br />log4j.appender.Threshold=DEBUG <br />log4j.appender.CONSOLE.Target=System.out <br />log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout <br />log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n <br />#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n <br /><br /><br />#应用于文件 <br /><br />log4j.appender.FILE=org.apache.log4j.FileAppender <br />log4j.appender.FILE.File=file.log <br />log4j.appender.FILE.Append=false <br />log4j.appender.FILE.layout=org.apache.log4j.PatternLayout <br />log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n <br /># Use this layout for LogFactor 5 analysis <br /><br /><br /><br /># 应用于文件回滚 <br /><br />log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender <br />log4j.appender.ROLLING_FILE.Threshold=ERROR <br />log4j.appender.ROLLING_FILE.File=rolling.log <br />log4j.appender.ROLLING_FILE.Append=true <br />log4j.appender.ROLLING_FILE.MaxFileSize=10KB <br />log4j.appender.ROLLING_FILE.MaxBackupIndex=1 <br />log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout <br />log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n <br /><br /><br />#应用于socket <br />log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender <br />log4j.appender.SOCKET.RemoteHost=localhost <br />log4j.appender.SOCKET.Port=5001 <br />log4j.appender.SOCKET.LocationInfo=true <br /># Set up for Log Facter 5 <br />log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout <br />log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n <br /><br /><br /># Log Factor 5 Appender <br />log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender <br />log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000 <br /><br /><br /><br /># 发送日志给邮件 <br /><br />log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender <br />log4j.appender.MAIL.Threshold=FATAL <br />log4j.appender.MAIL.BufferSize=10 <br />log4j.appender.MAIL.From=web@www.wuset.com <br />log4j.appender.MAIL.SMTPHost=www.wusetu.com <br />log4j.appender.MAIL.Subject=Log4J Message <br />log4j.appender.MAIL.To=web@www.wusetu.com <br />log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout <br />log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n <br /><br /><br /><br /># 用于数据库 <br />log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender <br />log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test <br />log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver <br />log4j.appender.DATABASE.user=root <br />log4j.appender.DATABASE.password= <br />log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n') <br />log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout <br />log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n <br /><br /><br />log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender <br />log4j.appender.A1.File=SampleMessages.log4j <br />log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j' <br />log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout <br /><br />#自定义Appender <br /><br />log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender <br /><br />log4j.appender.im.host = mail.cybercorlin.net <br />log4j.appender.im.username = username <br />log4j.appender.im.password = password <br />log4j.appender.im.recipient = corlin@cybercorlin.net <br /><br />log4j.appender.im.layout=org.apache.log4j.PatternLayout <br />log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n <img src ="http://www.blogjava.net/limq/aggbug/40328.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2006-04-10 21:41 <a href="http://www.blogjava.net/limq/archive/2006/04/10/40328.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Acegi＋hibernate 动态实现基于角色的权限管理 </title><link>http://www.blogjava.net/limq/archive/2006/01/19/28585.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Wed, 18 Jan 2006 18:16:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2006/01/19/28585.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/28585.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2006/01/19/28585.html#Feedback</comments><slash:comments>27</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/28585.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/28585.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp;&nbsp; 最近在做项目遇到了权限管理，用户要求可以自己建立不同的角色对系统的资源进行控制， 不同的用户有不同的角色，又恰恰框架中用到了struts＋spring＋hibernate，要求在web层调用 业务逻辑层 时不考虑权限，web层可以控制用户的显示界面，逻辑层处理用户权限问题。 想来想去好像只有spring 的aop 可以做到，在调用到 接口 中的...&nbsp;&nbsp;<a href='http://www.blogjava.net/limq/archive/2006/01/19/28585.html'>阅读全文</a><img src ="http://www.blogjava.net/limq/aggbug/28585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2006-01-19 02:16 <a href="http://www.blogjava.net/limq/archive/2006/01/19/28585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>四舍五入保留小数后两位</title><link>http://www.blogjava.net/limq/archive/2005/09/21/13694.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Wed, 21 Sep 2005 15:59:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/09/21/13694.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/13694.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/09/21/13694.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/13694.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/13694.html</trackback:ping><description><![CDATA[<P>&nbsp;</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008080">&nbsp;1</SPAN>&nbsp;<SPAN style="COLOR: #008000">/**</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;2</SPAN>&nbsp;<SPAN style="COLOR: #008000">&nbsp;*&nbsp;Contains&nbsp;static&nbsp;utility&nbsp;methods.<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;3</SPAN>&nbsp;<SPAN style="COLOR: #008000">&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;4</SPAN>&nbsp;<SPAN style="COLOR: #000000"></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;BOUtils&nbsp;{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;5</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;6</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;Double&nbsp;getRoundedDouble(&nbsp;</SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000">&nbsp;unroundedValue&nbsp;){<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;7</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;Get&nbsp;the&nbsp;integer&nbsp;portion&nbsp;of&nbsp;the&nbsp;value</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;8</SPAN>&nbsp;<SPAN style="COLOR: #008000"></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000">&nbsp;intPortion&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Math.floor(&nbsp;unroundedValue&nbsp;);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;9</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">10</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;Get&nbsp;the&nbsp;unrounded&nbsp;decimal&nbsp;portion</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">11</SPAN>&nbsp;<SPAN style="COLOR: #008000"></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000">&nbsp;unroundedDecimalPortion&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(&nbsp;unroundedValue&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">&nbsp;intPortion&nbsp;);<BR></SPAN><SPAN style="COLOR: #008080">12</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">13</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">&nbsp;ALERT&nbsp;-&nbsp;This&nbsp;next&nbsp;code&nbsp;interferes&nbsp;with&nbsp;I18N.&nbsp;We&nbsp;eventually&nbsp;need&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">14</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;change&nbsp;this&nbsp;not&nbsp;assume&nbsp;only&nbsp;round&nbsp;to&nbsp;2&nbsp;decimal&nbsp;places.&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">15</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">16</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">&nbsp;Multiply&nbsp;the&nbsp;decimal&nbsp;places&nbsp;by&nbsp;100,&nbsp;which&nbsp;shitfs&nbsp;the&nbsp;decimal&nbsp;point<BR></SPAN><SPAN style="COLOR: #008080">17</SPAN>&nbsp;<SPAN style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;two&nbsp;places&nbsp;to&nbsp;the&nbsp;left.&nbsp;Then&nbsp;round&nbsp;it&nbsp;so&nbsp;that&nbsp;we&nbsp;get&nbsp;a&nbsp;round&nbsp;to<BR></SPAN><SPAN style="COLOR: #008080">18</SPAN>&nbsp;<SPAN style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;two&nbsp;decimal&nbsp;places.&nbsp;For&nbsp;example,&nbsp;if&nbsp;we&nbsp;started&nbsp;with&nbsp;17.655&nbsp;and&nbsp;stripped<BR></SPAN><SPAN style="COLOR: #008080">19</SPAN>&nbsp;<SPAN style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;off&nbsp;the&nbsp;int&nbsp;portion,&nbsp;which&nbsp;left&nbsp;.655.&nbsp;After&nbsp;we&nbsp;shift,&nbsp;we&nbsp;are&nbsp;left&nbsp;with<BR></SPAN><SPAN style="COLOR: #008080">20</SPAN>&nbsp;<SPAN style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;65.5.&nbsp;Then&nbsp;a&nbsp;round&nbsp;will&nbsp;gives&nbsp;us&nbsp;66.&nbsp;We&nbsp;can&nbsp;then&nbsp;put&nbsp;it&nbsp;all&nbsp;back<BR></SPAN><SPAN style="COLOR: #008080">21</SPAN>&nbsp;<SPAN style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;together&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">22</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000">&nbsp;roundedDecimalPortion&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Math.round(&nbsp;unroundedDecimalPortion&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">100</SPAN><SPAN style="COLOR: #000000">&nbsp;);<BR></SPAN><SPAN style="COLOR: #008080">23</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">24</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;Shift&nbsp;the&nbsp;decimal&nbsp;point&nbsp;back&nbsp;two&nbsp;places&nbsp;to&nbsp;the&nbsp;right</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">25</SPAN>&nbsp;<SPAN style="COLOR: #008000"></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;roundedDecimalPortion&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;roundedDecimalPortion&nbsp;</SPAN><SPAN style="COLOR: #000000">/</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">100</SPAN><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #008080">26</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">27</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;Add&nbsp;the&nbsp;int&nbsp;portion&nbsp;and&nbsp;decimal&nbsp;portions&nbsp;back&nbsp;together</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">28</SPAN>&nbsp;<SPAN style="COLOR: #008000"></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">double</SPAN><SPAN style="COLOR: #000000">&nbsp;total&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;intPortion&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;roundedDecimalPortion;<BR></SPAN><SPAN style="COLOR: #008080">29</SPAN>&nbsp;<SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">30</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Double(&nbsp;total&nbsp;);<BR></SPAN><SPAN style="COLOR: #008080">31</SPAN>&nbsp;<SPAN style="COLOR: #000000">&nbsp;&nbsp;}<BR></SPAN><SPAN style="COLOR: #008080">32</SPAN>&nbsp;<SPAN style="COLOR: #000000">}</SPAN></DIV><img src ="http://www.blogjava.net/limq/aggbug/13694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-09-21 23:59 <a href="http://www.blogjava.net/limq/archive/2005/09/21/13694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jakarta Commons:巧用类和组件（转）</title><link>http://www.blogjava.net/limq/archive/2005/09/21/13611.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Wed, 21 Sep 2005 02:03:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/09/21/13611.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/13611.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/09/21/13611.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/13611.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/13611.html</trackback:ping><description><![CDATA[Jakarta Commons是Jakarta的子项目，它创建和维护着许多独立软件包，这些包一般与其他框架或产品无关，其中收集了大量小型、实用的组件，大部分面向服务器端编程。 <br /><br />　　Commons的包分成两部分：Sandbox，Commons代码库。Sandbox是一个测试平台，用来检验各种设想、计划。本文介绍的组件属于Commons代码库，文章将展示各个组件的功能、适用场合，并通过简单的例子介绍其用法。 <br /><br />　　<b>一、概述</b><br /><br />　　可重用性是Jakarta Commons项目的灵魂所在。这些包在设计阶段就已经考虑了可重用性问题。其中一些包，例如Commons里面用来记录日志的Logging包，最初是为其他项目设计的，例如Jakarta Struts项目，当人们发现这些包对于其他项目也非常有用，能够极大地帮助其他项目的开发，他们决定为这些包构造一个"公共"的存放位置，这就是Jakarta Commons项目。 <br /><br />　　为了真正提高可重用性，每一个包都必须不依赖于其他大型的框架或项目。因此，Commons项目的包基本上都是独立的，不仅是相对于其他项目的独立，而且相对于Commons内部的大部分其他包独立。虽然存在一些例外的情况，例如Betwixt包要用到XML API，但绝大部分只使用最基本的API，其主要目的就是要能够通过简单的接口方便地调用。 <br /><br />　　不过由于崇尚简洁，许多包的文档变得过于简陋，缺乏维护和支持，甚至有一部分还有错误的链接，文档也少得可怜。大部分的包需要我们自己去找出其用法，甚至有时还需要我们自己去分析其适用场合。本文将逐一介绍这些包，希望能够帮助你迅速掌握这一积累了许多人心血的免费代码库。 <br /><br />　　说明：Jakarta Commons和<a href="http://commons.apache.org/" target="_blank">Apache Commons</a>是不同的，后者是Apache Software Foundation的一个顶层项目，前者则是Jakarta项目的一个子项目，同是也是本文要讨论的主角。本文后面凡是提到Commons的地方都是指Jakarta的Commons。 <br /><br />　　为了便于说明，本文把Commons项目十八个成品级的组件（排除了EL、Latka和Jexl）分成5类，如下表所示。 <br /><br /><br />参考 <a href="/sean/archive/2005/08.html">http://www.blogjava.net/sean/archive/2005/08.html</a><br /><br /><center> </center><br /><br />　　必须指出的是，这种分类只是为了方便文章说明，Commons项目里面实际上并不存在这种分类，同时这些分类的边界有时也存在一定的重叠。 <br /><br />　　本文首先介绍Web相关类和其他类里面的组件，下一篇文章将涉及XML相关、包装这两类，最后一篇文章专门介绍属于工具类的包。 <br /><br />　　<b>二、其他类</b><br /><br />　　CLI、Discovery、Lang和Collections包归入其他类，这是因为它们都各自针对某个明确、实用的小目标，可谓专而精。 <br /><br />　　<b>2.1 CLI</b><br /><br />　　■ 概况：CLI即Command Line Interface，也就是"命令行接口"，它为Java程序访问和解析命令行参数提供了一种统一的接口。 <br /><br />　　■ 官方资源：<a href="http://jakarta.apache.org/commons/cli/index.html" target="_blank">主页</a>，<a href="http://www.apache.org/dist/jakarta/commons/discovery/binaries/commons-discovery-0.2.zip" target="_blank">二进制</a>，<a href="http://www.apache.org/dist/jakarta/commons/discovery/source/commons-discovery-0.2-src.zip" target="_blank">源代码</a><br /><br />　　■ 何时适用：当你需要以一种一致的、统一的方式访问命令行参数之时。 <br /><br />　　■ 示例应用：CLIDemo.java。CLASSPATH中必须包含commons-cli-1.0.jar。 <br /><br />　　■ 说明： <br /><br />　　有多少次你不得不为一个新的应用程序重新设计新的命令行参数处理方式？如果能够只用某个单一的接口，统一完成诸如定义输入参数（是否为强制参数，数值还是字符串，等等）、根据一系列规则分析参数、确定应用要采用的路径等任务，那该多好！答案就在CLI。 <br /><br />　　在CLI中，每一个想要在命令中指定的参数都是一个Option对象。首先创建一个Options对象，将各个Option对象加入Options对象，然后利用CLI提供的方法来解析用户的输入参数。Option对象可以要求用户必须输入某个参数，例如必须在命令行提供文件名字。如果某个参数是必须的，创建Option对象的时候就要显式地指定。 <br /><br />　　下面是使用CLI的步骤。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// …
// ①  创建一个Options：
Options options = new Options();
options.addOption("t", false, "current time");
// …
// ② 创建一个解析器，分析输入：
CommandLineParser parser = new BasicParser();
CommandLine cmd;
try {
	cmd = parser.parse(options, args); 
} catch (ParseException pe) {
	usage(options);
	return;
}
// …
// ③ 最后就可以根据用户的输入，采取相应的操作：
if (cmd.hasOption("n")) {
	System.err.println("Nice to meet you: " +
	cmd.getOptionValue('n'));
}</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　这就是使用CLI的完整过程了。当然，CLI还提供了其他高级选项，例如控制格式和解析过程等，但基本的使用思路仍是一致的。请参见本文最后提供的示例程序。 <br /><br />　　<b>2.2 Discovery</b><br /><br />　　■ 概况：Discovery组件是发现模式（Discovery Pattern）的一个实现，它的目标是按照一种统一的方式定位和实例化类以及其他资源。 <br /><br />　　■ 官方资源：<a href="http://jakarta.apache.org/commons/discovery/" target="_blank">主页</a>，<a href="http://www.apache.org/dist/jakarta/commons/discovery/binaries/commons-discovery-0.2.zip" target="_blank">二进制</a>，<a href="http://www.apache.org/dist/jakarta/commons/discovery/source/commons-discovery-0.2-src.zip" target="_blank">源代码</a>。 <br /><br />　　■ 何时适用：当你想用最佳的算法在Java程序中查找Java接口的各种实现之时。 <br /><br />　　■ 应用实例：DiscoveryDemo.java，MyInterface.java，MyImpl1.java，MyImpl2.java，MyInterface。要求CLASSPATH中必须包含commons-discovery.jar和commons-logging.jar。 <br /><br />　　■ 说明： <br /><br />　　Discovery的意思就是"发现"，它试图用最佳的算法查找某个接口的所有已知的实现。在使用服务的场合，当我们想要查找某个服务的所有已知的提供者时，Discovery组件尤其有用。 <br /><br />　　考虑一下这种情形：我们为某个特别复杂的任务编写了一个接口，所有该接口的实现都用各不相同的方式来完成这个复杂任务，最终用户可以根据需要来选择完成任务的具体方式。那么，在这种情形下，最终用户应该用什么办法来找出接口的所有可用实现（即可能的完成任务的方式）呢？ <br /><br />　　上面描述的情形就是所谓的服务-服务提供者体系。服务的功能由接口描述，服务提供者则提供具体的实现。现在的问题是最终用户要用某种办法来寻找系统中已经安装了哪些服务提供者。在这种情形下，Discovery组件就很有用了，它不仅可以用来查找那些实现了特定接口的类，而且还可以用来查找资源，例如图片或其他文件等。在执行这些操作时，Discovery遵从Sun的服务提供者体系所定义的规则。 <br /><br />　　由于这个原因，使用Discovery组件确实带来许多方便。请读者参阅本文后面示例程序中的接口MyInterface.java和两个实现类MyImpl1.java、MyImple2.java，了解下面例子的细节。在使用Discovery的时候要提供MyInterface文件，把它放入META-INF/services目录，注意该文件的名字对应接口的完整限定名称（Fully Qualified Name），如果接口属于某个包，该文件的名字也必须相应地改变。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// …
// ① 创建一个类装入器的实例。
ClassLoaders loaders =
	ClassLoaders.getAppLoaders(MyInterface.class, getClass(), false);
// …
// ② 用DiscoverClass的实例来查找实现类。
DiscoverClass discover = new DiscoverClass(loaders);
// …
// ③ 查找实现了指定接口的类：
Class implClass = discover.find(MyInterface.class);
System.err.println("Implementing Provider: " + implClass.getName());</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　运行上面的代码，就可以得到在MyInterface文件中注册的类。再次提醒，如果你的实现是封装在包里面的，在这里注册的名字也应该作相应地修改，如果该文件没有放在正确的位置，或者指定名字的实现类不能找到或实例化，程序将抛出DiscoverException，表示找不到符合条件的实现。下面是MyInterface文件内容的一个例子：MyImpl2 # Implementation 2。 <br /><br />　　当然，实现类的注册办法并非只有这么一种，否则的话Discovery的实用性就要大打折扣了！实际上，按照Discovery内部的类查找机制，按照这种方法注册的类将是Discovery最后找到的类。另一种常用的注册方法是通过系统属性或用户定义的属性来传递实现类的名字，例如，放弃META-INF/services目录下的文件，改为执行java -DMyInterface=MyImpl1 DiscoveryDemo命令来运行示例程序，这里的系统属性是接口的名字，值是该接口的提供者，运行的结果是完全一样的。 <br /><br />　　Discovery还可以用来创建服务提供者的(singleton)实例并调用其方法，语法如下：((MyInterface)discover.newInstance(MyInterface.class)).myMethod();。注意在这个例子中，我们并不知道到底哪一个服务提供者实现了myMethod，甚至我们根本不必关心这一点。具体的情形与运行这段代码的方式以及运行环境中已经注册了什么服务提供者有关，在不同的环境下运行，实际得到的服务提供者可能不同。 <br /><br />　　<b>2.3 Lang</b><br /><br />　　■ 概况：Lang是java.lang的一个扩展包，增加了许多操作String的功能，另外还支持C风格的枚举量。 <br /><br />　　■ 官方资源：<a href="http://jakarta.apache.org/commons/lang.html" target="_blank">主页</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-lang/v1.0.1/commons-lang-1.0.1.zip" target="_blank">二进制</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-lang/v1.0.1/commons-lang-1.0.1-src.zip" target="_blank">源代码</a>。 <br /><br />　　■ 何时适用：当java.lang包提供的方法未能满足需要，想要更多的功能来处理String、数值和System属性时；还有，当你想要使用C风格的枚举量时。 <br /><br />　　■ 示例应用：LangDemo.java，Mortgage.java，OnTV.java。CLASSPATH中必须包含commons-lang.jar。 <br /><br />　　■ 说明： <br /><br />　　这个包提供了许多出于方便目的而提供的方法，它们中的大多数是静态的，简化了日常编码工作。StringUtils类是其中的一个代表，它使得开发者能够超越标准的java.lang.String包来处理字符串。使用这些方法很简单，通常只要在调用静态方法时提供适当的参数就可以了。例如，如果要将某个单词的首字符改为大写，只需调用：StringUtils.capitalise("name")，调用的输出结果是Name。请浏览StringUtils API文档了解其他静态方法，也许你会找到一些可以直接拿来使用的代码。本文提供的示例程序示范了其中一些方法的使用。 <br /><br />　　另一个值得注意的类是RandomStringUtils，它提供了生成随机字符串的方法，用来创建随机密码实在太方便了。 <br /><br />　　NumberUtils类提供了处理数值数据的方法，许多方法值得一用，例如寻找最大、最小数的方法，将String转换成数值的方法，等等。NumberRange和CharRange类分别提供了创建和操作数值范围、字符范围的方法。 <br /><br />　　Builder包里的类提供了一些特殊的方法，可用来构造类的toString、hashCode、compareTo和equals方法，其基本思路就是构造出类的高质量的toString、hashCode、compareTo和equals方法，从而免去了用户自己定义这些方法之劳，只要调用一下Builder包里面的方法就可以了。例如，我们可以用ToStringBuilder来构造出类的toString描述，如下例所示： <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>public class Mortgage {
	private float rate;
	private int years;
	....
	public String toString() {
		return new ToStringBuilder(this).
			append("rate",  this.rate).
			append("years", this.years).
			toString();
	}
}</ccid_code></pre></td></tr></tbody></table><span class="myp11"><font id="zoom">　　使用这类方法有什么好处呢？显然，它使得我们有可能通过一种统一的方式处理所有数据类型。所有Builder方法的用法都和上例相似。 <br /><br />　　Java没有C风格的枚举量，为此，lang包提供了一个类型安全的Enum类型，填补了空白。Enum类是抽象的，如果你要创建枚举量，就要扩展Enum类。下面的例子清楚地说明了Enum的用法。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>import org.apache.commons.lang.enum.Enum;
import java.util.Map;
import java.util.List;
import java.util.Iterator;
    
public final class OnTV extends Enum {
            
	public static final OnTV IDOL= 
	  new OnTV("Idol");
	public static final OnTV SURVIVOR =
	  new OnTV("Survivor");
	public static final OnTV SEINFELD = 
	  new OnTV("Seinfeld");

	private OnTV(String show) {
		super(show);
	}
	public static OnTV getEnum(String show){
		return (OnTV) getEnum(OnTV.class, show);
	}
	public static Map getEnumMap() {
		return getEnumMap(OnTV.class);
	}
	public static List getEnumList() {
		return getEnumList(OnTV.class);
	}
	public static Iterator iterator() {
		return iterator(OnTV.class);
	}
}</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　以后我们就可以按照下面的方式使用枚举变量：OnTV.getEnum("Idol")。该调用从前面创建的枚举数据类型返回Idol。这个例子比较简单，实际上Enum类还提供了许多有用的方法，请参见本文后面提供的完整实例。 <br /><br />　　<b>2.4 Collections</b><br /><br />　　■ 概况：扩展了Java Collection框架，增添了新的数据结构、迭代机制和比较操作符。 <br /><br />　　■ 官方资源：<a href="http://jakarta.apache.org/commons/collections.html" target="_blank">主页</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-collections/v2.1/commons-collections-2.1.zip" target="_blank">二进制</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-collections/v2.1/commons-collections-2.1-src.zip" target="_blank">源代码</a>。 <br /><br />　　■ 何时适用：几乎所有需要操作数据结构的重要Java开发项目都可以使用Collections API。和Java的标准实现相比，Collections API有着诸多优势。 <br /><br />　　■ 示例应用：CollectionsDemo.java。要求CLASSPATH中包含commons-collections.jar。 <br /><br />　　■ 说明： <br /><br />　　要在有限的文章篇幅之内详尽地介绍 Collections API实在是太困难了，不过这里仍将涵盖大多数最重要的类，希望能够引起你的兴趣，认真了解一下其余的类。Collections本身的文档也提供了许多资料并解释了每一个类的用法。 <br /><br />　　Bag接口扩展标准的Java Collection，允许生成计数器来跟踪Bag里面的所有元素。当你想要跟踪进出某个集合的元素的总数时，Bag是非常有用的。由于Bag本身是一个接口，所以实际使用的应该是实现了该接口的类，例如HashBag或TreeBag--从这些类的名字也可以看出，HashBag实现的是一个HashMap的Bag，而TreeBag实现的是TreeMap的Bag。Bag接口中两个最重要的方法是：getCount(Object o)，用来返回Bag里面特定对象的出现次数；uniqueSet()，返回所有唯一元素。 <br /><br />　　Buffer接口允许按照预定义的次序删除集合中的对象，删除次序可以是LIFO（Last In First Out，后进先出），或FIFO（First In First Out，先进先出），另外还可以是自定义的次序。下面来看看如何实现一个Buffer，按照自然次序删除元素。 <br /><br />　　BinaryHeap类实现了Buffer接口，能够按照自然次序删除元素。如果要颠倒次序，则必须传入一个false，告诉Heap采用自然次序的逆序。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>BinaryHeap heap = new BinaryHeap();
// …
// 将元素加入该Heap
heap.add(new Integer(-1));
heap.add(new Integer(-10));
heap.add(new Integer(0));
heap.add(new Integer(-3));
heap.add(new Integer(5));
//…
// 删除一个元素
heap.remove();</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　调用该Heap的remove，按照自然次序，元素集合中的-10将被删除。如果我们要求按照逆序排序，则被删除的将是5。 <br /><br />　　FastArrayList、FastHashMap和FastTreeMap类能够按照两种模式操作，超越了与它们对应的标准Collection。第一种模式是"慢模式"，类的修改操作（添加、删除元素）是同步的。与此相对，另一种模式是"快模式"，对这些类的访问假定为只读操作，因此不需要同步，速度较快。在快模式中，结构性的改动通过下列方式完成：首先克隆现有的类，修改克隆得到的类，最后用克隆得到的类替换原有的类。FastArrayList、FastHashMap和FastTreeMap类特别适合于那种初始化之后大部分操作都是只读操作的多线程环境。 <br /><br />　　iterators包为各种集合和对象提供标准Java Collection包没有提供的迭代器。本文的示例应用示范了ArrayIterator，通过迭代方式访问Array的内容。iterators包里面各种迭代器的用法基本上与标准Java迭代器一样。 <br /><br />　　最后，comparators包提供了一些实用的比较符。所谓比较符其实也是一个类，它定义的是如何比较两个属于同一类的对象，决定它们的排序次序。例如，在前面提到的Buffer类中，我们可以定义自己的比较符，用自定义的比较符来决定元素的排序次序，而不是采用元素的自然排序次序。下面来看看具体的实现经过。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// …
// ① 创建一个BinaryHeap类，但这一次参数中
//    指定NullComparator。NullComparator比较
//    null与其他对象，根据nullsAreHigh标记来
//    判断null值比其他对象大还是小：如果
//    nullsAreHigh的值是false，则认为null要比
//    其他对象小。
BinaryHeap heap2 = new BinaryHeap
 (new NullComparator(false));
// …
// ② 将一些数据（包括几个null值）加入heap：
heap2.add(null);
heap2.add(new Integer("6"));
heap2.add(new Integer("-6"));
heap2.add(null);
// …
// ③ 最后删除一个元素，Bag包含的null将减少
//    一个，因为null要比其他对象小。
heap2.remove();</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　有关其他类Commons组件的介绍就到这里结束。如果你想了解更多细节信息，请参见API文档，最好再看看这些包的源代码。 <br /><br />　　<b>三、Web类</b><br /><br />　　Web类的组件用来执行与Web相关的任务。 <br /><br />　　<b>3.1 FileUpload</b><br /><br />　　■ 概况：一个可以直接使用的文件上载组件。 <br /><br />　　■ 官方资源：<a href="http://jakarta.apache.org/commons/fileupload/index.html" target="_blank">主页</a>。由于这个组件尚未正式发布，今年二月发布的Beta版又有许多BUG，所以建议从<a href="http://cvs.apache.org/builds/jakarta-commons/nightly/commons-fileupload/" target="_blank">nightly builds</a>下载最新的版本。 <br /><br />　　■ 何时适用：当你想要在Java服务器环境中加入一个易用、高性能的文件上载组件之时。 <br /><br />　　■ 示例应用：fileuploaddemo.jsp，fileuploaddemo.htm，和msg.jsp。要求服务器端应用目录的WEB-INF/lib下面有commons-fileupload-1.0-dev.jar。 <br /><br />　　■ 说明： <br /><br />　　FileUpload组件解决了常见的文件上载问题。它提供了一个易用的接口来管理上载到服务器的文件，可用于JSP和Servlet之中。FileUpload组件遵从RFC1867，它分析输入请求，向应用程序提供一系列上载到服务器的文件。上载的文件可以保留在内存中，也可以放入一个临时位置（允许配置一个表示文件大小的参数，如果上载的文件超过了该参数指定的大小，则把文件写入一个临时位置）。另外还有一些参数可供配置，包括可接受的最大文件、临时文件的位置等。 <br /><br />　　下面介绍一下使用FileUpload组件的步骤。 <br /><br />　　首先创建一个HTML页面。注意，凡是要上载文件的表单都必须设置enctype属性，且属性的值必须是multipart/form-data，同时请求方法必须是POST。下面的表单除了上载两个文件，另外还有一个普通的文本输入框： <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code><form name="myform" action="fileuploaddemo.jsp" method="post" enctype="multipart/form-data">
    输入你的名字:<br /><input size="15" name="name" /><br />
  图形:<br /><input type="file" name="myimage" /><br />
  文件:<br /><input type="file" name="myfile" /><br /><br /><input type="submit" value="Submit your files" name="Submit" /></form></ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　接下来创建JSP页面。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// …
// ① 检查输入请求是否为multipart的表单数据。
boolean isMultipart = FileUpload.
  isMultipartContent(request);
// …
// ② 为该请求创建一个句柄，通过它来解析请求。执行
//    解析后，所有的表单项目都保存在一个List中。
DiskFileUpload upload = new DiskFileUpload();
// 通过句柄解析请求，解析得到的项目保存在一个List中
List items = upload.parseRequest(request);
// …
// ③ 通过循环依次获得List里面的文件项目。要区分表示
//    文件的项目和普通的表单输入项目，使用isFormField()
//    方法。根据处理请求的要求，我们可以保存上载的文
//    件，或者一个字节一个字节地处理文件内容，或者打
//    开文件的输入流。
Iterator itr = items.iterator();

while(itr.hasNext()) {
	FileItem item = (FileItem) itr.next();
        
// 检查当前的项目是普通的表单元素，还是一个上载的文件
	if(item.isFormField()) {
// 获得表单域的名字
	String fieldName = item.getFieldName();
// 如果表单域的名字是name…
	if(fieldName.equals("name"))
		request.setAttribute("msg", 
		"Thank You: " + item.getString());
		
	} else {
// 该项目是一个上载的文件，把它保存到磁盘。
// 注意item.getName()
// 会返回上载文件在客户端的完整路径名称，这似乎是一个BUG。
// 为解决这个问题，这里使用了fullFile.getName()。
		File fullFile  = new File(item.getName());  
		File savedFile = new File
		(getServletContext().getRealPath("/"),
		fullFile.getName());
		item.write(savedFile);
	}
}</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　我们可以通过上载句柄的upload.setSizeMax来限制上载文件的大小。当上载文件的大小超过允许的值时，程序将遇到异常。在上面的例子中，文件大小的限制值是-1，表示允许上载任意大小的文件。 <br /><br />　　还有其他一些略有变化的使用形式，正如前面所指出的，我们可以在上载的文件上打开一个输入流，或者让它们驻留在内存中直至空间占用达到一定的限制值，或者在判断文件类型的基础上，以String或Byte数组的形式获取其内容，或者直接删除文件。这一切都只要使用FileItem类提供的方法就可以方便地做到（DefaultFileItem是FileItem的一个实现）。</font></span><span class="myp11"><font id="zoom">　　<b>3.2 HttpClient</b><br /><br />　　■ 概况：这个API扩展了java.net包，提供了模拟浏览器的功能。 <br /><br />　　■ 官方资源：<a href="http://jakarta.apache.org/commons/httpclient/index.html" target="_blank">主页</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-httpclient/v2.0/commons-httpclient-2.0-beta1.zip" target="_blank">二进制</a>，<a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-httpclient/v2.0/commons-httpclient-2.0-beta1-src.zip" target="_blank">源代码</a>。 <br /><br />　　■ 何时适用：当你要构造Web浏览器的功能；当你的应用需要一种高效的办法进行HTTP/HTTPS通信时。 <br /><br />　　■ 示例应用：HttpClientDemo.java。要求CLASSPATH中有commons-httpclient.jar，common-logging.jar。要求使用JDK 1.4或更高版本。 <br /><br />　　■ 说明： <br /><br />　　HttpClient扩展和增强了标准java.net包，是一个内容广泛的代码库，功能极其丰富，能够构造出各种使用HTTP协议的分布式应用，或者也可以嵌入到现有应用，为应用增加访问HTTP协议的能力。在Commons稳定版中，HttpClient的文档似乎要比其他包更完善一些，而且还带有几个实例。下面我们通过一个简单的例子来了解如何提取一个Web页面，HttpClient文档中也有一个类似的例子，我们将扩充那个例子使其支持SSL。注意本例需要JDK 1.4支持，因为它要用到Java Secure Socket Connection库，而这个库只有JDK 1.4及更高的版本才提供。 <br /><br />　　① 首先确定一个可以通过HTTPS下载的页面，本例使用的是https://www.paypal.com/。同时确保%JAVA_HOME%/jre/lib/security/java.security文件包含了下面这行代码：security.provider.2=com.sun.net.ssl.internal.ssl.Provider。 <br /><br />　　除了这些设置之外，HTTPS连接的处理方式没有其他特别的地方--至少对于本例来说如此。不过，如果远程网站使用的根证书不被你使用的Java认可，则首先必须导入它的证书。 <br /><br />　　② 创建一个HttpClient的实例。HttpClient类可以看成是应用的主驱动程序，所有针对网络的功能都依赖于它。HttpClient类需要一个Connection Manager来管理连接。HttpConnectionManager允许我们创建自己的连接管理器，或者，我们也可以直接使用内建的SimpleHttpConnectionManager或MultiThreadedHttpConnectionManager类。如果在创建HttpClient时没有指定连接管理器，HttpClient默认使用SimpleHttpConnectionManager。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// 创建一个HttpClient的实例
HttpClient client = new HttpClient();</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　③ 创建一个HttpMethod的实例，即确定与远程服务器的通信要采用哪种传输方式，HTTP允许采用的传输方式包括：GET，POST，PUT，DELETE，HEAD，OPTIONS，以及TRACE。这些传输方式分别作为一个独立的类实现，但所有这些类都实现HttpMethod接口。在本例中，我们使用的是GetMethod，创建GetMethod实例时在参数中指定我们想要GET的URL。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// 创建一个HttpMethod的实例
HttpMethod method = new GetMethod(url);</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　④ 执行HttpMethod定义的提取操作。执行完毕后，executeMethod方法将返回远程服务器报告的状态代码。注意executeMethod属于HttpClient，而不是HttpMethod。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// 执行HttpMethod定义的提取操作
statusCode = client.executeMethod(method);</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　⑤ 读取服务器返回的应答。如果前面的连接操作失败，程序将遇到HttpException或IOException，其中IOException一般意味着网络出错，继续尝试也不太可能获得成功。服务器返回的应答可以按照多种方式读取，例如作为一个字节数组，作为一个输入流，或者作为一个String。获得服务器返回的应答后，我们就可以按照自己的需要任意处置它了。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>byte[] responseBody = method.getResponseBody();</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　⑥ 最后要做的就是释放连接。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>method.releaseConnection();</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　以上只是非常简单地介绍了一下HttpClient库，HttpClient实际的功能要比本文介绍的丰富得多，不仅健壮而且高效，请参阅API文档了解详情。 <br /><br />　　<b>3.3 Net</b><br /><br />　　■ 概况：一个用于操作Internet基础协议的底层API。 <br /><br />　　■ 官方资源：<a href="http://jakarta.apache.org/commons/net/" target="_blank">主页</a>，<a href="http://apache.planetmirror.com/dist/jakarta/commons/net/binaries/" target="_blank">二进制</a>，<a href="http://apache.planetmirror.com.au/dist/jakarta/commons/net/source/" target="_blank">源代码</a>。 <br /><br />　　■ 何时适用：当你想要访问各种Internet底层协议之时（Finger，Whois，TFTP，Telnet，POP3，FTP，NNTP，以及SMTP）。 <br /><br />　　■ 示例应用：NetDemo.java。要求CLASSPATH中包含commons-net-1.0.0.jar。 <br /><br />　　■ 说明： <br /><br />　　Net包是一个强大、专业的类库，类库里的类最初属于一个叫做NetComponents的商业产品。 <br /><br />　　Net包不仅支持对各种低层次协议的访问，而且还提供了一个高层的抽象。大多数情况下，Net包提供的抽象已能满足一般需要，它使得开发者不再需要直接面对各种协议的Socket级的低层命令。使用高层抽象并不减少任何功能，Net API在这方面做得很出色，既提供了足够的功能，又不至于在特色方面作过多的妥协。 <br /><br />　　SocketClient是支持所有协议的基础类，它是一个抽象类，聚合了各种协议都需要的公用功能。各种不同协议的使用过程其实很相似，首先利用connect方法建立一个指向远程服务器的连接，执行必要的操作，最后终止与服务器的连接。下面通过实例介绍具体的使用步骤。 <br /><br /><ccid_nobr><table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="540" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre><ccid_code>// …
// ① 创建一个客户端。我们将用NNTPClient
//　　从新闻服务器下载新闻组清单。
client = new NNTPClient();
// …
// ② 利用前面创建的客户端连接到新闻服务器。
//　　这里选用的是一个新闻组较少的服务器。
client.connect("aurelia.deine.net");
// …
// ③ 提取新闻组清单。下面的命令将返回一个
//　　NewsGroupInfo对象的数组。如果指定的服
//　　务器上不包含新闻组，返回的数组将是空的，
//　　如果遇到了错误，则返回值是null。
list = client.listNewsgroups();
//...
// ④ 最后终止与服务器的连接。
 if (client.isConnected())
   client.disconnect();</ccid_code></pre></td></tr></tbody></table></ccid_nobr><br /><br />　　必须说明的是，listNewsgroups命令可能需要较长的时间才能返回，一方面是因为网络速度的影响，另外也可能是由于新闻组清单往往是很庞大的。NewsGroupInfo对象包含有关新闻组的详细信息，并提供了一些操作新闻组的命令，比如提取文章总数、最后发布的文章、发布文章的权限，等等。 <br /><br />　　其他客户端，例如FingerClient、POP3Client、TelnetClient等，用法也差不多。 <br /><br />　　结束语：有关Web相关类和其他类的介绍就到此结束。在下一篇文章中，我们将探讨XML类和包装类，最后一篇文章则介绍工具类。 <br /><br />　　希望读者有兴趣试试本文提供的程序实例。很多时候Jakarta Commons给人以混乱的感觉，希望本文使你加深了对Jakarta Commons了解，或者至少引起了你对Commons子项目以及它提供的各种实用API和库的兴趣。 <br /><br />请从这里下载本文代码：<a href="http://developer.ccidnet.com/pub/html/developer/code/download/jakartacommons1code.zip" target="_blank">JakartaCommons1_code.zip</a><br /></font></span></ccid_nobr><img src ="http://www.blogjava.net/limq/aggbug/13611.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-09-21 10:03 <a href="http://www.blogjava.net/limq/archive/2005/09/21/13611.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts＋Spring＋Hibernate开发实例</title><link>http://www.blogjava.net/limq/archive/2005/09/20/13565.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Tue, 20 Sep 2005 12:47:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/09/20/13565.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/13565.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/09/20/13565.html#Feedback</comments><slash:comments>67</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/13565.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/13565.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一 介绍本文并不想介绍Struts，Spring，Hibernate的原理系统架构等，本文地目的是通过一个较复杂地实例介绍如何整合Struts，Spring，Hibernate，网上现有的例子虽然也能达到目的，但功能都比较单一，复杂的例子时会有意想不到的麻烦。本文对读者假设已经具备了以上框架的基础知识。以及那些已经了解Struts，Spring，Hibernate的基本概念，但是还没有亲身在较...&nbsp;&nbsp;<a href='http://www.blogjava.net/limq/archive/2005/09/20/13565.html'>阅读全文</a><img src ="http://www.blogjava.net/limq/aggbug/13565.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-09-20 20:47 <a href="http://www.blogjava.net/limq/archive/2005/09/20/13565.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>条件查询(Criteria Query)</title><link>http://www.blogjava.net/limq/archive/2005/09/20/13564.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Tue, 20 Sep 2005 12:42:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/09/20/13564.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/13564.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/09/20/13564.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/13564.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/13564.html</trackback:ping><description><![CDATA[<P>现在Hibernate也支持一种直观的、可扩展的条件查询API。目前为止，这个API还没有更成熟的HQL查询那么强大，也没有那么多查询能力。特别要指出，条件查询也不支持投影（projection）或统计函数（aggregation）。 </P>
<DIV class=sect1 lang=zh-cn>
<DIV class=titlepage>
<DIV>
<DIV>
<H2 class=title style="CLEAR: both"><A name=querycriteria-creating></A>12.1.&nbsp;创建一个<TT class=literal>Criteria</TT>实例</H2></DIV></DIV></DIV>
<P><TT class=literal>net.sf.hibernate.Criteria</TT>这个接口代表对一个特定的持久化类的查询。<TT class=literal>Session</TT>是用来制造<TT class=literal>Criteria</TT>实例的工厂。 </P><PRE class=programlisting>Criteria crit = sess.createCriteria(Cat.class);<BR>crit.setMaxResults(50);<BR>List cats = crit.list();</PRE></DIV>
<DIV class=sect1 lang=zh-cn>
<DIV class=titlepage>
<DIV>
<DIV>
<H2 class=title style="CLEAR: both"><A name=querycriteria-narrowing></A>12.2.&nbsp;缩小结果集范围</H2></DIV></DIV></DIV>
<P>一个查询条件(Criterion)是<TT class=literal>net.sf.hibernate.expression.Criterion</TT>接口的一个实例。类<TT class=literal>net.sf.hibernate.expression.Expression</TT>定义了获得一些内置的<TT class=literal>Criterion</TT>类型。 </P><PRE class=programlisting>List cats = sess.createCriteria(Cat.class)<BR>    .add( Expression.like("name", "Fritz%") )<BR>    .add( Expression.between("weight", minWeight, maxWeight) )<BR>    .list();</PRE>
<P>表达式（Expressions）可以按照逻辑分组. </P><PRE class=programlisting>List cats = sess.createCriteria(Cat.class)<BR>    .add( Expression.like("name", "Fritz%") )<BR>    .add( Expression.or(<BR>    	Expression.eq( "age", new Integer(0) ),<BR>    	Expression.isNull("age")<BR>    ) )<BR>    .list();</PRE><PRE class=programlisting>List cats = sess.createCriteria(Cat.class)<BR>    .add( Expression.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )<BR>    .add( Expression.disjunction()<BR>        .add( Expression.isNull("age") )<BR>    	.add( Expression.eq("age", new Integer(0) ) )<BR>    	.add( Expression.eq("age", new Integer(1) ) )<BR>    	.add( Expression.eq("age", new Integer(2) ) )<BR>    ) )<BR>    .list();</PRE>
<P>有很多预制的条件类型（<TT class=literal>Expression</TT>的子类）。有一个特别有用，可以让你直接嵌入SQL。 </P><PRE class=programlisting>List cats = sess.createCriteria(Cat.class)<BR>    .add( Expression.sql("lower($alias.name) like lower(?)", "Fritz%", Hibernate.STRING) )<BR>    .list();</PRE>
<P>其中的<TT class=literal>{alias}</TT>是一个占位符，它将会被所查询实体的行别名所替代。(原文:The <TT class=literal>{alias}</TT> placeholder with be replaced by the row alias of the queried entity.) </P></DIV>
<DIV class=sect1 lang=zh-cn>
<DIV class=titlepage>
<DIV>
<DIV>
<H2 class=title style="CLEAR: both"><A name=querycriteria-ordering></A>12.3.&nbsp;对结果排序</H2></DIV></DIV></DIV>
<P>可以使用<TT class=literal>net.sf.hibernate.expression.Order</TT>对结果集排序. </P><PRE class=programlisting>List cats = sess.createCriteria(Cat.class)<BR>    .add( Expression.like("name", "F%")<BR>    .addOrder( Order.asc("name") )<BR>    .addOrder( Order.desc("age") )<BR>    .setMaxResults(50)<BR>    .list();</PRE></DIV>
<DIV class=sect1 lang=zh-cn>
<DIV class=titlepage>
<DIV>
<DIV>
<H2 class=title style="CLEAR: both"><A name=querycriteria-associations></A>12.4.&nbsp;关联（Associations）</H2></DIV></DIV></DIV>
<P>你可以在关联之间使用<TT class=literal>createCriteria()</TT>，很容易地在存在关系的实体之间指定约束。 </P><PRE class=programlisting>List cats = sess.createCriteria(Cat.class)<BR>    .add( Expression.like("name", "F%")<BR>    .createCriteria("kittens")<BR>        .add( Expression.like("name", "F%")<BR>    .list();</PRE>
<P>注意，第二个<TT class=literal>createCriteria()</TT>返回一个<TT class=literal>Criteria</TT>的新实例，指向<TT class=literal>kittens</TT>集合类的元素。 </P>
<P>下面的替代形式在特定情况下有用。 </P><PRE class=programlisting>List cats = sess.createCriteria(Cat.class)<BR>    .createAlias("kittens", "kt")<BR>    .createAlias("mate", "mt")<BR>    .add( Expression.eqProperty("kt.name", "mt.name") )<BR>    .list();</PRE>
<P>（<TT class=literal>createAlias()</TT>）并不会创建一个<TT class=literal>Criteria</TT>的新实例。） </P>
<P>请注意，前面两个查询中<TT class=literal>Cat</TT>实例所持有的kittens集合类<SPAN class=emphasis><EM>并没有</EM></SPAN>通过criteria预先过滤！如果你希望只返回满足条件的kittens,你必须使用<TT class=literal>returnMaps()</TT>。 </P><PRE class=programlisting>List cats = sess.createCriteria(Cat.class)<BR>    .createCriteria("kittens", "kt")<BR>        .add( Expression.eq("name", "F%") )<BR>    .returnMaps()<BR>    .list();<BR>Iterator iter = cats.iterator();<BR>while ( iter.hasNext() ) {<BR>    Map map = (Map) iter.next();<BR>    Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);<BR>    Cat kitten = (Cat) map.get("kt");<BR>}</PRE></DIV>
<DIV class=sect1 lang=zh-cn>
<DIV class=titlepage>
<DIV>
<DIV>
<H2 class=title style="CLEAR: both"><A name=querycriteria-dynamicfetching></A>12.5.&nbsp;动态关联对象获取（Dynamic association fetching）</H2></DIV></DIV></DIV>
<P>可以在运行时通过<TT class=literal>setFetchMode()</TT>来改变关联对象自动获取的策略。 </P><PRE class=programlisting>List cats = sess.createCriteria(Cat.class)<BR>    .add( Expression.like("name", "Fritz%") )<BR>    .setFetchMode("mate", FetchMode.EAGER)<BR>    .setFetchMode("kittens", FetchMode.EAGER)<BR>    .list();</PRE>
<P>这个查询会通过外连接(outer join)同时获得 <TT class=literal>mate</TT>和<TT class=literal>kittens</TT>。 </P></DIV>
<DIV class=sect1 lang=zh-cn>
<DIV class=titlepage>
<DIV>
<DIV>
<H2 class=title style="CLEAR: both"><A name=querycriteria-examples></A>12.6.&nbsp;根据示例查询（Example queries）</H2></DIV></DIV></DIV>
<P><TT class=literal>net.sf.hibernate.expression.Example</TT>类允许你从指定的实例创造查询条件。 </P><PRE class=programlisting>Cat cat = new Cat();<BR>cat.setSex('F');<BR>cat.setColor(Color.BLACK);<BR>List results = session.createCriteria(Cat.class)<BR>    .add( Example.create(cat) )<BR>    .list();</PRE>
<P>版本属性，表示符属性和关联都会被忽略。默认情况下，null值的属性也被排除在外。 </P>
<P>You can adjust how the <TT class=literal>Example</TT> is applied. 你可以调整<TT class=literal>示例(Example)</TT>如何应用。 </P><PRE class=programlisting>Example example = Example.create(cat)<BR>    .excludeZeroes()           //exclude zero valued properties<BR>    .excludeProperty("color")  //exclude the property named "color"<BR>    .ignoreCase()              //perform case insensitive string comparisons<BR>    .enableLike();             //use like for string comparisons<BR>List results = session.createCriteria(Cat.class)<BR>    .add(example)<BR>    .list();</PRE>
<P>你甚至可以用示例对关联对象建立criteria。 </P><PRE class=programlisting>List results = session.createCriteria(Cat.class)<BR>    .add( Example.create(cat) )<BR>    .createCriteria("mate")<BR>        .add( Example.create( cat.getMate() ) )<BR>    .list();</PRE></DIV><img src ="http://www.blogjava.net/limq/aggbug/13564.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-09-20 20:42 <a href="http://www.blogjava.net/limq/archive/2005/09/20/13564.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Framework标记库初学者指南(转）</title><link>http://www.blogjava.net/limq/archive/2005/03/10/1900.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Thu, 10 Mar 2005 06:08:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/03/10/1900.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/1900.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/03/10/1900.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/1900.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/1900.html</trackback:ping><description><![CDATA[<H3>Spring架构简要介绍：</H3><BR>&nbsp;&nbsp;&nbsp;&nbsp;Spring是一个服务于所有层面的application&nbsp;framework:提供了bean的配置基础，AOP的支持，JDBC的提取框架,抽象事务支持，等等。它有一个非常显著的特点：在某个层面上如果你不需要Spring的支持，你就可以不使用String的class，只使用它的某一部分的功能。从它的设计理念，你可以看到String帮助你实现了真正的逻辑层和web层的分离。<BR>&nbsp;&nbsp;&nbsp;相对于EJB来说，Spring是一个轻量级的J2EE应用开发框架。这里提到的轻量级指的是Spring框架本身，而不是说Spring只能适用于轻量级的应用开发。Spring的轻盈体现在其框架本身的基础结构以及对其他应用工具的支持和装配能力，与EJB这种庞然大物相比，Spring使我们把各个技术层次之间的风险降低。EJB的内聚性较强，比如数据持久层管理、事务管理、生命周期管理都全部交给了EJB容器中管理，内聚性的白盒特征使我们必须放弃一部分可控性而去信任容器能力。而Spring则是考虑如何“不造轮子”，如何更好的组装这些轮子，让他们更好的转动。比如数据持久层管理可以使用hibernate，日志管理可以使用jakartacommonlogging。一个比较恰当的比喻就是“我们要钉几个钉子，为了完成这个目的，锤子生产商生产了大大小小一系列的锤子，每个锤子都有一套复杂的使用方法，用来钉某种特别的钉子，结果令我们头疼不堪。解决锤子过多的问题，通过spring，我们可以使用几种锤子，但用起来象是只有一个锤子”。(注：这段话是在网上看见的，这里引用这个比喻，我个人觉得很生动)关于这个框架也有一些简单的总结：“Spring有几个主要的部分：Bean+ApplicationContext，以一种统一的、IoC的方式查找、管理、组装、使用系统的组件，取代一切工厂；持久化框架；web框架。“J2EE框架”是RodJohnson的愿景，他希望Spring为J2EE轻量级解决方案提供自底至顶的全面基础设施支持。”&nbsp;<BR>&nbsp;&nbsp;&nbsp;好了，上面是关于一个新的Framework的简单介绍，据说是未来J2EE发展的方向。以前在论坛上有关于J2EE最佳组合的讨论，听说这个JSTL+Struts(或webwork)+Spring+Hibernate的组合很被看好（观点不一，仅供参考，呵呵）,如果你感兴趣的话，可以到SpringFramework中文论坛上看看。下面转入本文的正题。<BR><BR>
<H3>Spring&nbsp;标记库介绍及用法：</H3><BR>&nbsp;&nbsp;&nbsp;&nbsp;本文将重点介绍Spring&nbsp;提供的标记库及其用法：<BR>当你在项目中用Spring&nbsp;Framework的时候，表现层可以选择Spring&nbsp;Framework自带的标记库。当然，这不是你唯一的选择。你可以选择其它标记库或模板替换技术。Spring&nbsp;Framework&nbsp;并没有为应用提供非常丰富的标记库。Spring&nbsp;Framework&nbsp;提供的标记库仅仅是为了够用就行，它并不是无所不包的。呵呵，这点与Struts丰富的标记库不一样。其实这点符合RodJohnson的出发点，既“不造轮子”。当然，Spring&nbsp;Framework标记库有它自身的特点，可以说是个有益的补充吧。<BR><B>Spring&nbsp;标记库分类如下：</B><BR>1。spring:hasBindErrors&nbsp;<BR>2。spring:bind&nbsp;<BR>3。spring:transform&nbsp;<BR>4。spring:message&nbsp;<BR>5。spring:htmlEscape&nbsp;<BR>6。spring:theme&nbsp;<BR><B>下面我们来具体介绍一下用法：</B><BR>1。<B>spring:hasBindErrors&nbsp;</B><BR>对应org.springframework.web.servlet.tags.BindErrorsTag标记库处理类。<BR>这个标记提供用于绑定对象的errors，如果这个标记被用到的话，那么关于这个对象的错误将在页面上显示出来。使用这个标记的前提条件是要先使用&lt;spring:bind&gt;标记,并且&lt;spring:hasBindErrors&gt;这个标记不能用来表示对象的状态，它仅仅可以绑定对象本身和对象的属性。&nbsp;具体用法如下：<BR>
<DIV class=codeStyle>
<OL>
<LI>&lt;spring:hasBindErrors&nbsp;name=<FONT color=#ff33ff>"priceIncrease"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;b&gt;Please&nbsp;fix&nbsp;all&nbsp;errors!&lt;/b&gt; 
<LI>&nbsp;&nbsp;&lt;/spring:hasBindErrors&gt; </LI></OL></DIV><BR>&nbsp;&nbsp;通过这个简单的例子，我来具体说一下这个标记的属性吧。<BR>&nbsp;&nbsp;name：是要被检查的Bean的名字。这个属性是必需要的。<BR>&nbsp;&nbsp;呵呵，这里是简单用法，所以就不介绍它包含的errors变量了。具体看英语文档。下同。<BR>&nbsp;&nbsp;<BR>2。<B>spring:bind&nbsp;</B><BR>对应org.springframework.web.servlet.tags.BindTag标记库处理类<BR>这个标记用来为某个bean或bean&nbsp;的属性赋值，通常和form一起用，相当于action的作用。它指明表单要提交到那个类或类的属性中去。<BR>其中path属性是必须的，指明转到的类的路径。举例如下：<BR>
<DIV class=codeStyle>
<OL>
<LI>&lt;form&nbsp;method=<FONT color=#ff33ff>"post"</FONT>&gt; 
<LI>&nbsp;&nbsp;&lt;table&nbsp;width=<FONT color=#ff33ff>"95%"</FONT>&nbsp;bgcolor=<FONT color=#ff33ff>"f8f8ff"</FONT>&nbsp;border=<FONT color=#ff33ff>"0"</FONT>&nbsp;cellspacing=<FONT color=#ff33ff>"0"</FONT>&nbsp;cellpadding=<FONT color=#ff33ff>"5"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;alignment=<FONT color=#ff33ff>"right"</FONT>&nbsp;width=<FONT color=#ff33ff>"20%"</FONT>&gt;Increase&nbsp;(%):&lt;/td&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;spring:bind&nbsp;path=<FONT color=#ff33ff>"priceIncrease.percentage"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;width=<FONT color=#ff33ff>"20%"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type=<FONT color=#ff33ff>"text"</FONT>&nbsp;name=<FONT color=#ff33ff>"percentage"</FONT>&nbsp;value=<FONT color=#ff33ff>"&lt;c:out&nbsp;value="</FONT>${status.value}<FONT color=#ff33ff>"/&gt;"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;width=<FONT color=#ff33ff>"60%"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;font&nbsp;color=<FONT color=#ff33ff>"red"</FONT>&gt;&lt;c:out&nbsp;value=<FONT color=#ff33ff>"${status.errorMessage}"</FONT>/&gt;&lt;/font&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/spring:bind&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt; 
<LI>&nbsp;&nbsp;&lt;/table&gt; 
<LI>&nbsp;&nbsp;&lt;br&gt; 
<LI>&nbsp;……………………省略 
<LI>&lt;/form&gt; </LI></OL></DIV><BR>3。<B>spring:transform&nbsp;</B><BR>对应org.springframework.web.servlet.tags.TransformTag标记库处理类,这个标记用来转换表单中不与bean中的属性一一对应的那些属性，通常和&lt;spring:bind&gt;一起使用。&lt;spring:transform&gt;标记为&lt;spring:bind&gt;使用提供了更好的支持。<BR>属性如下：<BR>value：必需要的。和当前&lt;spring:bind&gt;标记指向的bean类相同。就是你要转换的实体类名。<BR>var：不是必需的。这个字符串被用来绑定输出结果到page，request,&nbsp;session或application&nbsp;scope.默认情况输出到jsp中。<BR>scope：不是必需的。前提条件var必须设置的情况下。它的值可以是page，request,&nbsp;session或application。<BR><BR>4。<B>spring:message&nbsp;</B>对应org.springframework.web.servlet.tags.MessageTag标记库处理类<BR>这个标记用来帮助springframework支持国际化。和JSTL的fmt:message标记类似。当然这个标记可以很好的工作的本地的springframework框架下。<BR>属性如下：<BR>code：不是必需的。用来查找message,如果没有被使用的话，text将被使用。<BR>text：不是必需的。假如code不存在的话，默认是text输出。当code和text都没有设置的话，标记将输出为null.<BR>var：不是必需的。这个字符串被用来绑定输出结果到page，request,&nbsp;session或application&nbsp;scope.默认情况输出到jsp中。<BR>scope：不是必需的。前提条件var必须设置的情况下。它的值可以是page，request,&nbsp;session或application。<BR><BR>5。<B>spring:htmlEscape&nbsp;</B><BR>对应org.springframework.web.servlet.tags.HtmlEscapeTag标记库处理类<BR>不常用，这里省略<BR>6。<B>spring:theme&nbsp;</B><BR>对应org.springframework.web.servlet.tags.ThemeTag标记库处理类<BR>不常用，这里省略<BR>哈哈，学习完这些用法后，让我们来看个<B>具体的例子</B>吧。<BR>配置步骤如下：<BR><B>目录结构图：</B><BR>-spirngapp&nbsp;<BR>&nbsp;&nbsp;-WEB-INF&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-classes&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-lib&nbsp;<BR>&nbsp;&nbsp;-src&nbsp;<BR>&nbsp;&nbsp;-war<BR><B>1。</B>将spring.tld拷贝到WEB-INF目录。<BR><B>2。</B>将spring.jar拷贝到WEB-INF\lib包下<BR>举例如下：<BR>在web.xml中配置好taglib属性，代码如下：<BR>
<DIV class=codeStyle>
<OL>
<LI>&lt;?xml&nbsp;version=<FONT color=#ff33ff>"1.0"</FONT>&nbsp;encoding=<FONT color=#ff33ff>"UTF-8"</FONT>?&gt; 
<LI>&lt;!DOCTYPE&nbsp;web-app&nbsp;PUBLIC&nbsp;'-<I><FONT color=#339900>//Sun&nbsp;Microsystems,&nbsp;Inc.//DTD&nbsp;Web&nbsp;Application&nbsp;2.3//EN'&nbsp;'http://java.sun.com/dtd/web-app_2_3.dtd'&gt;</FONT></I> 
<LI>
<LI>&lt;web-app&gt; 
<LI>
<LI>&nbsp;&nbsp;&lt;servlet&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-name&gt;springapp&lt;/servlet-name&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-<B><FONT color=#0000ff>class</FONT></B>&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-<B><FONT color=#0000ff>class</FONT></B>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;load-on-startup&gt;1&lt;/load-on-startup&gt; 
<LI>&nbsp;&nbsp;&lt;/servlet&gt; 
<LI>
<LI>&nbsp;&nbsp;&lt;servlet-mapping&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;servlet-name&gt;springapp&lt;/servlet-name&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;url-pattern&gt;*.htm&lt;/url-pattern&gt; 
<LI>&nbsp;&nbsp;&lt;/servlet-mapping&gt; 
<LI>
<LI>&nbsp;&nbsp;&lt;welcome-file-list&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;welcome-file&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;index.jsp 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/welcome-file&gt; 
<LI>&nbsp;&nbsp;&lt;/welcome-file-list&gt; 
<LI>
<LI>&nbsp;&nbsp;&lt;taglib&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;taglib-uri&gt;/spring&lt;/taglib-uri&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;taglib-location&gt;/WEB-INFspring.tld&lt;/taglib-location&gt; 
<LI>&nbsp;&nbsp;&lt;/taglib&gt; 
<LI>
<LI>&lt;/web-app&gt; </LI></OL></DIV><BR>jsp页面代码如下：<BR>
<DIV class=codeStyle>
<OL>
<LI>&lt;%@&nbsp;include&nbsp;file=<FONT color=#ff33ff>"/WEB-INF/jsp/include.jsp"</FONT>&nbsp;%&gt; 
<LI>&lt;%@&nbsp;taglib&nbsp;prefix=<FONT color=#ff33ff>"spring"</FONT>&nbsp;uri=<FONT color=#ff33ff>"/spring"</FONT>&nbsp;%&gt; 
<LI>
<LI>&lt;html&gt; 
<LI>&lt;head&gt;&lt;title&gt;&lt;fmt:message&nbsp;key=<FONT color=#ff33ff>"title"</FONT>/&gt;&lt;/title&gt;&lt;/head&gt; 
<LI>&lt;body&gt; 
<LI>&lt;h1&gt;&lt;fmt:message&nbsp;key=<FONT color=#ff33ff>"priceincrease.heading"</FONT>/&gt;&lt;/h1&gt; 
<LI>&lt;form&nbsp;method=<FONT color=#ff33ff>"post"</FONT>&gt; 
<LI>&nbsp;&nbsp;&lt;table&nbsp;width=<FONT color=#ff33ff>"95%"</FONT>&nbsp;bgcolor=<FONT color=#ff33ff>"f8f8ff"</FONT>&nbsp;border=<FONT color=#ff33ff>"0"</FONT>&nbsp;cellspacing=<FONT color=#ff33ff>"0"</FONT>&nbsp;cellpadding=<FONT color=#ff33ff>"5"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;alignment=<FONT color=#ff33ff>"right"</FONT>&nbsp;width=<FONT color=#ff33ff>"20%"</FONT>&gt;Increase&nbsp;(%):&lt;/td&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;spring:bind&nbsp;path=<FONT color=#ff33ff>"priceIncrease.percentage"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;width=<FONT color=#ff33ff>"20%"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type=<FONT color=#ff33ff>"text"</FONT>&nbsp;name=<FONT color=#ff33ff>"percentage"</FONT>&nbsp;value=<FONT color=#ff33ff>"&lt;c:out&nbsp;value="</FONT>${status.value}<FONT color=#ff33ff>"/&gt;"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;width=<FONT color=#ff33ff>"60%"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;font&nbsp;color=<FONT color=#ff33ff>"red"</FONT>&gt;&lt;c:out&nbsp;value=<FONT color=#ff33ff>"${status.errorMessage}"</FONT>/&gt;&lt;/font&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/spring:bind&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt; 
<LI>&nbsp;&nbsp;&lt;/table&gt; 
<LI>&nbsp;&nbsp;&lt;br&gt; 
<LI>&nbsp;&nbsp;&lt;spring:hasBindErrors&nbsp;name=<FONT color=#ff33ff>"priceIncrease"</FONT>&gt; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&lt;b&gt;Please&nbsp;fix&nbsp;all&nbsp;errors!&lt;/b&gt; 
<LI>&nbsp;&nbsp;&lt;/spring:hasBindErrors&gt; 
<LI>&nbsp;&nbsp;&lt;br&gt;&lt;br&gt; 
<LI>&nbsp;&nbsp;&lt;input&nbsp;type=<FONT color=#ff33ff>"submit"</FONT>&nbsp;alignment=<FONT color=#ff33ff>"center"</FONT>&nbsp;value=<FONT color=#ff33ff>"Execute"</FONT>&gt; 
<LI>&lt;/form&gt; 
<LI>&lt;a&nbsp;href=<FONT color=#ff33ff>"&lt;c:url&nbsp;value="</FONT>hello.htm<FONT color=#ff33ff>"/&gt;"</FONT>&gt;Home&lt;/a&gt; 
<LI>&lt;/body&gt; 
<LI>&lt;/html&gt; </LI></OL></DIV><BR>&lt;spring:bind&gt;标记经常用来绑定&lt;input&gt;表单元素以便提交给PriceIncrease.java,其实PriceIncrease.java中就是包含一些getter和setter的方法的类。当用户按下按钮提交的时候，其表单中的值实际上就被framework放到了PriceIncrease.java中。&lt;spring:bind&gt;经常和form一起使用.这个${status.errorMessage}和${status.value}是一个framework定义的特殊变量，它们被用来显示错误信息和当前表单中的数据。呵呵，今天就到此为止吧，关于Spring&nbsp;Framework标记库的详细用法，请参考其文档。<BR>参考资料：<BR>http://www.springframework.org/<BR>Spring&nbsp;Framework英文文档<BR>Spring&nbsp;Framework中文论坛 <BR><img src ="http://www.blogjava.net/limq/aggbug/1900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-03-10 14:08 <a href="http://www.blogjava.net/limq/archive/2005/03/10/1900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java反射机制( 转)</title><link>http://www.blogjava.net/limq/archive/2005/03/09/1865.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Tue, 08 Mar 2005 17:36:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/03/09/1865.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/1865.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/03/09/1865.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/1865.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/1865.html</trackback:ping><description><![CDATA[<SPAN id=post1 style="FONT-SIZE: 12px; COLOR: #000000">Java反射机制<BR><BR>摘要<BR>Reflection 是Java被视为动态（或准动态）语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息，包括其modifiers（诸如public, static 等等）、superclass（例如Object）、实现之interfaces（例如Cloneable），也包括fields和methods的所有信息，并可于运行时改变fields内容或唤起methods。本文借由实例，大面积示范Reflection APIs。<BR><BR>关于本文：<BR>读者基础：具备Java 语言基础。<BR>本文适用工具：JDK1.5<BR><BR>关键词：<BR>Introspection（内省、内观）<BR>Reflection（反射）<BR><BR><BR>有时候我们说某个语言具有很强的动态性，有时候我们会区分动态和静态的不同技术与作法。我们朗朗上口动态绑定（dynamic binding）、动态链接（dynamic linking）、动态加载（dynamic loading）等。然而“动态”一词其实没有绝对而普遍适用的严格定义，有时候甚至像对象导向当初被导入编程领域一样，一人一把号，各吹各的调。<BR><BR>一般而言，开发者社群说到动态语言，大致认同的一个定义是：“程序运行时，允许改变程序结构或变量类型，这种语言称为动态语言”。从这个观点看，Perl，Python，Ruby是动态语言，C++，Java，C#不是动态语言。<BR><BR>尽管在这样的定义与分类下Java不是动态语言，它却有着一个非常突出的动态相关机制：Reflection。这个字的意思是“反射、映象、倒影”，用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说，Java程序可以加载一个运行时才得知名称的class，获悉其完整构造（但不包括methods定义），并生成其对象实体、或对其fields设值、或唤起其methods1。这种“看透class”的能力（the ability of the program to examine itself）被称为introspection（内省、内观、反省）。Reflection和introspection是常被并提的两个术语。<BR><BR>Java如何能够做出上述的动态特性呢？这是一个深远话题，本文对此只简单介绍一些概念。整个篇幅最主要还是介绍Reflection APIs，也就是让读者知道如何探索class的结构、如何对某个“运行时才获知名称的class”生成一份实体、为其fields设值、调用其methods。本文将谈到java.lang.Class，以及java.lang.reflect中的Method、Field、Constructor等等classes。<BR><BR>“Class”class<BR>众所周知Java有个Object class，是所有Java classes的继承根源，其内声明了数个应该在所有Java class中被改写的methods：hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class object。<BR><BR>Class class十分特殊。它和一般classes一样继承自Object，其实体用以表达Java程序运行时的classes和interfaces，也用来表达enum、array、primitive Java types（boolean, byte, char, short, int, long, float, double）以及关键词void。当一个class被加载，或当加载器（class loader）的defineClass()被JVM调用，JVM 便自动产生一个Class object。如果您想借由“修改Java标准库源码”来观察Class object的实际生成时机（例如在Class的constructor内添加一个println()），不能够！因为Class并没有public constructor（见图1）。本文最后我会拨一小块篇幅顺带谈谈Java标准库源码的改动办法。<BR><BR>Class是Reflection故事起源。针对任何您想探勘的class，唯有先为它产生一个Class object，接下来才能经由后者唤起为数十多个的Reflection APIs。这些APIs将在稍后的探险活动中一一亮相。<BR><BR>#001 public final<BR>#002 class Class&lt;T&gt; implements java.io.Serializable,<BR>#003 java.lang.reflect.GenericDeclaration,<BR>#004 java.lang.reflect.Type,<BR>#005 java.lang.reflect.AnnotatedElement {<BR>#006 private Class() {}<BR>#007 public String toString() {<BR>#008 return ( isInterface() ? "interface " :<BR>#009 (isPrimitive() ? "" : "class "))<BR>#010 + getName();<BR>#011 }<BR>...<BR>图1：Class class片段。注意它的private empty ctor，意指不允许任何人经由编程方式产生Class object。是的，其object 只能由JVM 产生。<BR><BR>“Class” object的取得途径<BR>Java允许我们从多种管道为一个class生成对应的Class object。图2是一份整理。<BR>Class object 诞生管道示例<BR>运用getClass()<BR>注：每个class 都有此函数String str = "abc";<BR>Class c1 = str.getClass();<BR>运用<BR>Class.getSuperclass()2Button b = new Button();<BR>Class c1 = b.getClass();<BR>Class c2 = c1.getSuperclass();<BR>运用static method<BR>Class.forName()<BR>（最常被使用）Class c1 = Class.forName ("java.lang.String");<BR>Class c2 = Class.forName ("java.awt.Button");<BR>Class c3 = Class.forName ("java.util.LinkedList$Entry");<BR>Class c4 = Class.forName ("I");<BR>Class c5 = Class.forName ("[I");<BR>运用<BR>.class 语法Class c1 = String.class;<BR>Class c2 = java.awt.Button.class;<BR>Class c3 = Main.InnerClass.class;<BR>Class c4 = int.class;<BR>Class c5 = int[].class;<BR>运用<BR>primitive wrapper classes<BR>的TYPE 语法<BR>Class c1 = Boolean.TYPE;<BR>Class c2 = Byte.TYPE;<BR>Class c3 = Character.TYPE;<BR>Class c4 = Short.TYPE;<BR>Class c5 = Integer.TYPE;<BR>Class c6 = Long.TYPE;<BR>Class c7 = Float.TYPE;<BR>Class c8 = Double.TYPE;<BR>Class c9 = Void.TYPE;<BR>图2：Java 允许多种管道生成Class object。<BR><BR>Java classes 组成分析<BR>首先容我以图3的java.util.LinkedList为例，将Java class的定义大卸八块，每一块分别对应图4所示的Reflection API。图5则是“获得class各区块信息”的程序示例及执行结果，它们都取自本文示例程序的对应片段。<BR><BR>package java.util; //(1)<BR>import java.lang.*; //(2)<BR>public class LinkedList&lt;E&gt; //(3)(4)(5)<BR>extends AbstractSequentialList&lt;E&gt; //(6)<BR>implements List&lt;E&gt;, Queue&lt;E&gt;,<BR>Cloneable, java.io.Serializable //(7)<BR>{<BR>private static class Entry&lt;E&gt; { … }//(8)<BR>public LinkedList() { … } //(9)<BR>public LinkedList(Collection&lt;? extends E&gt; c) { … }<BR>public E getFirst() { … } //(10)<BR>public E getLast() { … }<BR>private transient Entry&lt;E&gt; header = …;//(11)<BR>private transient int size = 0;<BR>}<BR>图3：将一个Java class 大卸八块，每块相应于一个或一组Reflection APIs（图4）。<BR><BR>Java classes 各成份所对应的Reflection APIs<BR>图3的各个Java class成份，分别对应于图4的Reflection API，其中出现的Package、Method、Constructor、Field等等classes，都定义于java.lang.reflect。<BR>Java class 内部模块（参见图3）Java class 内部模块说明相应之Reflection API，多半为Class methods。返回值类型(return type)<BR>(1) packageclass隶属哪个packagegetPackage()Package<BR>(2) importclass导入哪些classes无直接对应之API。<BR>解决办法见图5-2。<BR>(3) modifierclass（或methods, fields）的属性<BR>int getModifiers()<BR>Modifier.toString(int)<BR>Modifier.isInterface(int)int<BR>String<BR>bool<BR>(4) class name or interface nameclass/interface名称getName()String<BR>(5) type parameters参数化类型的名称getTypeParameters() TypeVariable &lt;Class&gt;[]<BR>(6) base classbase class（只可能一个）getSuperClass()Class<BR>(7) implemented interfaces实现有哪些interfacesgetInterfaces()Class[]<BR><BR>(8) inner classes内部classesgetDeclaredClasses()Class[]<BR>(8') outer class如果我们观察的class 本身是inner classes，那么相对它就会有个outer class。getDeclaringClass()Class<BR>(9) constructors构造函数getDeclaredConstructors()不论 public 或private 或其它access level，皆可获得。另有功能近似之取得函数。Constructor[]<BR>(10) methods操作函数getDeclaredMethods()不论 public 或private 或其它access level，皆可获得。另有功能近似之取得函数。Method[]<BR>(11) fields字段（成员变量）getDeclaredFields()不论 public 或private 或其它access level，皆可获得。另有功能近似之取得函数。Field[]<BR>图4：Java class大卸八块后（如图3），每一块所对应的Reflection API。本表并非<BR>Reflection APIs 的全部。<BR><BR>Java Reflection API 运用示例<BR>图5示范图4提过的每一个Reflection API，及其执行结果。程序中出现的tName()是个辅助函数，可将其第一自变量所代表的“Java class完整路径字符串”剥除路径部分，留下class名称，储存到第二自变量所代表的一个hashtable去并返回（如果第二自变量为null，就不储存而只是返回）。<BR><BR>#001 Class c = null;<BR>#002 c = Class.forName(args[0]);<BR>#003<BR>#004 Package p;<BR>#005 p = c.getPackage();<BR>#006<BR>#007 if (p != null)<BR>#008 System.out.println("package "+p.getName()+";");<BR><BR>执行结果（例）：<BR>package java.util;<BR>图5-1：找出class 隶属的package。其中的c将继续沿用于以下各程序片段。<BR><BR>#001 ff = c.getDeclaredFields();<BR>#002 for (int i = 0; i &lt; ff.length; i++)<BR>#003 x = tName(ff[i].getType().getName(), classRef);<BR>#004<BR>#005 cn = c.getDeclaredConstructors();<BR>#006 for (int i = 0; i &lt; cn.length; i++) {<BR>#007 Class cx[] = cn[i].getParameterTypes();<BR>#008 for (int j = 0; j &lt; cx.length; j++)<BR>#009 x = tName(cx[j].getName(), classRef);<BR>#010 }<BR>#011<BR>#012 mm = c.getDeclaredMethods();<BR>#013 for (int i = 0; i &lt; mm.length; i++) {<BR>#014 x = tName(mm[i].getReturnType().getName(), classRef);<BR>#015 Class cx[] = mm[i].getParameterTypes();<BR>#016 for (int j = 0; j &lt; cx.length; j++)<BR>#017 x = tName(cx[j].getName(), classRef);<BR>#018 }<BR>#019 classRef.remove(c.getName()); //不必记录自己（不需import 自己）<BR><BR>执行结果（例）：<BR>import java.util.ListIterator;<BR>import java.lang.Object;<BR>import java.util.LinkedList$Entry;<BR>import java.util.Collection;<BR>import java.io.ObjectOutputStream;<BR>import java.io.ObjectInputStream;<BR>图5-2：找出导入的classes，动作细节详见内文说明。<BR><BR>#001 int mod = c.getModifiers();<BR>#002 System.out.print(Modifier.toString(mod)); //整个modifier<BR>#003<BR>#004 if (Modifier.isInterface(mod))<BR>#005 System.out.print(" "); //关键词 "interface" 已含于modifier<BR>#006 else<BR>#007 System.out.print(" class "); //关键词 "class"<BR>#008 System.out.print(tName(c.getName(), null)); //class 名称<BR><BR>执行结果（例）：<BR>public class LinkedList<BR>图5-3：找出class或interface 的名称，及其属性（modifiers）。<BR><BR>#001 TypeVariable&lt;Class&gt;[] tv;<BR>#002 tv = c.getTypeParameters(); //warning: unchecked conversion<BR>#003 for (int i = 0; i &lt; tv.length; i++) {<BR>#004 x = tName(tv[i].getName(), null); //例如 E,K,V...<BR>#005 if (i == 0) //第一个<BR>#006 System.out.print("&lt;" + x);<BR>#007 else //非第一个<BR>#008 System.out.print("," + x);<BR>#009 if (i == tv.length-1) //最后一个<BR>#010 System.out.println("&gt;");<BR>#011 }<BR><BR>执行结果（例）：<BR>public abstract interface Map&lt;K,V&gt;<BR>或 public class LinkedList&lt;E&gt;<BR>图5-4：找出parameterized types 的名称<BR><BR>#001 Class supClass;<BR>#002 supClass = c.getSuperclass();<BR>#003 if (supClass != null) //如果有super class<BR>#004 System.out.print(" extends" +<BR>#005 tName(supClass.getName(),classRef));<BR><BR>执行结果（例）：<BR>public class LinkedList&lt;E&gt;<BR>extends AbstractSequentialList,<BR>图5-5：找出base class。执行结果多出一个不该有的逗号于尾端。此非本处重点，为简化计，不多做处理。<BR><BR>#001 Class cc[];<BR>#002 Class ctmp;<BR>#003 //找出所有被实现的interfaces<BR>#004 cc = c.getInterfaces();<BR>#005 if (cc.length != 0)<BR>#006 System.out.print(", \r\n" + " implements "); //关键词<BR>#007 for (Class cite : cc) //JDK1.5 新式循环写法<BR>#008 System.out.print(tName(cite.getName(), null)+", ");<BR><BR>执行结果（例）：<BR>public class LinkedList&lt;E&gt;<BR>extends AbstractSequentialList,<BR>implements List, Queue, Cloneable, Serializable,<BR>图5-6：找出implemented interfaces。执行结果多出一个不该有的逗号于尾端。此非本处重点，为简化计，不多做处理。<BR><BR>#001 cc = c.getDeclaredClasses(); //找出inner classes<BR>#002 for (Class cite : cc)<BR>#003 System.out.println(tName(cite.getName(), null));<BR>#004<BR>#005 ctmp = c.getDeclaringClass(); //找出outer classes<BR>#006 if (ctmp != null)<BR>#007 System.out.println(ctmp.getName());<BR><BR>执行结果（例）：<BR>LinkedList$Entry<BR>LinkedList$ListItr<BR>图5-7：找出inner classes 和outer class<BR><BR>#001 Constructor cn[];<BR>#002 cn = c.getDeclaredConstructors();<BR>#003 for (int i = 0; i &lt; cn.length; i++) {<BR>#004 int md = cn[i].getModifiers();<BR>#005 System.out.print(" " + Modifier.toString(md) + " " +<BR>#006 cn[i].getName());<BR>#007 Class cx[] = cn[i].getParameterTypes();<BR>#008 System.out.print("(");<BR>#009 for (int j = 0; j &lt; cx.length; j++) {<BR>#010 System.out.print(tName(cx[j].getName(), null));<BR>#011 if (j &lt; (cx.length - 1)) System.out.print(", ");<BR>#012 }<BR>#013 System.out.print(")");<BR>#014 }<BR><BR>执行结果（例）：<BR>public java.util.LinkedList(Collection)<BR>public java.util.LinkedList()<BR>图5-8a：找出所有constructors<BR><BR>#004 System.out.println(cn[i].toGenericString());<BR><BR>执行结果（例）：<BR>public java.util.LinkedList(java.util.Collection&lt;? extends E&gt;)<BR>public java.util.LinkedList()<BR>图5-8b：找出所有constructors。本例在for 循环内使用toGenericString()，省事。<BR><BR>#001 Method mm[];<BR>#002 mm = c.getDeclaredMethods();<BR>#003 for (int i = 0; i &lt; mm.length; i++) {<BR>#004 int md = mm[i].getModifiers();<BR>#005 System.out.print(" "+Modifier.toString(md)+" "+<BR>#006 tName(mm[i].getReturnType().getName(), null)+" "+<BR>#007 mm[i].getName());<BR>#008 Class cx[] = mm[i].getParameterTypes();<BR>#009 System.out.print("(");<BR>#010 for (int j = 0; j &lt; cx.length; j++) {<BR>#011 System.out.print(tName(cx[j].getName(), null));<BR>#012 if (j &lt; (cx.length - 1)) System.out.print(", ");<BR>#013 }<BR>#014 System.out.print(")");<BR>#015 }<BR><BR>执行结果（例）：<BR>public Object get(int)<BR>public int size()<BR>图5-9a：找出所有methods<BR><BR>#004 System.out.println(mm[i].toGenericString());<BR><BR>public E java.util.LinkedList.get(int)<BR>public int java.util.LinkedList.size()<BR>图5-9b：找出所有methods。本例在for 循环内使用toGenericString()，省事。<BR><BR>#001 Field ff[];<BR>#002 ff = c.getDeclaredFields();<BR>#003 for (int i = 0; i &lt; ff.length; i++) {<BR>#004 int md = ff[i].getModifiers();<BR>#005 System.out.println(" "+Modifier.toString(md)+" "+<BR>#006 tName(ff[i].getType().getName(), null) +" "+<BR>#007 ff[i].getName()+";");<BR>#008 }<BR><BR>执行结果（例）：<BR>private transient LinkedList$Entry header;<BR>private transient int size;<BR>图5-10a：找出所有fields<BR><BR>#004 System.out.println("G: " + ff[i].toGenericString());<BR><BR>private transient java.util.LinkedList.java.util.LinkedList$Entry&lt;E&gt; ??<BR>java.util.LinkedList.header<BR>private transient int java.util.LinkedList.size<BR>图5-10b：找出所有fields。本例在for 循环内使用toGenericString()，省事。<BR><BR>找出class参用（导入）的所有classes<BR>没有直接可用的Reflection API可以为我们找出某个class参用的所有其它classes。要获得这项信息，必须做苦工，一步一脚印逐一记录。我们必须观察所有fields的类型、所有methods（包括constructors）的参数类型和回返类型，剔除重复，留下唯一。这正是为什么图5-2程序代码要为tName()指定一个hashtable（而非一个null）做为第二自变量的缘故：hashtable可为我们储存元素（本例为字符串），又保证不重复。<BR><BR>本文讨论至此，几乎可以还原一个class的原貌（唯有methods 和ctors的定义无法取得）。接下来讨论Reflection 的另三个动态性质：(1) 运行时生成instances，(2) 执<BR>行期唤起methods，(3) 运行时改动fields。<BR><BR>运行时生成instances<BR>欲生成对象实体，在Reflection 动态机制中有两种作法，一个针对“无自变量ctor”，<BR>一个针对“带参数ctor”。图6是面对“无自变量ctor”的例子。如果欲调用的是“带参数ctor“就比较麻烦些，图7是个例子，其中不再调用Class的newInstance()，而是调用Constructor 的newInstance()。图7首先准备一个Class[]做为ctor的参数类型（本例指定为一个double和一个int），然后以此为自变量调用getConstructor()，获得一个专属ctor。接下来再准备一个Object[] 做为ctor实参值（本例指定3.14159和125），调用上述专属ctor的newInstance()。<BR><BR>#001 Class c = Class.forName("DynTest");<BR>#002 Object obj = null;<BR>#003 obj = c.newInstance(); //不带自变量<BR>#004 System.out.println(obj);<BR>图6：动态生成“Class object 所对应之class”的对象实体；无自变量。<BR><BR>#001 Class c = Class.forName("DynTest");<BR>#002 Class[] pTypes = new Class[] { double.class, int.class };<BR>#003 Constructor ctor = c.getConstructor(pTypes);<BR>#004 //指定parameter list，便可获得特定之ctor<BR>#005<BR>#006 Object obj = null;<BR>#007 Object[] arg = new Object[] {3.14159, 125}; //自变量<BR>#008 obj = ctor.newInstance(arg);<BR>#009 System.out.println(obj);<BR>图7：动态生成“Class object 对应之class”的对象实体；自变量以Object[]表示。<BR><BR>运行时调用methods<BR>这个动作和上述调用“带参数之ctor”相当类似。首先准备一个Class[]做为ctor的参数类型（本例指定其中一个是String，另一个是Hashtable），然后以此为自变量调用getMethod()，获得特定的Method object。接下来准备一个Object[]放置自变量，然后调用上述所得之特定Method object的invoke()，如图8。知道为什么索取Method object时不需指定回返类型吗？因为method overloading机制要求signature（署名式）必须唯一，而回返类型并非signature的一个成份。换句话说，只要指定了method名称和参数列，就一定指出了一个独一无二的method。<BR><BR>#001 public String func(String s, Hashtable ht)<BR>#002 {<BR>#003 …System.out.println("func invoked"); return s;<BR>#004 }<BR>#005 public static void main(String args[])<BR>#006 {<BR>#007 Class c = Class.forName("Test");<BR>#008 Class ptypes[] = new Class[2];<BR>#009 ptypes[0] = Class.forName("java.lang.String");<BR>#010 ptypes[1] = Class.forName("java.util.Hashtable");<BR>#011 Method m = c.getMethod("func",ptypes);<BR>#012 Test obj = new Test();<BR>#013 Object args[] = new Object[2];<BR>#014 arg[0] = new String("Hello,world");<BR>#015 arg[1] = null;<BR>#016 Object r = m.invoke(obj, arg);<BR>#017 Integer rval = (String)r;<BR>#018 System.out.println(rval);<BR>#019 }<BR>图8：动态唤起method<BR><BR>运行时变更fields内容<BR>与先前两个动作相比，“变更field内容”轻松多了，因为它不需要参数和自变量。首先调用Class的getField()并指定field名称。获得特定的Field object之后便可直接调用Field的get()和set()，如图9。<BR><BR>#001 public class Test {<BR>#002 public double d;<BR>#003<BR>#004 public static void main(String args[])<BR>#005 {<BR>#006 Class c = Class.forName("Test");<BR>#007 Field f = c.getField("d"); //指定field 名称<BR>#008 Test obj = new Test();<BR>#009 System.out.println("d= " + (Double)f.get(obj));<BR>#010 f.set(obj, 12.34);<BR>#011 System.out.println("d= " + obj.d);<BR>#012 }<BR>#013 }<BR>图9：动态变更field 内容<BR><BR>Java 源码改动办法<BR>先前我曾提到，原本想借由“改动Java标准库源码”来测知Class object的生成，但由于其ctor原始设计为private，也就是说不可能透过这个管道生成Class object（而是由class loader负责生成），因此“在ctor中打印出某种信息”的企图也就失去了意义。<BR><BR>这里我要谈点题外话：如何修改Java标准库源码并让它反应到我们的应用程序来。假设我想修改java.lang.Class，让它在某些情况下打印某种信息。首先必须找出标准源码！当你下载JDK 套件并安装妥当，你会发现jdk150\src\java\lang 目录（见图10）之中有Class.java，这就是我们此次行动的标准源码。备份后加以修改，编译获得Class.class。接下来准备将.class 搬移到jdk150\jre\lib\endorsed（见图10）。<BR><BR>这是一个十分特别的目录，class loader将优先从该处读取内含classes的.jar文件——成功的条件是.jar内的classes压缩路径必须和Java标准库的路径完全相同。为此，我们可以将刚才做出的Class.class先搬到一个为此目的而刻意做出来的\java\lang目录中，压缩为foo.zip（任意命名，唯需夹带路径java\lang），再将这个foo.zip搬到jdk150\jre\lib\endorsed并改名为foo.jar。此后你的应用程序便会优先用上这里的java.lang.Class。整个过程可写成一个批处理文件（batch file），如图11，在DOS Box中使用。<BR><BR><BR>图10：JDK1.5 安装后的目录组织。其中的endorsed 是我新建。<BR><BR>del e:\java\lang\*.class //清理干净<BR>del c:\jdk150\jre\lib\endorsed\foo.jar //清理干净<BR>c:<BR>cd c:\jdk150\src\java\lang<BR>javac -Xlint:unchecked Class.java //编译源码<BR>javac -Xlint:unchecked ClassLoader.java //编译另一个源码（如有必要）<BR>move *.class e:\java\lang //搬移至刻意制造的目录中<BR>e:<BR>cd e:\java\lang //以下压缩至适当目录<BR>pkzipc -add -path=root c:\jdk150\jre\lib\endorsed\foo.jar *.class<BR>cd e:\test //进入测试目录<BR>javac -Xlint:unchecked Test.java //编译测试程序<BR>java Test //执行测试程序<BR>图11：一个可在DOS Box中使用的批处理文件（batch file），用以自动化java.lang.Class<BR>的修改动作。Pkzipc(.exe)是个命令列压缩工具，add和path都是其命令。<BR><BR>更多信息<BR>以下是视野所及与本文主题相关的更多讨论。这些信息可以弥补因文章篇幅限制而带来的不足，或带给您更多视野。<BR><BR> &nbsp; &nbsp; &nbsp; &nbsp; "Take an in-depth look at the Java Reflection API -- Learn about the new Java 1.1 tools forfinding out information about classes", by Chuck McManis。此篇文章所附程序代码是本文示例程序的主要依据（本文示例程序示范了更多Reflection APIs，并采用JDK1.5 新式的for-loop 写法）。<BR> &nbsp; &nbsp; &nbsp; &nbsp; "Take a look inside Java classes -- Learn to deduce properties of a Java class from inside aJava program", by Chuck McManis。<BR> &nbsp; &nbsp; &nbsp; &nbsp; "The basics of Java class loaders -- The fundamentals of this key component of the Javaarchitecture", by Chuck McManis。<BR> &nbsp; &nbsp; &nbsp; &nbsp; 《The Java Tutorial Continued》, Sun microsystems. Lesson58-61, "Reflection".<BR><BR>注1用过诸如MFC这类所谓 Application Framework的程序员也许知道，MFC有所谓的dynamic creation。但它并不等同于Java的动态加载或动态辨识；所有能够在MFC程序中起作用的classes，都必须先在编译期被编译器“看见”。<BR><BR>注2如果操作对象是Object，Class.getSuperClass()会返回null。<BR><BR></SPAN><img src ="http://www.blogjava.net/limq/aggbug/1865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-03-09 01:36 <a href="http://www.blogjava.net/limq/archive/2005/03/09/1865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自定义标签 </title><link>http://www.blogjava.net/limq/archive/2005/03/03/1669.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Thu, 03 Mar 2005 15:55:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/03/03/1669.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/1669.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/03/03/1669.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/1669.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/1669.html</trackback:ping><description><![CDATA[转贴一篇文章,义务作一下普及工作吧.<BR><BR>1.&nbsp; 什么是自定义标签 <BR>答：1) 用户自定义的Java语言元素, 实质是运行一个或者两个接口的JavaBean; <BR>&nbsp;&nbsp; 2) 可以非常机密地和JSP的表示逻辑联系在一起，又具有和普通JavaBean相同的业务逻辑处理能力; <BR>&nbsp;&nbsp; 2) 当一个JSP页面转变为servlet时，其间的用户自定义标签转化为操作一个称为标签hander的对象; <BR>&nbsp;&nbsp; 3) 可操作默认对象，处理表单数据，访问数据库以及其它企业服务;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR><BR>2.&nbsp; 自定义标签库的特点 <BR>答：1) 通过调用页面传递参数实现定制; <BR>&nbsp;&nbsp; 2) 访问所有对JSP页面可能的对象; <BR>&nbsp;&nbsp; 3) 修改调用页面生成的响应; <BR>&nbsp;&nbsp; 4) 自定义标签间可相互通信; <BR>&nbsp;&nbsp; 5) 在同一个JSP页面中通过标签嵌套，可实现复杂交互。 <BR><BR>3.&nbsp; 如何使用自定义标签库 <BR>答：1) 声明标签库 <BR>&nbsp;&nbsp; 2) 使标签库执行对Web应用程序可用 <BR><BR>4.&nbsp; 声明标签库 <BR>答：1) 使用taglib指令声明标签库 <BR>&nbsp;&nbsp; 2) 语法：&lt;%@taglib uri="URI" prefix="pre" %&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意：a. uri属性可以是绝对的，也可以是相对URL，该URL指向标记库描述符(TLD)文件; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b. uri属性也可以是一个并不存在的URL，该URL为web.xml文件中将标记库描述符(TLD)文件的绝对URL到本地系统的一个映射; <BR>&nbsp;&nbsp; 3) 范例：&lt;%@taglib uri="/WEB-INF/template.tld" prefix="test" %&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;%@taglib uri="http://java.sun.com/jstl/core" prefix="core" %&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR><BR>5.&nbsp; 使标签库执行可用 <BR>答：方式一：在WEB-INF/classes目录下部署标记处理程序类; <BR>&nbsp;&nbsp; 方式二：将标记处理程序类打包成jar文件并置于WEB-INF/lib目录。 <BR><BR>6.&nbsp; 几种典型的标签(疑问：可以有带主体而没有属性的标签么？) <BR>答：1) 不带属性和主体的简单标签：&lt;mytaglibs:SomeTag/&gt;; <BR>&nbsp;&nbsp; 2) 不带主体但有属性的标签：&lt;mytaglibs:SomeTag user="TonyDeng"/&gt;; <BR>&nbsp;&nbsp; 3) 带有主体和属性的标签：&lt;mytaglibs:SomeTag user="TonyDeng"&gt; <BR>&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; ...// 标签体 <BR>&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; &lt;/mytaglibs:SomeTag&gt;; <BR>&nbsp;&nbsp; 注意：a. 属性列于start tag中，它是在标记库描述符(TLD)文件中指定，服务于标记库的自定义行为; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b. 标签体位于start tag和end tag间，可以是任何合法的JSP内容或者标签; <BR><BR>7.&nbsp; 定义标签 <BR>答：1) 开发实现tag的类(tag handler); <BR>&nbsp;&nbsp; 2) 编辑标记库描述符(TLD)文件; <BR>&nbsp;&nbsp; 3) 在web.xml中为标记库描述符(TLD)文件的绝对URL建立一个映射(该步骤可选); <BR><BR>8.&nbsp; 标记库描述符(TLD)文件 <BR>答：1) 一个描述标记库的XML文件; <BR>&nbsp;&nbsp; 2) 内容开始是整个库的描述，然后是tag的描述; <BR>&nbsp;&nbsp; 3) 标记库描述符(TLD)文件用于Web Container确认tag以及JSP页面发展工具; <BR><BR>9.&nbsp; 实现tag的类(tag handler) <BR>答：1) 是一些在引用了标签的JSP页面执行期间被Web Container调用以求自定义标签值的对象; <BR>&nbsp;&nbsp; 2) 必须实现Tag, SimpleTag和BodyTag之一; <BR>&nbsp;&nbsp; 3) 可以继承TagSupport和BodyTagSupport之一。 <BR><BR>10. 标签库的接口和类的继承关系 <BR>答：表现形式一： <BR>&nbsp;&nbsp; a. 接口的继承关系： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ☉ interface javax.servlet.jsp.tagext.JspTag <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ☉ interface javax.servlet.jsp.tagext.SimpleTag <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ☉ interface javax.servlet.jsp.tagext.Tag <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ☉ interface javax.servlet.jsp.tagext.IterationTag <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ☉ interface javax.servlet.jsp.tagext.BodyTag <BR>&nbsp;&nbsp; b. 类的继承关系： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ☉ class javax.servlet.jsp.tagext.TagSupport (implements javax.servlet.jsp.tagext.IterationTag, java.io.Serializable) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ☉ class javax.servlet.jsp.tagext.BodyTagSupport (implements javax.servlet.jsp.tagext.BodyTag) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ☉ class javax.servlet.jsp.tagext.SimpleTagSupport (implements javax.servlet.jsp.tagext.SimpleTag) <BR>&nbsp;&nbsp; 表现形式二： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Interface) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JspTag <BR>&nbsp;&nbsp;&nbsp;&nbsp;&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; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Interface)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Interface) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Tag&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SimpleTag ←－－SimpleTagSupport <BR>&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; <BR>&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; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Interface)&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IterationTag←－－TagSupport <BR>&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; ↑ <BR>&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; | <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Interface)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BodyTag&nbsp;&nbsp; ←－－BodyTagSupport <BR><BR>2004-10-9&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; <BR><BR><BR><BR>11. 一个Tag处理程序类必须实现的方法 <BR>答：标签处理程序类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 方法 <BR>&nbsp;&nbsp; Simple&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doStartTag, doEndTag, release <BR>&nbsp;&nbsp; Attributes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doStartTag, doEndTag, set/getAttribute...release <BR>&nbsp;&nbsp; Body,No Itrative and&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doStartTag, doEndTag, release <BR>&nbsp;&nbsp; Evaluation&nbsp;&nbsp; <BR>&nbsp;&nbsp; Body, Itrative Evaluation&nbsp;&nbsp; doStartTag, doAterTag, doEndTag, release <BR>&nbsp;&nbsp; Body, Interaction&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doStartTag, doEndTag, release, doInitbody, doAfterBody <BR><BR>12. 简单的标签处理程序类 <BR>答：1) 必须实现Tag接口的doStartTag()和doEndTag()方法; <BR>&nbsp;&nbsp; 2) 因为不存在Body，doStartTag()方法必须返回SKIP_BODY; <BR>&nbsp;&nbsp; 3) 如其余页面要执行，doEndTag()方法返回EVAL_PAGE, 否则返回SKIP_PAGE; <BR>&nbsp;&nbsp; 4) 对于每一个标签属性，你必须在标签处理程序类里定义一个特性以及get和set方法以一致于JavaBeans体系惯例 <BR><BR>13. 带Body的自定义标签 <BR>答：1) 必须实现Tag接口的doStartTag()和doEndTag()方法; <BR>&nbsp;&nbsp; 2) 可以实现IterationTag接口的doAfterBody()方法; <BR>&nbsp;&nbsp; 3) 可以实现BodyTag接口的doInitBody和setBodyContent方法; <BR>&nbsp;&nbsp; 4) doStartTag方法可以返回SKIP_BODY、EVAL_BODY_INCLUDE、或者EVAL_BODY_BUFFERED(当你想使用BodyContent); <BR>&nbsp;&nbsp; 5) doEndTag方法可以返回SKIP_PAGE或EVAL_PAGE; <BR>&nbsp;&nbsp; 6) doAfterBody方法可以返回EVAL_BODY_AGAIN, SKIP_BODY; <BR><BR>14. 定义脚本变量的标签(迭代的标签库) <BR>答：1) 定义脚本标签的二个步骤: <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a. 在标记库描述符(TLD)文件中列明脚本变量; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b. 定义标签扩展信息类(TEI)并且在TLD文件中包括这个类元素(tei-class); <BR>&nbsp;&nbsp; 2) 变量必须在标签处理程序类中使用pageContext.setAttribute()方法设置; <BR>&nbsp;&nbsp; 3) 标签扩展信息类(TEI)必须继承TagExtraInfo以及覆盖getVariableInfo()方法; <BR>&nbsp;&nbsp; 4) 变量的范围可以是AT_BEGIN, NESTED, AT_END(标签扩展信息类(TEI)的VariableInfo中定义)之一; <BR><BR>15. 脚本变量的有效性 <BR>答：变量&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; <BR>&nbsp;&nbsp; --------------------------------------- <BR>&nbsp;&nbsp; NESTED&nbsp;&nbsp; | 标签中的参数在starttag到endtag之间是有效的 <BR>&nbsp;&nbsp; AT_BEGIN | 标签中的参数在标签的开始到JSP页面结束是有效的 <BR>&nbsp;&nbsp; AT_END&nbsp;&nbsp; | 标签中的参数在标签的结束到JSP页面结束是有效的 <BR><BR>2004-10-10&nbsp;&nbsp;&nbsp;&nbsp; 星期四&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 晴 <BR><BR>16.&nbsp; Tag接口的方法 <BR>答：interface javax.servlet.jsp.tagext.Tag <BR>&nbsp;&nbsp; ------------------------------------------------------ <BR>&nbsp;&nbsp; +EVAL_BODY_INCLUDE:int <BR>&nbsp;&nbsp; +EVAL_PAGE:int <BR>&nbsp;&nbsp; +SKIP_BODY:int <BR>&nbsp;&nbsp; +SKIP_PAGE:int <BR>&nbsp;&nbsp; ------------------------------------------------------ <BR>&nbsp;&nbsp; +release():void <BR>&nbsp;&nbsp; +getParent():javax.servlet.jsp.tagext.Tag <BR>&nbsp;&nbsp; +setParent(javax.servlet.jsp.tagext.Tag):void <BR>&nbsp;&nbsp; +doEndTag():int <BR>&nbsp;&nbsp; +doStartTag():int <BR>&nbsp;&nbsp; +setPageContext(javax.servlet.jsp.PageContext):void <BR><BR>17.&nbsp; Tag的生命周期 <BR>答：1) setPageContext(javax.servlet.jsp.PageContext):void <BR>&nbsp;&nbsp; 2) setParent(javax.servlet.jsp.tagext.Tag):void <BR>&nbsp;&nbsp; 3) //setAttribute:void <BR>&nbsp;&nbsp; 4) doStartTag():int <BR>&nbsp;&nbsp; 5) doEndTag():int <BR>&nbsp;&nbsp; 6) release():void <BR><BR>18.&nbsp; BodyTag和Tag接口的关系 <BR>答：interface javax.servlet.jsp.tagext.BodyTag&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;&nbsp;&nbsp;&nbsp;&nbsp; interface javax.servlet.jsp.tagext.Tag <BR>&nbsp;&nbsp; ------------------------------------------ <BR>&nbsp;&nbsp; +EVAL_BODY_AGAIN:int <BR>&nbsp;&nbsp; ------------------------------------------ <BR>&nbsp;&nbsp; +doInitBody():void <BR>&nbsp;&nbsp; +setBodyContent(javax.servlet.jsp.tagext.BodyContext):void <BR>&nbsp;&nbsp; +doAfterBody():int <BR><BR>19.&nbsp; BodyTag的处理过程 <BR>答：1) setPageContext(javax.servlet.jsp.PageContext):void <BR>&nbsp;&nbsp; 2) setParent(javax.servlet.jsp.tagext.Tag):void <BR>&nbsp;&nbsp; 3) //setParent() <BR>&nbsp;&nbsp; 4) doStartTag():int <BR>&nbsp;&nbsp; 5) setBodyContent(javax.servlet.jsp.tagext.BodyContent):void <BR>&nbsp;&nbsp; 6) doInitBody():void <BR>&nbsp;&nbsp; 7) doAfterBody():int <BR>&nbsp;&nbsp; doEndTag():int <BR>&nbsp;&nbsp; 9) release():void <BR><BR>20.&nbsp; SimpleTag接口的方法 <BR>答：javax.servlet.jsp.tagext.SimpleTag <BR>&nbsp;&nbsp; ------------------------------------------ <BR>&nbsp;&nbsp; +doTag():void <BR>&nbsp;&nbsp; +getParent():JspTag <BR>&nbsp;&nbsp; +setJspBody(JspFragment jspBody):void <BR>&nbsp;&nbsp; +setJspContext(JspContext pc):void <BR>&nbsp;&nbsp; +setParent(JspTag parent):void <BR><BR>21.&nbsp; SimpleTage接口的生命周期 <BR>答：1) new: <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 每次遇到标签，容器构造一个SimpleTag的实例，这个构造方法没有参数。和红典的标签一样，SimpleTag不能缓冲，故不能重用，每次都需要构造新的实例。 <BR>&nbsp;&nbsp; 2) setJspContext()、setParent(): 只有这个标签在另一个标签之内时，才调用setParent()方法; <BR>&nbsp;&nbsp; 3) 设置属性：调用每个属性的setter方法; <BR>&nbsp;&nbsp; 4) setJspBody(); <BR>&nbsp;&nbsp; 5) doTag(): 所有标签的逻辑、迭代和Body计算，都在这个方法中; <BR>&nbsp;&nbsp; 6) return<img src ="http://www.blogjava.net/limq/aggbug/1669.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-03-03 23:55 <a href="http://www.blogjava.net/limq/archive/2005/03/03/1669.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate 入门实例（转载）</title><link>http://www.blogjava.net/limq/archive/2005/03/03/1659.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Thu, 03 Mar 2005 09:29:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/03/03/1659.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/1659.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/03/03/1659.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/1659.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/1659.html</trackback:ping><description><![CDATA[本文配置环境：<BR>JBuilder X<BR>jdk 1.4.2<BR>Mysql 4.0.11 驱动:mm.mysql-2.0.4-bin.jar(org.gjt.mm.mysql.Driver)<BR>Hibernate 2.1<BR><BR>解压Hibernate<BR><BR>打开JB，新建工程，名为：hibernate <BR>加入Hibernate需要的包与MYSQL驱动<BR>步骤:file-&gt;new project-&gt;name中输入hibernate,directory选择你要存放本工程的路径-&gt;next<BR><BR>-&gt;required libraries-&gt;add-&gt;new-&gt;name中输入你要设置的hibernate包名<BR><BR>-&gt;add-&gt;选择你hibernate解压到的目录，选中该目录下的hibernate2.jar与lib目录下的所有jar包，再把你的MYSQL驱动包也加进去<BR><BR>然后一直按OK，next。<BR><BR>新建一个类,名为Hello_Bean.java,代码如下：<BR><BR><BR><BR>package hibernate;<BR><BR>import java.io.Serializable;<BR><BR>/**<BR>* @author geezer<BR>* QQ:9986986 MSN:geezer_hot@hotmail.com<BR>*/<BR><BR>public class Hello_Bean implements Serializable {<BR><BR>private String name;//这里name与address和id的名字可以自己定，不会有什么影响.但get与set方法不可以。因为那得跟数据库与配置文件对应。<BR><BR>private String address;<BR><BR>private int id;<BR><BR><BR><BR>public Hello_Bean() {<BR><BR>}<BR><BR>public Hello_Bean(String name, String address) {//构造函数,看完本章以后相信你会明白的了<BR>this.name = name;<BR>this.address = address;<BR>}<BR><BR>public String getName() {//此方法名必须与Hello_Bean.hbm.xml文件里的对应的名字一样，下面会详细讲<BR>return name;<BR>}<BR><BR>public void setName(String name) {<BR>this.name = name;<BR>}<BR><BR>public String getAddress() {<BR>return address;<BR>}<BR><BR>public void setAddress(String address) {<BR>this.address = address;<BR>}<BR><BR>public int getId() {//必须的方法<BR>return id;<BR>}<BR><BR>public void setId(int id)//必须的方法<BR>{<BR>this.id = id;<BR>}<BR><BR><BR>}<BR><BR><BR><BR>完成这一步以后编译<BR><BR>将hibernate解压后的目录下的src文件夹里的hibernate.properties与log4j.properties文件复制到你的工程目录的classes目录下<BR><BR>(例如hibernate\classes\目录下)，<BR><BR>打开hibernate.properties文件，找到<BR><BR>## HypersonicSQL<BR><BR>hibernate.dialect net.sf.hibernate.dialect.HSQLDialect<BR>hibernate.connection.driver_class org.hsqldb.jdbcDriver<BR>hibernate.connection.username sa<BR>hibernate.connection.password<BR>hibernate.connection.url jdbc:hsqldb:hsql://localhost<BR>hibernate.connection.url jdbc:hsqldb:test<BR>hibernate.connection.url jdbc:hsqldb:.<BR><BR>改为<BR><BR>## HypersonicSQL<BR><BR>#hibernate.dialect net.sf.hibernate.dialect.HSQLDialect<BR>#hibernate.connection.driver_class org.hsqldb.jdbcDriver<BR>#hibernate.connection.username sa<BR>#hibernate.connection.password<BR>#hibernate.connection.url jdbc:hsqldb:hsql://localhost<BR>#hibernate.connection.url jdbc:hsqldb:test<BR>#hibernate.connection.url jdbc:hsqldb:.<BR><BR>再找到<BR><BR>## MySQL<BR><BR>#hibernate.dialect net.sf.hibernate.dialect.MySQLDialect<BR>#hibernate.connection.driver_class org.gjt.mm.mysql.Driver<BR>#hibernate.connection.driver_class com.mysql.jdbc.Driver<BR>#hibernate.connection.url jdbc:mysql:///test<BR>#hibernate.connection.username root<BR>#hibernate.connection.password <BR><BR>改为<BR><BR><BR>## MySQL<BR><BR>hibernate.dialect net.sf.hibernate.dialect.MySQLDialect<BR>hibernate.connection.driver_class org.gjt.mm.mysql.Driver<BR>hibernate.connection.url jdbc:mysql://localhost:3306/test<BR>hibernate.connection.username root<BR>hibernate.connection.password <BR><BR>上面的URL请改为你自己的<BR><BR>完成以后创建一个空的文件，保存在你工程的类文件同个文件夹里（例如hibernate\classes\hibernate\目录下），文件名为：Hello_Bean.hbm.xml<BR><BR>内容如下：<BR><BR><BR><BR>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<BR><BR>&lt;!DOCTYPE hibernate-mapping PUBLIC<BR>"-//Hibernate/Hibernate Mapping DTD 2.0//EN"<BR>"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"&gt;<BR>&lt;hibernate-mapping&gt;<BR><BR>&lt;class name="hibernate.Hello_Bean" table="test_hibernate" &gt;<BR><BR>&lt;id name="id" column="id"&gt;<BR><BR>&lt;generator class="identity"/&gt;<BR><BR>&lt;/id&gt;<BR><BR>&lt;property name="name" type="string" update="true" insert="true" column="name" /&gt;<BR>&lt;property name="address" type="string" update="true" insert="true" column="address" /&gt;<BR><BR>&lt;/class&gt;<BR><BR>&lt;/hibernate-mapping&gt;<BR><BR><BR><BR>稍微解释一下,&lt;class name="hibernate.Hello_Bean" table="test_hibernate" &gt;里的name指你的生成表的类，<BR><BR>table则指定你要创建的数据库表的名字，可以自由修改，没有影响.<BR><BR>&lt;id name="id" column="id"&gt;设置主键ID，这里name的值id跟Hello_Bean.java里的方法getId与setId对应，不用管这个,hibernate会自动调用，配置好就可以了，column的值为要生成的字段名，可以自由修改，没有影响。<BR><BR>&lt;generator class="identity"/&gt;属性让主键的ID自增（插入数据的时候自动加1）<BR><BR>&lt;property name="name" type="string" update="true" insert="true" column="name" /&gt;这里的name值"name"跟Hello_Bean.java里的getName方法对应，column为要生成的字段名<BR>&lt;property name="address" type="string" update="true" insert="true" column="address" /&gt;<BR><BR>分别添加一个字段name与address，注意这里的type属性类型为string,如果这里的类型与Hello_Bean.java里设置的类型不一样会出错。<BR><BR>修改完以后保存。<BR><BR>最后在JB里新建一个类，名字为Hello.java，我会一步步解释，代码如下：<BR><BR><BR><BR>package hibernate;<BR><BR>import net.sf.hibernate.cfg.Configuration;<BR>import net.sf.hibernate.SessionFactory;<BR>import net.sf.hibernate.tool.hbm2ddl.SchemaExport;<BR>import net.sf.hibernate.Session;<BR>import net.sf.hibernate.Query;<BR>import net.sf.hibernate.Hibernate;<BR>import net.sf.hibernate.type.LongType;<BR>import net.sf.hibernate.Transaction;<BR>import net.sf.hibernate.ScrollableResults;<BR>import java.util.*;<BR><BR>/**<BR>* @author geezer<BR>* QQ:9986986 MSN:geezer_hot@hotmail.com<BR>*/<BR><BR><BR>public class Hello {<BR><BR><BR>public Hello() {<BR><BR><BR>}<BR><BR>public static void main(String[] args) throws Exception {<BR><BR>Configuration cfg = new Configuration().addClass(Hello_Bean.class);//用Hello_Bean.class类初始化<BR><BR>SessionFactory sessions = cfg.buildSessionFactory();//用buildSessionFactory方法得到一个SessionFactory对象<BR><BR>Session session = sessions.openSession();//再用SessionFactory的openSession方法得到一个session<BR><BR><BR><BR>new SchemaExport(cfg).create(true, true);//这句意思是创建表，第一次运行以后，就是创建完表以后再把这行加上注释。如果建表以后不把这一句注释掉的话会删掉以前创建的表再重新建一个。<BR><BR><BR><BR><BR>Hello_Bean my_hibernate = new Hello_Bean();//得到一个Hello_Bean对象<BR><BR>my_hibernate.setName("my_name");//设置Hello_Bean对象的name值为my_name,这里其实就是说把字符串my_name当作数据库字段name的值.数据库字段name与Hello_Bean类里的getName,setName方法是对应的。形成一个映射关系。<BR><BR>my_hibernate.setAddress("my_address");//如上<BR><BR>session.save(my_hibernate);//这句很重要，将my_hibernate对象写进数据库（my_hibernate对象里的name与address我们刚刚已经设置了值了，会直接把name,address的值写进数据库去）<BR><BR>session.flush();<BR>session.close();<BR><BR><BR>//上面是一个简单的插入数据与第一次运行建表的介绍，下面我再介绍删除与修改的方法,下面的代码我都加了注释，自己需要什么方法（删除，修改，循环数据库的值）就把注释去掉就可以了<BR>HSQL比较简单，大家看一下例子就应该明白了，这里就不讲了。<BR>遍历数据库的方法有三种，分别是Query,find,iterate，Query和find返回一个List接口，iterate返回一个Iterator，具体方法可以查看这些类得知。<BR><BR>//删除数据<BR>/*<BR>int a=session.delete("from Hello_Bean where id=1");//如果没有找到id为1的数据那么返回0，如果找到返回1,这里的Hello_Bean是我们的Hello_Bean类，他跟数据库表对应，所以我们在这里是直接用Hello_Bean来代码数据库表的。<BR>System.out.println(a);<BR>session.flush();<BR>session.close();<BR><BR>*/<BR><BR>//Query方法查询数据<BR>/*<BR>Hello_Bean my_hibernate = null;<BR>Query q = session.createQuery("from Hello_Bean");<BR>// Query q = session.createQuery("from Hello_Bean where name=?");//这里的?跟JDBC的PreparedStatement方法的差不多，只不过这里的是以0开始，jdbc的是1开始。<BR>// q.setString(0,"my_name");<BR>// q.setFirstResult(0);//这句话的意思是说查询结果从第几行开始列出数据<BR>// q.setMaxResults(3);//这句话的意思是取多少条数据，就跟SQL SERVER的TOP方法和MYSQL的LIMIT方法一样的意思。<BR>// ScrollableResults sc=q.scroll();//得到一个ScrollableResults,可滚动的，如果你的数据库支持游标自由移动的话可以加上，也就是说可以判断查询结果有没有值，或者移动到下一行记录等等。<BR><BR>// if(!sc.next())<BR>// {<BR>// System.out.println("没有找到你需要的数据");<BR>// }<BR><BR>session.flush();//如果使用了ScrollableResults的话请把这行注释掉<BR>session.close();//如果使用了ScrollableResults的话请把这行注释掉<BR><BR>List l=q.list();//返回一个List接口，用来遍历结果集<BR><BR>for(int i=0;i&lt;l.size();i++){<BR>my_hibernate = (Hello_Bean) l.get(i);//从List中取得一个my_hibernate对象<BR>System.out.println(my_hibernate.getName());//调用my_hibernate对象的getName方法取得数据库name字段的值<BR><BR>}<BR><BR>*/<BR><BR>//find方法查询数据<BR>/*<BR>Hello_Bean my_hibernate = null;<BR>List q = session.find("from Hello_Bean");<BR>session.flush();<BR>session.close();<BR><BR>for(int i=0;i&lt;q.size();i++)<BR>{<BR>my_hibernate = (Hello_Bean) q.get(i);<BR>System.out.println(my_hibernate.getName());<BR>}<BR>*/<BR><BR>//iterate方法查询数据<BR>/*<BR>Hello_Bean my_hibernate = null;<BR>Iterator q = session.iterate("from Hello_Bean");<BR><BR>while(q.hasNext())<BR>{<BR>my_hibernate = (Hello_Bean) q.next();<BR>System.out.println(my_hibernate.getName());<BR>}<BR><BR>*/<BR><BR>//修改数据<BR>/*<BR>Query qq=session.createQuery("from Hello_Bean");<BR><BR>Hello_Bean my_hibernate=(Hello_Bean)session.load(Hello_Bean.class,new Integer(2));<BR>//这里的new Integer(2)意思是修改表中id为2的那一行数据,必须是一个包装类的对象，如果使用int的话会出错。<BR>my_hibernate.setName("geezer");//把id为2的那一行数据的name字段值改为"geezer"<BR>session.flush();<BR>session.close();<BR><BR>*/<BR><BR>}<BR><BR>}<BR><BR>最后运行就可以了。<BR><BR>如果大家有什么不清楚的，可以下载这篇文章的例子看看，运行一下。<BR><BR>下载完以后用JB打开hibernate.jpx就可以了。用之前把hibernate和MYSQL的驱动加进去，方法如果不知道再看看本章开头部分。<BR><BR><BR>常见错误：<BR>Caused by: org.dom4j.DocumentException: Invalid byte 2 of 2-byte UTF-8 sequence. Nested exception: Invalid byte 2 of 2-byte UTF-8 sequence.<BR>如果出现这行错误说明你的xml配置文件有不规范的字符，检查下。<BR><BR>net.sf.hibernate.MappingException: Error reading resource: hibernate/Hello_Bean.hbm.xml<BR><BR><BR>如果出现这行错误说明你的hibernate的XML配置文件有错<BR><BR>net.sf.hibernate.MappingException: Resource: hibernate/Hello_Bean.hbm.xml not found<BR><BR><BR>如果出现这行错误说明hibernate的XML配置文件没有找到，你应该把XML文件放在与你的类文件同个目录下,本文中是放在hibernate\classes\hibernate\目录下，也就是跟Hello_Bean.class类文件一起。<BR><BR>net.sf.hibernate.PropertyNotFoundException: Could not find a setter for property name in class hibernate.Hello_Bean<BR><BR><BR>如果出现这行错误说明你的xml文件里设置的字段名name的值与Hello_Bean.java类里的getXXX或setXXX方法不一致。<BR><BR>net.sf.hibernate.HibernateException: JDBC Driver class not found: org.gjt.mm.mysql.Driver<BR>如果出现这行错误说明你的MYSQL驱动没有加进JB库里或者不在CLASSPATH里。<BR><BR>
<HR>
<FONT face="verdana, arial, helvetica" size=2></FONT><BR>
<P><FONT face=verdana,arial,helvetica size=1>代码下载：</FONT></P>http://www.blogjava.net/Files/limq/hibernate_demo.rar<BR><!-----end of blog bot message---->
<HR align=left width="60%" SIZE=1>
<BR></FONT>我的生活就象是抽烟，自从点着火的那一刻开始就注定了一生一尘不变的味道，直到熄灭为止～ 而我的生命就是烟......<BR>==========================<BR>糊涂一生<A href="http://php.phpx.com/http://www.ht13.com" target=_blank>http://www.ht13.com</A></FONT> <BR><img src ="http://www.blogjava.net/limq/aggbug/1659.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-03-03 17:29 <a href="http://www.blogjava.net/limq/archive/2005/03/03/1659.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Servlet 路径 </title><link>http://www.blogjava.net/limq/archive/2005/03/01/1600.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Tue, 01 Mar 2005 15:29:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/03/01/1600.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/1600.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/03/01/1600.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/1600.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/1600.html</trackback:ping><description><![CDATA[<P>首先建立一个测试页面:path.jsp<BR>&lt;%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %&gt;<BR>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<A href="http://www.w3.org/TR/html4/loose.dtd">http://www.w3.org/TR/html4/loose.dtd</A>"&gt;<BR>&lt;html&gt;<BR>&lt;head&gt;<BR>&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<BR>&lt;title&gt;无标题文档&lt;/title&gt;<BR>&lt;/head&gt;</P>
<P>&lt;body&gt;<BR>请求服务器：<BR>&lt;%= request.getServerName() %&gt;&lt;br&gt;<BR>使用协议：<BR>&lt;%= request.getProtocol() %&gt;&lt;br&gt;<BR>请求方法：<BR>&lt;%= request.getMethod() %&gt;&lt;br&gt;<BR>请求断口号：<BR>&lt;%= request.getServerPort() %&gt;&lt;br&gt;<BR>Context路径：<BR>&lt;%= request.getContextPath() %&gt;&lt;br&gt;<BR>Servlet路径：<BR>&lt;%= request.getServletPath() %&gt;&lt;br&gt;<BR>URI路径：<BR>&lt;%= request.getRequestURI() %&gt;&lt;br&gt;<BR>查询字串：<BR>&lt;%= request.getQueryString() %&gt;&lt;br&gt;<BR>&lt;br&gt;<BR>使用者主機IP：<BR>&lt;%= request.getRemoteAddr() %&gt;&lt;br&gt;</P>
<P>&lt;%= request.getRemotePort() %&gt;<BR>&lt;/body&gt;<BR>&lt;/html&gt;<BR><BR>再用一下方式测试:<BR><A href="http://localhost:8080/WebModule1/path.jsp?name=justin&amp;nick=caterpillar">http://localhost:8080/WebModule1/path.jsp?name=justin&amp;nick=caterpillar<BR></A><A href="http://localhost:8080/WebModule1/path.jsp"></A><BR>结果为:<BR>请求服务器： localhost<BR>使用协议： HTTP/1.1<BR>请求方法： GET<BR>请求断口号： 8080<BR>Context路径： /WebModule1<BR>Servlet路径： /path.jsp<BR>URI路径： /WebModule1/path.jsp<BR>查询字串： name=justin&amp;nick=caterpillar<BR><BR>使用者主?CIP： 127.0.0.1<BR>1490</P><img src ="http://www.blogjava.net/limq/aggbug/1600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-03-01 23:29 <a href="http://www.blogjava.net/limq/archive/2005/03/01/1600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用 Jsp+Taglib+JavaBean 快速构建 动态数据库查询模板</title><link>http://www.blogjava.net/limq/archive/2005/02/28/1580.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Mon, 28 Feb 2005 14:58:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/02/28/1580.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/1580.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/02/28/1580.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/1580.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/1580.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本文主要介绍如何快速利用 jsp+taglib+javaBean 构建动态数据库查询模板的全过程,已经如和使用,扩展该模板的方法.在使用该框架之前,我们知道通常如果我们需要利用web查询数据库通常是用我们所说的Model 1 ,和 Model 2 即MVC.而本文介绍的大致如下图:&nbsp;本模板所要实现的功能是: 通过非常简单地继承一个模板中的方法产生类,和添加一个含有Tag的简单...&nbsp;&nbsp;<a href='http://www.blogjava.net/limq/archive/2005/02/28/1580.html'>阅读全文</a><img src ="http://www.blogjava.net/limq/aggbug/1580.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-02-28 22:58 <a href="http://www.blogjava.net/limq/archive/2005/02/28/1580.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JBuilder2005 下 jsp2.0 自定义标签 </title><link>http://www.blogjava.net/limq/archive/2005/02/20/1350.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Sat, 19 Feb 2005 16:20:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/02/20/1350.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/1350.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/02/20/1350.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/1350.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/1350.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="TEXT-INDENT: 10.5pt"><SPAN style="FONT-FAMILY: 宋体">要在</SPAN><SPAN lang=EN-US>jb2005</SPAN><SPAN style="FONT-FAMILY: 宋体">下实现</SPAN><SPAN lang=EN-US>jsp2.0</SPAN><SPAN style="FONT-FAMILY: 宋体">首先需要配置</SPAN><SPAN lang=EN-US>Tomcat5.0</SPAN><SPAN style="FONT-FAMILY: 宋体">以上的版本</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">其次还要</SPAN><SPAN lang=EN-US>jsp2.0</SPAN><SPAN style="FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US>jar</SPAN><SPAN style="FONT-FAMILY: 宋体">文件</SPAN><SPAN lang=EN-US>,</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">具体方法请参考</SPAN> <SPAN style="FONT-FAMILY: 宋体">上一篇文章</SPAN><B><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana"><A href="http://blog.csdn.net/mill_lmq/archive/2005/02/15/288675.aspx"><FONT color=#000080><SPAN class=3><SPAN style="BACKGROUND: white">JBuilder2005 </SPAN></SPAN><SPAN class=3><SPAN style="BACKGROUND: white; FONT-FAMILY: 宋体">下</SPAN><SPAN style="BACKGROUND: white"> jsp2.0 </SPAN></SPAN><SPAN class=3><SPAN style="BACKGROUND: white; FONT-FAMILY: 宋体">初体验</SPAN></SPAN></FONT></A>,</SPAN></B><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">本文主要讲的是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">jb2005</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">下自定义标签的开发</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">.</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 10pt"><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">为了能够快速开发</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">,</SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">我使用了</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">open source </SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">JSP Tag Wizards v3.0</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">插件</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">,</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">它可以帮助我们快速开发</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">jsp1.1,</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">到</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">jsp2.0</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">的各种标签</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">.</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">下载地址为</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial"> :</SPAN><SPAN lang=EN-US> </SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial"><A href="http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=21573">http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=21573</A>. </SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">将下载来的压缩包解压到</SPAN><SPAN lang=EN-US>JBuilder/lib/ext</SPAN><SPAN style="FONT-FAMILY: 宋体">中就可以了</SPAN><SPAN lang=EN-US>.</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 10.5pt"><SPAN style="FONT-FAMILY: 宋体">新建一个</SPAN><SPAN lang=EN-US>Mytag2</SPAN><SPAN style="FONT-FAMILY: 宋体">的工程</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">这里要将我们上一节说的</SPAN><SPAN lang=EN-US>jsp2.0</SPAN><SPAN style="FONT-FAMILY: 宋体">以及</SPAN><SPAN lang=EN-US>JSTL1.1</SPAN><SPAN style="FONT-FAMILY: 宋体">的包添加进去</SPAN><SPAN lang=EN-US>.<IMG height=452 alt=image001.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image001.jpg" width=554 border=0></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 10.5pt"><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体">新建一个</SPAN><SPAN lang=EN-US>web</SPAN><SPAN style="FONT-FAMILY: 宋体">模块</SPAN></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 10.5pt"><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><IMG height=433 alt=image002.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image002.jpg" width=554 border=0></SPAN></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 10.5pt"><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-FAMILY: 宋体">建立</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">jsp </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体">标签文件</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">,</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体">双击</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> JPS Tag</FONT></SPAN></SPAN></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 10.5pt"><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><IMG height=444 alt=image003.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image003.jpg" width=553 border=0></SPAN></SPAN></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 10.5pt"><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><IMG height=409 alt=image004.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image004.jpg" width=554 border=0></SPAN></SPAN></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 10.5pt"><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体">由于我们这里使用的是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">SimpleTagSupport </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体">所以勾选</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> Simple tag, </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体">点击</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> OK<IMG height=443 alt=image005.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image005.jpg" width=553 border=0></FONT></SPAN></SPAN></SPAN></SPAN></P><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><SPAN lang=EN-US>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">可以看到</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">JSP Tag Wizards v3.0</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">已经自动为我们生成了</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">Hello.java</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">文件</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">.</SPAN></P>
<P class=MsoNormal><SPAN style="COLOR: black; FONT-FAMILY: 宋体">这里我将</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">dotag()</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">方法</SPAN><SPAN style="COLOR: black; FONT-FAMILY: Arial"> </SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">改为</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>public void doTag() throws IOException, JspException {</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>        JspWriter out = getJspContext().getOut();</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>        /** @todo specify any output value for this tag */</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>        out.print("Hello JSp2.0 tag");</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>    }</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  </SPAN><SPAN style="FONT-FAMILY: 宋体">然后建立</SPAN><SPAN lang=EN-US> tld </SPAN><SPAN style="FONT-FAMILY: 宋体">文件</SPAN><SPAN lang=EN-US>. </SPAN><SPAN style="FONT-FAMILY: 宋体">如图选择</SPAN><SPAN lang=EN-US>Taglib Descriptor</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><IMG height=443 alt=image006.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image006.jpg" width=554 border=0></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体">接下来我们可以选择要生成</SPAN><SPAN lang=EN-US>tld </SPAN><SPAN style="FONT-FAMILY: 宋体">文件</SPAN> <SPAN style="FONT-FAMILY: 宋体">的</SPAN> <SPAN style="FONT-FAMILY: 宋体">位置</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">和名称</SPAN><SPAN lang=EN-US>, </SPAN><SPAN style="FONT-FAMILY: 宋体">这里我没有改变其默认值</SPAN><SPAN lang=EN-US>.</SPAN></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN lang=EN-US><IMG height=325 alt=image007.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image007.jpg" width=553 border=0></SPAN></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体">一直点击</SPAN><SPAN lang=EN-US> Next > </SPAN><SPAN style="FONT-FAMILY: 宋体">直到</SPAN></SPAN></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><IMG height=326 alt=image008.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image008.jpg" width=554 border=0></SPAN></SPAN></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-FAMILY: 宋体">这里我们可以选择标签体内容为</SPAN><SPAN lang=EN-US> Empty.   Finish .</SPAN></SPAN></SPAN></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><IMG height=395 alt=image009.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image009.jpg" width=554 border=0></SPAN></SPAN></SPAN></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体">可以看到</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">JSP Tag Wizards v3.0 </SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">为我们生成了</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">Mytag2.tld</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">文件</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">,</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">以及相关配置</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">.</SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">接下来我们需要将它转移到</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial"> Web-Inf/tld </SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">中</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">, </SPAN><SPAN style="COLOR: black; FONT-FAMILY: 宋体">右击</SPAN><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">WEB-INF>New>Directory</SPAN></SPAN></SPAN></SPAN></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial"><IMG height=205 alt=image010.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image010.jpg" width=294 border=0></SPAN></SPAN></SPAN></SPAN></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial"><IMG height=177 alt=image011.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image011.jpg" width=501 border=0></SPAN></SPAN></SPAN></SPAN></SPAN></P><SPAN lang=EN-US><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><SPAN lang=EN-US style="COLOR: black; FONT-FAMILY: Arial">
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">点击</SPAN><SPAN lang=EN-US> ok.</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">在将刚才生成的</SPAN><SPAN lang=EN-US> Mytag2.tld</SPAN><SPAN style="FONT-FAMILY: 宋体">文件移动至其中</SPAN><SPAN lang=EN-US>.</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><IMG height=349 alt=image012.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image012.jpg" width=209 border=0></SPAN></P></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN>
<P class=MsoNormal style="TEXT-INDENT: 10.5pt"><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><SPAN lang=EN-US><FONT face="Times New Roman"></FONT></SPAN></SPAN></SPAN></SPAN> </P><SPAN lang=EN-US><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><SPAN lang=EN-US>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">新建一个</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 宋体">文件</SPAN><SPAN lang=EN-US>.</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><%@ page contentType="text/html; charset=GB18030" %></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><%@ taglib uri="/WEB-INF/tld/Mytag2.tld"  prefix="mytag"%></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><html></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><head></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><title></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>jsp1</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></title></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></head></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><body bgcolor="#ffffff"></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><h1></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><mytag:Hello/></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></h1></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></body></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></html></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">好了大功告成了</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">让我们来看看执行结果吧</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"><IMG height=498 alt=image013.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images2/image013.jpg" width=553 border=0></SPAN></P></SPAN></SPAN></SPAN></SPAN><img src ="http://www.blogjava.net/limq/aggbug/1350.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-02-20 00:20 <a href="http://www.blogjava.net/limq/archive/2005/02/20/1350.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JBuilder2005 下 jsp2.0 初体验</title><link>http://www.blogjava.net/limq/archive/2005/02/19/1347.html</link><dc:creator>limq</dc:creator><author>limq</author><pubDate>Sat, 19 Feb 2005 15:38:00 GMT</pubDate><guid>http://www.blogjava.net/limq/archive/2005/02/19/1347.html</guid><wfw:comment>http://www.blogjava.net/limq/comments/1347.html</wfw:comment><comments>http://www.blogjava.net/limq/archive/2005/02/19/1347.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/limq/comments/commentRss/1347.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/limq/services/trackbacks/1347.html</trackback:ping><description><![CDATA[<P><IMG height=1 src="/FreeTextBox/Utility/spacer.gif" width=1></P>
<P class=MsoNormal><SPAN lang=EN-US>JBuilder2005 </SPAN><SPAN style="FONT-FAMILY: 宋体">比较前一个版本提供了</SPAN><SPAN lang=EN-US>jsp2.0,</SPAN><SPAN style="FONT-FAMILY: 宋体">以及</SPAN><SPAN lang=EN-US>servlet2.4</SPAN><SPAN style="FONT-FAMILY: 宋体">的支持</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">置于</SPAN><SPAN lang=EN-US>jsp2.0</SPAN><SPAN style="FONT-FAMILY: 宋体">规范这里就不多说了</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">以下介绍在</SPAN><SPAN lang=EN-US>jb2005</SPAN><SPAN style="FONT-FAMILY: 宋体">中的体会</SPAN><SPAN lang=EN-US>.</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">一</SPAN> <SPAN style="FONT-FAMILY: 宋体">安装设置</SPAN><SPAN lang=EN-US>Tomcat5.0</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">我们知道</SPAN><SPAN lang=EN-US>,Jsp2.0</SPAN><SPAN style="FONT-FAMILY: 宋体">是</SPAN><SPAN lang=EN-US>Tomcat5.0</SPAN><SPAN style="FONT-FAMILY: 宋体">以上的版本所支持的</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">所以如果你使用的是</SPAN><SPAN lang=EN-US>jbuilder</SPAN><SPAN style="FONT-FAMILY: 宋体">默认的</SPAN><SPAN lang=EN-US>tomcat4.0</SPAN><SPAN style="FONT-FAMILY: 宋体">在</SPAN><SPAN lang=EN-US>WEB</SPAN><SPAN style="FONT-FAMILY: 宋体">模块是看不到</SPAN><SPAN lang=EN-US>jsp2.0,</SPAN><SPAN style="FONT-FAMILY: 宋体">以及</SPAN><SPAN lang=EN-US>servlet2.4</SPAN><SPAN style="FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">所以要首先安装设置</SPAN><SPAN lang=EN-US>Tomcat5.0</SPAN><SPAN style="FONT-FAMILY: 宋体">以上的版本</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">然后在</SPAN><SPAN lang=EN-US>Jbuilder</SPAN><SPAN style="FONT-FAMILY: 宋体">中设置如下</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"><IMG height=475 alt=image001.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images/image001.jpg" width=554 border=0></SPAN></P><SPAN style="FONT-FAMILY: 宋体">
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">二</SPAN> <SPAN style="FONT-FAMILY: 宋体">去</SPAN><SPAN lang=EN-US> http://jakarta.apache.org</SPAN><SPAN style="FONT-FAMILY: 宋体">下载</SPAN> <SPAN lang=EN-US>jakarta-taglibs-standard-current.jar</SPAN><SPAN style="FONT-FAMILY: 宋体">就是</SPAN><SPAN lang=EN-US>JSTL1.1</SPAN><SPAN style="FONT-FAMILY: 宋体">的包</SPAN><SPAN lang=EN-US>,(jb</SPAN><SPAN style="FONT-FAMILY: 宋体">中也可以</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">但是总是提示有文件找不到</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">所以我就下了一个新的</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">问题解决了</SPAN><SPAN lang=EN-US>),</SPAN><SPAN style="FONT-FAMILY: 宋体">将解压后的</SPAN><SPAN lang=EN-US>jstl.jar, standard.jar</SPAN><SPAN style="FONT-FAMILY: 宋体">复制到</SPAN><SPAN lang=EN-US>JBuilder2005\lib</SPAN><SPAN style="FONT-FAMILY: 宋体">下</SPAN><SPAN lang=EN-US>,</SPAN><SPAN style="FONT-FAMILY: 宋体">配置如下</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"><IMG height=322 alt=image002.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images/image002.jpg" width=553 border=0></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-FAMILY: 宋体">然后设置</SPAN><SPAN lang=EN-US>jsp-api.jar,</SPAN><SPAN style="FONT-FAMILY: 宋体">我的路径为</SPAN><SPAN lang=EN-US>C:\Program Files\Apache Software Foundation\Tomcat 5.0\common\lib</SPAN></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US><IMG height=322 alt=image003.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images/image003.jpg" width=553 border=0></SPAN></SPAN></P><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">三</SPAN> <SPAN style="FONT-FAMILY: 宋体">新建立一个程序</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>File>New Project> name</SPAN><SPAN style="FONT-FAMILY: 宋体">为</SPAN><SPAN lang=EN-US>jsp2 Next></SPAN><SPAN style="FONT-FAMILY: 宋体">在</SPAN><SPAN lang=EN-US> Require Libraries </SPAN><SPAN style="FONT-FAMILY: 宋体">中将我们刚才添加的</SPAN><SPAN lang=EN-US>jsp2.0</SPAN><SPAN style="FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US>JTSL1.1</SPAN><SPAN style="FONT-FAMILY: 宋体">选上</SPAN><SPAN lang=EN-US>.>Finish</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>File>new>Web> WebModule </SPAN><SPAN style="FONT-FAMILY: 宋体">这里</SPAN> <SPAN style="FONT-FAMILY: 宋体">要记得选择</SPAN><SPAN lang=EN-US> servlet2.4,jsp2.0 ,name </SPAN><SPAN style="FONT-FAMILY: 宋体">为</SPAN><SPAN lang=EN-US> jsp2  Next></SPAN><SPAN style="FONT-FAMILY: 宋体">选择</SPAN><SPAN lang=EN-US>JTSL1.1(JTSL1.0)</SPAN><SPAN style="FONT-FAMILY: 宋体">选项</SPAN><SPAN lang=EN-US>.> Finish</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">四</SPAN> <SPAN style="FONT-FAMILY: 宋体">将刚才下载的</SPAN><SPAN lang=EN-US>jakarta-taglibs-standard-current.jar</SPAN><SPAN style="FONT-FAMILY: 宋体">中的</SPAN><SPAN lang=EN-US>tld</SPAN><SPAN style="FONT-FAMILY: 宋体">文件夹复制到</SPAN><SPAN lang=EN-US>WEB-INF</SPAN><SPAN style="FONT-FAMILY: 宋体">中 </SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"><IMG height=338 alt=image004.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images/image004.jpg" width=636 border=0></SPAN></P><SPAN style="FONT-FAMILY: 宋体">
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">五</SPAN> <SPAN style="FONT-FAMILY: 宋体">修改</SPAN><SPAN lang=EN-US>web.xml</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><?xml version="1.0" encoding="UTF-8"?></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  <display-name>Web</display-name></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  <jsp-config></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>    <taglib></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>      <taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>      <taglib-location>/WEB-INF/tld/c.tld</taglib-location></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>    </taglib></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>    <taglib></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>      <taglib-uri>http://java.sun.com/jsp/jstl/xml</taglib-uri></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>      <taglib-location>/WEB-INF/tld/x.tld</taglib-location></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>    </taglib></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>    <taglib></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>      <taglib-uri>http://java.sun.com/jsp/jstl/fmt</taglib-uri></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>      <taglib-location>/WEB-INF/tld/fmt.tld</taglib-location></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>    </taglib></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>    <taglib></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>      <taglib-uri>http://java.sun.com/jsp/jstl/sql</taglib-uri></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>      <taglib-location>/WEB-INF/tld/sql.tld</taglib-location></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>    </taglib></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  </jsp-config></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></web-app></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">六</SPAN> <SPAN style="FONT-FAMILY: 宋体">建立一个</SPAN><SPAN lang=EN-US>html </SPAN><SPAN style="FONT-FAMILY: 宋体">文件方法是右击</SPAN><SPAN lang=EN-US>Moudule directory>New>File>Name=Param,Type=Html</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">代码为</SPAN><SPAN lang=EN-US>:</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><html></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><head></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  <title>CH6 - Param.html</title></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></head></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><body></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN lang=EN-US><h2>EL</SPAN><SPAN style="FONT-FAMILY: 宋体">隐含对象</SPAN><SPAN lang=EN-US> param</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>paramValues</h2></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN lang=EN-US><form method="post" action="Param.jsp"></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  <p></SPAN><SPAN style="FONT-FAMILY: 宋体">姓名：</SPAN><SPAN lang=EN-US><input type="text" name="username" size="15" /></p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  <p></SPAN><SPAN style="FONT-FAMILY: 宋体">密码：</SPAN><SPAN lang=EN-US><input type="password" name="password" size="15" /></p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  <p></SPAN><SPAN style="FONT-FAMILY: 宋体">性别：</SPAN><SPAN lang=EN-US><input type="radio" name="sex" value="Male" checked/></SPAN><SPAN style="FONT-FAMILY: 宋体">男</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>             <input type="radio" name="sex" value="Female"  /> </SPAN><SPAN style="FONT-FAMILY: 宋体">女</SPAN><SPAN lang=EN-US></p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  <p></SPAN><SPAN style="FONT-FAMILY: 宋体">年龄：</SPAN><SPAN lang=EN-US><select name="old"></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>              <option value="10">10 - 20</option></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>              <option value="20" selected>20 - 30</option></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>              <option value="30">30 - 40</option></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>              <option value="40">40 - 50</option></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>            </select></p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  <p></SPAN><SPAN style="FONT-FAMILY: 宋体">兴趣：</SPAN><SPAN lang=EN-US><input type="checkbox" name="habit" value="Reading"/></SPAN><SPAN style="FONT-FAMILY: 宋体">看书</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>        <input type="checkbox" name="habit" value="Game"/></SPAN><SPAN style="FONT-FAMILY: 宋体">玩游戏</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>        <input type="checkbox" name="habit" value="Travel"/></SPAN><SPAN style="FONT-FAMILY: 宋体">旅游</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>        <input type="checkbox" name="habit" value="Music"/></SPAN><SPAN style="FONT-FAMILY: 宋体">听音乐</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>        <input type="checkbox" name="habit" value="Tv"/></SPAN><SPAN style="FONT-FAMILY: 宋体">看电视</SPAN><SPAN lang=EN-US></p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN lang=EN-US>  <p>       <input type="submit" value="</SPAN><SPAN style="FONT-FAMILY: 宋体">传送</SPAN><SPAN lang=EN-US>"/></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>          <input type="reset" value="</SPAN><SPAN style="FONT-FAMILY: 宋体">清除</SPAN><SPAN lang=EN-US>"/></p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></form></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></body></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></html></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">七</SPAN> <SPAN style="FONT-FAMILY: 宋体">新建一个</SPAN><SPAN lang=EN-US>jsp</SPAN><SPAN style="FONT-FAMILY: 宋体">文件</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>File>New>Web>JSP >(Name=Param)>Next></SPAN><SPAN style="FONT-FAMILY: 宋体">勾选</SPAN><SPAN lang=EN-US>JSTL1.1(JSTL1.0)>Finish</SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">代码如下</SPAN><SPAN lang=EN-US>:</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><%@ page contentType="text/html; charset=GB2312" %></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><html></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><head></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  <title>CH6 - Param.jsp</title></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></head></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><body></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN lang=EN-US>  <h2>EL</SPAN><SPAN style="FONT-FAMILY: 宋体">隐含对象</SPAN><SPAN lang=EN-US> param</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>paramValues</h2></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN lang=EN-US>  <fmt:requestEncoding value="GB2312" /></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN lang=EN-US>  </SPAN><SPAN style="FONT-FAMILY: 宋体">姓名：</SPAN><SPAN lang=EN-US><c:out value="${param.username}"/></br></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  </SPAN><SPAN style="FONT-FAMILY: 宋体">密码：</SPAN><SPAN lang=EN-US><c:out value="${param.password}"/></br></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  </SPAN><SPAN style="FONT-FAMILY: 宋体">性别：</SPAN><SPAN lang=EN-US><c:out value="${param.sex}"/></br></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  </SPAN><SPAN style="FONT-FAMILY: 宋体">年龄：</SPAN><SPAN lang=EN-US><c:out value="${param.old}"/></br></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>  </SPAN><SPAN style="FONT-FAMILY: 宋体">兴趣：</SPAN><SPAN lang=EN-US><c:out value="${paramValues.habit[0]}"/></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>              <c:out value="${paramValues.habit[1]}"/></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN lang=EN-US></body></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></html></SPAN></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">建立好后应为</SPAN></P>
<P class=MsoNormal></SPAN></SPAN></SPAN></SPAN><A href="http://www.blogjava.net/limq/limq/"><IMG height=503 alt=image005.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images/image005.jpg" width=624 border=0></A></P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">执行结果</SPAN><SPAN lang=EN-US>:</SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><IMG height=501 alt=image006.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images/image006.jpg" width=502 border=0></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P class=MsoNormal><SPAN lang=EN-US><IMG height=360 alt=image007.jpg src="http://www.blogjava.net/images/blogjava_net/limq/images/image007.jpg" width=420 border=0></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US></SPAN> </P>
<P> </P>
<P> </P><img src ="http://www.blogjava.net/limq/aggbug/1347.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/limq/" target="_blank">limq</a> 2005-02-19 23:38 <a href="http://www.blogjava.net/limq/archive/2005/02/19/1347.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>