﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-爪哇之家-文章分类-java</title><link>http://www.blogjava.net/hszdz/category/5297.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 18:25:56 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 18:25:56 GMT</pubDate><ttl>60</ttl><item><title> 实验: 使用 Apache 反向代理实现负载均衡及热备</title><link>http://www.blogjava.net/hszdz/articles/74376.html</link><dc:creator>爪哇之家</dc:creator><author>爪哇之家</author><pubDate>Tue, 10 Oct 2006 12:59:00 GMT</pubDate><guid>http://www.blogjava.net/hszdz/articles/74376.html</guid><description><![CDATA[
		<h3>初步设想</h3>
		<ul>
				<li>早些时候在 JavaEye 上看到过一些使用 lighttpd 或者 apache 作前端, 通过负载均衡, 实现高性能的 Web 系统的讨论, 于是留意了一下这方面的技术;</li>
				<li>考虑到对不同的 App Server 而言, 实现 Session 复制的配置各不相同(通常是需要配置集群), 因此从通用的角度, 觉得使用 session sticky 方式实现的负载均衡比较方便;</li>
				<li>由于没有看到有资料说 lighttpd 能够实现 session sticky, 所以决定先使用 Apache 试试.</li>
		</ul>

参考资料:
<ul><li>JavaEye 上的一篇短文: <a href="http://thinkbase.net/w/main/Wiki?%E4%BD%BF%E7%94%A8+Apache+%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E5%AE%9E%E7%8E%B0%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%8F%8A%E7%83%AD%E5%A4%87-ref001-from_JavaEye">请教apache跟tomcat做集群session不同步问题</a></li><li>Apache 2.2 HTTP Server 文档中的 mod_proxy 部分: <a href="http://thinkbase.net/w/main/Wiki?%E4%BD%BF%E7%94%A8+Apache+%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E5%AE%9E%E7%8E%B0%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%8F%8A%E7%83%AD%E5%A4%87-ref002-mod_proxy">英文</a>, <a href="http://thinkbase.net/w/main/Wiki?%E4%BD%BF%E7%94%A8+Apache+%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E5%AE%9E%E7%8E%B0%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%8F%8A%E7%83%AD%E5%A4%87-ref003-mod_proxy">中文翻译</a></li></ul><h3>环境准备</h3><ul><li>下载安装 Apache, 测试时使用的是 XAMPP ( <a style="border-bottom-width: 1px; border-bottom-style: dotted;" class="externallink" href="http://www.apachefriends.org/en/xampp.html">http://www.apachefriends.org/en/xampp.html</a> ) 的 Linux 版本 (xampp-linux-1.5.4.tar.gz), 按照安装说明, 解压到 /opt/lampp 目录下就可以使用了;
<ul><li>启动 Apache: <code>sudo /opt/lampp/lampp startapache</code></li><li>重新加载 Apache: <code>sudo /opt/lampp/lampp reloadapache</code> (在 httpd.conf 文件被修改后可以不重启, 而是直接 reload 就可以了)</li><li>停止服务: <code>sudo /opt/lampp/lampp stop</code></li></ul></li><li>准备两个运行同样程序的 Web 服务器, 这里使用的是 Tomcat 5.5, 并使用一个 jsp 文件作为测试文件(相关源代码参见文章最后的附件);
<ul><li>这两个 Tomcat 服务器需要将 HTTP 服务配置在不同的端口上, 同时由于测试时运行在同一台机器上, 其它端口也需要避免冲突;</li></ul></li><li>下载安装 JMeter ( jakarta-jmeter-2.2), 用于压力测试, 验证负载均衡的效果;   </li></ul><h3>测试 jsp 文件的说明</h3>
测试用的 jsp 文件 (test.jsp) 具有如下功能:
<ul><li>显示当前运行的服务器的 IP 地址及端口号, 这样从返回的页面就能够知道是运行在哪一个 Web 服务器上的了;</li><li>统计每个客户端(不同的 session)向同一台服务器发出请求的次数, 通过这个计数可以验证是否实现了 session sticky;</li><li>通过 clear 请求参数(即 .../test.jsp?clear=1)清除请求次数的计数结果, 以便进行下一次测试;</li><li>模拟 JSESSIONID +jvmRoute 的机制, 自行实现了一个 STICK_PORT_TOKEN 的 Cookie, 直接使用不同服务器的 HTTP 端口号作为 route;
<ul><li><strong>说明1</strong>: 考虑到方案的通用性, 这里没有直接使用 JSESSIONID +jvmRoute 的机制;</li><li><strong>说明2</strong>: 虽然作为一个例子, 相关代码是写死在 jsp 文件中的, 但是这个机制可以很方便的用一个 Filter 统一实现;</li></ul></li></ul><h3>Apache 的配置</h3>
编辑 Apache 的 httpd.conf 文件(如果使用 xampp-linux 的话, 应该在 /opt/lampp/etc 目录下), 在文件的最后加上如下内容:<br /><pre>###############################################################################<br /># Reverse Proxy and Load Balance ##############################################<br />###############################################################################<br /># 1)简单的反向代理<br />ProxyRequests Off<br />&lt;Proxy *&gt;<br />    Order deny,allow<br />    Allow from all<br />&lt;/Proxy&gt;<br />ProxyPass /1 http://localhost:8080/test<br />#ProxyPassReverse /1 http://localhost:8080/test<br />ProxyPass /2 http://localhost:18080/test<br />#ProxyPassReverse /2 http://localhost:18080/test<br /># 2)非 stickysession 的 balance<br />ProxyPass /3 balancer://non-sticky-cluster nofailover=On<br />&lt;Proxy balancer://non-sticky-cluster&gt;<br />    BalancerMember http://localhost:8080/test<br />    BalancerMember http://localhost:18080/test smax=10<br />&lt;/Proxy&gt;<br /># 3)stickysession 的 balance<br />ProxyPass /4 balancer://sticky-cluster stickysession=STICK_PORT_TOKEN nofailover=On<br />&lt;Proxy balancer://sticky-cluster&gt;<br />    BalancerMember http://localhost:8080/test route=8080<br />    BalancerMember http://localhost:18080/test route=18080 loadfactor=2<br />&lt;/Proxy&gt;</pre>

这个配置分为3个部分, 包括了 1)简单的反向代理, 2)非 session sticky 的 load balance, 以及
3)session sticky 的 load balance 三种方式的配置(这里假设两个 Tomcat 服务器的 HTTP 服务被配置在
8080 和 18080 端口), 其中第 2) 和 3) 的配置中 "nofailover=On" 适合于没有 session
复制的情况下, 这种情况下, 如果其中一台 HTTP 服务器出错, 那么原来分配在这个出错机器上的浏览器客户端不会被自动转移到另外的服务器上,
必须重新启动浏览器才能将请求分配到另外一台服务器上去.<br /><br /><h3>使用 JMeter 测试结果</h3>
使用 JMeter 对 "3)session sticky 的 load balance" 的效果进行测试, 通过压力测试的方式, 检查两台 Tomcat 服务器被分配到的请求数量, 相关的测试脚本参见文章最后的附件.<br /><br />

注意如果重复测试, 在下一次测试开始之前请对每个 Tomcat 服务器执行 .../test.jsp?clear=1 的请求, 清除上一次的计数结果.<br /><br />

从下图的测试结果可见: 50个线程中有21个被分配在 8080 端口的服务器上, 29个则被分配到 18080 端口的服务器; 另外, 所有的 session 请求次数都是 20 次, 说明 session sticky 达到了预期的效果.<img src ="http://www.blogjava.net/hszdz/aggbug/74376.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hszdz/" target="_blank">爪哇之家</a> 2006-10-10 20:59 <a href="http://www.blogjava.net/hszdz/articles/74376.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何使用Log4j？</title><link>http://www.blogjava.net/hszdz/articles/64544.html</link><dc:creator>爪哇之家</dc:creator><author>爪哇之家</author><pubDate>Sat, 19 Aug 2006 12:23:00 GMT</pubDate><guid>http://www.blogjava.net/hszdz/articles/64544.html</guid><description><![CDATA[
		<font size="2">
				<strong>1、 Log4j是什么？<br /></strong>  Log4j可以帮助调试（有时候debug是发挥不了作 用的）和分析，要下载和了解更详细的内容，还是访问其官方网站吧：</font>
		<a href="http://jakarta.apache.org/log4j">
				<font size="2">http://jakarta.apache.org/log4j</font>
		</a>
		<font size="2">。<br /><br /><strong>2、Log4j的概念</strong><br />  <!--StartFragment --> Log4j中有三个主要的组件，它们分别是</font>
		<font size="2">Logger、Appender和Layout，L<!--StartFragment -->og4j
允许开发人员定义多个Logger，每个Logger拥有自己的名字，Logger之间通过名字来表明隶属关系。有一个Logger称为Root，它永远
存在，且不能通过名字检索或引用，可以通过Logger.getRootLogger()方法获得，其它Logger通过
Logger.getLogger(String name)方法。<br />   Appender则是用来指明将所有的log信息存放到什么地方，Log4j中支持多种appender，如<!--StartFragment --></font>
		<font size="3">
		</font>
		<font size="2">console、files、GUI components、NT Event Loggers等，一个Logger可以拥有多个Appender，也就是你既可以将Log信息输出到屏幕，同时存储到一个文件中。<br />   Layout的作用是控制Log信息的输出方式，也就是格式化输出的信息。<br />  
Log4j中将要输出的Log信息定义了5种级别，依次为DEBUG、INFO、WARN、ERROR和FATAL，当输出时，只有级别高过配置中规定的
级别的信息才能真正的输出，这样就很方便的来配置不同情况下要输出的内容，而不需要更改代码，这点实在是方便啊。<br /><br /><strong>3、Log4j的配置文件</strong><br /> 
虽然可以不用配置文件，而在程序中实现配置，但这种方法在如今的系统开发中显然是不可取的，能采用配置文件的地方一定一定要用配置文件。Log4j支持两
种格式的配置文件：XML格式和Java的property格式，本人更喜欢后者，首先看一个简单的例子吧，如下：<br /><br /></font>
		<font color="#614db3">
				<font size="2">  log4j.rootLogger=debug, <strong>stdout, R</strong><br />  log4j.appender.<strong>stdout</strong>=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] <strong>(%F:%L)</strong> - %m%n<br /><br />  log4j.appender.<strong>R</strong>=org.apache.log4j.RollingFileAppender<br />  log4j.appender.R.File=example.log<br />  log4j.appender.R.MaxFileSize=</font>
				<font size="2">
						<strong>100KB<br /></strong>
						<br />  # Keep one backup file<br />  log4j.appender.R.MaxBackupIndex=1<br /><br />  log4j.appender.R.layout=org.apache.log4j.PatternLayout<br />  log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n         <br /><br /></font>
				<font color="#000000">
						<font size="2">  首先，是设置root，格式为<!--StartFragment --> log4j.rootLogger=[level],appenderName, ...，其中level就是设置需要输出信息的级别，后面是appender的输出的目的地，<!--StartFragment -->appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。</font>
						<font size="2">配置日志信息输出目的地Appender，其语法为<br /></font>
						<font size="2">  log4j.appender.appenderName = fully.qualified.name.of.appender.class<br />  log4j.appender.appenderName.option1 = value1<br />  ...<br />  log4j.appender.appenderName.option = valueN</font>
						<br />
						<font size="2">Log4j提供的appender有以下几种：<br />  org.apache.log4j.ConsoleAppender（控制台）<br />  org.apache.log4j.FileAppender（文件）<br />  org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件）<br />  org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生新文件）<br />  org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br /></font>
				</font>
		</font>
		<font color="#614db3">
				<font color="#000000">
						<font size="2">配置日志信息的格式（布局），其语法为：<br /></font>
						<font size="2">  log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class<br />  log4j.appender.appenderName.layout.option1 = value1<br />  ....<br />  log4j.appender.appenderName.layout.option = valueN</font>
						<br />
						<font size="2">Log4j提供的layout有以下几种：<br />  org.apache.log4j.HTMLLayout（以HTML表格形式布局），<br />  org.apache.log4j.PatternLayout（可以灵活地指定布局模式），<br />  org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串），<br />  org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息） <br /><br /></font>
				</font>
		</font>
		<font color="#000000">
				<span style="font-size: 10.5pt;">
						<font size="2">
								<span lang="EN-US">Log4J采用类似C语言中的printf函数的打印格式格式化日志信息，打印参数如下： %m 输出代码中指定的消息<o:p></o:p></span>
						</font>
				</span>
		</font>
		<p>
				<font color="#000000">
						<span style="font-size: 10.5pt;">
								<font size="2">　　</font>
								<span lang="EN-US">
										<font size="2">%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL <br />　　%r 输出自应用启动到输出该log信息耗费的毫秒数 <br />　　%c 输出所属的类目，通常就是所在类的全名 <br />　　%t 输出产生该日志事件的线程名 <br />　　%n 输出一个回车换行符，Windows平台为“\r\n”，Unix平台为“\n” <br />　　%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyy MMM dd HH:mm:ss,SSS}，输出类似：</font>
								</span>
						</span>
						<st1:chsdate isrocdate="False" islunardate="False" day="18" month="10" year="2002">
								<span style="font-size: 10.5pt;" lang="EN-US">
										<font size="2">2002年10月18日</font>
								</span>
						</st1:chsdate>
						<span style="font-size: 10.5pt;" lang="EN-US">
								<font size="2"> 22：10：28，921 <br />　　%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。举例：Testlog4.main(TestLog4.java:10)</font>
						</span>
				</font>
		</p>
		<br />
		<font color="#614db3">
				<font color="#000000">
						<font size="2">
								<br />
								<strong>4、Log4j在程序中的使用</strong>
						</font>
				</font>
		</font>
		<font color="#614db3">
				<font color="#000000">
						<br />
				</font>
				<font color="#a0a0a0">
						<font color="#090909" size="2"> 
要在自己的程序中使用Log4j，首先需要将commons-logging.jar和logging-log4j-1.2.9.jar导入到构建路径
中。然后再将log4j.properties放到src根目录下。这样就可以在程序中使用log4j了。在类中使用log4j，</font>
				</font>
		</font>
		<font color="#614db3">
				<font color="#a0a0a0">
						<font color="#090909" size="2">首先声明一个静态变量</font>
				</font>
		</font>
		<font color="#614db3">
				<font color="#a0a0a0">
						<font color="#090909" size="2">Logger
logger=Logger.getLog("classname")；现在就可以使用了，用法如下：logger.debug("debug
message")或者logger.info("info message")，看下面一个小例子：</font>
				</font>
		</font>
		<font color="#614db3">
				<font color="#a0a0a0">
						<br />
				</font>
				<br />
				<font size="2">  import com.foo.Bar;<br />  import org.apache.log4j.Logger;<br />  import org.apache.log4j.PropertyConfigurator;<br />  public class MyApp {<br />    static Logger logger = Logger.getLogger(MyApp.class.getName());<br />    public static void main(String[] args) {<br />      // BasicConfigurator replaced with PropertyConfigurator.<br />      PropertyConfigurator.configure(args[0]);<br />      logger.info("Entering application.");<br />      Bar bar = new Bar();<br />      bar.doIt();<br />      logger.info("Exiting application.");<br />    }<br />  }</font>
		</font>
<img src ="http://www.blogjava.net/hszdz/aggbug/64544.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hszdz/" target="_blank">爪哇之家</a> 2006-08-19 20:23 <a href="http://www.blogjava.net/hszdz/articles/64544.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTML结构化：实践DIV＋CSS网页布局入门指南(转载)</title><link>http://www.blogjava.net/hszdz/articles/63433.html</link><dc:creator>爪哇之家</dc:creator><author>爪哇之家</author><pubDate>Mon, 14 Aug 2006 03:40:00 GMT</pubDate><guid>http://www.blogjava.net/hszdz/articles/63433.html</guid><description><![CDATA[
		<div class="postbody">
				<p style="TEXT-INDENT: 2em">你正在学习CSS布局吗？是不是还不能完全掌握纯CSS布局？通常有两种情况阻碍你的学习： </p>
				<p style="TEXT-INDENT: 2em">第一种可能是你还没有理解CSS处理页面的原理。在你考虑你的页面整体表现效果前，你应当先考虑内容的语义和结构，然后再针对语义、结构添加CSS。这篇文章将告诉你应该怎样把HTML结构化。 </p>
				<p style="TEXT-INDENT: 2em">另一种原因是你对那些非常熟悉的表现层属性(例如：cellpadding,、hspace、align="left"等等)束手无策，不知道该转换成对 应的什么CSS语句。 当你解决了第一种问题，知道了如何结构化你的HTML，我再给出一个列表，详细列出原来的表现属性用什么CSS来代替。 </p>
				<p style="TEXT-INDENT: 2em">
						<strong>结构化HTML</strong>
				</p>
				<p style="TEXT-INDENT: 2em">我们在刚学习网页制作时，总是先考虑怎么设计，考虑那些图片、字体、颜色、以及布局方案。然后我们用Photoshop或者Fireworks画出来、切割成小图。最后再通过编辑HTML将所有设计还原表现在页面上。 </p>
				<p style="TEXT-INDENT: 2em">如果你希望你的HTML页面用CSS布局(是CSS-friendly的)，你需要回头重来，先不考虑“外观”，要先思考你的页面内容的语义和结构。 </p>
				<p style="TEXT-INDENT: 2em">外观并不是最重要的。一个结构良好的HTML页面可以以任何外观表现出来，CSS Zen Garden是一个典型的例子。CSS Zen Garden帮助我们最终认识到CSS的强大力量。 </p>
				<p style="TEXT-INDENT: 2em">HTML不仅仅只在电脑屏幕上阅读。你用photoshop精心设计的画面可能不能显示在PDA、移动电话和屏幕阅读机上。但是一个结构良好的HTML页面可以通过CSS的不同定义，显示在任何地方，任何网络设备上。 </p>
				<p style="TEXT-INDENT: 2em">
						<strong>开始思考</strong>
				</p>
				<p style="TEXT-INDENT: 2em">首先要学习什么是"结构"，一些作家也称之为"语义"。这个术语的意思是你需要分析你的内容块，以及每块内容服务的目的，然后再根据这些内容目的建立起相应的HTML结构。 </p>
				<p style="TEXT-INDENT: 2em">如果你坐下来仔细分析和规划你的页面结构，你可能得到类似这样的几块： </p>
				<p style="TEXT-INDENT: 2em">标志和站点名称 </p>
				<p style="TEXT-INDENT: 2em">主页面内容 </p>
				<p style="TEXT-INDENT: 2em">站点导航(主菜单) </p>
				<p style="TEXT-INDENT: 2em">子菜单 </p>
				<p style="TEXT-INDENT: 2em">搜索框 </p>
				<p style="TEXT-INDENT: 2em">功能区(例如购物车、收银台) </p>
				<p style="TEXT-INDENT: 2em">页脚(版权和有关法律声明) </p>
				<p style="TEXT-INDENT: 2em">我们通常采用DIV元素来将这些结构定义出来，类似这样： </p>
				<p style="TEXT-INDENT: 2em">＜div id="header"＞＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">＜div id="content"＞＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">＜div id="globalnav"＞＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">＜div id="subnav"＞＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">＜div id="search"＞＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">＜div id="shop"＞＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">＜div id="footer"＞＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">这不是布局，是结构。这是一个对内容块的语义说明。当你理解了你的结构，就可以加对应的ID在DIV上。DIV容器中可以包含任何内容块，也可以嵌套另一个DIV。内容块可以包含任意的HTML元素---标题、段落、图片、表格、列表等等。 </p>
				<p style="TEXT-INDENT: 2em">根据上面讲述的，你已经知道如何结构化HTML，现在你可以进行布局和样式定义了。每一个内容块都可以放在页面上任何地方，再指定这个块的颜色、字体、边框、背景以及对齐属性等等。 </p>
				<p style="TEXT-INDENT: 2em">
						<strong>使用选择器是件美妙的事</strong>
				</p>
				<p style="TEXT-INDENT: 2em">id的名称是控制某一内容块的手段,通过给这个内容块套上DIV并加上唯一的id,你就可以用CSS选择器来精确定义每一个页面元素的外观表现,包括标 题、列表、图片、链接或者段落等等。例如你为#header写一个CSS规则，就可以完全不同于#content里的图片规则。 </p>
				<p style="TEXT-INDENT: 2em">另外一个例子是：你可以通过不同规则来定义不同内容块里的链接样式。类似这样：#globalnav a:link或者 #subnav a:link或者#content a:link。你也可以定义不同内容块中相同元素的样式不一样。例如，通过#content p和#footer p分别定义#content和#footer中p的样式。从结构上讲，你的页面是由图片、链接、列表、段落等组成的，这些元素本身并不会对显示在什么网络 设备中(PDA还是手机或者网络电视)有影响，它们可以被定义为任何的表现外观。 </p>
				<p style="TEXT-INDENT: 2em">一个仔细结构化的HTML页面非常简单，每一个元素都被用于结构目的。当你想缩进一个段落，不需要使用blockquote标签，只要使用p标签，并对p 加一个CSS的margin规则就可以实现缩进目的。p是结构化标签，margin是表现属性，前者属于HTML，后者属于CSS。(这就是结构于表现的 相分离.) </p>
				<p style="TEXT-INDENT: 2em">良好结构的HTML页面内几乎没有表现属性的标签。代码非常干净简洁。例如，原先的代码＜table width="80%" cellpadding="3" border="2" align="left"＞，现在可以只在HTML中写＜table＞，所有控制表现的东西都写到CSS中去，在结构化的HTML中， table就是表格，而不是其他什么(比如被用来布局和定位)。 </p>
				<p style="TEXT-INDENT: 2em">
						<a name="part">
								<font color="#1d58d1">
										<strong>亲自实践一下结构化</strong>
								</font>
						</a>
				</p>
				<p style="TEXT-INDENT: 2em">上面说的只是最基本的结构，实际应用中，你可以根据需要来调整内容块。常常会出现DIV嵌套的情况，你会看到"container"层中又有其它层，结构类似这样： </p>
				<p style="TEXT-INDENT: 2em">＜div id="navcontainer"＞ </p>
				<p style="TEXT-INDENT: 2em">＜div id="globalnav"＞ </p>
				<p style="TEXT-INDENT: 2em">＜ul＞a list＜/ul＞ </p>
				<p style="TEXT-INDENT: 2em">＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">＜div id="subnav"＞ </p>
				<p style="TEXT-INDENT: 2em">＜ul＞another list＜/ul＞ </p>
				<p style="TEXT-INDENT: 2em">＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">＜/div＞ </p>
				<p style="TEXT-INDENT: 2em">嵌套的div元素允许你定义更多的CSS规则来控制表现，例如：你可以给#navcontainer一个规则让列表居右，再给#globalnav一个规则让列表居左，而给#subnav的list另一个完全不同的表现。 </p>
				<p style="TEXT-INDENT: 2em">
						<strong>用CSS替换传统方法</strong>
				</p>
				<p style="TEXT-INDENT: 2em">下面的列表将帮助你用CSS替换传统方法： </p>
				<p style="TEXT-INDENT: 2em">HTML属性以及相对应的CSS方法 </p>
				<p style="TEXT-INDENT: 2em">HTML属性 </p>
				<p style="TEXT-INDENT: 2em">CSS方法说明 </p>
				<p style="TEXT-INDENT: 2em">align="left" </p>
				<p style="TEXT-INDENT: 2em">align="right" float: left; </p>
				<p style="TEXT-INDENT: 2em">float: right; 使用CSS可以浮动 任何元素:图片、段落、div、标题、表格、列表等等 </p>
				<p style="TEXT-INDENT: 2em">当你使用float属性，必须给这个浮动元素定义一个宽度。 </p>
				<p style="TEXT-INDENT: 2em">marginwidth="0" leftmargin="0" marginheight="0" topmargin="0" margin: 0; 使用CSS, margin可以设置在任何元素上, 不仅仅是body元素.更重要的，你可以分别指定元素的top, right, bottom和left的margin值。 </p>
				<p style="TEXT-INDENT: 2em">vlink="#333399" alink="#000000" link="#3333FF" a:link #3ff; </p>
				<p style="TEXT-INDENT: 2em">a:visited: #339; </p>
				<p style="TEXT-INDENT: 2em">a:hover: #999; </p>
				<p style="TEXT-INDENT: 2em">a:active: #00f; </p>
				<p style="TEXT-INDENT: 2em">在HTML中，链接的颜色作为body的一个属性值定义。整个页面的链接风格都一样。使用CSS的选择器，页面不同部分的链接样式可以不一样。 </p>
				<p style="TEXT-INDENT: 2em">bgcolor="#FFFFFF" background-color: #fff; 在CSS中，任何元素都可以定义背景颜色，不仅仅局限于body和table元素。 </p>
				<p style="TEXT-INDENT: 2em">bordercolor="#FFFFFF" border-color: #fff; 任何元素都可以设置边框(boeder)，你可以分别定义top, right, bottom和left </p>
				<p style="TEXT-INDENT: 2em">border="3"cellspacing="3" border-width: 3px; 用CSS，你可以定义table的边框为统一样式，也可以分别定义top, right, bottom and left边框的颜色、尺寸和样式。 </p>
				<p style="TEXT-INDENT: 2em">你可以使用 table, td or th 这些选择器. </p>
				<p style="TEXT-INDENT: 2em">如果你需要设置无边框效果，可以使用CSS定义： border-collapse: collapse; </p>
				<p style="TEXT-INDENT: 2em">＜br clear="left"＞ </p>
				<p style="TEXT-INDENT: 2em">＜br clear="right"＞ </p>
				<p style="TEXT-INDENT: 2em">＜br clear="all"＞ </p>
				<p style="TEXT-INDENT: 2em">clear: left; </p>
				<p style="TEXT-INDENT: 2em">clear: right; </p>
				<p style="TEXT-INDENT: 2em">clear: both; </p>
				<p style="TEXT-INDENT: 2em">许多2列或者3列布局都使用 float属性来定位。如果你在浮动层中定义了背景颜色或者背景图片，你可以使用clear属性. </p>
				<p style="TEXT-INDENT: 2em">cellpadding="3" </p>
				<p style="TEXT-INDENT: 2em">vspace="3" </p>
				<p style="TEXT-INDENT: 2em">hspace="3" padding: 3px; 用CSS，任何元素都可以设定padding属性，同样，padding可以分别设置top, right, bottom and left。padding是透明的。 </p>
				<p style="TEXT-INDENT: 2em">align="center" text-align: center; </p>
				<p style="TEXT-INDENT: 2em">margin-right: auto; margin-left: auto; </p>
				<p style="TEXT-INDENT: 2em">Text-align 只适用于文本. </p>
				<p style="TEXT-INDENT: 2em">象div，p这样的块级可以通过margin-right: auto; 和margin-left: auto;来水平居中 </p>
				<p style="TEXT-INDENT: 2em">
						<strong>一些令人遗憾的技巧和工作环境 </strong>
				</p>
				<p style="TEXT-INDENT: 2em">由于浏览器对CSS支持的不完善，我们有时候不得不采取一些技巧(hacks)或建立一种环境(Workarounds)来让CSS实现传统方法同样的效 果。例如块级元素有时侯需要使用水平居中的技巧，盒模型bug的技巧等等。所有这些技巧都在Molly Holzschlag的文章《Integrated Web Design: Strategies for Long-Term CSS Hack Management》中有详细说明</p>
		</div>
<img src ="http://www.blogjava.net/hszdz/aggbug/63433.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hszdz/" target="_blank">爪哇之家</a> 2006-08-14 11:40 <a href="http://www.blogjava.net/hszdz/articles/63433.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP 70问</title><link>http://www.blogjava.net/hszdz/articles/63426.html</link><dc:creator>爪哇之家</dc:creator><author>爪哇之家</author><pubDate>Mon, 14 Aug 2006 03:22:00 GMT</pubDate><guid>http://www.blogjava.net/hszdz/articles/63426.html</guid><description><![CDATA[
		<div class="postbody">1. 问：在JAVA与JSP中要调用一个LINUX上的脚本程序,或WINDOWS上的脚本程序,该怎么写？<br />答：System.getRuntime().exec("bash &lt; aaa.sh");<br /><br />2. 问：java中用什么表示双引号<br />答："""<br /><br />3. 问：如何在JSP程序里另起一个线程？<br />答：<br />JSP本身就是独立线程运行而不象CGI都是独立进程.<br />一般:<br />Thread t = new Thread("你的对象");<br />t.start();就可以了.<br />要求你这个对象要实现runnable接口或继承thread.<br /><br />4. 问：jsp如何获得客户端的IP地址？<br />答：<br />request.getRemoteAddr()<br />看看各个webserver的API文档说明，一般都有自带的，resin和tomcat都有<br /><br />5. 问：程序终止与输出终止<br />答：<br />程序中止:return;<br />输出中止out.close();这一句相当于ASP的response.end<br /><br />6. 问：jsp中如何得到上页的URL？<br />答：request.getHeader("referer");<br /><br />7. 问：提交网页的网页过期功能是怎么做的？<br />答：response.setHader("Expires","0");<br /><br />8. 问：在JSP网页中如何知道自已打开的页面的名称<br />答：<br />request.getRequestURI() ;//文件名<br />request.getRequestURL() ;//全部ＵＲＬ<br /><br />9. 问：提交表单后验证没有通过，返回提交页面，如何使原提交页面中的数据保留？<br />答：javascript的go(-1)可以把上页的表单内容重新显示出来,但password域没有<br /><br />10. 问：如何取得http的头信息？<br />答：request.getHader(headerName);<br /><br />11. 问：&amp;&amp;和&amp;的区别？<br />答：<br />&amp;&amp;是短路的与操作，也就是当地一个条件是false的时候，第二个条件不用执行<br />&amp;相反，两个条件总是执行。<br /><br />12. 问：将*以正弦曲线的一个周期显示出来<br />答：<br />public void paint(Graphics g)<br />{<br />for(int i=0;i&lt;200;i++)<br />g.drawString("*",i,(int)(Math.sin(i)*20)+50);<br />}<br />}<br /><br />13. 问：浮点数相乘后结果不精确如100.0 * 0.6 结果等于 60.0004<br />答：<br />这不叫错误,float和double是这样实现的.如果要精确计算，java提供了一个strictfp,它的计算遵循IEEE 754标准.而普通的float和double是<br /><br />由地平台浮点格式或硬件提供的额外精度或表示范围。<br /><br />14. 问：如何获得当前用的cursors的位置？<br />答：<br />int row = rs.getRow()就是当前指针行数,还有isFrist();isBeforeFist();isLast();isAfterLast();可以测试是不是在方法名所说的位置<br /><br />15. 问：表单成功提交了，点后退显示网页过期<br />答：<br />在&lt;head&gt;&lt;/head&gt;里面加以下代码<br />&lt;META HTTP-EQUIV="Pragma" CONTENT="no-cache"&gt; <br />&lt;META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"&gt; <br />&lt;META HTTP-EQUIV="Expires" CONTENT="0"&gt; <br />或者在表单页中加上<br />&lt;% <br />response.setHeader("Pragma","no-cache"); <br />response.setHeader("Cache-Control","no-cache"); <br />response.setDateHeader("Expires",0); <br />%&gt;<br /><br />16. 问：接口的简单理解<br />答：接口为了规范,比如我在接口中定义了一个方法:<br />getData()<br />这是用来从不同的数据库中取数据的,就是JDBC的实现对于用户,我不要知道每种数据库是如何做的,但我知道如何它们要实现这个接口就一定有<br /><br />这个方法可以供我调用.这样SUN就把这个接口给各个数据库开发商,让他们自己实现. 但为什么不用继承而用接口哩,因为继承只能从一个你类<br /><br />继承,而接口可以实现多个,就是说我实现的子类有多个规定好的接口中的功能. 这只是简单的理解,等你深入理解抽象的时候就知道抽象到抽象<br /><br />类时为什么还要再抽象到接口.<br /><br />17. 问：怎样编写一个取消按钮（怎样返回上一个页面，象工具栏的后退按钮）？<br />答：<br />javascript把每次浏览过的location都压到了一个栈中,这个栈就是history,然后你如果要回到第几个页面它就做几次POP操作,把最后POP出来<br /><br />的那个LOCATION给你. 这就是JAVASCRIPT在实现history.go(-x)的原理.<br /><br />18. 问：什么是回调？<br />答：<br />简单说,回调用不是让你去监听谁做完了什么事,而是谁做完了什么事就报告给你. 这就是回调用的思想.例子太多了,AWT的事件,SWING事件模型<br /><br />都是这样有. 还有多线程中,如果要控制线程数,不能总是查询每个线程是否结束,要在每个线程结束时让线程自己告诉主线程我结束了,你可以<br /><br />开新的线程了.<br /><br />19. 问：简要介绍一下compareTo方法<br />答：<br />compareTo方法是Comparable 接口必需实现的方法,只要实现Comparable <br /><br />就可以用Arrays.srot()排序就象实现Runnable接口的run就能Thread()一样.<br /><br />20. 问：如何可以从别的Web服务器检索页, 然后把检索到的网页的HTML代码储存在一个变量中返回过来<br />答：这是一个简单的WEB ROBOT实现,用URL类实现从网页中抓内容,然后自己写一个分析程序从中找出新的URL,不断递归下去就行了.<br /><br />21. 问：applet中如何获得键盘的输入<br />答：application的System.in是当前系统的标准输入,applet因为安全的原因不可能读取当前系统(客户端)的标准输入,只能从它的ROOT组件的<br /><br />事件中,比如键盘事件中取得键值.<br /><br />22. 问：怎样计算代码执行所花费的时间？<br />答：<br />代码开始取时间，结束后取时间，相减<br />long t1 = System.currentTimeMillis();<br />///////////////// your code<br />long t2 = System.currentTimeMillis() ;<br />long time = t2-t1;<br /><br />23. 问：如何获在程序中获得一个文件的ContentType？<br />答：<br />URL u = new URL("file:///aaa.txt");<br />URLConnection uc = u.openConnection();<br />String s = uc.getContentType();<br /><br />24. 问：连接池的使用是建立很多连接池，还是一个连接池里用多个连接？<br />答：<br />只有在对象源不同的情况下才会发生多个池化,如果你只连一结一个数据源,永远不要用多个连结池. 所以连结池的初始化一定要做成静态的,而<br /><br />且应该在构造对象之前,也就是只有在类LOAD的时候,别的时候不应该有任何生成新的连结池的时候。<br /><br />25. 问：JavaMail要怎么安装？<br />答：下载两个包，一个是javamail包，另一个是jaf包。下载完直接把这两个包不解压加到CLASSPATH。<br /><br />26. 问：怎样把地址栏里的地址锁定？<br />答：把你的服务器的可访问目录索引选项关闭就行了,任何服务器都有一个conf文件,里面都有这个选项。<br /><br />27. 问：在JAVA中怎么取得环境变量啊。比如： TEMP = C：TEMP ？<br />答：String sss = System.getProperty(key)<br /><br />28. 问：怎样实现四舍五入，保留小数点后两位小数？<br />答：<br />import java.text.*;<br />...<br />NumberFormat nf=NumberFormat.getNumberInstance();<br />nf.setMaximumFractionDigits(2);<br />nf.setMinimumFractionDigits(2);<br />nf.format(numb);<br /><br />29. 问：Applet和form如何通信？<br />答：<br />取得的参数传到param里面<br />&lt;% <br />String xxx = request.getParameter("xxx"); <br />%&gt; <br />&lt;applet&gt; <br />&lt;param value="&lt;%=xxx%&gt;"&gt; <br />&lt;/applet&gt;<br /><br /><br />30. 问：java-plug-in是什么？<br />答：Java Runtime Environment的插件。用来运行java程序。不需要什么特别的设置。等于你的机器里面有了jvm。<br /><br />31. 问：WEB上面怎么样连接上一个EXCEL表格？<br />答：<br />定义页面得contentType="application/vnd.ms-excel"，让页面以excel得形式打开。同样也可以以word得形式打开：application/msword。<br /><br />32. 问：怎样才能避免textarea字数限制？<br />答：是使用了FORM的默认方法的缘故,如果什么也不写默认是GET改用Post即可，在Form中定义mothod="post"。<br /><br />33. 问：为什么加了&lt;%@page contentType="text/html;charset=gb2312" %&gt;插入数据库的中文，依然是乱码？<br />答：<br />这要从环境看,能显示说明你的JSP引擎没有问题,但写入数据库时你的JDBC能不能处理中文,同一公司不同版本的JDBC都有支持中文和不支持中<br /><br />文的情况,RESIN自带的MYSQL JDBC就不支持,MM的就支持,还有你的数据库类型是否支持中文?CHAR的一般支持,但是否用binary存储双字节码<br /><br />34. 问：对于JFrame，hide()，show()与setVisibel()有什么区别吗？<br />答：<br />setVisible()从Component继承过来，而hide(),show()从Window里面继承过来。<br />Makes the Window visible. If the Window and/or its owner are not yet displa yable, both are made displayable. The Window will <br /><br />be validated prior to being made visible. If t he Window is already visible, this will bring the Window to the front. 区别在<br /><br />这。<br />36. 问：sendRedirect为什么不可以转到mms协议的地址的？response.sendRedirect("mms://missiah.adsldns.org:9394");<br />答：java平台目前实现的protocol中并没有mms,你可以取系统属性java.protocol.handler.pkgs看看它的值中有没有mms,所以如果要想重定向<br /><br />到mms://host这样和URL,只有生成客户端的JAVASCRIPT让它来重定向<br /><br />37. 问：JTable中怎样定义各个Columns和Width和怎样设置表格的内容靠做靠右或居中？<br />答：<br />TableColumn tc = table.getColumn("Name");//取得列名为"Name"的列Handle<br />int currentWidth = tc.getPreferredWidth(); //取得该列当前的宽度<br />tc.setPreferredWidth(200); //设置当前列宽<br />tc.setMaxWidth(200); //设置该列最大宽度<br />tc.setMinWidth(50); //设置该列最小宽度<br /><br />38. 问：批操作是否可用于select语句？<br />答：批操作其实是指成批理更新的操作,绝对不可能用于select操作。<br /><br />39. 问：为什么jsp路径太深文件名太长就无法读取文件？<br />答：path不能超过255长度,不然就找不到了.这是作业系统的事。<br /><br />40. 问：如何让页面不保留缓存？<br />答：<br />&lt;% <br />response.setHeader("Pragma","No-cache"); <br />response.setHeader("Cache-Control","no-cache"); <br />response.setDateHeader("Expires", 0); <br />%&gt;<br /><br />41. 问：我的applet code 中用到jbutton 时就出错是否由于ie不支持swing package 请问应怎么办？<br />答：JBUTTON是SWING基本包啊,只要把jdk/jre/lib/rt.jar放在classpath就行了.不要加载任何别的库。<br /><br />42. 问：不知道java是否支持midi格式，如果支持，应该怎么把wave格式转换成midi格式？<br />答：目前还不行,可以看一下JMF三个版中对MIDI的格式支持是read only,而WAVE是read/write,MIDI只能播放,不能生成。<br /><br />43. 问：在jsp里面防止用户直接输入url进去页面，应该怎么做呢？<br />答：<br />一是从web服务器控制,对某一目录的所有访问要通过验证.<br />二是在要访问的页面中加入控制.这个一般用session,也可以用请求状态码实现<br /><br />44. 问：<br />例如后台有一计算应用程序（此程序运算起来很慢，可持续几分钟到几小时，这不管，主要是能激活它），客户机讲任务提交后，服务器对任<br /><br />务进行检测无误后将向服务器后台程序发送信息，并将其激活。要求如下：<br />1）首先将后台程序激活，让它执行此任务（比如，前台将计算的C代码提交上后，后台程序程序能马上调用，并将其运行）<br />2）要在前台JSP页面中显示运行过程信息（由于运行时间长，希望让客户看到运行过程中产生的信息）如何完成？<br /><br />答：<br />活是可以的,运行一个shell让它去运行后台就行,但不可能取出运行信息,因为HTTP的超时限制不可能永远等你后台运行的,而且信息如果要动态<br /><br />实时推出来就得用SERVER PUSH技术。<br /><br />45. 问：数据库是datetime 型 ，插入当前时间到数据库？<br />答：<br />java.sql.Date sqlDate = new java.sql.Date();<br />PreparedStatement pstmt = conn.prepareStatement("insert into foo(time) values(?)");<br />pstmt.setDate(1,sqlDate);<br />pstmt.executeUpdate();<br /><br />46. 问：怎样去掉字符串前后的空格。<br />答：String.trim()<br /><br />47. 问：session怎样存取int类型的变量？<br />答：<br />session.setAttribute("int", i+"");<br />int i = Integer.parseInt(session.getAttribute("int"));<br /><br />48. 问：在javascript中如何使输出的float类型的数据保留两位小数。<br />答：Math.round(aaaaa*100)/100。<br /><br />49. 问：在bean种如何调用session<br />答：<br />你可把session对象作为一个参数传给bean<br />在BEAN中定义HttpServletRequest request;HttpSession session;<br />然后<br />session = request.getSession(false);<br />false为如果session为空,不建立新的session<br />将session作为参数传入.其实只要将request传入就可以<br /><br />50. 问：如何把txt或word文件按原格式显示在jsp页面或servlet上？<br />答：<br />其实一个非常简单的解决方法就是在服务器的MIME中指点定TEXT和WORD的解释方式,然后用JSP或SERVLET生成它就行了,客户端就会自动调用相<br /><br />应程序打开你的文档。<br />如果是希望按原格式的显示在页面上，而不是调用其他程序打开那么你可以试试用WEBDEV协议,可以说这是MS的一个亮点.它是在WEB方式下打开<br /><br />文档,和共享一样.完全符合的要求。<br /><br />51. 问：object的clone方法为什么不能直接调用？<br />答：<br />这个方法在object中是protected<br />为什么要把这个方法定义为protected,这是一个折中,它的目的是想知道你这个方法在Object里只是一个标记,而不是一个实现,比如<br /><br />public class Object<br />{<br />.............<br />protected Object clone()<br />{}<br />}<br /><br />所以直接继承的clone()方法并不能做任何时,你要使用这个方法就要重载这个方法并放宽访问权限为public,或实现cloneable接口. 但它没法<br /><br />这样告诉你它没有真的实现,只好用protected 方法加以警示<br /><br />52. 问：一个页面中如何刷新另外一个页面？<br />答：<br />要求是这些面页必须有关联,一是它们都有一个共同的顶层帧,也就是说是一个帧内的分级页面,当然可以是任意级,帧内再分帧也可以,另一个可<br /><br />能是当前窗口弹出的窗口,如果没有联系,那就不可能用一个页面刷新另一个页面. 帧内只要一级一级引用就行了. <br /><br />比如在左帧中一个页面中写top.right.location.reload();那么名为right的右帧中的页面就会刷新. 弹出的一样,用open时的名称刷新子窗口,<br /><br />子窗口用opener刷新主窗口<br /><br />53. 问：如何在jsp中怎么样向客户端写cookies？<br />答：<br />Cookie coo = new Cookie(name, value);<br />HttpServletResponse.addCookie(name);<br /><br />54. 问：为什么jTextField1.setText("aaabbb");jTextField2.setText("AAABBB"); 得到的字体宽度不一样？<br />答：就是说如果不是指定为等宽字体,每个字体的宽度都是不一样的.因此JAVA中用FontMetrics 类来取字符宽度。<br /><br />55. 问：String kk=application/octet-stream; name="G:/SMBCrack.exe";如何得到SMBCrack.exe？<br />答：<br />这应该是解析上传时候的二进制流得到的这一行里面格式是固定的，取到name="后面的字符串，然后把";去掉。然后取最后一个/后面的所有字<br /><br />符组成一个新字符串就行了。<br /><br />56. 问：如何传值并不刷新页面？<br />答：<br />弹出一个页面进行值的选择或者输入，ok后使用将值传给原窗口，使用javascript关闭打开的窗口即可：<br />window.close();opener.focus();<br /><br />57. 问：有一个字符串："EF0C114EA4"，如何变为a[0] = 0xEF a[1] = 0x0C a[2] = 0x11 a[3] = 0x4E a[4] = 0xA4？<br />答：<br />String str="EF0C114EA4F";<br />out.print(str+"&lt;br&gt;");<br />int l=str.length()/2+str.length()%2,j=0,k=0;<br />String[] a=new String[l];<br />for(int i=0;i&lt;l;i++){<br />if(str.length()-j==1)<br />k=str.length();<br />else<br />k=j+2;<br />a="0x"+str.substring(j,k);<br />out.print("a["+Integer.toString(i)+"]="+a+"&lt;br&gt;");<br />j+=2;<br />}<br /><br />58. 问：怎样将一个int转换成一个四字节的byte数组？<br />答：<br />int x = 1234567;<br />byte[] b = new byte[4];<br />for(int i=0;i&lt;b.length;i++)<br />{<br />b = (x &gt;&gt;( i*8)) &amp; 0xFF;<br />}<br /><br />59. 问：indexOf()的使用需要注意什么？<br />答：参数是指从第几位（1，2，3，...）开始搜索，而返回值是指搜索到的位置（0，1，2，3.......）注意是从零算起的。<br /><br />60. 问：在Java应用程序中如何动态的添加一个按钮？<br />答：<br />这里涉及一个组件重绘的问题,组件要先于panel被显示之处存在,如果一panel已经显示了,那么加在上面你能看到吗?但如果在同一个panel上, <br /><br />先有button A,假如按下它加了butt on B,这时你如果使整个panel重给,那么A本身要重绘,它的事件监听就没有了,当然也就加不成B了,所以如<br /><br />果要先有另一个panel,当按A时把B加在这个panel上并重绘这个paenl,其实更好的方法是先把B加在panel中,同一个也行.把它setVisiable(flas<br /><br />e),按A时设为 true。<br /><br />61. 问：book mybook=new book(bookid);book是servlet,出错。<br />答：<br />book是servlet,能book mybook=new book(bookid);<br />说明自己实现了servlet容器?不然,servlet能让你自己去调用? servlet如果调用其实和EJB连1%的区别都没有,它们都是自己继承或实现一些接<br /><br />口,在这些父类或接口中实现了如果和容器"打交道"的方法,然后容器调用这些方法来管理它,让它生成实例,池化,钝化,销毁,再生等.所以这样<br /><br />写是错误的。<br /><br />62. 问：给定一个字符串5*(5+9)/7怎样计算出结果？<br />答：<br />可有两种方法<br />1。用堆栈完成<br />2。最简单的方法，不用编程，如果有任何一个数据库的化，用select (5*(5+9)/7) from oneTable<br /><br />63. 问：如何实现递交表单内容的加密解密？<br />答：<br />如果你用IE目前只能用SSL协议,这一层不要你考虑,否则只你用你自己的工具加密传输,接收后再解密友,至于如何加解,如果要和公认的系统结<br /><br />合,就用通用的MD5,RAS等公开算法,如果你只是自己传自己解,你随便按你的想法把数据加上一些东西,取回来按规则减掉这些东西,我敢保证除<br /><br />你自己没有任何人能知道解密方法.<br /><br />64. 问：为什么Integer.parseInt("+1");会抛出NumberFormatException的异常？<br />答：因为"+"运行算在JAVA中被重载.系统无法确定你用的是算术加还是字符+。<br />这一点可以在JAVASCRIPT中更好地理解:<br />&lt;form name="t"&gt;&lt;input name=s value=1234&gt;&lt;/form&gt;<br />var a = document.t.s.value+1;<br />这时a = 12345,因为document.t.s.value作为字符串.但var a = document.t.s.value-1;<br />a 就是1233,因为系统知道-运算肯定是算术运行.所以把document.t.s.value转换成数字.<br /><br /><br />65. 问：hashCode() 有什么用为什么有时候需要覆盖Object里的hashcode()方法？<br />答：这就是这个对象的身份证啊,要不如何区分哪个对象。<br /><br />66. 问：怎样在tomcat中实现一个定时执行的东东？<br />答：<br />在应用程序启动时自动运行。servlet2.3中定义了ServletListener,监听Servlet Con text的启动或则关闭（可在配置文件中配置），启动时<br /><br />触发一个守护程序的运行(可以实现java.util.Timer或则 javax.swing.Timer).<br /><br />67. 问：程序可以输出自己吗？<br />答：孔德悖论这个非常有名的法则.就是说任何程序都不可能输出自己.<br /><br />68. 问：能够把字符转化成ASCII码？比如将 A 转化成 65？<br />答：<br />int a='A';<br />out.println(a);<br /><br />69. 问：如何区分输入的文字中的全角与半角？<br />答：由于不能分辨出全角和半角字符的值有什么规律,只好把全角符号牧举出来了.<br /><br />70. 问：用户注册后的自动发信程序该怎么做？<br />答：<br />这种发信程序不考虑性能,因为不可能1秒就有一个人注册,我们说的考虑性能的发信程序是指上百万封信在队列里要不停发送的那种,象你这个<br /><br />随便怎么写一个程序都行,没有必要用JAVAMAIL.只要指定一个发信的服务器然后用cocket连它的25口就行了.自己用SOCKET连SMTP的25口发一封<br /><br />信就好象两个邻居之间送一样东西,直接递过去得了,用JAVAMAIL,消息机制就是你把这个东西从邮局寄给你的邻居了. </div>
<img src ="http://www.blogjava.net/hszdz/aggbug/63426.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hszdz/" target="_blank">爪哇之家</a> 2006-08-14 11:22 <a href="http://www.blogjava.net/hszdz/articles/63426.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用JSF、SpringFramework和Hibernate构建Web应用的实例讲述</title><link>http://www.blogjava.net/hszdz/articles/21507.html</link><dc:creator>爪哇之家</dc:creator><author>爪哇之家</author><pubDate>Sat, 26 Nov 2005 07:09:00 GMT</pubDate><guid>http://www.blogjava.net/hszdz/articles/21507.html</guid><wfw:comment>http://www.blogjava.net/hszdz/comments/21507.html</wfw:comment><comments>http://www.blogjava.net/hszdz/articles/21507.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hszdz/comments/commentRss/21507.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hszdz/services/trackbacks/21507.html</trackback:ping><description><![CDATA[<font face="verdana, arial, helvetica" size="2">[原作者]</font><font face="verdana, arial, helvetica" size="2"><strong> Derek Yang Shen<br></strong>[原文链接] <a href="http://www.javaworld.com/javaworld/jw-07-2004/jw-0719-jsf.html">http://www.javaworld.com/javaworld/jw-07-2004/jw-0719-jsf.html</a><br>[源码链接] <a href="http://www.javaworld.com/javaworld/jw-07-2004/jsf/jw-0719-jsf.zip">http://www.javaworld.com/javaworld/jw-07-2004/jsf/jw-0719-jsf.zip</a><br>[翻译] 本人<br>[点评] 该文是我看的第一篇讲述JSF与Spring整合的文章，是一个很好的范例，比较适合于对Spring有了一定了解人学习。其中大量篇幅讲述的JSF，对JSF感兴趣的也可以来看看。<br>[声明] 该文是本人第一次翻译大块头的文章，由于本人才疏学浅、英语较烂，但考虑到和我一样不喜欢看洋文的大有人在，遂用近4小时的时间翻译该文，对一些技术名词和不会翻译的地方用原文代替，其中难免有很多错误，欢迎批评指正。<br><br>[译文]<br><br>JSF
是一种新的用于构架j2ee应用用户界面的技术，它尤其适合于基于MVC架构的应用中。虽已有很多文章介绍过了JSF，然而它们大多从理论高度来介绍
JSF而不是面向于实际应用。目前对于实际应用，JSF仍有很多问题没有解决，例如：如何使JSF适应于MVC整体构架中？如何将JSF与其他Java
框架整合起来？是否应该将业务逻辑放置在JSF的backing
beans中？如何处理JSF中的安全机制？更为重要的是如何利用JSF构架现实世界的Web应用？<br><br>本文将涉及到上面的这些问题，它将演示如何将JSF、Spring和Hibernate整合在一起，构架出一个名为JCatalog的</font><font face="verdana, arial, helvetica" size="2">在线产品价目系统</font><font face="verdana, arial, helvetica" size="2">。利用该Demo，本文涵盖了Web应用开发的每一个阶段，包括需求收集、分析，技术选择，系统架构和实现。本文讨论了在JCatalog中涉及到的各种技术的优点和缺点并展示了一些关键部分的设计方法。<br><br>本文的对象是从事基于J2ee的Web应用架构人员和开发人员，它并不是对JSF、SpringFramework和Hibernate的简单介绍，如果对这些领域不甚了解，请参看相关资源。<br><br><font size="5"><b>该范例的功能需求</b></font><br>JCatalog是一个现实世界的Web应用，我首先描述JCatalog的需求，在通篇的技术决策和架构设计时都将涉及到本部分。<br><br>在
设计Web应用的第一阶段是收集系统的功能需求，范例应用是一个典型的电子商务应用系统，用户可以浏览产品的catalog并查看产品的详细情况，而管理
员可以管理产品的catalog。通过增加一些其他功能，如inventory管理和订单处理等，该应用可成为一个成熟的电子商务系统。<br><br><b><font size="3">Use cases</font></b><br>Use-case分析被用来展示范例应用的功能需求，图1就是该应用的use-case图。<br>&nbsp;&nbsp;&nbsp;&nbsp; <p align="center"><a href="http://www.huihoo.com/java/jsf/jw-0719-jsf1.gif"><img style="width: 324px; height: 196px;" alt="" src="http://www.huihoo.com/java/jsf/jw-0719-jsf1.gif" align="bottom" border="0" height="127" hspace="0" width="228"></a></p><br>use
-case图用于表示系统中的actors以及可能进行的operations，在该应用中将有七个use-case，用户能够浏览产品
catalog和查看产品的详细情况，一旦用户登录到系统中，她将成为管理员，从而可以创建新的产品，编辑已存在的产品或者删除老的产品等。<br><br><b><font size="3">Business rules</font></b><br>JCatalog必须符合以下business rules:</font> 
<ul>
<li><font face="verdana, arial, helvetica" size="2">每个产品必须具有唯一的ID</font> </li><li><font size="2">每个产品必须属于至少一个category</font><font face="verdana, arial, helvetica" size="2"> <br></font> </li><li><font face="verdana, arial, helvetica" size="2">产品ID一旦创立不得修改</font></li>
</ul>
<font face="verdana, arial, helvetica" size="2"><b><font size="3">Assumptions</font></b><br>我们在系统的设计和实现中做以下假定：<br></font> 
<ul>
<li><font face="verdana, arial, helvetica" size="2">英语讲是缺省语言，且不需事先国际化</font> </li><li><font face="verdana, arial, helvetica" size="2">在Catalog不讲不会超过500个产品</font> </li><li><font face="verdana, arial, helvetica" size="2">catalog将不会被频繁的修改</font></li>
</ul>
<font face="verdana, arial, helvetica" size="2"><b><font size="3">Page flow</font></b><br>图2显示了所有的JCatalog的pages以及它们之间的transitions关系：<br>&nbsp;&nbsp;&nbsp;&nbsp; <p align="center"><a href="http://www.huihoo.com/java/jsf/jw-0719-jsf2.gif"><img style="width: 250px; height: 159px;" alt="" src="http://www.huihoo.com/java/jsf/jw-0719-jsf2.gif" align="bottom" border="0" height="102" hspace="0" width="176"></a></p><br>该
应用中存在两组pages：公开的internet和用于管理的intranet，其中intranet只能被那些成功登录到系统的用户访问。
ProductSummary不作为一个单独的page展示给用户，它显示在Catalog
page中的frame中。ProductList只对管理员可视，它包含用于创建、编辑和删除产品的链接。<br><br>图3是一个Catalog页面的示意图，理想状况下，在需求文档中应该包含每一页的详细示意图。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <p align="center"><a href="http://www.huihoo.com/java/jsf/jw-0719-jsf3.gif"><img style="width: 222px; height: 160px;" alt="" src="http://www.huihoo.com/java/jsf/jw-0719-jsf3.gif" align="bottom" border="0" height="114" hspace="0" width="222"></a></p><br><font size="5"><b>构架设计</b></font><br>Web应用开发的下一个阶段是构架设计，它包括将应用划分为多个功能组件并将这些组件分割组合成层，高层的构架设计应该中立于所选用的特定技术。<br><br><b><font size="3">多层架构</font></b><br>多
层架构是将整个系统清晰的分为多个功能单元：client、presentation、business-logic、integration和
EIS，这将确保职责得到清晰的划分，使得系统更易于维护和扩展。具有三层或等多层的系统被证明比C/S模型具有更好的伸缩性和灵活性。<br><br>client层是使用和表示数据模型的地方，对于一个Web应用，client层通常是浏览器，基于浏览器的瘦客户端不包含任何表示逻辑，它依赖于</font><font face="verdana, arial, helvetica" size="2">presentation</font><font face="verdana, arial, helvetica" size="2">层。<br><br>presentation层将business-logic层的服务展示给用户，它应知道如何处理用户的请求，如何同business-logic层交互，并且知道如何选择下一个视图显示给用户。<br><br>business-logic层包含应用的business objects和business services。它接受来在于presentation层的请求、基于请求处理业务逻辑。业务逻辑层组件将受益于系统级的服务，如安全管理、事务管理和资源管理等。<br><br>integration层是介于</font><font face="verdana, arial, helvetica" size="2">business-logic</font><font face="verdana, arial, helvetica" size="2">层和EIS层之间的桥梁，它封装了与EIS层交互的逻辑。有时，将integration层和business-logic层合称为中间层。<br><br>应用的数据被保存在EIS层中，它包括关系数据库、面向对象数据库和以及遗留系统等。<br><br><b><font size="3">JCatalog的构架设计</font></b><br>图4显示了JCatalog的构架设计以及如何应用于多层构架系统中。<br>&nbsp; </font>
<p align="center"><font face="verdana, arial, helvetica" size="2"><a href="http://www.huihoo.com/java/jsf/jw-0719-jsf4.gif"><img style="width: 326px; height: 218px;" alt="" src="http://www.huihoo.com/java/jsf/jw-0719-jsf4.gif" align="bottom" border="0" height="120" hspace="0" width="196"></a></font></p>
<font face="verdana, arial, helvetica" size="2"><br>该
应用采用了多层非分布式的构架，图4展示了系统的分层以及每一层中选择的技术，它同时又是该范例的部署图，它的presentation、
business-logic和integration层将存在于同一个web容器中。定义良好的接口将孤立每一层的职责，这一架构使得应用更为简单和更
好的伸缩性。<br><br>对于presentation层，经验表明，最好的方法是选择已存在的并已得到证明了的Web应用框架，而不是自己去设计和开发新的框架。我们拥有多个可选择的框架，如Struts，WebWork和JSF等，在JCatalog中，我们选择采用JSF。<br><br>EJB
和POJO都可以用来创建业务逻辑层，如果应用是分布式的，采用具有remote接口的EJB是一个好的选择；由于JCatalog是一个典型的不需要远
程访问的Web应用，因此选用POJO，并充分利用Spring Framework的帮助，将是实现业务逻辑层的更好选择。<br><br>integration层利用关系型数据库事先数据的持续化，存在多种方法可用来实现：<br></font> 
<ul>
<li><font face="verdana, arial, helvetica" size="2">JDBC：这是最为灵活的方法，然而，低级的JDBC难以使用，而且质量差的JDBC代码很难运转良好</font> </li><li><font face="verdana, arial, helvetica" size="2">Entity beans：CMP的Entity bean是一种分离数据访问代码和处理ORM的昂贵的方法，它是以应用服务器为中心的方法，即entity bean不是将应用与某种数据库类型而是EJB容器约束在一起。</font> </li><li><font face="verdana, arial, helvetica" size="2">O/R
mapping
framework：一个ORM框架采用以对象为中心的方法实现数据持续化，一个以对象为中心的应用易于开发并具有高度的可移植性。在该领域中存在几个框
架可用—JDO、Hibernate、TopLink以及CocoBase等。在我们的范例中将选用Hibernate。</font></li>
</ul>
<font face="verdana, arial, helvetica" size="2">现在，我们将讨论每一层中的设计问题，由于JSF是一个相对较新的技术，因此将着重于它的使用：<br><br></font><font size="3"><b><font face="verdana, arial, helvetica">presentation</font></b></font><font face="verdana, arial, helvetica" size="2"><font size="3"><b>层和JSF</b></font><br>表示层的功能是收集用户的输入、展示数据、控制页面导航并将用户的输入传递给业务逻辑层，表示层同时需要验证用户的输入以及维护应用的session状态。在下面几部分中，我将讨论表示层设计时的考虑和模式，并说明选择JSF作为JCatalog表示层的原因。<br><br><b>MVC</b><br>MVC是Java-Blueprints推荐的架构设计模式，MVC将几个方面分离开来，从而减少代码的重复，它以控制为中心并使得应用更具扩展性。MVC同时可帮助具有不同技能的用户更关注于自己的技能，通过定义良好的接口进行相互合作。MVC是表示层的架构设计模式。<br><br><b>JSF</b><br>JSF
是Web应用的服务器端用户组件框架，它包含以下API：表示UI组件、管理它们的状态、处理事件、服务器端验证、数据转换、定义页面导航、支持国际化，
并为这些特性提供扩展能力。它同时包括两个JSP的tag库以在JSP页面中表示UI组件，以及将组件wire为服务器端对象。<br><br><b>JSF和MVC</b><br>JSF非常适合于基于MVC的表示层架构，它在行为和表示之间提供了清晰的分离，它使得你可以采用熟悉的UI组件和web层概念而无需受限于某种特殊的脚本技术或标记语言。<br><br>JSF
backing
beans是JSF的Model层，此外，它同样包含actions，action是controller层的扩展，用于将用户的请求委派给业务逻辑层。
这里请注意，从整体的应用构架看，业务逻辑层也被称为model层。包含JSF标签的JSP页面是表示层，Faces
Servlet提供了controller的功能。<br><br><b>为什么选用JSF？</b></font><font face="verdana, arial, helvetica" size="2"><br>JSF不仅仅是另外一个Web框架，下面这些特性是JSF区别于其他Web框架之所在：</font> 
<ul>
<li><font face="verdana, arial, helvetica" size="2">类Swing的面向对象的Web应用开发：服务器端有状态的UI组件模型，配合event listeners和handlers，促进了面向对象的Web应用开发。</font> </li><li><font face="verdana, arial, helvetica" size="2">backing
-bean管理： backing
bean是与页面中使用的UI组件相关联的javabean组件，backing-bean管理将UI组件对象的定义同执行应用相关处理和拥有数据的对象
分离开来。JSF在合适的范围内保存和管理这些backing-bean实例。</font> </li><li><font face="verdana, arial, helvetica" size="2">可扩展的UI模型：JSF的UI模型是可配置的、可重用的，用以构建JSF应用的用户界面。你可以通过扩展标准的UI组件来开发出更为复杂的组件，例如菜单条、树组件等。</font> </li><li><font face="verdana, arial, helvetica" size="2">灵活的rendering模型：renderer分离了UI组件的功能和显示，多个renderers可创建和用来为同一客户端或不同的客户端定义不同的显示。</font> </li><li><font face="verdana, arial, helvetica" size="2">可扩展的转换和验证模型：基于标准的converter和validator，你可以开发出自己的可提供更好的模型保护的converter和validator。</font></li>
</ul>
<font face="verdana, arial, helvetica" size="2">尽
管如此，JSF目前尚未成熟，随同JSF发布的
components、converters和validators都是最基础的，而且per-component验证模型不能处理components
和validators间的many-to-many验证。此外，JSF标签不能与JSTL间无缝的整合在一起。<br><br>在下面的章节中，我将讨论几个在JCatalog实现中的关键部分和设计决策。我首先解释managed bean的定义和使用以及JSF中的backing bean，然后，我将说明如何处理安全、分页、caching、file upload、验证以及错误信息定制。<br><br><b>Managed bean,backing bean,view object 和domain object model</b><br>JSF
中引入了两个新的名词：managed bean和backing
bean。JSF提供了一个强大的managed-bean工具，由JSF来管理的JavaBean对象称为managed-bean，一个
managed bean表述了一个bean如何被创建和管理，它不包含该bean的任何功能性描述。<br><br>backing
bean定义了与页面中使用的UI组件相关联的属性和处理逻辑。每一个backing-bean属性邦定于一个组件实例或某实例的value。一个
backing-bean同时定义了一组执行组件功能的方法，例如验证组件的数据、处理组件触发的事件、实施与组件相关的导航等。<br><br>一个典
型的JSF应用将其中的每个页面和一个backing-bean结合起来，然而在现实应用中，强制的执行这种one-on-one的关系不是一种理想的解
决方案，它可能会导致代码重复等问题。在现实的应用中，多个页面可以共享一个backing-bean，例如在JCatalog中，
CreateProduct和EditProduct将共享同一个ProductBean定义。<br><br>model对象特定于表示层中的一个
view对象，它包含必须显示在view层的数据以及验证用户输入、处理事件和与业务逻辑层交互的处理逻辑等。在基于 JSF的应用中backing
bean就是view对象，在本文中backing bean和view对象是可互换的名词。<br><br>对比于struts中的
ActionForm和Action，利用JSF中的backing-bean进行开发将能更好的遵循面向对象方法，一个
backing-bean不仅包含view数据，而且还包含与这些数据相关的行为，而在struts中，Action和ActionForm分别包含数据
和逻辑。<br><br>我们都应该听说过domain object model，那么，domain object
model和view对象之间有什么区别呢？在一个简单的Web应用中，一个domain object
model能够横穿所有层中，而在复杂的应用中，需要用到一个单独的view对象模型。domain object
model应该属于业务逻辑层，它包含业务数据和与特定业务对象相关的业务逻辑；一个view对象包含presentation-specific的数据
和逻辑。将view对象从domain object
model中分离出来的缺点是在这两个对象模型之间必将出现数据映射。在JCatalog中，ProductBeanBuilder和
UserBeanBuilder利用reflection-based Commons BeanUtils来实现数据映射。<br><br><b>安全</b><br>目前，JSF没有内建的安全特性，而对于范例应用来说安全需求是非常基础的：用户登录到administration intranet中仅需用户名和密码认证，而无需考虑授权。<br>针对于JSF的认证，已有几种方法提出：<br></font> 
<ul>
<li><font face="verdana, arial, helvetica" size="2">利用一个backing bean：这一个方法非常简单，然而它却将backing bean与特殊的继承关系结合起来了</font> </li><li><font face="verdana, arial, helvetica" size="2">利用JSF的ViewHandler decorator：这一方法中，安全逻辑紧密地与一特定Web层技术联系在了一起</font> </li><li><font face="verdana, arial, helvetica" size="2">利用servlet filter：一个JSF应用与其他的Web应用没有什么两样，filter仍是处理认证检查的最好地方，这种方法中，认证逻辑与Web应用分离开来</font></li>
</ul>
<font face="verdana, arial, helvetica" size="2">在我们的范例程序中，SecurityFilter类被用来处理用户的认证，目前，受保护的资源只包含三个页面，出于简单的考虑，将它们的位置被硬编码到Filter类中。<br><br><b>分页</b><br>该
应用中的Catalog页面需要分页，表示层可用来处理分页，即它取出所有的数据并保存在这一层；分页同样可在business-logic层、
integration层、甚至EIS层中实现。由于在JCatalog中假设不超过500个产品，因此所有的产品信息能存放在一个user
session中，我们将分页逻辑放在了ProductListBean中，与分页相关的参数将通过JSF managed-bean工具配置。<br><br><b>Caching</b><br>Caching
是提高Web应用性能的最重要技术之一，在应用构建中的很多层中都可以实现caching。JSF
managed-bean工具可以使在表示层实现caching非常容易。通过改变一个managed bean的范围，这个managed
bean中包含的数据可以在不同的范围内缓存。<br><br>范例应用中采用了两级caching，第一级caching存在于业务逻辑层，
CachedCatalogServiceImpl类维护了一个所有产品和目录的读写cache，Spring将该类作为一个singleton
service bean来管理，所以，一级cache是一个应用范围的读写cache。<br><br>为了简化分页逻辑并进而提高应用的速度，产品同
样在session范围内缓存到表示层，每一个用户维护着他自己的ProductListBean，这一方法的缺点是内存的消耗和数据的失效问题，在一个
用户session中，如果管理员更改了catalog，用户可到的将是失效的数据，然而，由于我们假设应用的数据不会经常的改变，所以这些缺点将能够忍
受。<br><br><b>File upload</b><br>目前的JSF Sun参考实现中不支持file
upload。Struts虽已具有非常不错的file
upload能力，然而要想使用这一特性需要Struts-Faces整合库。在JCatalog中，一个图像与一个产品相关联，在一个用户创建了新的产
品后，她必须将相应的图片上传，图片将保存在应用服务器的文件系统里，产品的ID就是图像名称。<br><br>范例应用中采用<input type="file">、Servlet和Jakarta Common的file-upload API来实现简单的文件上传功能，该方法包含两个参数：图像路径和图像上传结果页面。它们将通过ApplicationBean来配置，详细内容请参看 FileUploadServlet类。<br><br><b>Validation</b><br>JSF中发布的标准validator是非常基础的，无法满足现实的需要，但很容易开发出自己的JSF validator，在范例中，我开发了SelectedItemsRange validator，它用来验证UISelectMany组件中选择的数量：<br><br>&nbsp; <h:selectmanylistbox id="selectedCategoryIds" value="#{productBean.selectedCategoryIds}"><br>&nbsp; &nbsp;&nbsp; <catalog:validateselecteditemsrange minnum="1"></catalog:validateselecteditemsrange><br>&nbsp;&nbsp;&nbsp;&nbsp; <f:selectitems id="categories" value="#{applicationBean.categorySelectItems}"></f:selectitems><br>&nbsp; </h:selectmanylistbox><br><br>详细情况请参看范例。<br><br><b>定制错误信息</b><br>在JSF中，你可以为converters和validators创建resource bundle和定制错误信息，一个resource bundle可在faces-config.xml中创建：<br><br>&nbsp; <message-bundle>catalog.view.bundle.Messages</message-bundle><br><br>并将错误信息的key-value对加到Message.properties文件中：<br><br>&nbsp; javax.faces.component.UIInput.CONVERSION=Input data is not in the correct type.<br>&nbsp; javax.faces.component.UIInput.REQUIRED=Required value is missing.<br><br><b><font size="3">业务逻辑层和Spring Framework</font></b><br>业务对象和业务服务存在于业务逻辑层中，一个业务对象不仅包含数据，而且包含相应的逻辑，在范例应用中包含三个业务对象：Product、Category和User。<br><br>业
务服务与业务对象交互并提供更高级的业务逻辑，需要首先定义一个正式的业务接口，它是直接与终端用户交互的服务接口。在JCatalog中，通过在
Spring
Framework帮助下的POJO实现业务逻辑层，其中共有两个业务服务：CatalogService包含Catalog管理相关的业务逻辑，
UserService中包含User管理逻辑。<br><br>Spring是基于IoC概念的框架，在范例应用中用到的Spring特性包括：<br></font> 
<ul>
<li><font face="verdana, arial, helvetica" size="2">Bean management with application contexts：Spring可以有效地组织我们的中间层对象，它能够消除singleton的proliferation，并易于实现良好的面向对象编程方法，即“编程到接口”。</font> </li><li><font face="verdana, arial, helvetica" size="2">Declarative
Transaction management:
Spring利用AOP实现事务管理，而无需借助于EJB容器，利用这种方法，事务管理可以用于任何POJO中。Spring的事务管理不局限于JTA，
而是可以采用不同的事务策略，在范例应用中，我们将使用declarative transaction management with
Hibernate transaction。</font> </li><li><font face="verdana, arial, helvetica" size="2">Data-access exception hierarchy：Spring提供了非常好的异常来代替SQLException，为利用Spring的异常，必须在Spring的配置文件中定义以下异常转换：</font></li>
</ul>
<font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <bean class="" id="jdbcExceptionTranslator"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <property name="dataSource"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <ref bean="dataSource"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </ref><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </property><br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 在范例应用中，如果一个具有重复ID的新产品被插入，将会抛出DataIntegrityViolationException，这一异常将被 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch并rethrown一个DuplicateProductIdException。这样，该异常就可以与其它的异常区别处理。<br></bean></font> 
<ul>
<li><font face="verdana, arial, helvetica" size="2">Hibernate
integration：Spring与Hibernate这样的ORM框架整合的非常好，Spring提供了对Hibernate
session的高效和安全的处理，它可通过application
context配置Hibernate的SessionFactories和JDBC数据源，并使得应用易于测试。</font></li>
</ul>
<font face="verdana, arial, helvetica" size="2"><br><b><font size="3">Integration层和Hibernate</font></b><br>Hibernate是一个开源的ORM框架，它可以支持所有主流SQL数据库系统，Hibernate的查询语言为对象和关系架起了非常好的桥梁。Hibernate提供了强大的功能以实现：数据读取和更新、事务管理、数据连接池、查询和实体关系管理等。<br><br><b><font size="3">Data Access Ojbect(DAO)</font></b><br>JCatalog
中采用了Dao模式，该模式抽象和封装了所有对数据源的访问，该应用中包括两个DAO接口：CatalogDao和UserDao，它们相应的实现
HibernateCatalogDaoImpl和HibernateUserDAoImpl包含了Hibernate特定的逻辑来实现数据的管理和持久
化。<br><br><b><font size="5">实现</font></b><br>现在我们来看看如何将上面讨论的这些东西包装在一起以实现JCatalog，你可以从这个地址下载源码：<a href="http://www.javaworld.com/javaworld/jw-07-2004/jsf/jw-0719-jsf.zip">source code</a><br><br><b><font size="3">数据库设计</font></b><br>我们为该范例应用创建了包含4个表的数据库，如图5所示：<br> <p align="center"><a href="http://www.huihoo.com/java/jsf/jw-0719-jsf5.gif"><img style="width: 290px; height: 211px;" alt="" src="http://www.huihoo.com/java/jsf/jw-0719-jsf5.gif" align="bottom" border="0" height="150" hspace="0" width="248"></a></p><br><b><font size="3">类设计</font></b><br>图6显示了JCatalog的类图<br> <p align="center"><a href="http://www.huihoo.com/java/jsf/jw-0719-jsf6.gif"><img style="width: 414px; height: 255px;" alt="" src="http://www.huihoo.com/java/jsf/jw-0719-jsf6.gif" align="bottom" border="0" height="232" hspace="0" width="120"></a></p><br>“编
程到接口”的思想贯穿了整个设计实现中，在表示层，共用到四个backing
bean：ProductBean、ProductListBean、UserBean和MessageBean;业务逻辑层包含两个业务服务
(CatalogService和UserService)和三个业务对象(Product、Category和User);Integration层有
两个Dao接口和它们相应的Hibernate实现，Spring的application
context用来管理绝大多数的业务逻辑层和integration层的对象；ServiceLocator将JSF和业务逻辑层整合在了一起。<br><br><b><font size="3">Wire everything up</font></b><br>由于篇幅所限，我们仅举例说明，范例中use case CreateProduct展示了如何装配和构建应用，在详细讲述细节前，我们利用sequence图(图7)来说明所有层的end-tp-end整合。<br> <p align="center"><a href="http://www.huihoo.com/java/jsf/jw-0719-jsf7.gif"><img style="width: 470px; height: 128px;" alt="" src="http://www.huihoo.com/java/jsf/jw-0719-jsf7.gif" align="bottom" border="0" height="128" hspace="0" width="120"></a></p><br><br><b>表示层</b>：<br>表示层实现包括创建JSP页面、定义页导航、创建和配置backing bean以及将JSF与业务逻辑层整合。<br></font> 
<ul>
<li><font face="verdana, arial, helvetica" size="2">JSP page：createProduct.jsp是用来创建新产品的页面，它包含UI组件并将组件打包成ProductBean，ValidateItemsRange标签用来验证用户选择的种类数量，对每一个产品至少要有一个种类被选中。</font></li>
</ul>
 
<ul>
<li><font face="verdana, arial, helvetica" size="2">页面导航：应用中的导航被定义在应用的配置文件faces-navigation.xml中，CreateProduct的导航准则如下：</font></li>
</ul>
 
<blockquote><font face="verdana, arial, helvetica" size="2"><navigation-rule></navigation-rule></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <from-view-id>*</from-view-id></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <navigation-case></navigation-case></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <from-outcome>createProduct</from-outcome></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <to-view-id>/createProduct.jsp</to-view-id></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; </font><br><br></blockquote>
 
<blockquote><font face="verdana, arial, helvetica" size="2"><navigation-rule></navigation-rule></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <from-view-id>/createProduct.jsp</from-view-id></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <navigation-case></navigation-case></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <from-outcome>success</from-outcome></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <to-view-id>/uploadImage.jsp</to-view-id></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; </font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <navigation-case></navigation-case></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <from-outcome>retry</from-outcome></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <to-view-id>/createProduct.jsp</to-view-id></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; </font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <navigation-case></navigation-case></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <from-outcome>cancel</from-outcome></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <to-view-id>/productList.jsp</to-view-id></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; </font><br><br></blockquote>
 
<ul>
<li><font face="verdana, arial, helvetica" size="2">Backing bean：ProductBean不仅包含有将数据映射到页面上的UI组件的属性，还包括三个action：createAction、editAction和deleteAction，下面是createAction方法的代码：</font></li>
</ul>
 
<blockquote><font face="verdana, arial, helvetica" size="2">public String createAction() {</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; try {</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Product product = ProductBeanBuilder.createProduct(this);</font><br><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Save the product.</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.serviceLocator.getCatalogService().saveProduct(product);</font><br><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Store the current product id inside the session bean.</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //For the use of image uploader.</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FacesUtils.getSessionBean().setCurrentProductId(this.id);</font><br><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Remove the productList inside the cache.</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.logger.debug("remove ProductListBean from cache");</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FacesUtils.resetManagedBean(BeanNames.PRODUCT_LIST_BEAN);</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; } catch (DuplicateProductIdException de) {</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String msg = "Product id already exists";</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.logger.info(msg);</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FacesUtils.addErrorMessage(msg);</font><br><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NavigationResults.RETRY;</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; } catch (Exception e) {</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String msg = "Could not save product";</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.logger.error(msg, e);</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FacesUtils.addErrorMessage(msg + ": Internal Error");</font><br><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NavigationResults.FAILURE;</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; }</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; String msg = "Product with id of " + this.id + " was created successfully.";</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; this.logger.debug(msg);</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; FacesUtils.addInfoMessage(msg);</font><br><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; return NavigationResults.SUCCESS;</font><br><font face="verdana, arial, helvetica" size="2">}</font><br></blockquote>
 
<ul>
<li><font face="verdana, arial, helvetica" size="2">Managed-bean声明：ProductBean必须在JSF配置文件faces-managed-bean.xml中配置：</font></li>
</ul>
 
<blockquote><font face="verdana, arial, helvetica" size="2"><managed-bean></managed-bean></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <description></description></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Backing bean that contains product information.</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; </font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <managed-bean-name>productBean</managed-bean-name></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <managed-bean-class>catalog.view.bean.ProductBean</managed-bean-class></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <managed-bean-scope>request</managed-bean-scope>&nbsp;&nbsp;&nbsp; </font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <managed-property></managed-property></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <property-name>id</property-name></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <value>#{param.productId}</value></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; </font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <managed-property></managed-property></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <property-name>serviceLocator</property-name></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <value>#{serviceLocatorBean}</value></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; </font><br><br></blockquote>
 
<ul>
<li><font face="verdana, arial, helvetica" size="2">&nbsp;
表示层和业务逻辑层之间的整合：
ServiceLocator抽象了查找服务的逻辑，在范例应用中，ServiceLocator被定义为一个接口，该接口实现为一个JSF的
managed bean，即ServiceLocatorBean，它将在Spring的application context中寻找服务：</font></li>
</ul>
 
<blockquote><font face="verdana, arial, helvetica" size="2">ServletContext context = FacesUtils.getServletContext();</font><br><font face="verdana, arial, helvetica" size="2">this.appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);</font><br><font face="verdana, arial, helvetica" size="2">this.catalogService = (CatalogService)this.lookupService(CATALOG_SERVICE_BEAN_NAME);</font><br><font face="verdana, arial, helvetica" size="2">this.userService = (UserService)this.lookupService(USER_SERVICE_BEAN_NAME);</font><br></blockquote>
<font face="verdana, arial, helvetica" size="2"><b>业务逻辑层</b><br></font> 
<ul>
<li><font face="verdana, arial, helvetica" size="2">业务对象：由于采用Hibernate提供持久化，因此Product和Category两个业务对象需要为它们的所有field提供getter和setter。</font></li>
</ul>
 
<ul>
<li><font face="verdana, arial, helvetica" size="2">业务服务：CatalogService接口中定义了所有的与Catalog management相关的服务：</font></li>
</ul>
 
<blockquote><font face="verdana, arial, helvetica" size="2">public interface CatalogService {</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; public Product saveProduct(Product product) throws CatalogException;</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; public void updateProduct(Product product) throws CatalogException;</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; public void deleteProduct(Product product) throws CatalogException;</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; public Product getProduct(String productId) throws CatalogException;</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; public Category getCategory(String categoryId) throws CatalogException;</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; public List getAllProducts() throws CatalogException;</font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; public List getAllCategories() throws CatalogException;</font><br><font face="verdana, arial, helvetica" size="2">}</font><br></blockquote>
 
<ul>
<li><font face="verdana, arial, helvetica" size="2">Spring Configuration：这里是CatalogService的Spring配置：</font></li>
</ul>
 
<blockquote><font face="verdana, arial, helvetica" size="2"><!-- Hibernate Transaction Manager Definition --></font><br><font face="verdana, arial, helvetica" size="2"><bean class="org" id="transactionManager"></bean></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <property name="sessionFactory"><ref local="sessionFactory"></ref></property></font><br><br><br><font face="verdana, arial, helvetica" size="2"><!-- Cached Catalog Service Definition --></font><br><font face="verdana, arial, helvetica" size="2"><bean class="catalog" id="catalogServiceTarget" init-method="init"></bean></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <property name="catalogDao"><ref local="catalogDao"></ref></property></font><br><br><br><font face="verdana, arial, helvetica" size="2"><!-- Transactional proxy for the Catalog Service --></font><br><font face="verdana, arial, helvetica" size="2"><bean class="org" id="catalogService"></bean></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <property name="transactionManager"><ref local="transactionManager"></ref></property></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <property name="target"><ref local="catalogServiceTarget"></ref></property></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; <property name="transactionAttributes"></property></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <props></props></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <prop key="save*">PROPAGATION_REQUIRED</prop></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <prop key="update*">PROPAGATION_REQUIRED</prop></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <prop key="delete*">PROPAGATION_REQUIRED</prop></font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><br><font face="verdana, arial, helvetica" size="2">&nbsp;&nbsp; </font><br><br></blockquote>
 
<ul>
<li><font face="verdana, arial, helvetica" size="2">Spring和Hibernate的整合：下面是HibernateSessionFactory的配置：</font></li>
</ul>
 
<blockquote><font face="verdana, arial, helvetica" size="2"><!-- Hibernate SessionFactory Definition --></font><br>
<code></code><p>
&lt;!-- Hibernate SessionFactory Definition --&gt;<br>

&lt;bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"&gt;<br>

&nbsp;&nbsp; &lt;property name="mappingResources"&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;list&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;catalog/model/businessobject/Product.hbm.xml&lt;/value&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;catalog/model/businessobject/Category.hbm.xml&lt;/value&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;catalog/model/businessobject/User.hbm.xml&lt;/value&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br>

&nbsp;&nbsp; &lt;/property&gt;<br>

&nbsp;&nbsp; &lt;property name="hibernateProperties"&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;props&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;prop
key="hibernate.dialect"&gt;net.sf.hibernate.dialect.MySQLDialect&lt;/prop&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.show_sql"&gt;true&lt;/prop&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.cglib.use_reflection_optimizer"&gt;true&lt;/prop&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop
key="hibernate.cache.provider_class"&gt;net.sf.hibernate.cache.HashtableCacheProvider&lt;/prop&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/props&gt;<br>

&nbsp;&nbsp; &lt;/property&gt;		<br>

&nbsp;&nbsp; &lt;property name="dataSource"&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref bean="dataSource"/&gt;<br>

&nbsp;&nbsp; &lt;/property&gt;<br>

&lt;/bean&gt;<br>
</p><p>
<code>CatalogDao</code> uses <code>HibernateTemplate</code> to integrate between Hibernate and Spring. Here's the configuration for <code>HibernateTemplate</code>: 
</p><p>
<code></code></p><p>
&lt;!-- Hibernate Template Defintion --&gt;<br>

&lt;bean id="hibernateTemplate" class="org.springframework.orm.hibernate.HibernateTemplate"&gt; <br>

&nbsp;&nbsp; &lt;property name="sessionFactory"&gt;&lt;ref bean="sessionFactory"/&gt;&lt;/property&gt; <br>

&nbsp;&nbsp; &lt;property name="jdbcExceptionTranslator"&gt;&lt;ref bean="jdbcExceptionTranslator"/&gt;&lt;/property&gt; <br>

&lt;/bean&gt; <br>
</p><p>

<br><br></p></blockquote>
<font face="verdana, arial, helvetica" size="2"><b>Integration层</b><br>Hibernate通过xml配置文件来映射业务对象和关系数据库，在JCatalog中，Product.hbm.xml表示了Product对象的映射，Category.hbm.xml则用来表示Category的映射，Product.hbm.xml如下：<br></font> 
<blockquote><font face="verdana, arial, helvetica" size="2">

<code></code></font><p>
<font face="verdana, arial, helvetica" size="2">&lt;?xml version="1.0"?&gt;<br>

&lt;!DOCTYPE hibernate-mapping PUBLIC <br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"-//Hibernate/Hibernate Mapping DTD 2.0//EN"<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"&gt;<br>

&lt;hibernate-mapping package="catalog.model.businessobject"&gt;<br>

&nbsp;&nbsp; &lt;class name="Product" table="product"&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;id name="id" column="ID" unsaved-value="null"&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="assigned"/&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/id&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="name" column="NAME" unique="true" not-null="true"/&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="price" column="PRICE"/&gt;&nbsp;&nbsp;&nbsp;&nbsp; <br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="width" column="WIDTH"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="height" column="height"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="description" column="description"/&gt;	&nbsp;&nbsp;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;set name="categoryIds" table="product_category" cascade="all"&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key column="PRODUCT_ID"/&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;element column="CATEGORY_ID" type="string"/&gt;<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/set&gt;<br>

&nbsp;&nbsp; &lt;/class&gt;<br>

&lt;/hibernate-mapping&gt;<br>

</font></p><p>
<code><font face="verdana, arial, helvetica" size="2">CatalogDao</font></code><font face="verdana, arial, helvetica" size="2"> is wired with <code>HibernateTemplate</code> by Spring: 
</font></p><p>
<code></code></p><p>
<font face="verdana, arial, helvetica" size="2">&lt;!-- Catalog DAO Definition: Hibernate implementation --&gt;<br>

&lt;bean id="catalogDao" class="catalog.model.dao.hibernate.CatalogDaoHibernateImpl"&gt;<br>

&nbsp;&nbsp; &lt;property name="hibernateTemplate"&gt;&lt;ref bean="hibernateTemplate"/&gt;&lt;/property&gt; <br>

&lt;/bean&gt;	<br>
</font></p><p>

</p></blockquote>
<font face="verdana, arial, helvetica" size="2"><font face="verdana, arial, helvetica" size="2"><b><font size="5">结论</font></b><br>本
文主要讲述了如何将JSF与Spring、Hibernate整合在一起来构建实际的Web应用，这三种技术的组合提供了一个强大的Web应用开发框架。
在Web应用的高层设计中应该采用多层构架体系，JSF非常适合MVC设计模式以实现表示层，Spring可用在业务逻辑层中管理业务对象，并提供事物管
理和资源管理等，Spring与Hibernate结合的非常出色，Hibernate是强大的O/R映射框架，它可以在integration层中提供
最好的服务。<br><br>通过将整个Web应用分割成多层，并借助于“编程到接口”，应用程序的每一层所采用的技术都是可替换的，例如Struts可
以用来替换JSF，JDO可替换Hibernate。各层之间的整合不是不值得研究，采用IoC和ServiceLocator设计模式可使得整合非常容
易。JSF提供了其它Web框架欠缺的功能，然而，这并不意味着你马上抛弃Struts而开始使用JSF，是否采用JSF取决于项目目前的状况和功能需
求，以及开发团队的意见等。<br><br></font></font><img src ="http://www.blogjava.net/hszdz/aggbug/21507.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hszdz/" target="_blank">爪哇之家</a> 2005-11-26 15:09 <a href="http://www.blogjava.net/hszdz/articles/21507.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>