﻿<?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-轻松-随笔分类-Struts相关</title><link>http://www.blogjava.net/relax/category/272.html</link><description>记述我学习java的里程</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:59:57 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:59:57 GMT</pubDate><ttl>60</ttl><item><title>使用struts+spring+hibernate 组装web应用</title><link>http://www.blogjava.net/relax/archive/2005/03/22/2315.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Tue, 22 Mar 2005 03:19:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/03/22/2315.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/2315.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/03/22/2315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/2315.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/2315.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 width="85%" align=center border=0>
<TBODY>
<TR>
<TD style="FONT-SIZE: 9pt" align=middle width="100%" height=30><FONT color=#666666>matrix.com.cn&nbsp;&nbsp;&nbsp;&nbsp;<!--阅读335次--></FONT>&nbsp;&nbsp;<A href="http://www.dangdang.com/league/leagueref.asp?from=P-2023703&amp;backurl=http://211.100.16.156/dangdang.dll?key=WEB开发"><FONT color=red>相关书籍</FONT></A></TD></TR>
<TR>
<TD style="FONT-SIZE: 9pt" align=middle width="100%"></TD></TR>
<TR>
<TD style="FONT-SIZE: 14px" align=middle width="100%">
<TABLE cellSpacing=0 cellPadding=0 align=center border=0>
<TBODY>
<TR>
<TD style="FONT-SIZE: 14px">
<TABLE class=tf width="98%" align=center border=0>
<TBODY>
<TR>
<TD class=bw width="100%"><FONT class=htd id=font_word style="FONT-SIZE: 14px" font-family:宋体, Verdana, Arial, Helvetica, sans-serif;>src=http://pagead2.googlesyndication.com/pagead/show_ads.js&gt;</SCRIPT><SPAN class=postbody>其实，就算用Java建造一个不是很烦琐的web应用，也不是件轻松的事情。 在构架的一开始就有很多事情要考虑。 从高处看，摆在开发者面前有很多问题：要考虑是怎样建立用户接口？在哪里处理业务逻辑？ 怎样持久化的数据。 而这三层构架中，每一层都有他们要仔细考虑的。 各个层该使用什么技术？ 怎样的设计能松散耦合还能灵活改变？ 怎样替换某个层而不影响整体构架？应用程序如何做各种级别的业务处理（比如事务处理）？ <BR><BR><BR><BR>构架一个Web应用需要弄明白好多问题。 幸运的是，已经有不少开发者已经遇到过这类问题，并且建立了处理这类问题的框架。 一个好框架具备以下几点： 减轻开发者处理复杂的问题的负担（“不重复发明轮子”）； 内部有良好的扩展； 并且有一个支持它的强大的用户团体。 好的构架一般有针对性的处理某一类问题，并且能将它做好（Do One Thing well）。 然而，你的程序中有几个层可能需要使用特定的框架，已经完成的UI(用户接口) 并不代表你也可以把你的业务逻辑和持久逻辑偶合到你的UI部分。 举个例子， 你不该在一个Controller(控制器)里面写JDBC代码作为你的业务逻辑， 这不是控制器应该提供的。 一个UI 控制器应该委派给其它给在UI范围之外的轻量级组件。 好的框架应该能指导代码如何分布。 更重要的是，框架能把开发者从编码中解放出来，使他们能专心于应用程序的逻辑（这对客户来说很重要）。 <BR><BR><BR><BR>这篇文章将讨论怎样结合几种著名的框架来使得你的应用程序做到松弛耦合。 <BR><BR>如何建立你的架构，并且怎样让你的各个应用层保持一致。？如何整合框架以便让每个层在以一种松散偶合的方式彼此作用而不用管低层的技术细节？这对我们来说真是一种挑战。 这里讨论一个整合框架的策略( 使用3 种受欢迎的开源框架) ：表示层我们用Struts； 业务层我们用Spring；而持久层则用Hibernate。 你也可以用其他FrameWork替换只要能得到同样的效果。 见图1 （框架组合示意图） <BR><BR><IMG src="http://www.onjava.com/onjava/2004/04/07/graphics/wiring.gif" border=0> <BR><BR><SPAN style="FONT-WEIGHT: bold">应用程序的分层</SPAN> <BR><BR>大部分的Web应用在职责上至少能被分成4层。 这四层是：presentation（描述），persistence（持久），business（业务）和domain model（域模块）。每个层在处理程序上都应该有一项明确的责任, 而不应该在功能上与其它层混合，并且每个层要与其它层分开的，但要给他们之间放一个通信接口。 我们就从介绍各个层开始，讨论一下这些层应该提供什么，不应该提供什么。 <BR><BR><BR><BR><SPAN style="FONT-WEIGHT: bold">表示层(The Presentation Layer) </SPAN><BR><BR>一般来讲，一个典型的Web应用的的末端应该是表示层。 很多Java发者也理解Struts所提供的。 象业务逻辑之类的被打包到org.apache.struts.Action.， 因此，我们很赞成使用Struts这样的框架。 <BR><BR><BR><BR>下面是Struts所负责的： <BR><BR>* 管理用户的请求,做出相应的响应。 <BR><BR>* 提供一个Controller ,委派调用业务逻辑和其它上层处理。 <BR><BR>* 处理异常，抛给Struts Action <BR><BR>* 为显示提供一个模型 <BR><BR>* UI验证。 <BR><BR><BR><BR>以下条款，不该在Struts显示层的编码中经常出现。 它们与显示层无关的。 <BR><BR>* 直接的与数据库通信，例如JDBC调用。 <BR><BR>* 与你应用程序相关联的业务逻辑以及校验。 <BR><BR>* 事物管理。 <BR><BR>在表示层引入这些代码，则会带来高偶合和麻烦的维护。 <BR><BR><BR><BR><BR><BR><SPAN style="FONT-WEIGHT: bold">持久层(The Persistence Layer)</SPAN> <BR><BR>典型的Web应用的另一个末端是持久层。这里通常是程序最容易失控的地方。开发者总是低估构建他们自己的持久框架的挑战性。系统内部的持续层不但需要大量调试时间，而且还经常缺少功能使之变得难以控制，这是持久层的通病。 还好有几个ORM开源框架很好的解决了这类问题。尤其是Hibernate。 Hibernate为java提供了OR持久化机制和查询服务, 它还给已经熟悉SQL和JDBC API 的Java开发者一个学习桥梁，他们学习起来很方便。 Hibernate的持久对象是基于POJO和Java collections。此外，使用Hibernate并不妨碍你正在使用的IDE。 <BR><BR><BR><BR>请看下面的条目，你在持久层编码中需要了解的。 <BR><BR>* 查询对象的相关信息的语句。 Hibernate通过一个OO查询语言（HQL）或者正则表达的API来完成查询。 HQL非常类似于SQL-- 只是把SQL里的table和columns用Object和它的fields代替。 你需要学习一些新的HQL语言； 不管怎样，他们容易理解而文档也做的很好。 HQL是一种对象查询的自然语言，花很小的代价就能学习它。 <BR><BR>* 如何存储，更新，删除数据库记录。 <BR><BR>* 象Hibernate这类的高级ORM框架支持大部分主流数据库，并且他们支持 Parent/child关系，事物处理，继承和多态。 <BR><BR><BR><BR><SPAN style="FONT-WEIGHT: bold">业务层（The Business Layer）</SPAN> <BR><BR>一个典型Web应用的中间部分是业务层或者服务层。 从编码的视角来看，这层是最容易被忽视的一层。 而我们却往往在UI层或持久层周围看到这些业务处理的代码，这其实是不正确的，因为它导致了程序代码的紧密偶合，这样一来，随着时间推移这些代码很难维护。幸好，针对这一问题有好几种Frameworks存在。 最受欢迎的两个框架是Spring和PicoContainer。 这些为也被称为microcontainers，他们能让你很好的把对象搭配起来。 这两个框架都着手于‘依赖注射’(dependency injection)(还有我们知道的‘控制反转’Inversion of Control=IoC)这样的简单概念。 这篇文章将关注于Spring的注射（译注：通过一个给定参数的Setter方法来构造Bean,有所不同于Factory）, Spring还提供了Setter Injection(type2)，Constructor Injection(type3)等方式供我们选择。 Spring把程序中所涉及到包含业务逻辑和Dao的Objects——例如transaction management handler（事物管理控制）、Object Factoris(对象工厂)、service objects（服务组件）——都通过XML来配置联系起来。 <BR><BR><BR><BR>后面我们会举个例子来揭示一下Spring 是怎样运用这些概念。 <BR><BR>业务层所负责的如下： <BR><BR>* 处理应用程序的 业务逻辑和业务校验 <BR><BR>* 管理事物 <BR><BR>* 允许与其它层相互作用的接口 <BR><BR>* 管理业务层级别的对象的依赖。 <BR><BR>* 在显示层和持久层之间增加了一个灵活的机制，使得他们不直接的联系在一起。 <BR><BR>* 通过揭示 从显示层到业务层之间的Context来得到business services。 <BR><BR>* 管理程序的执行（从业务层到持久层）。 <BR><BR><BR><BR><BR><BR><SPAN style="FONT-WEIGHT: bold">域模块层（The Domain Model Layer ）</SPAN> <BR>既然我们致力于的是一个不是很复杂的Web的应用， 我们需要一个对象集合，让它在不同层之间移动的。 域模块层由实际需求中的业务对象组成 比如, OrderLineItem , Product等等。 开发者在这层 不用管那些DTOs，仅关注domain object即可。 例如，Hibernate允许你将数据库中的信息存放入对象（domain objects），这样你可以在连接断开的情况下把这些数据显示到UI层。 而那些对象也可以返回给持续层，从而在数据库里更新。 而且，你不必把对象转化成DTOs（这可能似的它在不同层之间的在传输过程中丢失），这个模型使得Java开发者能很自然运用OO，而不需要附加的编码。 <BR><BR>一个简单例子 <BR><BR><BR><BR>既然我们已经从全局上理解这些组件。 现在就让我们开始实践吧。 我们还是用 Struts，Spring 和Hibernate。这三个框架已经被描述够多了，这里就不重复介绍了。 这篇文章举例指导你如何使用这三个框架整合开发, 并向你揭示 一个请求是如何贯穿于各个层的。（从用户的加入一个Order到数据库，显示；进而更新、删除）。 <BR><BR><BR><BR>从这里可以下载到程序程序原代码（<A class=postlink href="http://www.onjava.com/onjava/2004/04/07/examples/wiring.zip" target=_blank><FONT color=#006699>download</FONT></A>） <BR><BR>既然每个层是互相作用的，我们就先来创建domain objects。首先，我们要在这些Object中要确定那些是需要持久化的，哪些是提供给business logic，那些是显示接口的设计。 下一步，我们将配置我们的持久层并且定义好Hibernate的OR mappings。然后定义好Business Objects。有了这些组成部分之后，我们将 使用Spring把这些连接起来。 最后，我们提供给Spring一个持久层，从这个持久层里我们可以知道它是如何与业务逻辑层（business service layer）通信的，以及它是怎样处理其他层抛出的异常的。。 <BR><BR><BR><BR><SPAN style="FONT-WEIGHT: bold">域对象层（Domain Object Layer）</SPAN> <BR><BR><BR>这层是编码的着手点，我们的编码就从这层开始。 例子中Order 与OrderItem 是一个One—To—Many的关系。 下面就是Domain Object Layer的两个对象： <BR><BR><BR><BR>· com.meagle.bo.Order.java: 包含了一个Order的概要信息 <BR><BR>· com.meagle.bo.OrderLineItem.java: 包含了Order的详细信息 <BR><BR>好好考虑怎你的package命名,这反应出了你是怎样分层的。 例如 domain objects在程序中可能打包在com.meagle.bo内。 更详细一点将打包在com. meagle.bo的子目录下面。business logic应该从com.meagle.serice开始打包，而DAO 对象应该位于com.meagle.service.dao.hibernate。反应Forms和Actions的 持久对象（presentation classes） 应该分别放在 com.meagle.action和com.meagle.forms包。 准确的给包命名使得你的classes很好分割并且易于维护，并且在你添加新的classes时，能使得程序结构上保持上下一致。 <BR><BR><SPAN style="FONT-WEIGHT: bold">持久层的配置（Persistence Layer Configuration）</SPAN> <BR><BR>建立Hibernate的持久层 需要好几个步骤。 第一步让我们把BO持久化。 既然Hibernate是通过POJO工作的， 因此Order和 OrderLineItem对象需要给所有的fileds 加上getter,setter方法。 Hibernate通过XML文件来映射(OR)对象，以下两个xml文件分别映射了Order 和OrderItem对象。（这里有个叫XDoclet工具可以自动生成你的XML影射文件） <BR><BR>- Order.hbm.xml <BR>- OrderLineItem.hbm.xml <BR><BR>你可以在WebContent/WEB-INF/classes/com/meagle/bo目录下找到这些xml文件。Hibernate的 [urlhttp://www.hibernate.org/hib_docs/api/net/sf/hibernate/SessionFactory.html]SessionFactory [/url]是用来告诉程序 应该与哪个数据库通信，该使用哪个连接池或使用了DataSource， 应该加载哪些持久对象。而<A class=postlink href="http://www.hibernate.org/hib_docs/api/net/sf/hibernate/Session.html" target=_blank><FONT color=#006699>Session</FONT></A>接口是用来完成Selecting，Saving，Delete和Updating这些操作。 后面的我们将讲述SessionFactory和Session是怎样设置的。 <BR><BR><SPAN style="FONT-WEIGHT: bold">业务层的配置（Business Layer Configuration）</SPAN> <BR><BR>既然我们已经有了domain objects，接下来我们就要business service objects了，用他们来执行程序的logic,调用持久层，得到UI层的requests,处理transactions，并且控制exceptions。 为了将这些连接起来并且易于管理，我们将使用面向方面的 SpringFramework。 Spring 提供了 控制倒置（inversion of control 0==IoC)和注射依赖设置（setter dependency injection）这些方式（可供选择），用XML文件将对象连接起来。 IoC是一个简单概念（它允许一个对象在上层接受其他对象的创建），用IoC这种方式让你的对象从创建中释放了出来，降低了偶合度。 <BR><BR><BR><BR><BR>这里是一个没有使用IoC的对象创建的例子，它有很高偶合度。 <BR><BR><BR><IMG src="http://www.onjava.com/onjava/2004/04/07/graphics/nonioc.gif" border=0> <BR><BR><SPAN style="FONT-STYLE: italic">图 2.没有使用 IoC. A 创建了 B 和 C</SPAN> <BR><BR>而这里是一个使用IoC的例子，这种方式允许对象在高层可以创建并进入另外一个对象，所以这样可以直接被执行。 <BR><IMG src="http://www.onjava.com/onjava/2004/04/07/graphics/ioc.gif" border=0> <BR><BR><SPAN style="FONT-STYLE: italic">图 3. 对象使用了 IoC。 A 包含了接受B,C的 setter方法 , 这同样达到了 由A创建B,C的目的。</SPAN> <BR><BR>建立我们的业务服务对象（Building Our Business Service Objects） <BR><BR><BR>Business Object中的Setter方法接受的是接口，这样我们可以很松散的定义对象实现，然后注入。 在我们的案例中，我们将用一个business service object接收一个DAO,用它来控制domain objects的持久化。 由于在这个例子中使用了Hibernate，我们可以很方便的用其他持久框架实现 同时通知Spring 有新的DAO可以使用了。 <BR><BR>在面向接口的编程中，你会明白 “注射依赖”模式是怎样松散耦合你的业务逻辑和持久机制的：）。 <BR><BR><BR><BR>下面是一个接口business service object，DAO代码片段： <BR><BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>代码:</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code><BR>public interface IOrderService { <BR><BR>&nbsp; public abstract Order saveNewOrder(Order order) <BR><BR>&nbsp; &nbsp; throws OrderException, <BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;OrderMinimumAmountException; <BR><BR>&nbsp; <BR><BR>&nbsp; public abstract List findOrderByUser( <BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;String user) <BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throws OrderException; <BR><BR>&nbsp; <BR><BR>&nbsp; public abstract Order findOrderById(int id) <BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throws OrderException; <BR><BR>&nbsp; <BR><BR>&nbsp; public abstract void setOrderDAO( <BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IOrderDAO orderDAO); <BR><BR>} <BR><BR>&nbsp;</TD></TR></TBODY></TABLE><SPAN class=postbody><BR>注意到这段代码里有一个 setOrderDao（），它就是一个DAO Object设置方法（注射器）。 但这里并没有一个getOrderDao的方法，这不必要，因为你并不会在外部访问这个orderDao。这个DAO Objecte将被调用，和我们的persistence layer 通信。我们将用Spring把DAO Object 和 business service object搭配起来的。因为我们是面向接口编程的，所以并不需要将实现类紧密的耦合在一起。 <BR><BR><BR><BR>接下去我们开始我们的DAO的实现类进行编码。 既然Spring已经有对Hibernate的支持，那这个例子就直接继承<A class=postlink href="http://www.springframework.org/docs/api/org/springframework/orm/hibernate/support/HibernateDaoSupport.html" target=_blank><FONT color=#006699>HibernateDaoSupport</FONT></A>类了，这个类很有用，我们可以参考<A class=postlink href="http://www.springframework.org/docs/api/org/springframework/orm/hibernate/HibernateTemplate.html" target=_blank><FONT color=#006699>HibernateTemplate</FONT></A>（它主要是针对HibernateDaoSupport的一个用法，译注：具体可以查看<A class=postlink href="http://www.springframework.org/docs/api/index.html" target=_blank><FONT color=#006699>Srping 的API</FONT></A>）。 下面是这个DAO接口代码： <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>代码:</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>public interface IOrderDAO { <BR>&nbsp; public abstract Order findOrderById( <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final int id); <BR>&nbsp; <BR>&nbsp; public abstract List findOrdersPlaceByUser( <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;final String placedBy); <BR>&nbsp; public abstract Order saveOrder( <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;final Order order); <BR>}</TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>我们仍然要给我们持久层组装很多关联的对象，这里包含了HibernateSessionFactory 和TransactionManager。 Spring 提供了一个 <A class=postlink href="http://www.springframework.org/docs/api/org/springframework/orm/hibernate/HibernateTransactionManager.html" target=_blank><FONT color=#006699>HibernateTransactionManager</FONT></A>，他用线程捆绑了一个Hibernate Session，用它来支持transactions(请查看<A class=postlink href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ThreadLocal.html" target=_blank><FONT color=#006699>ThreadLocal</FONT></A>) 。 <BR><BR>下面是HibernateSessionFactory 和 HibernateTransactionManager:的配置： <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>代码:</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>&lt;bean id="mySessionFactory" <BR>&nbsp; &nbsp; &nbsp; &nbsp;class="org.springframework.orm.hibernate. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LocalSessionFactoryBean"&gt; <BR>&nbsp; &lt;property name="mappingResources"&gt; <BR>&nbsp; &nbsp; &lt;list&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;value&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; com/meagle/bo/Order.hbm.xml <BR>&nbsp; &nbsp; &nbsp; &lt;/value&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;value&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; com/meagle/bo/OrderLineItem.hbm.xml <BR>&nbsp; &nbsp; &nbsp; &lt;/value&gt; <BR>&nbsp; &nbsp; &lt;/list&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="hibernateProperties"&gt; <BR>&nbsp; &nbsp; &lt;props&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;prop key="hibernate.dialect"&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; net.sf.hibernate.dialect.MySQLDialect <BR>&nbsp; &nbsp; &nbsp; &lt;/prop&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;prop key="hibernate.show_sql"&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; false <BR>&nbsp; &nbsp; &nbsp; &lt;/prop&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;prop key="hibernate.proxool.xml"&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; C:/MyWebApps/.../WEB-INF/proxool.xml <BR>&nbsp; &nbsp; &nbsp; &lt;/prop&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;prop key="hibernate.proxool.pool_alias"&gt; <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; spring <BR>&nbsp; &nbsp; &nbsp; &lt;/prop&gt; <BR>&nbsp; &nbsp; &lt;/props&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt; <BR>&nbsp; <BR>&lt;!-- Transaction manager for a single Hibernate <BR>SessionFactory (alternative to JTA) --&gt; <BR>&lt;bean id="myTransactionManager" <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;class="org. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; springframework. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; orm. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hibernate. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HibernateTransactionManager"&gt; <BR>&nbsp; &lt;property name="sessionFactory"&gt; <BR>&nbsp; &nbsp; &lt;ref local="mySessionFactory"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;/bean&gt;</TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR><BR>可以看出：每个对象都可以在Spring 配置信息中用&lt;bean&gt;标签引用。在这里，mySessionFactory引用了HibernateSessionFactory，而myTransactionManager引用了HibernateTransactionManage。 注意代码中myTransactionManger Bean有个sessionFactory属性。 HibernateTransactionManager有个sessionFactory setter 和 getter方法，这是用来在Spring启动的时候实现“依赖注入” （dependency injection）的。 在sessionFactory 属性里 引用mySessionFactory。这两个对象在Spring容器初始化后就被组装了起来了。 这样的搭配让你从 单例（singleton objects）和工厂（factories）中解放了出来，降低了代码的维护代价。 mySessionFactory.的两个属性，分别是用来注入mappingResources 和 hibernatePropertes的。通常，如果你在Spring之外使用Hibernate,这样的设置应该放在hibernate.cfg.xml中的。 不管怎样,Spring提供了一个便捷的方式-----在Spring内部配置中并入了Hibernate的配置。 如果要得到更多的信息，可以查阅Spring API。 <BR><BR><BR><BR><BR><BR>既然我们已经组装配置好了Service Beans，就需要把Business Service Object和 DAO也组装起来，并把这些对象配到一个事务管理器（transaction manager）里。 <BR><BR><BR><BR>在Spring中的配置信息： <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>代码:</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code><BR>&lt;!-- ORDER SERVICE --&gt; <BR>&lt;bean id="orderService" <BR>&nbsp; class="org. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;springframework. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;transaction. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;interceptor. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TransactionProxyFactoryBean"&gt; <BR>&nbsp; &lt;property name="transactionManager"&gt; <BR>&nbsp; &nbsp; &lt;ref local="myTransactionManager"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="target"&gt; <BR>&nbsp; &nbsp; &lt;ref local="orderTarget"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&nbsp; &lt;property name="transactionAttributes"&gt; <BR>&nbsp; &nbsp; &lt;props&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;prop key="find*"&gt; <BR>&nbsp; &nbsp; &nbsp;PROPAGATION_REQUIRED,readOnly,-OrderException <BR>&nbsp; &nbsp; &nbsp; &lt;/prop&gt; <BR>&nbsp; &nbsp; &nbsp; &lt;prop key="save*"&gt; <BR>&nbsp; &nbsp; &nbsp;PROPAGATION_REQUIRED,-OrderException <BR>&nbsp; &nbsp; &nbsp; &lt;/prop&gt; <BR>&nbsp; &nbsp; &lt;/props&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt; <BR>&nbsp; <BR>&lt;!-- ORDER TARGET PRIMARY BUSINESS OBJECT: <BR>Hibernate implementation --&gt; <BR>&lt;bean id="orderTarget" <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;class="com. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; meagle. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; service. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; spring. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OrderServiceSpringImpl"&gt; <BR>&nbsp; &lt;property name="orderDAO"&gt; <BR>&nbsp; &nbsp; &lt;ref local="orderDAO"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt; <BR>&nbsp; <BR>&lt;!-- ORDER DAO OBJECT --&gt; <BR>&lt;bean id="orderDAO" <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;class="com. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; meagle. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; service. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dao. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hibernate. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OrderHibernateDAO"&gt; <BR>&nbsp; &lt;property name="sessionFactory"&gt; <BR>&nbsp; &nbsp; &lt;ref local="mySessionFactory"/&gt; <BR>&nbsp; &lt;/property&gt; <BR>&lt;/bean&gt;</TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR><BR><BR>图4 是我们对象搭建的一个提纲。 从中可以看出，每个对象都联系着Spring，并且能通过Spring注入到其他对象。把它与Spring的配置文件比较，观察他们之间的关系 <BR><BR><IMG src="http://www.onjava.com/onjava/2004/04/07/graphics/spring_wiring.gif" border=0> <BR><BR><SPAN style="FONT-STYLE: italic">图 4. Spring就是这样基于配置文件，将各个Bean搭建在一起。</SPAN> <BR><BR>这个例子使用一个TransactionProxyFactoryBean，它定义了一个setTransactionManager()。 这对象很有用，他能很方便的处理你申明的事物还有Service Object。 你可以通过transactionAttributes属性来定义怎样处理。 想知道更多还是参考TransactionAttributeEditor吧。 <BR><BR>TransactionProxyFactoryBean 还有个setter. 这会被我们 Business service object（orderTarget）引用， orderTarget定义了 业务服务层，并且它还有个属性，由setOrderDAO()引用。这个属性 <BR><BR><BR><BR>Spring 和Bean 的还有一点要注意的： bean可以以用两种方式创造。 这些都在单例模式（Sington）和原型模式（propotype）中定义了。 默认的方式是singleton,这意味着共享的实例将被束缚。 而原形模式是在Spring用到bean的时候允许新建实例的。当每个用户需要得到他们自己Bean的Copy时，你应该仅使用prototype模式。（更多的请参考设计模式中的单例模式和原形模式） <BR><BR><SPAN style="FONT-WEIGHT: bold">提供一个服务定位器（Providing a Service Locator）</SPAN> <BR>既然我们已经将我们的Serices和DAO搭配起来了。我们需要把我们的Service显示到其他层。 这个通常是在Struts或者Swing这层里编码。一个简单方法就是用 服务定位器返回给Spring context 。当然，可以通过直接调用Spring中的Bean来做。 <BR><BR>下面是一个Struts Actin 中的服务定位器的一个例子。 <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>代码:</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code><BR>public abstract class BaseAction extends Action { <BR>&nbsp; <BR>&nbsp; private IOrderService orderService; <BR>&nbsp; <BR>&nbsp; public void setServlet(ActionServlet <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;actionServlet) { <BR>&nbsp; &nbsp; super.setServlet(actionServlet); <BR>&nbsp; &nbsp; ServletContext servletContext = <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;actionServlet.getServletContext(); <BR>&nbsp; <BR>&nbsp; &nbsp; WebApplicationContext wac = <BR>&nbsp; &nbsp; &nbsp; WebApplicationContextUtils. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getRequiredWebApplicationContext( <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;servletContext); <BR>&nbsp; <BR>&nbsp; &nbsp; &nbsp; this.orderService = (IOrderService) <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;wac.getBean("orderService"); <BR>&nbsp; } <BR>&nbsp; <BR>&nbsp; protected IOrderService getOrderService() { <BR>&nbsp; &nbsp; return orderService; <BR>&nbsp; } <BR>} <BR>&nbsp;</TD></TR></TBODY></TABLE><SPAN class=postbody><BR><SPAN style="FONT-WEIGHT: bold">UI 层配置 （UI Layer Configuration）</SPAN> <BR><BR>这个例子里UI层 使用了Struts framework. 这里我们要讲述一下在给程序分层的时候， 哪些是和Struts部分的。我们就从一个Struts-config.xml文件中的Action的配置信息开始吧。 <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>代码:</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code><BR>struts-config.xml file. <BR><BR>&lt;action path="/SaveNewOrder" <BR>&nbsp; &nbsp; type="com.meagle.action.SaveOrderAction" <BR>&nbsp; &nbsp; name="OrderForm" <BR>&nbsp; &nbsp; scope="request" <BR>&nbsp; &nbsp; validate="true" <BR>&nbsp; &nbsp; input="/NewOrder.jsp"&gt; <BR>&nbsp; &lt;display-name&gt;Save New Order&lt;/display-name&gt; <BR>&nbsp; &lt;exception key="error.order.save" <BR>&nbsp; &nbsp; path="/NewOrder.jsp" <BR>&nbsp; &nbsp; scope="request" <BR>&nbsp; &nbsp; type="com.meagle.exception.OrderException"/&gt; <BR>&nbsp; &lt;exception key="error.order.not.enough.money" <BR>&nbsp; &nbsp; path="/NewOrder.jsp" <BR>&nbsp; &nbsp; scope="request" <BR>&nbsp; &nbsp; type="com. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; meagle. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exception. <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OrderMinimumAmountException"/&gt; <BR>&nbsp; &lt;forward name="success" path="/ViewOrder.jsp"/&gt; <BR>&nbsp; &lt;forward name="failure" path="/NewOrder.jsp"/&gt; <BR>&lt;/action&gt;</TD></TR></TBODY></TABLE><SPAN class=postbody><BR>SaveNewOrder 这个Action是用来持久化UI层里的表单提交过来Order的。这是Struts中一个很典型的Action; 注意观察这个Action中exception配置，这些Exceptions也在Spring 配置文件(applicationContext-hibernate.xml)中配置了（就在 business service object 的transactionAttributes属性里）。 当异常在业务层被被抛出时，我们可以控制他们，并适当的显示给UI层。 <BR><BR>第一个异常，OrderException,在持久层保存order对象失败的时候被触发。这将导致事物回滚并且通过BO把异常回传到Struts这一层。 <BR><BR>第二个异常，OrderMinimumAmountException也同第一个一样。 <BR><BR><BR><BR><BR><BR>搭配整和的最后一步 通过是让你显示层和业务层相结合。这个已经被服务定位器（service locator）实现了（前面讨论过了）， 这里服务层作为一个接口提供给我们的业务逻辑和持久层。 <BR><BR><BR><BR>SaveNewOrder Action 在Struts中用一个服务定位器（service locator）来调用执行业务方法的。 方法代码如下： <BR><BR><BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B><FONT size=2>代码:</FONT></B></SPAN></TD></TR>
<TR>
<TD class=code>public ActionForward execute( <BR><BR>&nbsp; ActionMapping mapping, <BR><BR>&nbsp; ActionForm form, <BR><BR>&nbsp; javax.servlet.http.HttpServletRequest request, <BR><BR>&nbsp; javax.servlet.http.HttpServletResponse response) <BR><BR>&nbsp; throws java.lang.Exception { <BR><BR>&nbsp; <BR><BR>&nbsp; OrderForm oForm = (OrderForm) form; <BR><BR>&nbsp; <BR><BR>&nbsp; // Use the form to build an Order object that <BR><BR>&nbsp; // can be saved in the persistence layer. <BR><BR>&nbsp; // See the full source code in the sample app. <BR><BR>&nbsp; <BR><BR>&nbsp; // Obtain the wired business service object <BR><BR>&nbsp; // from the service locator configuration <BR><BR>&nbsp; // in BaseAction. <BR><BR>&nbsp; // Delegate the save to the service layer and <BR><BR>&nbsp; // further upstream to save the Order object. <BR><BR>&nbsp; getOrderService().saveNewOrder(order); <BR><BR>&nbsp; <BR><BR>&nbsp; oForm.setOrder(order); <BR><BR>&nbsp; <BR><BR>&nbsp; ActionMessages messages = new ActionMessages(); <BR><BR>&nbsp; messages.add( <BR><BR>&nbsp; &nbsp; &nbsp; ActionMessages.GLOBAL_MESSAGE, <BR><BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new ActionMessage( <BR><BR>&nbsp; &nbsp; &nbsp; "message.order.saved.successfully")); <BR><BR>&nbsp; <BR><BR>&nbsp; saveMessages(request, messages); <BR><BR>&nbsp; <BR><BR>&nbsp; return mapping.findForward("success"); <BR><BR>}</TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>总结 <BR><BR>这篇文章在技术和构架方面掩盖了很多低层的基础信息， 文章的主要的意图在于让你意识到如何给你应用程序分层。 分层可以“解耦”你的代码——允许新的组件被添加进来，而且让你的代码易于维护。 这里用到的技术只是专注于把“解偶”做好。 不管怎样，使用这样的构架可以让你用其他技术代替现在的层。 例如，你可能不使用Hibernate实现持久化。既然你在DAO中面向接口的编程的，所以你完全可以用iBATIS来代替。或者，你也可能想用Struts外的其他的技术或者框架替换现在的UI层（转换久层，实现层并不应该直接影响到你的业务逻辑和业务服务层）。 用适当的框架搭建你的Web应用，其实也不是一件烦琐的工作，更主要的是它“解耦”了你程序中的各个层。 <BR><BR><BR><BR><BR><BR>后记： <BR><BR>看完这篇文章后，只是觉得很喜欢，于是就翻译了，当然同时也准备着挨大家扔来的鸡蛋：）。 <BR><BR>这篇文章里并没有太多的技术细节，和详细的步骤。如果你从未使用过这些框架而在运行实例程序遇上困难的话，可以到CSDN论坛Java Open Source版发贴，我一定会详细解答的（啊哦，这不算做广告吧？）， <BR><BR>文章是从一个构架的角度讲述了如何搭配现有的开源框架进行分层， 有太多的术语我都不知道怎么表达，而且可能有很多语句存在错误。如果影响了你的阅读，请你直接点原文地址，我同时也象你说声抱歉。 <BR><BR><BR><BR>作者简介：Mark Eagle 高级软件工程师，亚特兰大。 <BR>翻 译：Totodo,软件工程师 </SPAN></FONT></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/relax/aggbug/2315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-03-22 11:19 <a href="http://www.blogjava.net/relax/archive/2005/03/22/2315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate+Struts应用程序的JavaWebStudio 2005下快速、可视化开发 (转)</title><link>http://www.blogjava.net/relax/archive/2005/02/04/1027.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Fri, 04 Feb 2005 05:35:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/02/04/1027.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/1027.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/02/04/1027.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/1027.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/1027.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Hibernate+Struts应用程序的JavaWebStudio 2005下快速、可视化开发 Struts中文论坛：http://www.javawebstudio.com/ JavaWebStudio 2005下载地址：http://www.javawebstudio.com/bbs/dispbbs.asp?boardID=5&amp;ID=3&amp;page=1 &nbsp;...&nbsp;&nbsp;<a href='http://www.blogjava.net/relax/archive/2005/02/04/1027.html'>阅读全文</a><img src ="http://www.blogjava.net/relax/aggbug/1027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-02-04 13:35 <a href="http://www.blogjava.net/relax/archive/2005/02/04/1027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> "struts中文问题"，"struts国际化问题"的终极解决方案 (转)</title><link>http://www.blogjava.net/relax/archive/2005/02/02/920.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Wed, 02 Feb 2005 07:45:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/02/02/920.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/920.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/02/02/920.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/920.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/920.html</trackback:ping><description><![CDATA[<SPAN id=ArticleContent1_ArticleContent1_lblContent><FONT face=Verdana>Java本身就支持多国语言编码，不需要写任何程序，可以很简单的 实现。 秘诀就是两点： </FONT>
<P></P>
<P>1、所有HTML/JSP页面全部采用UTF-8编码 </P>
<P>2、客户端浏览器完全支持UTF-8编码 </P>
<P>步骤： <BR>1、首先把所有的HTML/JSP的ContentType都设为UTF-8 </P>
<P>2、然后对于JSP程序中的非ASCII码提示信息都不应该写在程序里面，都应该放在 <BR>application.properties里面统一管理。 </P>
<P>3、对HTML用native2ascii工具统一做一次处理，把HTML中的非ASCII码都转换为Unicode编码。 </P>
<P>4、针对不同的语言，写不同的application.properties，比如说简体中文是 <BR>application_zh_CN.properties，繁体中文是application_zh_TW.properties这样，然后对这些配置信 <BR>息文件同样用native2ascii工具处理一次，把非ASCII码统统转为Unicode编码。 </P>
<P>5、在Servlet的request.getCharacterEncoding()获得客户端的操作系统默认编码，然后set到Struts <BR>的HTTPSession的Locale中。 </P>
<P>OK！现在不同的客户访问，就会显示不同的语言版本了。你可以看看此时你的浏览器的字符集，就是 <BR>UTF-8。现在你的网站和Google一样了，嘿嘿，其实你有心的话，看看你的浏览器访问Google的时候是 <BR>什么字符集吧 </P>
<P>切记：所有的HTML/JSP都要设为UTF-8编码，所有的文件中的非ASCII码字符都要用native2ascii工具转 <BR>为用ASCII表示的Unicode编码。 
<HR hight="1">
上面所述是我从网上下的一篇于中文问题的解决方案，确切的说应该是关于Struts的国际化问题，下面我结合我的实践谈谈具体如何实现Struts的国际化问题，我对理论不是非常精通，我只能完全凭自己的理解和实践来讲述，所以下面讲的内容可能不是非常正确，还请大家原谅。但有一点可以肯定，我通过自己的努力解决了Struts的中文问题，并实现Struts的国际化，其实一切并不复杂，下面是具体步骤： 
<P></P>
<P>0.遇到的问题(这些问题也许不会同时出现) <BR>a.中文数据从数据库中到jsp中后就变成了"????" <BR>b.做好的中文properties文件，其中的中文value在页面显示乱码 <BR>c.jsp文件中的中文到浏览器后显示时也是乱码（建议不要在jsp文件中输入中文，尽量放在properties文件中） <BR>d.由jsp传给bean的中文值，再由bean传回页面又是乱码 <BR>e.当更换本地浏览器的语言选项时，Web应用程序不能自动根据你的locale选择合适的*.properties文件。导致Web应用程序不能国际化。 <BR>1.环境： <BR>Web服务器： Tomcat 5.0.19 <BR>操作系统： Win2000 Server <BR>JVM ： jdk 1.4 <BR>数 据 库： Oracle 8.1.7 <BR>开发工具： struts studio 5.2 pro for eclipse <BR>2.先将所有*.jsp 网页中开头处加入 </P>
<P><BR>再设置 </P>
<P>3.然后编辑好两个*.properties文件，放在classes文件夹下你指定的地方，这里是放在/web-inf/classes/com/wiley 下，它们分别是： </P>
<P>ApplicationResources.properties (英文资源文件) <BR>ApplicationResources_zh.properties (中文资源文件) <BR>随便用什么工具编写都行啊！ <BR>4.将ApplicationResources_zh.properties转码成gb2312。上面引文说要转成UTF-8，结果我试了，不行。转成gb2312就行了，操作是。 <BR>将ApplicationResources_zh.properties更名为ApplicationResources_xx.properties <BR>在DOS命令行进入ApplicationResources_xx.properties所在的文件夹 <BR>使用命令：native2ascii -encoding gb2312 ApplicationResources_xx.properties ApplicationResources_zh.properties(至于你为什么会出现“native2ascii不是内部命令”，，请查其它资料，可能你要设置环境变量，因为他是jdk的文件夹bin下的一个应用程序) <BR>5.接下来配置struts-config.xml,很简单，我们加入： </P>
<P>就行了； </P>
<P>到此已能解决大多数中文问题。如上面所说的a,b,e 现在打开浏览器，选择菜单：工具》internet选项》语言，将“中文－中国[zh-cn]”删掉，添加一个“英语－英国[zh-gb]”确定后，重启Tomcat,输入网址你就会发现，你的页面的文本信息就会用的是ApplicationResources.properties (英文资源文件)中的内容。如果换回“中文－中国[zh-cn]”，它就会显示ApplicationResources_zh.properties (中文资源文件)中的中文内容。 </P>
<P>至于问题“c.jsp文件中的中文到浏览器后显示时也是乱码” 你就要用与第4步类似的方法来重新对*.jsp 文件编码，这时-encoding的参数就要用UTF-8了，如果你用的也是struts studio 5.2 pro for eclipse工具，这一步就免了。它会自动用UTF-8的格式存储。 <BR>至于问题“d.由jsp传给bean的中文值，再由bean传回页面又是乱码”的解决，我只是加了个过滤器。 <BR>你可以现在web.xml中加入： </P>
<P>Set Character Encoding <BR>com.wiley.SetCharacterEncodingFilter </P>
<P>encoding <BR>utf-8 </P>
<P><BR>ignore <BR>true </P>
<P>&nbsp;</P>
<P>Set Character Encoding <BR>action </P>
<P><BR>然后在你指定的包内加个java文件 我放在了/web-inf/classes/com/wiley 里，下面是源代码： <BR>/* <BR>* XP Forum <BR>* <BR>* Copyright (c) 2002-2003 RedSoft Group. All rights reserved. <BR>* <BR>*/ <BR>package com.huahang.tj.struts.filters; </P>
<P>import javax.servlet.*; <BR>import java.io.IOException; </P>
<P>/** <BR>* <BR>Filter that sets the character encoding to be used in parsing the <BR>* incoming request, either unconditionally or only if the client did not <BR>* specify a character encoding. Configuration of this filter is based on <BR>* the following initialization parameters:</P>
<P><BR>* </P>
<P>* <BR>encoding - The character encoding to be configured <BR>* for this request, either conditionally or unconditionally based on <BR>* the ignore initialization parameter. This parameter <BR>* is required, so there is no default. <BR>* <BR>ignore - If set to "true", any character encoding <BR>* specified by the client is ignored, and the value returned by the <BR>* selectEncoding() method is set. If set to "false, <BR>* selectEncoding() is called only if the <BR>* client has not already specified an encoding. By default, this <BR>* parameter is set to "true". <BR>* </P>
<P>* <BR>* <BR>Although this filter can be used unchanged, it is also easy to <BR>* subclass it and make the selectEncoding() method more <BR>* intelligent about what encoding to choose, based on characteristics of <BR>* the incoming request (such as the values of the Accept-Language <BR>* and User-Agent headers, or a value stashed in the current <BR>* user´s session.</P>
<P><BR>* <BR>* @author John Wong <BR>* <BR>* @version $Id: SetCharacterEncodingFilter.java,v 1.1 2002/04/10 13:59:27 johnwong Exp $ <BR>*/ <BR>public class SetCharacterEncodingFilter implements Filter { </P>
<P>// ----------------------------------------------------- Instance Variables </P>
<P><BR>/** <BR>* The default character encoding to set for requests that pass through <BR>* this filter. <BR>*/ <BR>protected String encoding = null; </P>
<P><BR>/** <BR>* The filter configuration object we are associated with. If this value <BR>* is null, this filter instance is not currently configured. <BR>*/ <BR>protected FilterConfig filterConfig = null; </P>
<P><BR>/** <BR>* Should a character encoding specified by the client be ignored? <BR>*/ <BR>protected boolean ignore = true; </P>
<P><BR>// --------------------------------------------------------- Public Methods </P>
<P><BR>/** <BR>* Take this filter out of service. <BR>*/ <BR>public void destroy() { </P>
<P>this.encoding = null; <BR>this.filterConfig = null; </P>
<P>} </P>
<P><BR>/** <BR>* Select and set (if specified) the character encoding to be used to <BR>* interpret request parameters for this request. <BR>* <BR>* @param request The servlet request we are processing <BR>* @param result The servlet response we are creating <BR>* @param chain The filter chain we are processing <BR>* <BR>* @exception IOException if an input/output error occurs <BR>* @exception ServletException if a servlet error occurs <BR>*/ <BR>public void doFilter(ServletRequest request, ServletResponse response, <BR>FilterChain chain) <BR>throws IOException, ServletException { </P>
<P>// Conditionally select and set the character encoding to be used <BR>if (ignore || (request.getCharacterEncoding() == null)) { <BR>String encoding = selectEncoding(request); <BR>if (encoding != null) <BR>request.setCharacterEncoding(encoding); <BR>} </P>
<P>// Pass control on to the next filter <BR>chain.doFilter(request, response); </P>
<P>} </P>
<P><BR>/** <BR>* Place this filter into service. <BR>* <BR>* @param filterConfig The filter configuration object <BR>*/ <BR>public void init(FilterConfig filterConfig) throws ServletException { </P>
<P>this.filterConfig = filterConfig; <BR>this.encoding = filterConfig.getInitParameter("encoding"); <BR>String value = filterConfig.getInitParameter("ignore"); <BR>if (value == null) <BR>this.ignore = true; <BR>else if (value.equalsIgnoreCase("true")) <BR>this.ignore = true; <BR>else if (value.equalsIgnoreCase("yes")) <BR>this.ignore = true; <BR>else <BR>this.ignore = false; </P>
<P>} </P>
<P><BR>// ------------------------------------------------------ Protected Methods </P>
<P><BR>/** <BR>* Select an appropriate character encoding to be used, based on the <BR>* characteristics of the current request and/or filter initialization <BR>* parameters. If no character encoding should be set, return <BR>* null. <BR>* </P>
<P>* The default implementation unconditionally returns the value configured <BR>* by the encoding initialization parameter for this <BR>* filter. <BR>* <BR>* @param request The servlet request we are processing <BR>*/ <BR>protected String selectEncoding(ServletRequest request) { </P>
<P>return (this.encoding); </P>
<P>} </P>
<P>}//EOC <BR>到此我遇到的中文问题已全部得到解决，并从中理解到struts的国际化的深刻含义。 <BR>我个人觉得struts作为一个功能强大的应用框架，应该早就考虑到它的国际化问题，并在实际应用中不会很复杂，只要我们遵循一些规则，就可以尽情享受struts给我们带来的无穷乐趣。希望以上所述对大家有所帮助。</P></SPAN><img src ="http://www.blogjava.net/relax/aggbug/920.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-02-02 15:45 <a href="http://www.blogjava.net/relax/archive/2005/02/02/920.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts环境配置手顺(eclipse版)，包括SQL Server的连接</title><link>http://www.blogjava.net/relax/archive/2005/01/24/693.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Mon, 24 Jan 2005 09:01:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/01/24/693.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/693.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/01/24/693.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/693.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/693.html</trackback:ping><description><![CDATA[Struts环境配置手顺<BR><BR>1.Eclipse<BR>&nbsp;&nbsp;下载网址：&nbsp;&nbsp;http://www.eclipse.org/<BR><BR>2.tomcat<BR>&nbsp;&nbsp;下载网址：&nbsp;&nbsp;http://jakarta.apache.org/site/binindex.cgi<BR><BR>3.struts<BR>&nbsp;&nbsp;下载网址：&nbsp;&nbsp;http://jakarta.apache.org/site/binindex.cgi<BR><BR>4.tomcat&nbsp;for&nbsp;Eclipse插件<BR>&nbsp;&nbsp;下载网址：&nbsp;&nbsp;http://www.sysdeo.com/eclipse/tomcatPlugin.html<BR><BR>5.easy&nbsp;struts插件<BR>&nbsp;&nbsp;下载网址：&nbsp;&nbsp;http://sourceforge.net/projects/easystruts<BR><BR>6.EJB开发工具lomboz(不是必需的)&nbsp;&nbsp;<BR>&nbsp;&nbsp;下载网址：&nbsp;&nbsp;http://www.objectlearn.com/<BR><BR>把上述4中的com.sysdeo.eclipse.tomcat_2.2.1和上述5中的com.cross.easystruts.eclipse_0.6.4分别COPY到<BR>eclipse\plugins\,然后进行以下设置<BR><BR>1.Tomcat的初始化设置:启动Eclipse，通过菜单Windows-&gt;Preferences打开设置窗口<BR>&nbsp;&nbsp;选择Tomcat并做配置<BR>1.Easy&nbsp;Struts的初始化设置：启动Eclipse，通过菜单Windows-&gt;Preferences打开设置窗口<BR>&nbsp;&nbsp;选择struts&nbsp;1.1并在struts&nbsp;1.1所需的库文件中找到并添加struts.jar文件<BR>3.在struts&nbsp;1.1所需的类型库描述文件中建议至少加入前面提到的三个描述文件分别是：<BR>&nbsp;&nbsp;struts_html.tld、struts_bean.tld、struts_logic.tld，这三个文件会在创建struts应用项目时自动拷贝到项目的WEB-INF目录下。<BR>4.新建一个Tomcat项目,然后右击project-&gt;Properties-&gt;Libraries,把struts&nbsp;1.1中的包全部加入\r<BR>5.新建Add&nbsp;Easy&nbsp;Struts&nbsp;Support<BR>6.把struts&nbsp;1.1中的包全部COPY到project-&gt;WEB-INF\LIB\<BR><BR>用JAVA连接SQL&nbsp;Server&nbsp;2000取得数据<BR>1.下载JDBC&nbsp;FOR&nbsp;SQLSERVER&nbsp;的驱动：<BR>http://www.microsoft.com/downloads/details.aspx?FamilyID=4f8f2f01-1ed7-4c4d-8f7b-3d47969e66ae&amp;DisplayLang=en#filelist<BR>点击setup.exe下载驱动<BR>2.下载后开始安装，就用默认设置安装,会被安装到：<BR>&nbsp;&nbsp;&nbsp;C:\Program&nbsp;Files\Microsoft&nbsp;SQL&nbsp;Server&nbsp;2000&nbsp;Driver&nbsp;for&nbsp;JDBC<BR>3.把C:\Program&nbsp;Files\Microsoft&nbsp;SQL&nbsp;Server&nbsp;2000&nbsp;Driver&nbsp;for&nbsp;JDBC\lib<BR>&nbsp;&nbsp;下面的mssqlserver.jar,msbase.jar,msutil.jar三个文件拷贝到你的<BR>&nbsp;&nbsp;&nbsp;JDK主目录\jre\lib\ext下面，现在JDBC驱动就算配置好了<BR>4.编译运行测试程序：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;driverName&nbsp;=&nbsp;"com.microsoft.jdbc.sqlserver.SQLServerDriver";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;connURL&nbsp;=&nbsp;"jdbc:microsoft:sqlserver://BLUESKY:1433;User=sa;Password=sa;DatabaseName=sitedb";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class.forName(driverName);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;conn&nbsp;=&nbsp;DriverManager.getConnection(connURL);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Statement&nbsp;stmt&nbsp;=&nbsp;conn.createStatement();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer&nbsp;strsql&nbsp;=&nbsp;new&nbsp;StringBuffer();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strsql.append("select&nbsp;*&nbsp;from&nbsp;USERTABLE&nbsp;where&nbsp;username&nbsp;='"&nbsp;+&nbsp;username&nbsp;+&nbsp;"'");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ResultSet&nbsp;rs&nbsp;=&nbsp;stmt.executeQuery(strsql.toString());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!rs.next()&nbsp;||!password.equals(NulltoString(rs.getString("password")).trim())){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DBmsg&nbsp;=&nbsp;"对不起，您所输入的用户不存在或用户密码不正确";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;username&nbsp;=&nbsp;NulltoString(rs.getString("username"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selectright&nbsp;=&nbsp;NulltoString(rs.getString("selectright"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deleteright&nbsp;=&nbsp;NulltoString(rs.getString("deleteright"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;updateright&nbsp;=&nbsp;NulltoString(rs.getString("updateright"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}catch&nbsp;(ClassNotFoundException&nbsp;ex){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}catch&nbsp;(SQLException&nbsp;ex){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>接下来就可以开始做struts了!!!&nbsp;<img src ="http://www.blogjava.net/relax/aggbug/693.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-01-24 17:01 <a href="http://www.blogjava.net/relax/archive/2005/01/24/693.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP学习经验总结（转）</title><link>http://www.blogjava.net/relax/archive/2005/01/24/692.html</link><dc:creator>轻松</dc:creator><author>轻松</author><pubDate>Mon, 24 Jan 2005 08:57:00 GMT</pubDate><guid>http://www.blogjava.net/relax/archive/2005/01/24/692.html</guid><wfw:comment>http://www.blogjava.net/relax/comments/692.html</wfw:comment><comments>http://www.blogjava.net/relax/archive/2005/01/24/692.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/relax/comments/commentRss/692.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/relax/services/trackbacks/692.html</trackback:ping><description><![CDATA[一、JSP工作原理&nbsp;<BR><BR>在一个JSP文件第一次被请求时，JSP引擎把该JSP文件转换成为一个servlet。而这个引擎本身也是一个servlet，在JSWDK或WEBLOGIC中，它就是JspServlet。&nbsp;JSP引擎先把该JSP文件转换成一个Java源文件，在转换时如果发现jsp文件有任何语法错误，转换过程将中断，并向服务端和客户端输出出错信息；如果转换成功，&nbsp;JSP引擎用javac把该Java源文件编译成相应的class文件。然后创建一个该SERVLET的实例，该SERVLET的jspInit()方法被执行，jspInit()方法在servlet的生命周期中只被执行一次。然后jspService()方法被调用来处理客户端的请求。对每一个请求，JSP引擎创建一个新的线程来处理该请求。如果有多个客户端同时请求该JSP文件，则JSP引擎会创建多个线程。每个客户端请求对应一个线程。以多线程方式执行可大大降低对系统的资源需求,提高系统的并发量及响应时间.但应该注意多线程的编程限制，由于该servlet始终驻于内存，所以响应是非常快的。&nbsp;如果.jsp文件被修改了，服务器将根据设置决定是否对该文件重新编译，如果需要重新编译，则将编译结果取代内存中的servlet，并继续上述处理过程。&nbsp;虽然JSP效率很高，但在第一次调用时由于需要转换和编译而有一些轻微的延迟。&nbsp;此外，如果在任何时候如果由于系统资源不足的原因，JSP引擎将以某种不确定的方式将servlet从内存中移去。当这种情况发生时jspDestroy()方法首先被调用,&nbsp;然后servlet实例便被标记加入"垃圾收集"处理。&nbsp;jspInit()及jspDestory()格式如下：可在jspInit()中进行一些初始化工作,如建立与数据库的连接，或建立网络连接，从配置文件中取一些参数等，在jspDestory()中释放相应的资源。&nbsp;&nbsp;<BR><BR>&lt;%!&nbsp;<BR>public&nbsp;void&nbsp;jspInit()&nbsp;<BR>{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("jspinit");&nbsp;&nbsp;<BR>}&nbsp;<BR>&nbsp;&nbsp;<BR>%&gt;&nbsp;<BR>&nbsp;&nbsp;<BR>&lt;%!&nbsp;<BR>public&nbsp;void&nbsp;jspDestory()&nbsp;<BR>{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("jspDestory");&nbsp;&nbsp;<BR>}&nbsp;<BR>%&gt;&nbsp;<BR><BR>二、服务端的输出缓冲区&nbsp;<BR><BR>缺省情况下:服务端要输出到客户端的内容,不直接写到客户端,而是先写到一个输出缓冲区中.只有在下面三中情况下，才会把该缓冲区的内容输出到客户端上：&nbsp;<BR><BR><BR>该JSP网页已完成信息的输出&nbsp;&nbsp;<BR>输出缓冲区已满&nbsp;&nbsp;<BR>JSP中调用了out.flush()或response.flushbuffer()&nbsp;&nbsp;<BR>输出缓冲区的大小可以用:或response.setBufferSize()设置,如下：&nbsp;&nbsp;<BR>设置输出缓冲区的大小为1KB。或response.setBufferSize(1);&nbsp;&nbsp;<BR>设置输出缓冲区的大小为0，即不缓冲。或response.setBufferSize(0);&nbsp;&nbsp;<BR>用response.getBufferSize()或out.getBufferSize()可取的输出缓冲区的大小,单位为字节.&nbsp;用response.isCommitted()可检查看服务端是否已将数据输出到客户端.&nbsp;如果返回值是TRUE则已将数据输出到客户端,是FALSE则还没有.&nbsp;&nbsp;<BR><BR>三、服务端输出重定向&nbsp;<BR><BR>有以下3种方法可以做到输出重定向:&nbsp;&nbsp;<BR><BR>RESPONSE.SETREDERECT("URL")&nbsp;该方法通过修改HTTP协议的HEADER部分,对浏览器下达重定向指令的,使浏览器显示重定向网页的内容.&nbsp;response.sendRedirect("http://localhost:7001/index.html");&nbsp;&nbsp;<BR>下面的方法也能改变HTTP&nbsp;HEADER属性，它的原理和&nbsp;1&nbsp;是一样的.&nbsp;&nbsp;<BR>&lt;%&nbsp;&nbsp;<BR>response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);&nbsp;&nbsp;<BR>String&nbsp;newLocn="/index.html";&nbsp;&nbsp;<BR>response.setHeader("Location",newLocn);&nbsp;&nbsp;<BR>%&nbsp;&gt;&nbsp;&nbsp;<BR>采用&lt;JSP:FORWORD&gt;&nbsp;该方法是利用服务器端先将数据输出到缓冲区的机制,在把缓冲区的内容发送到客户端之前,原来的不发送,改为发送该页面的内容,如果在&lt;JSP:FORWORD&gt;之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么该语句将不起作用,这一点应该特别注意.&nbsp;如下面的例子中(1)会输出index.html的内容，2&nbsp;不会输出index.html的内容，而是输出out.println("@@@@@@@@@@@@@@@@@");&nbsp;中的内容,并且在服务端会抛出:java.lang.IllegalStateException:&nbsp;Response&nbsp;already&nbsp;committed&nbsp;异常，但客户端没有任何错误输出。&nbsp;&nbsp;<BR>(1)&nbsp;<BR>&lt;%@page&nbsp;buffer="1kb"%&gt;&nbsp;<BR>&nbsp;&nbsp;<BR>&lt;%&nbsp;<BR>long&nbsp;i=0;&nbsp;<BR>&nbsp;&nbsp;<BR>for(i=0;i&lt;10;i++)&nbsp;<BR>{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.println("@@@@@@@@@@@@@@@@@");&nbsp;<BR>}&nbsp;<BR>%&gt;&nbsp;<BR>&nbsp;&nbsp;<BR>&lt;jsp:forward&nbsp;page="./index.html"&nbsp;/&gt;&nbsp;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;<BR>(2)&nbsp;<BR>&lt;%@page&nbsp;buffer="1kb"%&gt;&nbsp;<BR>&nbsp;&nbsp;<BR>&lt;%&nbsp;<BR>long&nbsp;i=0;&nbsp;<BR>&nbsp;&nbsp;<BR>for(i=0;i&lt;600;i++)&nbsp;<BR>{&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;out.println("@@@@@@@@@@@@@@@@@");&nbsp;<BR>}&nbsp;<BR>%&gt;&nbsp;<BR>&nbsp;&nbsp;<BR><BR>说明：&nbsp;<BR>1.&nbsp;方法(1),(2)可以使用变量表示重定向的地址;方法(3)不能使用变量表示重定向的地址。&nbsp;<BR>String&nbsp;add="./index.html";&nbsp;&nbsp;<BR>&lt;jsp:forward&nbsp;page=&nbsp;add&nbsp;/&gt;&nbsp;&nbsp;<BR>无法重定向到index.html中去&nbsp;&nbsp;<BR><BR>String&nbsp;add=http://localhost:7001/index.html&nbsp;&nbsp;<BR>response.sendRedirect(add);&nbsp;&nbsp;<BR>可以重定向到http://localhost:7001/index.html中去。&nbsp;&nbsp;<BR><BR>2.&nbsp;采用方法(1),(2)request中的变量(通过request.setAttribute()保存到request中的值)不能在新的页面中采用,采用方法(3)能.&nbsp;综上,我们应该采用(1),(2)重定向比较好.&nbsp;&nbsp;<BR><BR><BR>四、JSP中正确应用类:&nbsp;&nbsp;<BR><BR>应该把类当成JAVA&nbsp;BEAN来用，不要在&lt;%&nbsp;%&gt;&nbsp;中直接使用.&nbsp;如下的代码(1)经过JSP引擎转化后会变为代码(2):&nbsp;<BR>从中可看出如果把一个类在JSP当成JAVA&nbsp;BEAN&nbsp;使用,JSP会根据它的作用范围把它保存到相应的内部对象中.&nbsp;<BR>如作用范围为request,则把它保存到request对象中.并且只在第一次调用(对象的值为null)它时进行实例化.&nbsp;而如果在&lt;%&nbsp;%&gt;中直接创建该类的一个对象,则每次调用JSP时,都要重新创建该对象,会影响性能.&nbsp;&nbsp;<BR><BR>代码(1)&nbsp;<BR>&lt;jsp:useBean&nbsp;id="test"&nbsp;scope="request"&nbsp;class="demo.com.testdemo"&gt;&nbsp;<BR>&lt;/jsp:useBean&gt;&nbsp;<BR>&nbsp;&nbsp;<BR>&lt;%&nbsp;<BR>test.print("this&nbsp;is&nbsp;use&nbsp;java&nbsp;bean");&nbsp;<BR>&nbsp;&nbsp;<BR>testdemo&nbsp;td=&nbsp;new&nbsp;testdemo();&nbsp;<BR>td.print("this&nbsp;is&nbsp;use&nbsp;new");&nbsp;<BR>%&gt;&nbsp;<BR>&nbsp;&nbsp;<BR><BR><BR>代码(2)&nbsp;<BR>demo.com.testdemo&nbsp;test&nbsp;=&nbsp;(demo.com.testdemo)request.getAttribute("test");&nbsp;&nbsp;<BR>if&nbsp;(test&nbsp;==&nbsp;null)&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;&nbsp;<BR>&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;test&nbsp;=&nbsp;(demo.com.testdemo)&nbsp;java.beans.Beans.instantiate(getClass().getClassLoader(),"demo.com.testdemo");&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;_beanException)&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;weblogic.utils.NestedRuntimeException("cannot&nbsp;instantiate&nbsp;'demo.com.testdemo'",_beanException);&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request.setAttribute("test",&nbsp;test);&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.print("\r\n");&nbsp;<BR>}&nbsp;&nbsp;<BR>out.print("\r\n\r\n\r\n");&nbsp;<BR>test.print("this&nbsp;is&nbsp;use&nbsp;java&nbsp;bean");&nbsp;&nbsp;<BR>&nbsp;&nbsp;<BR>testdemo&nbsp;td=&nbsp;new&nbsp;testdemo();&nbsp;<BR>td.print("this&nbsp;is&nbsp;use&nbsp;new");&nbsp;<BR><BR>&nbsp;&nbsp;<BR><BR><BR><BR>五、JSP的调试&nbsp;&nbsp;<BR><BR>JSP的调试比较麻烦,特别是当bean是在一个session中存在时，更加困难。得从好几个页面开始往里面走才行。通常是用out.println()或System.out.print()来打一大堆的信息来查问题。如果是用jbuilder做开发,它能直接调试JSP.不过更重要的是知道错误产生的原因及解决方法。下面对一些JSP编程常见错误进行分析。&nbsp;&nbsp;<BR><BR>(1).java.lang.NullPointerException异常&nbsp;<BR>一般是对一个为NULL值的变量进行操作引起的.如下面的操作就会抛出&nbsp;<BR>java.lang.NullPointerException&nbsp;<BR>String&nbsp;a&nbsp;=&nbsp;null;&nbsp;&nbsp;<BR>a.substring(0,1);&nbsp;&nbsp;<BR>&nbsp;&nbsp;<BR>为避免这种异常最好在对变量操作之前检查看它是否为NULL值.如:&nbsp;<BR>&lt;%&nbsp;String&nbsp;ss=Session.getAttribute("NAME")&nbsp;&nbsp;<BR>if&nbsp;isnull(ss)&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR><BR>}&nbsp;&nbsp;<BR>else&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR><BR>}&nbsp;&nbsp;<BR>%&gt;&nbsp;&nbsp;<BR><BR>(2).JSP是用JAVA写的，所以它是大小写敏感的，用过其他编程语言的人最容易犯这个错误。另外在浏览器的地址栏中输入的访问JSP的地址也是区分大小写的.如http://localhost:7001/demo/t.jsp与http://localhost:7001/Demo/t.jsp是不一样的&nbsp;<BR><BR>(3).在jsp中判断字符串要使用compareTo方法，不要用==，因为在java中String变量不是一个简单的变量而是一个类实例，不同的方法会得到&nbsp;不同的结果，如下所示：&nbsp;&nbsp;<BR><BR>　　&nbsp;<BR><BR>　　String&nbsp;str1="ABCD";&nbsp;&nbsp;<BR>　　String&nbsp;str2="ABCD";&nbsp;(或&nbsp;String&nbsp;str2="AB"+"CD";&nbsp;&nbsp;&nbsp;<BR>　　if&nbsp;(str1==str2)&nbsp;&nbsp;<BR>　　&nbsp;out.print("yes");&nbsp;&nbsp;<BR>　　else&nbsp;&nbsp;<BR>　　&nbsp;out.print("no");&nbsp;&nbsp;<BR>　　结果是"yes"。&nbsp;&nbsp;<BR>　&nbsp;&nbsp;<BR><BR>　　String&nbsp;str1,str2,str3;&nbsp;&nbsp;<BR>　　str1="ABCD";&nbsp;&nbsp;<BR>　　str2="AB";&nbsp;&nbsp;<BR>　　str3=str2+"CD";&nbsp;&nbsp;<BR>　　if&nbsp;(str1==str3)&nbsp;&nbsp;<BR>　　&nbsp;out.print("yes");&nbsp;&nbsp;<BR>　　else&nbsp;&nbsp;<BR>　　&nbsp;out.print("no");&nbsp;&nbsp;<BR>　　结果是"no"。&nbsp;&nbsp;<BR><BR><BR>String&nbsp;str1=new&nbsp;String("ABCD");&nbsp;&nbsp;<BR>　　String&nbsp;str2=new&nbsp;String("ABCD");&nbsp;&nbsp;<BR>　　if&nbsp;(str1==str2)&nbsp;&nbsp;<BR>　　&nbsp;out.print("yes");&nbsp;&nbsp;<BR>　　else&nbsp;&nbsp;<BR>　　&nbsp;out.print("no");&nbsp;&nbsp;<BR>　　结果是"no"。&nbsp;&nbsp;<BR><BR><BR>String&nbsp;str1=new&nbsp;String("ABCD");&nbsp;&nbsp;<BR>　　String&nbsp;str2=new&nbsp;String("ABCD");&nbsp;&nbsp;<BR>　　if&nbsp;(str1.compareTo(str2)==0)&nbsp;&nbsp;<BR>　　&nbsp;out.print("yes");&nbsp;&nbsp;<BR>　　else&nbsp;&nbsp;<BR>　　&nbsp;out.print("no");&nbsp;&nbsp;<BR>　　结果是"yes"。&nbsp;&nbsp;<BR><BR>(4)防止JSP或SERVLET中的输出被浏览器保存在缓冲区中:&nbsp;<BR>浏览器在默认情况下会把浏览过的网页保存在缓冲区中,在调试时,一般不希望这样.把下面的脚本加入程序中,就可防止JSP或SERVLET中的输出被浏览器保存在缓冲区中&nbsp;&nbsp;<BR>&lt;%&nbsp;&nbsp;<BR>response.setHeader("Cache-Control","no-store");&nbsp;//HTTP&nbsp;1.1&nbsp;&nbsp;<BR>response.setHeader("Pragma","no-cache");&nbsp;//HTTP&nbsp;1.0&nbsp;&nbsp;<BR>response.setDateHeader&nbsp;("Expires",&nbsp;0);&nbsp;//prevents&nbsp;caching&nbsp;at&nbsp;the&nbsp;proxy&nbsp;server&nbsp;&nbsp;<BR>%&gt;&nbsp;&nbsp;<BR>在IE中也可通过设置实现：把/工具/INTERNET选项/常规/设置/的检察所存页面的较新版本,设为每次访问该页时都检查.&nbsp;<BR><BR><BR>六、COOKIE&nbsp;<BR><BR>HTTP&nbsp;COOKIE实质是服务端与在客户端之间传送的普通HTTP头,可保存也可不保存在客户的硬盘上.如果保存,每一个文件大小不超过4K的文本文件.多个COOKIE可保存到同一个文件中.&nbsp;如果从编程角度来看,在JSP中COOKIE就是JAVA提供的一个类.常用的方法如下所表示，因为客户端可能不接受COOKIE，所以建议不用它，改用SESSION等其他方式。&nbsp;&nbsp;<BR><BR><BR>public&nbsp;class&nbsp;cookie&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>public&nbsp;String&nbsp;getDomain()&nbsp;//返回该COOKIE的有效域&nbsp;&nbsp;<BR>public&nbsp;int&nbsp;getMaxAge()&nbsp;//返回该COOKIE的有效期,单位为秒&nbsp;&nbsp;<BR>public&nbsp;String&nbsp;getName()&nbsp;//返回该COOKIE的名称&nbsp;&nbsp;<BR>public&nbsp;String&nbsp;getPath()&nbsp;//返回该COOKIE的有效路径&nbsp;&nbsp;<BR>public&nbsp;boolean&nbsp;getSecure()&nbsp;//返回该COOKIE的安全设置&nbsp;&nbsp;<BR>public&nbsp;String&nbsp;getValue()&nbsp;//返回该COOKIE的值&nbsp;&nbsp;<BR>public&nbsp;void&nbsp;setDomain(java.lang.String&nbsp;pattern)&nbsp;//设置该COOKIE的有效域&nbsp;&nbsp;<BR>public&nbsp;void&nbsp;setMaxAge(int&nbsp;expiry)&nbsp;//设置该COOKIE的有效期,单位为秒&nbsp;&nbsp;<BR>public&nbsp;void&nbsp;setPath(java.lang.String&nbsp;uri)&nbsp;//设置该COOKIE的有效路径&nbsp;&nbsp;<BR>public&nbsp;void&nbsp;setSecure(boolean&nbsp;flag)&nbsp;//设置该COOKIE的安全设置&nbsp;&nbsp;<BR>public&nbsp;void&nbsp;setValue(java.lang.String&nbsp;newValue)&nbsp;//设置该COOKIE的值&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR>一个COOKIE包含以下五部分:&nbsp;&nbsp;<BR><BR>NAME/VALUE对,设置该COOKIE的名字及它保存的值&nbsp;&nbsp;<BR>COOKIE通常和服务器相关,如果将域设为JAVA.SUN.COM,那么该COOKIE就和这个域相关,只对该网址起作用,当浏览该网址时,浏览器将把该COOKIE的内容发送给服务端,COOKIE是作为HTTP&nbsp;HEADER的一部分被发送的，如果没有设置域,那么COOKIE就只和创建该COOKIE的服务器相关.&nbsp;&nbsp;<BR>路径用于指定服务器上可以使用该COOKIE的文件所在的路径,它只对该网址下的该路径下的应用起作用."/"表示服务器上所有目录都可以使用该COOKIE.&nbsp;&nbsp;<BR>COOKIE都有一个有效期,有效期默认值为-1,这表示没有保存该COOKIE,当该浏览器退出时,该COOKIE立即失效.&nbsp;&nbsp;<BR>安全选项true/false,如果设置为true,那么在服务端与在客户端之间传送该COOKIE的内容时,采用HTTPS协议.&nbsp;&nbsp;<BR>如何检查一个客户端是否支持COOKIE的方法:&nbsp;&nbsp;<BR>用下面的方法写一个COOKIE到客户端,并确认成功&nbsp;&nbsp;<BR>try&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>Cookie&nbsp;c&nbsp;=&nbsp;new&nbsp;Cookie("mycookie","COOKIE&nbsp;TEST");&nbsp;&nbsp;<BR>response.addCookie(c);&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR>catch(Exception&nbsp;e)&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(e);&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR><BR><BR>然后在一个新的JSP文件中:用下面的方法取客户端的COOKIE到cookies中,&nbsp;如果cookies.length&nbsp;==0,说明该客户端的浏览器不支持COOKIE&nbsp;&nbsp;<BR>try&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>Cookie[]&nbsp;cookies&nbsp;=&nbsp;request.getCookies();&nbsp;&nbsp;<BR>if(cookies.length&nbsp;==0)&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("not&nbsp;support&nbsp;cookie");&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR>catch(Exception&nbsp;e)&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(e);&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR><BR><BR><BR>七、JSP和SERVLET的区别:&nbsp;<BR><BR>SUN首先发展出SERVLET，其功能比较强劲，体系设计也很先进，只是，它输出HTML语句还是采用了老的CGI方式，是一句一句输出，所以，编写和修改HTML非常不方便。&nbsp;后来SUN推出了类似于ASP的JSP，把JAVA代码嵌套到HTML语句中，这样，就大大简化和方便了网页的设计和修改。ASP，PHP，JSP都是嵌套型的SCRIPT语言。&nbsp;一个分布式系统应分为三层：表示层,业务逻辑层,数据存取层,在J2EE体系结构中,SERVLET用来写业务逻辑层是很强大的，但是对于写表示层就很不方便。JSP则主要是为了方便写表示层而设计的。ENTITY&nbsp;BEAN实现数据存取层，SESSION&nbsp;BEAN实现业务逻辑层。如果是简单的应用系统,可采用JSP+BEANS的结构进行设计,JSP中应该仅仅存放与表示层有关的东西，也就是说，只放输出HTML网页的部份。而所有的数据计算，数据分析，数据库联结处理，统统是属于业务逻辑层，应该放在JAVA&nbsp;BEANS中。通过JSP调用JAVA&nbsp;BEANS，实现两层的整合。&nbsp;实际上，微软的DNA技术，简单说，就是ASP+COM/DCOM技术。与JSP+BEANS完全类似，所有的表示层由ASP完成，所有的业务逻辑由COM/DCOM完成。&nbsp;为什么要采用这些组件技术呢？因为单纯的ASP/JSP语言是非常低效率执行的，如果出现大量用户点击，纯SCRIPT语言很快就到达了他的功能上限，而组件技术就能大幅度提高功能上限，加快执行速度。另外一方面，纯SCRIPT语言将表示层和业务逻辑层混在一起，造成修改不方便，并且代码不能重复利用，采用组件技术就只改组件就可以了。&nbsp;对于复杂的应用，应该采用ENTITY&nbsp;BEAN实现数据存取层，SESSION&nbsp;BEAN实现业务逻辑层，用JSP来调用SESSION&nbsp;BEAN，由SESSION&nbsp;BEAN调用ENTITY&nbsp;BEAN。即采用JSP+EJB来构建一个复杂的分布式系统。它比JSP+BEAN具有更高的吞吐量，可靠性，安全性。综上所述，对简单应用，可采用JSP+BAEN，对复杂的应用系统，应采用JSP+EJB，SERVLET变的无足轻重。用JSP完全可替代它。<img src ="http://www.blogjava.net/relax/aggbug/692.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/relax/" target="_blank">轻松</a> 2005-01-24 16:57 <a href="http://www.blogjava.net/relax/archive/2005/01/24/692.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>