﻿<?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-happyfish-随笔分类-MVC</title><link>http://www.blogjava.net/happyfish/category/555.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 10:31:09 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 10:31:09 GMT</pubDate><ttl>60</ttl><item><title>让Struts与Hibernate顺利协同工作 </title><link>http://www.blogjava.net/happyfish/archive/2005/03/02/1624.html</link><dc:creator>小鱼儿</dc:creator><author>小鱼儿</author><pubDate>Wed, 02 Mar 2005 15:02:00 GMT</pubDate><guid>http://www.blogjava.net/happyfish/archive/2005/03/02/1624.html</guid><wfw:comment>http://www.blogjava.net/happyfish/comments/1624.html</wfw:comment><comments>http://www.blogjava.net/happyfish/archive/2005/03/02/1624.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happyfish/comments/commentRss/1624.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happyfish/services/trackbacks/1624.html</trackback:ping><description><![CDATA[摘自<A href="http://www.99college.com/">久久学院</A><BR>　<B><FONT color=#990000>安装篇</FONT></B><BR><BR>　　一，下载安装 j2sdk1.4（www.sun.com)）或以上,设置 CLASSPATH，java_home。 <BR><BR>　　二，下载服务器，免费版本的有 tomcat,resin,当然也还有 weblogic之类的巨无霸，不过得看你电脑的配置是否承受的了!<BR><BR>　　这里只以resin来说明，其他的配置都差不多，可以查看各个服务器自带的说明文件。<BR><BR>　　resin 服务器可以在 caucho.com下载，选择合适的版本，下载解压缩就可以直接使用。<BR><BR>　　这里resin有一个 resin-ee版本，这个主要是带ejb功能支持的。 如果用不到ejb，一般的就足够了。 <BR>　　三，然后就是数据库，有很多数据库产品可以选择，DB2,Oracle,MSSQL,MySQL等等太多了。这里我选择MySQL，不仅因为它是免费的，而且它的4.0版本在继承以前版本的快速稳定的基础上，整合了InnoDB(http://www.innodb.com)先进的事务处理机制。相信伴随着Linux的壮大，它将在商业数据库市场占的一席之地。不过就数据库本身，它还缺少子查询等强大功能的支持。<BR>安装就不多说了，配置好用户名，密码。 然后就可以下载 MySQL-Front 来可视化操作数据库。 <BR><BR>　　四，在Java编程上，一个IDE的功能显然不可缺少，现在流行的IDE很多，有JBuilder,Eclipse,IntellJ IDEA,JCreator等等，其中 eclipse借着开源东风，依靠强大的插件功能被誉为最有前途的工具，JBuilder从来都最强大功能的java工具，不过大到我的电脑实在运行不了，穷啊，可没钱配新电脑。所以我还是喜欢JCreator，小巧而又功能不俗，应付小规模的应用绰绰有余。编译开发时要想获得提示支持，需要在 configure--option--JDK Profiles 导入jar文件。<BR><BR>　　五，一个站点前台的界面开发，当然离不开大名鼎鼎的 Dreamweaver 了，它支持jsp，asp等很多语言的开发。特别是最近的Dreamweaver MX 2004 增强了站点的功能，可以方便的对一个站点进行控制。面对struts的前台自定义标签，有一个mxp插件可以用来支持显示sturts的标签。使用前还要在编辑--标签库 里面导入.tld文件，目前只支持html，和bean 两个标签。<BR><BR>　　<B><FONT color=#990000>配置篇</FONT></B><BR><BR>　　一，resin虚拟站点配置 <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜host id='yourweb:8080' app-dir='e:\blog\' class-update-interval='2'＞<BR>＜web-app id='/'＞<BR>＜directory-servlet id='false'/＞ <BR>＜/web-app＞<BR>＜error-log id='log/web-error.log'/＞ <BR>＜host＞</TD></TR></TBODY></TABLE><BR>　　然后在定义的目录下面建立站点。 <BR><BR>　　二，Dreamweaver站点的配置就不多说了。<BR><BR>　　三，Struts的配置<BR><BR>　　这里我们使用的是struts1.1,下载并解压缩到临时文件夹，就假设是tem文件夹吧。<BR><BR>　　首先拷贝tem/lib/下面所有的.tld文件到站点的/WEB-INF/目录下，再拷贝所有的.jar文件到/WEB-INF/lib/目录下，最后web.xml文件中的配置差不多如下： <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜?xml version="1.0" encoding="ISO-8859-1"?＞ <BR>＜!DOCTYPE web-app<BR>PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"<BR>"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"＞<BR><BR>＜web-app＞<BR><BR>＜servlet＞<BR>＜servlet-name＞action＜/servlet-name＞<BR>＜servlet-class＞org.apache.struts.action.ActionServlet＜/servlet-class＞<BR>＜init-param＞<BR>＜param-name＞config＜/param-name＞<BR>＜param-value＞/WEB-INF/struts-config.xml＜/param-value＞<BR>＜/init-param＞<BR>＜init-param＞<BR>＜param-name＞debug＜/param-name＞<BR>＜param-value＞2＜/param-value＞<BR>＜/init-param＞<BR>＜init-param＞<BR>＜param-name＞detail＜/param-name＞<BR>＜param-value＞2＜/param-value＞<BR>＜/init-param＞<BR>＜load-on-startup＞2＜/load-on-startup＞<BR>＜/servlet＞<BR><BR>＜servlet-mapping＞<BR>＜servlet-name＞action＜/servlet-name＞<BR>＜url-pattern＞*.do＜/url-pattern＞<BR>＜/servlet-mapping＞<BR><BR><BR>＜!-- The Usual Welcome File List --＞<BR>＜welcome-file-list＞<BR>＜welcome-file＞index.jsp＜/welcome-file＞<BR>＜/welcome-file-list＞<BR><BR><BR>＜!-- Struts Tag Library Descriptors --＞<BR>＜taglib＞<BR>＜taglib-uri＞/tags/struts-bean＜/taglib-uri＞<BR>＜taglib-location＞/WEB-INF/struts-bean.tld＜/taglib-location＞<BR>＜/taglib＞<BR><BR>＜taglib＞<BR>＜taglib-uri＞/tags/struts-html＜/taglib-uri＞<BR>＜taglib-location＞/WEB-INF/struts-html.tld＜/taglib-location＞<BR>＜/taglib＞<BR><BR>＜taglib＞<BR>＜taglib-uri＞/tags/struts-logic＜/taglib-uri＞<BR>＜taglib-location＞/WEB-INF/struts-logic.tld＜/taglib-location＞<BR>＜/taglib＞<BR><BR>＜taglib＞<BR>＜taglib-uri＞/tags/struts-nested＜/taglib-uri＞<BR>＜taglib-location＞/WEB-INF/struts-nested.tld＜/taglib-location＞<BR>＜/taglib＞<BR><BR>＜taglib＞<BR>＜taglib-uri＞/tags/struts-tiles＜/taglib-uri＞<BR>＜taglib-location＞/WEB-INF/struts-tiles.tld＜/taglib-location＞<BR>＜/taglib＞<BR><BR>＜/web-app＞</TD></TR></TBODY></TABLE><BR>　　四，Hibernate配置<BR><BR>　　下载并拷贝/lib目录下的<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>hibernate2.jar <BR>commons-beanutils.jar <BR>commons-collections.jar <BR>commons-dbcp.jar <BR>commons-lang.jar <BR>commons-logging.jar <BR>commons-pool.jar <BR>dom4j.jar <BR>cglib-asm.jar <BR>connector.jar </TD></TR></TBODY></TABLE><BR>　　到应用站点的/lib目录下。接下来配置 hibernate.cfg.xml文件 <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜?xml version='1.0' encoding='utf-8'?＞<BR>＜!DOCTYPE hibernate-configuration<BR>PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"<BR>"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"＞ <BR>＜hibernate-configuration＞<BR>＜session-factory＞<BR><BR>＜property name="hibernate.connection.url"＞<BR>jdbc:mysql://localhost:3306/yourdatabase<BR>＜/property＞<BR>＜property name="hibernate.connection.driver_class"＞<BR>org.gjt.mm.mysql.Driver<BR>＜/property＞<BR>＜property name="hibernate.connection.username"＞<BR>yourname<BR>＜/property＞<BR>＜property name="hibernate.connection.password"＞<BR>youyrpassword<BR>＜/property＞<BR><BR>＜!?- 是否将运行期生成的SQL输出到日志以供调试--＞<BR>＜property name="show_sql"＞false＜/property＞<BR><BR>＜!--dialect ，每个数据库都有其对应的Dialet以匹配其平台特性--＞<BR>＜propertyname="dialect"＞net.sf.hibernate.dialect.MySQLDialect＜/property＞<BR>＜!?- 事务管理类型，这里我们使用JDBC Transaction --＞<BR>＜property name="transaction.factory_class"＞<BR>net.sf.hibernate.transaction.JDBCTransactionFactory＜/property＞<BR><BR>＜property name="jdbc.batch_size"＞10＜/property＞<BR>＜property name="jdbc.use_scrollable_resultset"＞true＜/property＞<BR><BR>＜!?映射文件配置，注意配置文件名必须包含其相对于根的全路径--＞<BR>＜mapping resource="net/seerlog/hbm/Cat.hbm.xml"/＞<BR><BR>＜/session-factory＞<BR><BR>＜/hibernate-configuration＞</TD></TR></TBODY></TABLE><BR>　　以上配置了数据库连接所用的地址和用户名，密码等。具体参数的含义请参考官方文档。<BR><BR>　　映射文件的内容可以手工来写，也可通过一些工具来自动生成。 <BR><BR>　　整个需要两种文件： .hbm.xml配置文件 和 .java持久化对象 , 两者是相互关联的，.hbm.xml 对数据库的映射还需要 .java这个bean来操作。所以整个过程需要首先设计好数据库，然后根据数据库导出 .hbm.xml文件 ,然后再导出 .java 文件。 有很多工具可以实现这个工程，我们这里采用 Middlegen-Hibernate来实现 数据库到.hbm.xml文件的转化，用Hibernate-Extension工具包中的 hbm2java 来实现 .hbm.xml 到 .java 文件的转化！<BR><BR>&nbsp; <IMG height=455 src="http://www.yesky.com/image20010518/237769.gif" width=599 useMap=#Map2 border=0> <MAP name=Map2><AREA shape=RECT target=_blank coords=281,253,534,270 href="http://dev.yesky.com/SoftChannel/72342371961929728/index.shtml"></MAP><MAP name=Map><AREA shape=RECT target=_blank coords=281,253,532,267 href="http://dev.yesky.com/SoftChannel/72342371961929728/index.shtml"></MAP><BR><BR>　　查找关键字”<FONT color=#ff0000>!ENTITY</FONT>”，得到：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜!DOCTYPE project [<BR>＜!ENTITY database SYSTEM<BR>"file:./config/database/<FONT color=#ff0000>hsqldb.xml</FONT>"＞<BR>]＞</TD></TR></TBODY></TABLE><BR>　　b) Application name<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜property name="name" value="<FONT color=#ff0000>airline</FONT>"/＞ </TD></TR></TBODY></TABLE><BR>　　c) 输出目录<BR><BR>　　查找关键字“name="build.gen-src.dir"”，得到：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜property name="build.gen-src.dir" value="<FONT color=#ff0000>${build.dir}/gen-src</FONT>"/＞ </TD></TR></TBODY></TABLE><BR>　　d) 对应代码的Package name<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜hibernate<BR>destination="${build.gen-src.dir}"<BR>package="<FONT color=#ff0000>${name}.hibernate</FONT>"<BR>genXDocletTags="false"<BR>genIntergratedCompositeKeys="false"<BR>javaTypeMapper="middlegen.plugins.hibernate.HibernateJavaTypeMapper"<BR>/＞ </TD></TR></TBODY></TABLE><BR>　　配置完成后，在MiddleGen 根目录下运行ant，就将出现MiddleGen的界面：<BR><BR>　　选择需要的表，单击窗口顶部的Generate 按钮，MiddleGen 即为我们生成这些数据库表所对应的Hibernate映射文件。 <BR><BR>　　接下来的工作通过Hibernate Extension 来完成，Hibernate Extension 的tools\bin目录下包含三个工具：<BR><BR>　　1． hbm2java.bat<BR><BR>　　根据映射文件生成对应的POJO。通过MiddleGen 我们已经得到了映射文件，下一步就是通过hbm2java.bat工具生成对应的POJO。<BR><BR>　　2． class2hbm.bat<BR><BR>　　根据POJO class 生成映射文件，这个工具很少用到，这里也就不再详细介绍。<BR><BR>　　3． ddl2hbm.bat<BR><BR>　　由数据库导出库表结构，并生成映射文件以及POJO。这个功能与MiddleGen的功能重叠，但由于目前还不够成熟（实际上已经被废弃，不再维护），提供的功能也有限，所以我们还是采用MiddleGen生成映射文件，之后由hbm2java根据映射文件生成POJO 的方式。 <BR><BR>　　这里我们使用第一个hbm2java.bat，利用刚才生成的.hbm.xml文件自动生成 java 文件。 <BR><BR>　　为了使用这个工具，首先我们需要配置一些参数，打开tools\bin\setenv.bat 文件，修改其中的JDBC_DRIVER和HIBERNATE_HOME环境变量，使其指向我们的实际JDBC Driver文件和Hibernate所在目录。同时检查一下环境变量CP中的各个项目中是否实际存在，特别是%CORELIB%下的jar文件，某些版本的发行包中，默认配置中的文件名与实际的文件名有所出入（如%CORELIB%\commons-logging.jar, 在Hibernate 发行包中，可能实际的文件名是commons-logging-1.0.3.jar，诸如此类）。 <BR><BR>　　使用hbm2java，根据MiddleGen生成的映射文件生成Java 代码：<BR><BR>　　打开Command Window，在tools\bin目录下执行：<BR><BR>hbm2java c:\sample\org\hibernate\sample\*.xml --output=c:\sample\ <BR><BR>　　通过以上步骤我们就生成了所需要的所有基本配置文件。接下来就可以来初始化这些配置啦。 <BR>
<TABLE cellSpacing=0 cellPadding=0 width=776 border=0>
<TBODY>
<TR>
<TD vAlign=top bgColor=#f0f2fb height=10></TD></TR>
<TR>
<TD vAlign=top bgColor=#f0f2fb>
<TABLE cellSpacing=0 cellPadding=0 width=590 align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=f14>　　<FONT color=#990000><B>实战篇</B></FONT><BR><BR>　　在这一节我们要配置一个完整的应用配置。其实每一个单独拿出来都能写本书，不过我只是侧重对自己总结，在以后我会不断地把学习的经验教训写下来。<BR><BR>　　一，Log4j 的初始化 <BR><BR>　　配置log4j.properties <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>### direct log messages to stdout ###<BR>#log4j.appender.stdout=org.apache.log4j.ConsoleAppender<BR>#log4j.appender.stdout.Target=System.out<BR>#log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<BR>%c{1}:%L - %m%n<BR>#log4j.appender.stdout.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %l%n%m%n <BR>log4j.logger.seerlog=DEBUG,A2<BR>log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender<BR>log4j.appender.A2.file=d:\\log\\applog.txt<BR>log4j.appender.A2.DatePattern='.'yyyy-MM-dd<BR>log4j.appender.A2.layout=org.apache.log4j.PatternLayout<BR>log4j.appender.A2.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %m%n<BR><BR>#log4j.logger.ALL=DEBUG,A1<BR>log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender<BR>log4j.appender.A1.file=d:\\log\\all.log<BR>log4j.appender.A1.DatePattern='.'yyyy-MM-dd<BR>log4j.appender.A1.layout=org.apache.log4j.PatternLayout<BR>log4j.appender.A1.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %l%n%m%n<BR><BR>### direct messages to file hibernate.log ###<BR>#log4j.appender.file=org.apache.log4j.FileAppender<BR>#log4j.appender.file.File=hibernate.log<BR>#log4j.appender.file.layout=org.apache.log4j.PatternLayout<BR>#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n<BR><BR>### set log levels - for more verbose logging change 'info' to 'debug' ###<BR><BR>###log4j.rootLogger=warn, stdout<BR>log4j.rootLogger=info, A1<BR><BR>#以下是hibernate API需要的配置<BR><BR>log4j.logger.net.sf.hibernate=info<BR><BR>### log just the SQL<BR>#log4j.logger.net.sf.hibernate.SQL=debug<BR><BR>### log JDBC bind parameters ###<BR>log4j.logger.net.sf.hibernate.type=info<BR><BR>### log schema export/update ###<BR>log4j.logger.net.sf.hibernate.tool.hbm2ddl=debug<BR><BR>### log cache activity ###<BR>#log4j.logger.net.sf.hibernate.cache=debug<BR><BR>### enable the following line if you want to track down connection ###<BR>### leakages when using DriverManagerConnectionProvider ###<BR>#log4j.logger.net.sf.hibernate.connection.DriverManagerConnectionProvider=trac</TD></TR></TBODY></TABLE><BR>　　配置后如下来调用,首先需要初始化配置文件，这个过程只需要一次，所以我们可以在ServletContextListener中来进行。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>String prefix = context.getRealPath("/");<BR>PropertyConfigurator.configure(prefix+"/WEB-INF/classes/log4j.properties"); </TD></TR></TBODY></TABLE><BR>　　这里需要你的配置文件的路径来初始化。<BR><BR>　　初始化完成后，我们在以后的action中就可以 象下面一样来调用：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>static Logger log=Logger.getLogger("seerlog");<BR>log.warn("it's log4j warn");<BR>log.info("it's log4j info"); </TD></TR></TBODY></TABLE><BR>　　关于 log4j 的完全使用方法，偶会在以后做详细的说明！ <BR><BR>　　二，hibernate 的初始化 <BR><BR>　　首先我们要把hibernate.cfg.xml 放到应用的 classes 目录中，然后可以使用hibernate参考文档提供的例子来封装对后台的使用。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>public class Hi{<BR><BR>private static final SessionFactory sessionFactory;<BR>private static Connection conn;<BR>static {<BR>　try {<BR>　　sessionFactory = new Configuration().configure().buildSessionFactory();<BR>　} catch (HibernateException ex) {<BR>　　throw new RuntimeException("Exception building SessionFactory: " + ex.getMessage(), ex);<BR>　}<BR>}<BR><BR>public static final ThreadLocal session = new ThreadLocal();<BR>public static Session getSession() throws HibernateException {<BR>　Session s = (Session) session.get();<BR>　// 假如没有一个可用的线程，开启一个新 Session,<BR>　if (s == null) {<BR>　　conn=DBConnectionManager.getConnection();<BR>　　s = sessionFactory.openSession(conn);<BR>　　session.set(s);<BR>　}<BR>　return s;<BR>}<BR><BR>public static void closeSession() throws HibernateException {<BR>　Session s = (Session) session.get();<BR>　session.set(null);<BR>　if (s != null)<BR>　　s.close();<BR>　if(conn!=null)<BR>　　DBConnectionManager.returnConnection(conn);<BR>　}<BR>}</TD></TR></TBODY></TABLE><BR>　　文中DBConnectionManager.getConnection()是一个DAO类，提供连接池的实现。 <BR><BR>　　我们使用这个con连接来创建一个 session ，sission是一个数据库连接操作的会话周期，它提供了强大的管理数据的能力。 <BR><BR>　　以后我们在action的 execute 方法中就可以使用 Hi.getSession()来获得一个会话支持。典型的应用如下： <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>try{<BR>　//开启一个会话，并启动事务回滚能力<BR>　Session session = Hi.getSession();<BR>　Transaction tx= session.beginTransaction();<BR><BR>　//查询数据库，使用HQL<BR>　Query q = session.createQuery("from Topic as topic order by topic.id desc");<BR>　q.setFirstResult(0);<BR>　q.setMaxResults(5);<BR><BR>　//得到一个List类型的数据 <BR>　List newTopicList = q.list();<BR><BR>　// 业务处理 <BR>　NewTopicList ntlBean=new NewTopicList();<BR>　ntlBean.setList(newTopicList);<BR>　req.setAttribute("newtopiclist",ntlBean);<BR><BR>　//事务提交，记得关闭会话！ <BR>　tx.commit();<BR>　Hi.closeSession();<BR><BR>}//因为整个会话会抛出异常，所以需要用try--catch来包裹<BR>catch(HibernateException e){<BR><BR>　//日志记录 <BR>　Log.error(e.toString());<BR>}</TD></TR></TBODY></TABLE><BR>　　其中的HQL 可以参考 hibernate 官方文档来学习。 <BR></SPAN></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=776 border=0>
<TBODY>
<TR>
<TD vAlign=top bgColor=#f0f2fb height=10></TD></TR>
<TR>
<TD vAlign=top bgColor=#f0f2fb>
<TABLE cellSpacing=0 cellPadding=0 width=590 align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=f14>　　<FONT color=#990000><B>实战篇</B></FONT><BR><BR>　　在这一节我们要配置一个完整的应用配置。其实每一个单独拿出来都能写本书，不过我只是侧重对自己总结，在以后我会不断地把学习的经验教训写下来。<BR><BR>　　一，Log4j 的初始化 <BR><BR>　　配置log4j.properties <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>### direct log messages to stdout ###<BR>#log4j.appender.stdout=org.apache.log4j.ConsoleAppender<BR>#log4j.appender.stdout.Target=System.out<BR>#log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<BR>%c{1}:%L - %m%n<BR>#log4j.appender.stdout.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %l%n%m%n <BR>log4j.logger.seerlog=DEBUG,A2<BR>log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender<BR>log4j.appender.A2.file=d:\\log\\applog.txt<BR>log4j.appender.A2.DatePattern='.'yyyy-MM-dd<BR>log4j.appender.A2.layout=org.apache.log4j.PatternLayout<BR>log4j.appender.A2.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %m%n<BR><BR>#log4j.logger.ALL=DEBUG,A1<BR>log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender<BR>log4j.appender.A1.file=d:\\log\\all.log<BR>log4j.appender.A1.DatePattern='.'yyyy-MM-dd<BR>log4j.appender.A1.layout=org.apache.log4j.PatternLayout<BR>log4j.appender.A1.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %l%n%m%n<BR><BR>### direct messages to file hibernate.log ###<BR>#log4j.appender.file=org.apache.log4j.FileAppender<BR>#log4j.appender.file.File=hibernate.log<BR>#log4j.appender.file.layout=org.apache.log4j.PatternLayout<BR>#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n<BR><BR>### set log levels - for more verbose logging change 'info' to 'debug' ###<BR><BR>###log4j.rootLogger=warn, stdout<BR>log4j.rootLogger=info, A1<BR><BR>#以下是hibernate API需要的配置<BR><BR>log4j.logger.net.sf.hibernate=info<BR><BR>### log just the SQL<BR>#log4j.logger.net.sf.hibernate.SQL=debug<BR><BR>### log JDBC bind parameters ###<BR>log4j.logger.net.sf.hibernate.type=info<BR><BR>### log schema export/update ###<BR>log4j.logger.net.sf.hibernate.tool.hbm2ddl=debug<BR><BR>### log cache activity ###<BR>#log4j.logger.net.sf.hibernate.cache=debug<BR><BR>### enable the following line if you want to track down connection ###<BR>### leakages when using DriverManagerConnectionProvider ###<BR>#log4j.logger.net.sf.hibernate.connection.DriverManagerConnectionProvider=trac</TD></TR></TBODY></TABLE><BR>　　配置后如下来调用,首先需要初始化配置文件，这个过程只需要一次，所以我们可以在ServletContextListener中来进行。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>String prefix = context.getRealPath("/");<BR>PropertyConfigurator.configure(prefix+"/WEB-INF/classes/log4j.properties"); </TD></TR></TBODY></TABLE><BR>　　这里需要你的配置文件的路径来初始化。<BR><BR>　　初始化完成后，我们在以后的action中就可以 象下面一样来调用：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>static Logger log=Logger.getLogger("seerlog");<BR>log.warn("it's log4j warn");<BR>log.info("it's log4j info"); </TD></TR></TBODY></TABLE><BR>　　关于 log4j 的完全使用方法，偶会在以后做详细的说明！ <BR><BR>　　二，hibernate 的初始化 <BR><BR>　　首先我们要把hibernate.cfg.xml 放到应用的 classes 目录中，然后可以使用hibernate参考文档提供的例子来封装对后台的使用。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>public class Hi{<BR><BR>private static final SessionFactory sessionFactory;<BR>private static Connection conn;<BR>static {<BR>　try {<BR>　　sessionFactory = new Configuration().configure().buildSessionFactory();<BR>　} catch (HibernateException ex) {<BR>　　throw new RuntimeException("Exception building SessionFactory: " + ex.getMessage(), ex);<BR>　}<BR>}<BR><BR>public static final ThreadLocal session = new ThreadLocal();<BR>public static Session getSession() throws HibernateException {<BR>　Session s = (Session) session.get();<BR>　// 假如没有一个可用的线程，开启一个新 Session,<BR>　if (s == null) {<BR>　　conn=DBConnectionManager.getConnection();<BR>　　s = sessionFactory.openSession(conn);<BR>　　session.set(s);<BR>　}<BR>　return s;<BR>}<BR><BR>public static void closeSession() throws HibernateException {<BR>　Session s = (Session) session.get();<BR>　session.set(null);<BR>　if (s != null)<BR>　　s.close();<BR>　if(conn!=null)<BR>　　DBConnectionManager.returnConnection(conn);<BR>　}<BR>}</TD></TR></TBODY></TABLE><BR>　　文中DBConnectionManager.getConnection()是一个DAO类，提供连接池的实现。 <BR><BR>　　我们使用这个con连接来创建一个 session ，sission是一个数据库连接操作的会话周期，它提供了强大的管理数据的能力。 <BR><BR>　　以后我们在action的 execute 方法中就可以使用 Hi.getSession()来获得一个会话支持。典型的应用如下： <BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>try{<BR>　//开启一个会话，并启动事务回滚能力<BR>　Session session = Hi.getSession();<BR>　Transaction tx= session.beginTransaction();<BR><BR>　//查询数据库，使用HQL<BR>　Query q = session.createQuery("from Topic as topic order by topic.id desc");<BR>　q.setFirstResult(0);<BR>　q.setMaxResults(5);<BR><BR>　//得到一个List类型的数据 <BR>　List newTopicList = q.list();<BR><BR>　// 业务处理 <BR>　NewTopicList ntlBean=new NewTopicList();<BR>　ntlBean.setList(newTopicList);<BR>　req.setAttribute("newtopiclist",ntlBean);<BR><BR>　//事务提交，记得关闭会话！ <BR>　tx.commit();<BR>　Hi.closeSession();<BR><BR>}//因为整个会话会抛出异常，所以需要用try--catch来包裹<BR>catch(HibernateException e){<BR><BR>　//日志记录 <BR>　Log.error(e.toString());<BR>}</TD></TR></TBODY></TABLE><BR>　　其中的HQL 可以参考 hibernate 官方文档来学习。 </SPAN></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/happyfish/aggbug/1624.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happyfish/" target="_blank">小鱼儿</a> 2005-03-02 23:02 <a href="http://www.blogjava.net/happyfish/archive/2005/03/02/1624.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转)Spring学习笔记1 </title><link>http://www.blogjava.net/happyfish/archive/2005/03/02/1623.html</link><dc:creator>小鱼儿</dc:creator><author>小鱼儿</author><pubDate>Wed, 02 Mar 2005 14:50:00 GMT</pubDate><guid>http://www.blogjava.net/happyfish/archive/2005/03/02/1623.html</guid><wfw:comment>http://www.blogjava.net/happyfish/comments/1623.html</wfw:comment><comments>http://www.blogjava.net/happyfish/archive/2005/03/02/1623.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happyfish/comments/commentRss/1623.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happyfish/services/trackbacks/1623.html</trackback:ping><description><![CDATA[<H2><FONT color=#99cc00>1、概念理解</FONT> </H2>
<P>对Spring耳闻已久，但一直没有时间和心情去看它，最近它的声音是越来越大了，Java视线<A href="http://forum.javaeye.com/"><FONT color=#223355>http://forum.javaeye.com/</FONT></A>有不高手在谈论它。于是趁着有空闲时间，我也花了两个晚上看了看Spring，看的是夏昕的&lt;Spring开发指南&gt;http://www.xiaxin.net/Spring_Dev_Guide.rar，文章写得不错。以下谈谈我的学习感受</P>
<P><FONT color=#ccffcc><STRONG><FONT color=#66cc00>一、Spring的IoC(Inversion of Control)。</FONT></STRONG><BR></FONT>这是Spring中得有特点的一部份。IoC又被翻译成“控制反转”，也不知道是谁翻译得这么别扭，感觉很深奥的词。其实，原理很简单，用一句通俗的话来说：就是用XML来定义生成的对象。IoC其实是一种设计模式，Spring只是实现了这种设计模式。</P>
<P>这种设计模式是怎么来的呢？是实践中逐渐形成的。</P>
<P>第一阶段：用普通的无模式来写Java程序。一般初学者都要经过这个阶段。<BR>第二阶段：频繁的开始使用接口，这时，接口一般都会伴随着使用工厂模式。<BR>第三阶段：使用IoC模式。工厂模式还不够好：（1）因为的类的生成代码写死在程序里，如果你要换一个子类，就要修改工厂方法。（2）一个接口常常意味着一个生成工厂，会多出很多工厂类。<BR>&nbsp;&nbsp;&nbsp; 可以把IoC模式看做是工厂模式的升华，可以把IoC看作是一个大工厂，只不过这个大工厂里要生成的对象都是在XML文件中给出定义的，然后利用Java的“反射”编程，根据XML中给出的类名生成相应的对象。从实现来看，IoC是把以前在工厂方法里写死的对象生成代码，改变为由XML文件来定义，也就是把工厂和对象生成这两者独立分隔开来，目的就是提高灵活性和可维护性。</P>
<P>&nbsp;&nbsp;&nbsp; IoC中最基本的Java技术就是“反射”编程。反射又是一个生涩的名词，通俗的说反射就是根据给出的类名（字符串）来生成对象。这种编程方式可以让对象在生成时才决定要生成哪一种对象。我在最近的一个项目也用到了反射，当时是给出一个.properties文本文件，里面写了一些全类名（包名＋类名），然后，要根据这些全类名在程序中生成它们的对象。反射的应用是很广泛的，象Hibernate、String中都是用“反射”做为最基本的技术手段。</P>
<P>&nbsp;&nbsp;&nbsp; 在过去，反射编程方式相对于正常的对象生成方式要慢10几倍，这也许也是当时为什么反射技术没有普通应用开来的原因。但经SUN改良优化后，反射方式生成对象和通常对象生成方式，速度已经相差不大了（但依然有一倍以上的差距）。</P>
<P><BR>&nbsp;&nbsp;&nbsp; 所以要理解IoC，你必须先了解工厂模式和反射编程，否则对它产生的前因后果和实现原理都是无法理解透彻的。只要你理解了这一点，你自己也完全可以自己在程序中实现一个IoC框架，只不是这还要涉及到XML解析等其他知识，稍微麻烦一些。</P>
<P><BR>&nbsp;&nbsp;&nbsp; IoC最大的好处是什么？因为把对象生成放在了XML里定义，所以当我们需要换一个实现子类将会变成很简单（一般这样的对象都是现实于某种接口的），只要修改XML就可以了，这样我们甚至可以实现对象的热插拨（有点象USB接口和SCIS硬盘了）。</P>
<P>&nbsp;&nbsp;&nbsp; IoC最大的缺点是什么？（1）生成一个对象的步骤变复杂了（其实上操作上还是挺简单的），对于不习惯这种方式的人，会觉得有些别扭和不直观。（2）对象生成因为是使用反射编程，在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说，这点损耗是微不足道的，除非某对象的生成对效率要求特别高。（3）缺少IDE重构操作的支持，如果在Eclipse要对类改名，那么你还需要去XML文件里手工去改了，这似乎是所有XML方式的缺憾所在。</P>
<P>&nbsp;&nbsp;&nbsp; 总的来说IoC无论原理和实现都还算是很简单的。一些人曾认为IoC没什么实际作用，这种说法是可以理解的，因为如果你在编程中很少使用接口，或很少使用工厂模式，那么你根本就没有使用IoC的强烈需要，也不会体会到IoC可贵之处。有些人也说要消除工厂模式、单例模式，但是都语焉不详、人云亦云。但如果你看到IoC模式和用上Spring，那么工厂模式和单例模式的确基本上可以不用了。但它消失了吗？没有！Spring的IoC实现本身就是一个大工厂，其中也包含了单例对象生成方式，只要用一个设置就可以让对象生成由普通方式变单一实例方式，非常之简单。</P>
<P><STRONG><FONT color=#666699>&nbsp;&nbsp; 总结：<BR>&nbsp;&nbsp; （1）IoC原理很简单，作用的针对性也很强，不要把它看得很玄乎。<BR>&nbsp;&nbsp; （2）要理解IoC，首先要了解“工厂、接口、反射”这些概念。</FONT></STRONG></P>
<P><BR><STRONG><FONT color=#66cc00>二、Spring的MVC</FONT></STRONG></P>
<P>如果你已经熟悉Struts，那么不必把MVC做为重点学习内容。基本上我认为Spring&nbsp; MVC是一个鸡肋，它的技术上很先进，但易用性上没有Struts好。而且Struts有这么多年的基础了，Spring很难取代Struts的地位。这就是先入为主的优秀，一个项目经理选用一种框架，不能单纯的从它的技术上考虑，还有开发效率，人员配置等都是考虑因素。但做为研究性的学习，Spring的MVC部份还是蛮有价值的。</P>
<P><BR><STRONG><FONT color=#66cc00>三、数据库层的模板</FONT></STRONG><BR>Spring主要是提供了一些数据库模板（模板也是一种Java设计模式），让数据部分的代码更简洁，那些try...catch都可以不见了。这个的确是个好东东。</P>
<P><BR><STRONG><FONT color=#66cc00>四、AOP</FONT></STRONG></P>
<P>AOP又称面向方面编程，它的实现原理还是用了反射：通过对某一个种类的方法名做监控来实现统一处理。比如：监控以“insert”字符串开头的方法名，在这种方法执行的前后进行某种处理（数据库事务等）。但这里我有一个疑问？不一定所有以insert开头的方法都是数据库操作，哪么当某个insert开头的方法不是数据库操作，你又对它进行了数据事务的操作，这样的错误如何防止？？？我对这方面了解不深，还是只知道一个大概。</P>
<P><BR>曾看过一个程序员发出这样的感慨：“框架一个接一个，学也学不完，而且有必要吗？这样一层层的加上框架，还不如直接写JSP来得直接，效率还高”。我想这种困惑很多人都有吧？但如果你经过的项目渐多，就会发现，维护项目要比开发项目更艰难，代价更大。那种用JSP直接来写，层次又不清楚的开发，往往最后得到一个不可再修改的软件，一团乱麻，移一发而动全身。但软件不象电视机，做好了就不会改动了，软件是一个变化的事物，用户的需求随时会改变，这时你会体会到分层和使用框架的好处了，它们为你做了软件中很多和业务无关的工作，你可以只关注业务，并减少代码量。唯一缺点就是有一个学习的代价，框架配置上也较麻烦。</P>
<P><BR>学习框架，我认为应该：第一步，了解这个框架中的一些关键概念，它的具体含义是什么。第二步，了解这个框架的精华在哪里，它能对开发起到什么样的作用，最好能对它的原理有一定的了解。第三步，用这个框架来写几个例子，实际体会一下。我现在还是刚刚大概完成了前两步，这几天会再看看Spring的文档并用Spring写几个例子，到时一起发出来。</P>
<P>另外，很赞赏&lt;Spring开发指南&gt;的作者夏昕的观点，将自已的经验写成文档公开出来，不过一个人的力量终究太弱。最好能够形成一个组织，对一种新技术，由一两个人出一个大纲，大家把它分了，更写一章，然后由两三个人总集起。我个人感觉，由于英文语言的关系，新技术引进到国内的还是太慢了，至少要比国外慢上一年以上，成立一个开源文档组织还是很有意义的事。</P><img src ="http://www.blogjava.net/happyfish/aggbug/1623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happyfish/" target="_blank">小鱼儿</a> 2005-03-02 22:50 <a href="http://www.blogjava.net/happyfish/archive/2005/03/02/1623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转)Spring的下载和安装 </title><link>http://www.blogjava.net/happyfish/archive/2005/03/02/1622.html</link><dc:creator>小鱼儿</dc:creator><author>小鱼儿</author><pubDate>Wed, 02 Mar 2005 14:49:00 GMT</pubDate><guid>http://www.blogjava.net/happyfish/archive/2005/03/02/1622.html</guid><wfw:comment>http://www.blogjava.net/happyfish/comments/1622.html</wfw:comment><comments>http://www.blogjava.net/happyfish/archive/2005/03/02/1622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happyfish/comments/commentRss/1622.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happyfish/services/trackbacks/1622.html</trackback:ping><description><![CDATA[<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">下载主页</SPAN><SPAN lang=EN-US><A href="http://www.springframework.org/download.html"><FONT color=#223355>http://www.springframework.org/download.html</FONT></A> </SPAN><SPAN style="FONT-FAMILY: 宋体">，或者直接使用链接地址：</SPAN><SPAN lang=EN-US><A href="http://voxel.dl.sourceforge.net/sourceforge/springframework/spring-framework-1.1.4-with-dependencies.zip"><FONT color=#223355>http://voxel.dl.sourceforge.net/sourceforge/springframework/spring-framework-1.1.4-with-dependencies.zip</FONT></A></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的下载包有两种：</SPAN><SPAN lang=EN-US>spring-framework-1.1.4-with-dependencies.zip</SPAN><SPAN style="FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US>spring-framework-1.1.4.zip</SPAN><SPAN style="FONT-FAMILY: 宋体">，上面的第二个链接就是下载前者，建议你也下载前者，因为前者比后者多了一些</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">要用到的第三方包，如</SPAN><SPAN lang=EN-US>hibernate</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>j2ee</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>dom4j</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>aopalliance</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>jakarta-commons</SPAN><SPAN style="FONT-FAMILY: 宋体">等。下载包名称的</SPAN><SPAN lang=EN-US>dependencies</SPAN><SPAN style="FONT-FAMILY: 宋体">就是“依赖”的意思。</SPAN></P>
<H3><SPAN lang=EN-US>1、解压后的目录结构如下：</SPAN></H3>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=321 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image001.jpg" width=286 border=0></SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">目录说明：</SPAN></P>
<P class=Char><SPAN lang=EN-US style="FONT-SIZE: 7.5pt; FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>dist&nbsp; Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">自已的核心库</SPAN></P>
<P class=Char><SPAN lang=EN-US style="FONT-SIZE: 7.5pt; FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>docs&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-FAMILY: 宋体">有一些文档。</SPAN></P>
<P class=Char><SPAN lang=EN-US style="FONT-SIZE: 7.5pt; FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>lib&nbsp;&nbsp; </SPAN><SPAN style="FONT-FAMILY: 宋体">是一些用到的第三方库。</SPAN></P>
<P class=Char><SPAN lang=EN-US style="FONT-SIZE: 7.5pt; FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>mock&nbsp; </SPAN><SPAN style="FONT-FAMILY: 宋体">仿制品？？？？？？？？？？？？？我也不知道</SPAN></P>
<P class=Char><SPAN lang=EN-US style="FONT-SIZE: 7.5pt; FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>samples </SPAN><SPAN style="FONT-FAMILY: 宋体">一些项目例子</SPAN></P>
<P class=Char><SPAN lang=EN-US style="FONT-SIZE: 7.5pt; FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>src&nbsp; Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的源代码</SPAN></P>
<P class=Char><SPAN lang=EN-US style="FONT-SIZE: 7.5pt; FONT-FAMILY: Wingdings">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US>test&nbsp; </SPAN><SPAN style="FONT-FAMILY: 宋体">测试用例</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<H3><SPAN lang=EN-US>2、新建一个Eclipse项目</SPAN></H3>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>1</SPAN><SPAN style="FONT-FAMILY: 宋体">）项目名</SPAN><SPAN lang=EN-US>myspring</SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=462 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image002.jpg" width=500 border=0></SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>2</SPAN><SPAN style="FONT-FAMILY: 宋体">）直接单击“下一步”，再单击“完成”</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>3</SPAN><SPAN style="FONT-FAMILY: 宋体">）在项目下创建一个</SPAN><SPAN lang=EN-US>lib</SPAN><SPAN style="FONT-FAMILY: 宋体">目录</SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=121 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image003.jpg" width=253 border=0></SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>4</SPAN><SPAN style="FONT-FAMILY: 宋体">）将</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的解压缩目录</SPAN><SPAN lang=EN-US>dist</SPAN><SPAN style="FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US>lib</SPAN><SPAN style="FONT-FAMILY: 宋体">都复制到这个</SPAN><SPAN lang=EN-US>lib</SPAN><SPAN style="FONT-FAMILY: 宋体">目录中，然后前者改名成</SPAN><SPAN lang=EN-US>spring</SPAN><SPAN style="FONT-FAMILY: 宋体">，后者先暂时不动吧，以后用到时才管它。</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<H3><SPAN lang=EN-US>3、将spring库加入到库引用</SPAN></H3>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">将</SPAN><SPAN lang=EN-US>spring</SPAN><SPAN style="FONT-FAMILY: 宋体">库加入到库引用中，有如下两种方法。</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">方法一：单击“添加</SPAN><SPAN lang=EN-US>JAR</SPAN><SPAN style="FONT-FAMILY: 宋体">”把</SPAN><SPAN lang=EN-US>spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的核心包加入。</SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=438 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image004.jpg" width=438 border=0></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">方法二：上面的“方法一”简单易行，但如果一个项目要引入的包种类很多，那么就显示得较乱。还有一种操作麻烦，但较清晰一些的方法。这种方法是使用</SPAN><SPAN lang=EN-US>Eclipse</SPAN><SPAN style="FONT-FAMILY: 宋体">中的“用户库”的方式，如下图所示：</SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=456 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image005.jpg" width=553 border=0></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=397 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image006.jpg" width=554 border=0></SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=514 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image007.jpg" width=553 border=0></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">最后的结果如下图所示，然后单击“确定”</SPAN></P><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 黑体"><BR style="PAGE-BREAK-BEFORE: always" clear=all></SPAN>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=383 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image008.jpg" width=553 border=0></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">返回上一界面后，再单击“完成”，得到如下图所示的效果</SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=456 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image009.jpg" width=553 border=0></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">最后，项目里的</SPAN><SPAN lang=EN-US>spring</SPAN><SPAN style="FONT-FAMILY: 宋体">包的引用都在一个目录下，显示层次感强很多。</SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=315 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image010.jpg" width=288 border=0></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal><SPAN style="FONT-FAMILY: 宋体">以后如果要引入</SPAN><SPAN lang=EN-US>myspring/lib/lib</SPAN><SPAN style="FONT-FAMILY: 宋体">目录下的第三方包，也按方法二较好：将第三方包的目录复制到</SPAN><SPAN lang=EN-US>myspring/lib</SPAN><SPAN style="FONT-FAMILY: 宋体">下，再参照方法二，将其加入库引用中即可</SPAN></P>
<H3><SPAN lang=EN-US>4、设置日志包的库引用</SPAN></H3>
<P class=MsoNormal><SPAN lang=EN-US>jakarta-commons</SPAN><SPAN style="FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US>log4j</SPAN><SPAN style="FONT-FAMILY: 宋体">包主要是做为</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的运行时输出</SPAN><SPAN lang=EN-US>log</SPAN><SPAN style="FONT-FAMILY: 宋体">（日志）用，如果不设置日志包，那么日志就没法输出到控制台，不利于开发和调试。设置方式如下：</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>1</SPAN><SPAN style="FONT-FAMILY: 宋体">）就照上面的方法，放</SPAN><SPAN lang=EN-US>myspring/lib/lib</SPAN><SPAN style="FONT-FAMILY: 宋体">目录下的</SPAN><SPAN lang=EN-US>log4j</SPAN><SPAN style="FONT-FAMILY: 宋体">目录和</SPAN><SPAN lang=EN-US>jakarta-commons</SPAN><SPAN style="FONT-FAMILY: 宋体">目录往上移一层到</SPAN><SPAN lang=EN-US>myspring/lib</SPAN><SPAN style="FONT-FAMILY: 宋体">目录下。最后设置的结果如下图所示，这里我们把</SPAN><SPAN lang=EN-US>log4j</SPAN><SPAN style="FONT-FAMILY: 宋体">移到了</SPAN><SPAN lang=EN-US>others</SPAN><SPAN style="FONT-FAMILY: 宋体">目录，因为</SPAN><SPAN lang=EN-US>log4j</SPAN><SPAN style="FONT-FAMILY: 宋体">就一个</SPAN><SPAN lang=EN-US>JAR</SPAN><SPAN style="FONT-FAMILY: 宋体">包，专门为它象</SPAN><SPAN lang=EN-US>jakarta-commons</SPAN><SPAN style="FONT-FAMILY: 宋体">创建一个目录和用户库太不值了，以后可能还会有这种引用单个包的时候，到时都放到</SPAN><SPAN lang=EN-US>others</SPAN><SPAN style="FONT-FAMILY: 宋体">目录里好了。</SPAN><SPAN lang=EN-US> </SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=619 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image011.jpg" width=513 border=0></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>2</SPAN><SPAN style="FONT-FAMILY: 宋体">）日志的库引用完成之后，还要创建一个日志的配置文件：</SPAN><SPAN lang=EN-US>log4j.properties</SPAN><SPAN style="FONT-FAMILY: 宋体">，其文件内容如下：</SPAN></P>
<DIV style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #fff0e1; PADDING-BOTTOM: 1pt; BORDER-LEFT: windowtext 1pt solid; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid">
<P class=a0><SPAN lang=EN-US>log4j.rootLogger=DEBUG, stdout</SPAN></P>
<P class=a0><SPAN lang=EN-US>log4j.appender.stdout=org.apache.log4j.ConsoleAppender</SPAN></P>
<P class=a0><SPAN lang=EN-US>log4j.appender.stdout.layout=org.apache.log4j.PatternLayout</SPAN></P>
<P class=a0><SPAN lang=EN-US>log4j.appender.stdout.layout.ConversionPattern=%c{1} - %m%n</SPAN></P></DIV>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN lang=EN-US>log4j.properties</SPAN><SPAN style="FONT-FAMILY: 宋体">文件的创建位置在</SPAN><SPAN lang=EN-US>src</SPAN><SPAN style="FONT-FAMILY: 宋体">目录下，如下图所示：</SPAN></P>
<P class=a style="TEXT-INDENT: 20pt"><SPAN lang=EN-US><IMG height=148 alt="" src="http://blog.csdn.net/images/blog_csdn_net/glchengang/97615/r_20050217image012.jpg" width=258 border=0></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 0cm"><SPAN lang=EN-US></SPAN>&nbsp;</P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN style="FONT-FAMILY: 宋体">如果没有设置日志设置或设置不对，在使用控制台时会出现下面所示的红字。</SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 20pt"><SPAN lang=EN-US style="FONT-SIZE: 10pt; BACKGROUND: white; COLOR: red; FONT-FAMILY: 宋体">java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory</SPAN></P><BR><img src ="http://www.blogjava.net/happyfish/aggbug/1622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happyfish/" target="_blank">小鱼儿</a> 2005-03-02 22:49 <a href="http://www.blogjava.net/happyfish/archive/2005/03/02/1622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts 用户指南 </title><link>http://www.blogjava.net/happyfish/archive/2005/03/02/1621.html</link><dc:creator>小鱼儿</dc:creator><author>小鱼儿</author><pubDate>Wed, 02 Mar 2005 14:48:00 GMT</pubDate><guid>http://www.blogjava.net/happyfish/archive/2005/03/02/1621.html</guid><wfw:comment>http://www.blogjava.net/happyfish/comments/1621.html</wfw:comment><comments>http://www.blogjava.net/happyfish/archive/2005/03/02/1621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happyfish/comments/commentRss/1621.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happyfish/services/trackbacks/1621.html</trackback:ping><description><![CDATA[<FONT face=宋体>1.&nbsp;介绍<BR>1.1&nbsp;Model-View-Controller&nbsp;(MVC)&nbsp;设计模式<BR>FIXME&nbsp;-&nbsp;需要一个对该模式一般性的介绍。（译注：可以参考机械工业出版社的《设计模式》。）&nbsp;<BR>1.2&nbsp;将MVC概念映射到Struts组件中<BR>Struts&nbsp;的体系结构实现了Model-View-Controller设计模式的概念，它将这些概念映射到web应用程序的组件和概念中，如下图所示：&nbsp;<BR><BR>--------------------------------------------------------------------------------<BR><BR><BR><BR>--------------------------------------------------------------------------------<BR><BR>这一体系结构中每个主要的组件都将在下面做详细的讨论。&nbsp;<BR><BR>1.3&nbsp;Model:&nbsp;系统状态和商业逻辑JavaBeans<BR>基于MVC的系统中的&nbsp;Model&nbsp;部分可以细分为两个概念&nbsp;--&nbsp;系统的内部状态,&nbsp;能够改变状态的行为。用语法术语来说，我们可以把状态信息当作名词（事物），把行为当作动词（事物状态的改变）。&nbsp;<BR>通常说来，你的应用程序将系统内部的状态表示为一组一个或多个的JavaBeans，使用属性（properties）来表示状态的细节。依赖于你的应用程序的复杂度，这些beans可以是自包含的（以某种方式知道怎样永久地保存它们的状态信息），或者可以是正面的（facades），知道当被请求时怎样从外部数据源（例如数据库）中取得信息。Entity&nbsp;EJBs通常也用来表示内部状态。&nbsp;<BR><BR>大型应用程序经常将系统可能的商业逻辑行为表示为可以被维护状态信息的beans调用的方法。举个例子，你有一个为每个当前用户保存在session中的购物车bean，里面是表示当前用户决定购买物品的属性。这个bean有一个checkOut()方法用来验证用户的信用卡，将定单发给库房以选择货品和出货。别的系统分别地表示同样的行为，或许使用Session&nbsp;EJBs。&nbsp;<BR><BR>在一些小型应用程序中，同样的行为又可能嵌入到作为Controller一部分的&nbsp;Action&nbsp;类中。这在逻辑非常简单或者并不想要在其它环境中重用这些商业逻辑时是恰当的。Struts框架支持所有这些方法，但建议将商业逻辑（“做什么”）和&nbsp;Action&nbsp;类（“决定做什么”）分离开。&nbsp;<BR><BR>1.4&nbsp;View:&nbsp;JSP页面和表示组件<BR>基于Struts的应用程序中的&nbsp;View&nbsp;部分通常使用JSP技术来构建。JSP页面包含称为“模版文本”的静态HTML（或XML）文本，加上插入的基于对特殊行为标记解释的动态内容。JSP环境包括了其用途由JSP规范来描述的一套标准的行为标记，例如&nbsp;&lt;jsp:useBean&gt;&nbsp;。另外，还有一个用来定义你自己标记的标准机制，这些自定义的标记组织在“定制标记库”中。&nbsp;<BR>Struts包括了一个广阔的便于创建用户界面，并且充分国际化的定制标记库，与作为系统&nbsp;Model&nbsp;部分一部分的ActionForm&nbsp;beans美妙地相互配合。这些标记的使用将在后面做详细讨论。&nbsp;<BR><BR>除了JSP页面和其包含的行为及定制标记，商业对象经常需要能够基于它们在被请求时的当前状态将自己处理成HTML（或XML）。从这些对象处理过的输出可以很容易地使用&nbsp;&lt;jsp:include&gt;&nbsp;标准行为标记包括在结果的JSP页面中。&nbsp;<BR><BR>1.5&nbsp;Controller:&nbsp;ActionServlet和ActionMapping<BR>应用程序的&nbsp;Controller&nbsp;部分集中于从客户端接收请求（典型情况下是一个运行浏览器的用户），决定执行什么商业逻辑功能，然后将产生下一步用户界面的责任委派给一个适当的View组件。在Struts中，controller的基本组件是一个&nbsp;ActionServlet&nbsp;类的servlet。这个servlet通过定义一组映射（由Java接口&nbsp;ActionMapping&nbsp;描述）来配置。每个映射定义一个与所请求的URI相匹配的路径和一个&nbsp;Action&nbsp;类（一个实现&nbsp;Action&nbsp;接口的类）完整的类名，这个类负责执行预期的商业逻辑，然后将控制分派给适当的View组件来创建响应。&nbsp;<BR>Struts也支持使用包含有运行框架所必需的标准属性之外的附加属性的&nbsp;ActionMapping&nbsp;类的能力。这允许你保存特定于你的应用程序的附加信息，同时仍可利用框架其余的特性。另外，Struts允许你定义控制将重定向到的逻辑名，这样一个行为方法可以请求“主菜单”页面（举例），而不需要知道相应的JSP页面的实际名字是什么。这个功能极大地帮助你分离控制逻辑（下一步做什么）和显示逻辑（相应的页面的名称是什么）。&nbsp;<BR><BR>2.&nbsp;创建Model组件<BR>2.1&nbsp;概述<BR>你用到的应用程序的需求文档很可能集中于创建用户界面。然而你应该保证每个提交的请求所需要的处理也要被清楚的定义。通常说来，Model&nbsp;组件的开发者集中于创建支持所有功能需求的JavaBeans类。一个特殊应用要求的beans的精确特性依赖于具体需求变化会非常的大，但是它们通常可以分成下面讨论的几种类型。然而，首先对“范围”概念做一个简短的回顾是有用的，因为它与beans有关。&nbsp;<BR>2.2&nbsp;JavaBeans和范围<BR>在一个基于web的应用程序中，JavaBeans可以被保存在（并从中访问）一些不同“属性”的集合中。每一个集合都有集合生存期和所保存的beans可见度的不同的规则。总的说来，定义生存期和可见度的这些规则被叫做这些beans的&nbsp;范围&nbsp;。JSP规范中使用以下术语定义可选的范围（在圆括号中定义servlet&nbsp;API中的等价物）：&nbsp;<BR>page&nbsp;-&nbsp;在一个单独的JSP页面中可见的Beans，生存期限于当前请求。（service()方法中的局部变量）&nbsp;request&nbsp;-&nbsp;在一个单独的JSP页面中可见的Beans，也包括所有包含于这个页面或从这个页面重定向到的页面或servlet。（Request属性）&nbsp;<BR>session&nbsp;-&nbsp;参与一个特定的用户session的所有的JSP和servlet都可见的Beans，跨越一个或多个请求。(Session属性）&nbsp;<BR>application&nbsp;-&nbsp;一个web应用程序的所有JSP页面和servlet都可见的Beans。（Servlet&nbsp;context属性）&nbsp;<BR>记住同一个web应用程序的JSP页面和servlets共享同样一组bean集合是很重要的。例如，一个bean作为一个request属性保存在一个servlet中，就象这样：&nbsp;<BR>MyCart&nbsp;mycart&nbsp;=&nbsp;new&nbsp;MyCart(...);<BR>request.setAttribute("cart",&nbsp;mycart);<BR>将立即被这个servlet重定向到的一个JSP页面使用一个标准的行为标记看到，就象这样：&nbsp;<BR>&lt;jsp:useBean&nbsp;id="cart"&nbsp;scope="request"<BR>class="com.mycompany.MyApp.MyCart"/&gt;<BR>2.3&nbsp;ActionForm&nbsp;Beans<BR>Struts框架通常假定你已经为每一个你的应用程序中请求的输入创建了一个&nbsp;ActionForm&nbsp;bean（即一个实现了&nbsp;ActionForm&nbsp;接口的类）。如果你在你的&nbsp;ActionMapping&nbsp;配置文件中定义了这样的beans（见“创建Controller组件”），Struts的controller&nbsp;servlet在调用适当的&nbsp;Action&nbsp;方法前将自动为你执行如下的服务：&nbsp;<BR>用适当的关键字检查用户的session中是否有适当的类的bean的一个实例。&nbsp;<BR>如果没有这样的session范围的bean，自动建立一个新的bean并添加到用户的session中。&nbsp;<BR>对每个名字对应于bean中的一个属性的请求参数，调用相应的set方法。这个操作类似于当你以通配符“*”选择所有属性使用标准的JSP行为标记&nbsp;&lt;jsp:setProperty&gt;&nbsp;。&nbsp;<BR>更新的ActionForm&nbsp;bean在被调用时将被传递给Acton类的perform()方法，以使这些值能够立即生效。&nbsp;<BR>当你在写你的ActionForm&nbsp;beans时，记住以下的原则：&nbsp;<BR>ActionForm&nbsp;接口本身不需要特殊的实现方法。它是用来标识这些特定的beans在整个体系结构中的作用。典型情况下，一个ActionForm&nbsp;bean只包括属性的get方法和set方法，没有商业逻辑。&nbsp;<BR>通常在一个ActionForm&nbsp;bean中只有很少的输入验证逻辑。这样的beans存在的主要理由是保存用户为相关的表单所输入的大部分近期值&nbsp;--&nbsp;甚至在错误被检测到时&nbsp;--&nbsp;这样同样的页面可以被重建，伴随有一组出错信息，这样用户仅仅需要纠正错误的字段。用户输入的验证应该在&nbsp;Action&nbsp;类中执行（如果是很简单的话），或者在适当的商业逻辑beans中执行。&nbsp;<BR>为每个表单中出现的字段定义一个属性（用相关的getXxx()和setXxx()方法）。字段名和属性名必须按照JavaBeans的约定相匹配。例如，一个名为&nbsp;username&nbsp;的输入字段将引起&nbsp;setUsername()&nbsp;方法被调用。&nbsp;<BR>你应该注意一个“表单”在这里讨论时的意义并不必须对应于用户界面中的一个单独的JSP页面。在很多应用程序中一个“表单”（从用户的观点）延伸至多个页面也是很平常的。想想看，例如，通常在安装新的应用程序时使用的导航安装程序的用户界面。Struts鼓励你定义一个包含所有字段属性的单独的ActionForm&nbsp;bean。不管字段实际上是显示在哪个页面上。同样的，同一表单的不同的页面应该提交到相同的Action类。如果你遵照这个建议，在大多数情况下，页面设计者可以重新组织不同页面中的字段而不需要改变处理逻辑。&nbsp;<BR>2.4&nbsp;系统状态Beans<BR>系统的实际状态通常表示为一组一个或多个的JavaBeans类，其属性定义当前状态。例如，一个购物车系统包括一个表示购物车的bean，这个bean为每个单独的购物者维护，这个bean中包括（在其它事物之中）一组购物者当前选择购买的项目。分别地，系统也包括保存用户信息（包括他们的信用卡和送货地址）、可获得项目的目录和它们当前库存水平的不同的beans。&nbsp;<BR>对于小规模的系统，或者对于不需要长时间保存的状态信息，一组系统状态beans可以包含所有系统曾经经历的特定细节的信息。或者经常是，系统状态beans表示永久保存在一些外部数据库中的信息（例如CustomerBean对象对应于表&nbsp;CUSTOMERS&nbsp;中的特定的一行），在需要时从服务器的内存中创建或清除。在大规模应用程序中，Entity&nbsp;EJBs也用于这种用途。&nbsp;<BR><BR>2.5&nbsp;商业逻辑Beans<BR>你应该把你的应用程序中的功能逻辑封装成对为此目的设计的JavaBeans的方法调用。这些方法可以是用于系统状态beans的相同的类的一部分，或者可以是在专门执行商业逻辑的独立的类中。在后一种情况下，你通常需要将系统状态beans传递给这些方法作为参数处理。&nbsp;<BR>为了代码最大的可重用性，商业逻辑beans应该被设计和实现为它们不知道自己被执行于web应用环境中。如果你发现在你的bean中你必须import一个&nbsp;javax.servlet.*&nbsp;类，你就把这个商业逻辑捆绑在了web应用环境中。考虑重新组织事物使你的&nbsp;Action&nbsp;类（Controller任务的一部分，在下面描述）翻译所有从HTTP请求中请求被处理为对你的商业逻辑beans属性set方法调用的信息，然后可以发出一个对&nbsp;execute()&nbsp;的调用。这样的一个商业逻辑类可以被重用在除它们最初被构造的web应用程序以外的环境中。&nbsp;<BR><BR>依赖于你的应用程序的复杂度和范围，商业逻辑beans可以是与作为参数传递的系统状态beans交互作用的普通的JavaBeans，或者使用JDBC调用访问数据库的普通的JavaBeans。而对于较大的应用程序，这些beans经常是有状态或无状态的EJBs。&nbsp;<BR><BR>2.6&nbsp;题外话:&nbsp;访问关系数据库<BR>很多web应用程序利用一个关系数据库（通过一个JDBC&nbsp;driver访问）来保存应用程序相关的永久数据。其它应用程序则使用Entity&nbsp;EJBs来实现这个目的，他们委派EJBs自己来决定怎样维护永久状态。如果你是使用EJBs来实现这个目的，遵照EJB规范中描述的客户端设计模式。&nbsp;<BR>对于基于直接数据库访问的web应用程序，一个普通的设计问题是当需要访问低层数据库时怎样产生一个适当的JDBC连接对象。解决这个问题有几种方法&nbsp;--&nbsp;以下原则描述了推荐的一种方法：&nbsp;<BR><BR>创建或得到一个允许一组数据库连接被多个用户共享的ConnectionPool类。Struts（当前）没有包括这样的一个类，但是有很多这样的类可以得到。&nbsp;<BR>当应用程序初始化时，在应用程序展开（deployment）描述符中定义一个有一个“启动时加载”值的servlet。我们将把这个servlet叫做&nbsp;启动&nbsp;servlet。在大多数情况下，这个servlet不需要处理任何的请求，所以没有一个&nbsp;&lt;servlet-mapping&gt;&nbsp;会指向它。&nbsp;<BR>在启动servlet的&nbsp;init()&nbsp;方法中，配置并初始化一个ConnectionPool类的实例，将其保存为一个servlet&nbsp;context属性（从JSP的观点看等同于一个application范围的bean）。通常基于传递给启动servlet初始化参数来配置联接缓冲池是很方便的。&nbsp;<BR>在启动servlet的&nbsp;destroy()&nbsp;方法中，包含了释放联接缓冲池所打开的联接的逻辑。这个方法将在servlet容器结束这个应用程序的时候被调用。&nbsp;<BR>当&nbsp;Action&nbsp;类需要调用一个需要数据库联接的商业逻辑bean中的方法（例如“insert&nbsp;a&nbsp;new&nbsp;customer”）时，将执行下面的步骤：&nbsp;<BR>为这个web应用程序从servelt&nbsp;context属性中得到一个联接缓冲池对象。&nbsp;<BR>调用联接缓冲池对象的&nbsp;open()&nbsp;方法来得到一个在&nbsp;Action&nbsp;类调用中使用的联接。&nbsp;<BR>调用商业逻辑bean中合适的方法，将数据库联接对象作为一个参数传递给它。&nbsp;<BR>调用分配的联接中的&nbsp;close()&nbsp;方法，这将引起这个联接为了以后其它请求的重用被返回到缓冲池中。&nbsp;<BR>一个通常的编程错误是忘记了把数据库联接返回给缓冲池，这将最终导致用完所有的联接。一定要确信&nbsp;Action&nbsp;类的逻辑总是返回联接，甚至在商业逻辑bean抛出一个违例时。&nbsp;<BR>遵照上面推荐的设计模式意味着你能够编写你的商业逻辑类而不需要担心它们怎样得到一个JDBC联接来使用--&nbsp;简单地在任何需要访问数据库的方法中包含一个Connection参数。当你的商业逻辑类在一个web应用程序中被利用时，分配和释放适当的联接是&nbsp;Action&nbsp;类的责任。当你使用相同的商业逻辑类时，例如，在一个批处理工作中，提供一个适当的联接是那个应用程序的责任（这不需要从缓冲池中获得，因为大多数批处理工作运行于一个单线程环境中）。&nbsp;<BR>3.&nbsp;创建View组件<BR>3.1&nbsp;概述<BR>这一章集中于创建应用程序中的&nbsp;View&nbsp;组件的任务，主要使用JSP技术建立。特别的，Struts除了提供了与输入表单的交互外还提供了建立国际化应用程序的支持。几个其它的与View相关的主题也被简单地讨论。&nbsp;<BR>3.2&nbsp;国际化消息<BR>几年之前，应用程序开发者能够考虑到仅仅支持他们本国的只使用一种语言（或者有时候是两种）和通常只有一种数量表现方式（例如日期、数字、货币值）的居民。然而，基于web技术的应用程序的爆炸性增长，以及将这些应用程序展开在Internet或其它被广泛访问的网络之上，已经在很多情况下使得国家的边界淡化到不可见。这种情况转变成为一种对于应用程序支持国际化（经常被称做“i18n”，因为18是字母“i”和字母“n”之间的字母个数）和本地化的需求。&nbsp;<BR>Struts建立于Java平台之上为建立国际化和本地化的应用程序提供帮助。需要熟悉的关键概念是：&nbsp;<BR><BR>Locale&nbsp;-&nbsp;基础的支持国际化的Java类是&nbsp;java.util.Locale&nbsp;。每个&nbsp;Locale&nbsp;代表一个特别的国家和语言选择（加上一个可选的语言变量），以及一套格式假定，例如数字和日期等等。&nbsp;<BR>ResourceBundle&nbsp;-&nbsp;java.util.ResourceBundle&nbsp;类提供支持多种语言消息的基本工具。查看文档中关于ResourceBundle&nbsp;类以及你的JDK版本的文档包中关于国际化的更多内容。&nbsp;<BR>PropertyResourceBundle&nbsp;-&nbsp;一个&nbsp;ResourceBundle&nbsp;类的标准实现允许你使用与初始化properties文件同样的“name=value”语法来定义资源。这对于使用为用于一个web应用程序的消息准备资源包是非常方便的，因为这些消息通常都是面向文本的。&nbsp;<BR>MessageFormat&nbsp;-&nbsp;java.text.MessageFormat&nbsp;类允许你使用运行时指定的参数替换一个消息字符串中的一部分（在这种情况下，是一个从一个资源包得到的消息）。这在你创建一个句子的场合中是有用的，但是词会以不同的语言按照不同的顺序出现。消息中的占位符字符串{0}用第一个运行时参数替换，{1}用第二个运行时参数替换，以此类推。&nbsp;<BR>MessageResources&nbsp;-&nbsp;Struts的类&nbsp;org.apache.struts.util.MessageResources&nbsp;使你能够将一套资源包视做一个数据库，并且允许你为一个特定的Locale（通常是与当前用户相对应）请求一个特定的消息，而不是为服务器运行在其中的缺省的Locale请求消息。&nbsp;<BR>对于一个国际化的应用程序，遵照JDK文档包中国际化文档所描述的步骤来创建一个包含每种语言的消息的属性文件。下面举一个例子说明。&nbsp;<BR>假设你的源代码建立在包&nbsp;com.mycompany.mypackage&nbsp;中，因此它保存于一个叫做（相对于你的源目录）com/mycompany/mypackage&nbsp;的目录中。为创建一个叫做&nbsp;com.mycompany.mypackage.MyResources&nbsp;的资源包，你应该在目录&nbsp;com/mycompany/mypackage&nbsp;中创建下列文件：&nbsp;<BR><BR>MyResources.properties&nbsp;-&nbsp;包含你的服务器的缺省语言的消息。如果你的缺省语言是英语，你可能有一个这样的条目：&nbsp;<BR>prompt.hello=Hello<BR>MyResources_xx.properties&nbsp;-&nbsp;包含ISO语言编程为“xx”（查看ResourceBundle的Java文档页面得到一个当前列表的联接）的同样的消息。对于上面的消息的法语版，你可以有这个条目：&nbsp;<BR>prompt.hello=Bonjour<BR>你可以有你需要的任意多的语言的资源包文件。<BR>当你在web应用程序展开描述符中配置controller&nbsp;servlet时，你需要在一个初始化参数中定义的一件事是应用程序的资源包的基础名。在上述的情况中，这应该是&nbsp;com.mycompany.mypackage.MyResources&nbsp;。&nbsp;<BR>3.3&nbsp;表单和FormBean的交互<BR>大部分web开发者曾经使用HTML的标准性能来建立表单，例如使用&nbsp;&lt;input&gt;&nbsp;标记。用户希望交互程序具有一定的行为，这些期待中的一个与错误处理有关&nbsp;--&nbsp;如果用户出现一个错误，应用程序应该允许他们仅仅修改需要修改的部分&nbsp;--&nbsp;而不需要重新敲入当前页面或表单中的任何其它信息。&nbsp;<BR>使用标准的HTML和JSP编程来完全实现这个期望是单调而繁重的。举例来说，一个用户名字段的输入元素看起来可以象是这样（在JSP中）&nbsp;<BR><BR>&lt;input&nbsp;type="text"&nbsp;name="username"<BR>value="&lt;%=&nbsp;loginBean.getUsername()&nbsp;%&gt;"&gt;<BR>这很难敲对，会把没有编程概念的HTML开发者搞糊涂，并且会在HTML编辑器中造成问题。取而代之的是，Struts提供了一种全面的基于JSP&nbsp;1.1的定制标记库功能的机制来建立表单。上面的情况使用Struts处理后将象是这样：&nbsp;<BR>&lt;struts:text&nbsp;name="username"/&gt;<BR>没有必要再显式地涉及到从中获得初始值的JavaBean。这将由框架自动处理。&nbsp;<BR>3.3.1&nbsp;使用Struts建立表单<BR>一个完整的注册表单将演示Struts相对于直接使用HTML和标准的JSP功能怎样极大地减轻了处理表单的痛苦。考虑以下称为logon.jsp的页面（来自Struts的例子程序）：&nbsp;<BR>&lt;%@&nbsp;page&nbsp;language="java"&nbsp;%&gt;<BR>&lt;%@&nbsp;taglib&nbsp;uri="/WEB-INF/struts.tld"&nbsp;prefix="struts"&nbsp;%&gt;<BR><BR>&lt;html&gt;<BR>&lt;head&gt;<BR>&lt;title&gt;&lt;struts:message&nbsp;key="logon.title"/&gt;&lt;/title&gt;<BR>&lt;body&nbsp;bgcolor="white"&gt;<BR><BR>&lt;struts:errors/&gt;<BR><BR>&lt;struts:form&nbsp;action="logon.do"&nbsp;name="logonForm"<BR>type="org.apache.struts.example.LogonForm"/&gt;<BR>&lt;table&nbsp;border="0"&nbsp;width="100%"&gt;<BR>&lt;tr&gt;<BR>&lt;th&nbsp;align="right"&gt;<BR>&lt;struts:message&nbsp;key="prompt.username"/&gt;<BR>&lt;/th&gt;<BR>&lt;td&nbsp;align="left"&gt;<BR>&lt;struts:text&nbsp;name="username"&nbsp;size="16"/&gt;<BR>&lt;/td&gt;<BR>&lt;/tr&gt;<BR>&lt;tr&gt;<BR>&lt;th&nbsp;align="right"&gt;<BR>&lt;struts:message&nbsp;key="prompt.password"/&gt;<BR>&lt;/th&gt;<BR>&lt;td&nbsp;align="left"&gt;<BR>&lt;struts:password&nbsp;name="password"&nbsp;size="16"/&gt;<BR>&lt;/td&gt;<BR>&lt;/tr&gt;<BR>&lt;tr&gt;<BR>&lt;td&nbsp;align="right"&gt;<BR>&lt;struts:submit&gt;<BR>&lt;struts:message&nbsp;key="button.submit"/&gt;<BR>&lt;/struts:submit&gt;<BR>&lt;/td&gt;<BR>&lt;td&nbsp;align="right"&gt;<BR>&lt;struts:reset&gt;<BR>&lt;struts:message&nbsp;key="button.reset"/&gt;<BR>&lt;/struts:reset&gt;<BR>&lt;/td&gt;<BR>&lt;/tr&gt;<BR>&lt;/table&gt;<BR>&lt;/struts:form&gt;<BR><BR>&lt;/body&gt;<BR>&lt;/html&gt;<BR>下面的条目基于这个例子演示在Struts中处理表单的关键的特性：&nbsp;<BR>taglib指令告诉JSP页面编译器从哪里找到Struts标记库的&nbsp;标记库描述符&nbsp;。在这种情况下，我们使用struts作为前缀来标识来自这个库中的标记，但是可以使用任何你想用的前缀。&nbsp;<BR>这个页面使用了几个&nbsp;message&nbsp;标记来从一个包含有这个应用程序所有资源的&nbsp;MessageResources&nbsp;对象中查找国际化的消息字符串。为了让这个页面能够工作，以下的消息关键字必须在这些资源中被定义：&nbsp;<BR>logon.title&nbsp;-&nbsp;注册页面的标题&nbsp;<BR>prompt.username&nbsp;-&nbsp;一个&nbsp;“Username:”&nbsp;提示字符串&nbsp;<BR>prompt.password&nbsp;-&nbsp;一个&nbsp;“Password:”&nbsp;提示字符串&nbsp;<BR>button.submit&nbsp;-&nbsp;“Submit”按钮的标签&nbsp;<BR>button.reset&nbsp;-&nbsp;“Reset”按钮的标签&nbsp;<BR>当用户注册时，应用程序可以在用户的session中保存一个&nbsp;Locale&nbsp;对象。这个&nbsp;Locale&nbsp;将用来选择适当语言的消息。这使得给用户一个切换语言的可选项实现起来变的容易了&nbsp;--&nbsp;仅仅改变保存的&nbsp;Locale&nbsp;对象，所有的消息就会自动切换。&nbsp;<BR>errors&nbsp;标记显示由一个商业逻辑组件保存的任何出错消息，或者如果没有出错消息保存就什么都没有。这个标记将在下面做深入的描述。&nbsp;<BR>form&nbsp;标记基于指定的属性对一个HTML&nbsp;&lt;form&gt;&nbsp;元素进行处理。它也将所有在这个表单中的字段与一个保存在关键字&nbsp;logonForm&nbsp;下的session范围的FormBean相关联。这个bean用来为所有的具有与bean中的属性名匹配的名字的输入字段提供初始值。如果适当的bean没有找到，一个新的bean将会被自动建立，使用指定的Java类名。&nbsp;<BR>text&nbsp;标记对一个类型为“text”的HTML&nbsp;&lt;input&gt;&nbsp;元素进行处理。在这种情况下，占据浏览器屏幕的字符位置的数字也被指定。当页面被执行时，是相对应的bean的&nbsp;username&nbsp;属性的当前值（也就是&nbsp;getUsername()&nbsp;的返回值）。&nbsp;<BR>password&nbsp;标记使用方法类似。不同之处是当用户敲入他们的口令时浏览器将回应星号字符，而不是输入值。&nbsp;<BR>submit&nbsp;和&nbsp;reset&nbsp;标记在表单低部生成相应的按钮。每个按钮的文本标签使用&nbsp;message&nbsp;标记建立，同时带有提示，这样这些值就是国际化的。&nbsp;<BR>3.3.2&nbsp;输入字段类型支持<BR>Struts为所有以下类型的输入字段定义了标记，带有与其相应的参考信息的超联接。&nbsp;<BR>checkboxes&nbsp;<BR>hidden&nbsp;字段&nbsp;<BR>password&nbsp;输入字段&nbsp;<BR>radio&nbsp;按钮&nbsp;<BR>reset&nbsp;按钮&nbsp;<BR>select&nbsp;列表和嵌入的&nbsp;<BR>options&nbsp;<BR>submit&nbsp;按钮&nbsp;<BR>text&nbsp;输入字段&nbsp;<BR>textareas&nbsp;<BR>在所有情况下，一个字段标记都必须嵌套在一个&nbsp;form&nbsp;标记中，这样字段才知道使用哪个bean来初始化显示的值。&nbsp;<BR>3.3.3&nbsp;其它有用的表示标记<BR>在Struts的标记库中有几个其它的标记对于建立用户界面是有帮助的：&nbsp;<BR>enumerate&nbsp;为一个指定集合的每个元素重复一次标记体（可以是一个Enumeration，一个Hashtable，一个Vector或一个对象数组）。&nbsp;<BR>getProperty&nbsp;从指定的bean中得到指定的属性，并且在本页面的其余部分作为一个page范围的bean存在。这是访问一个被&nbsp;enumerate&nbsp;使用的集合的方便的方法。&nbsp;<BR>ifAttributeExists&nbsp;只有在一个指定的属性存在于一个指定的范围中时才对标记体求值。&nbsp;<BR>ifAttributeMissing&nbsp;只有在一个指定的属性不存在于一个指定的范围中时才对标记体求值。&nbsp;<BR>ifParameterEquals&nbsp;只有在一个指定的请求参数具有一个指定的值时才对标记体求值。&nbsp;<BR>ifParameterNotEquals&nbsp;只有在一个指定的请求参数不具有一个指定的值或者不存在时才对标记体求值。&nbsp;<BR>ifParameterNotNull&nbsp;只有在一个指定的请求参数包含在这个请求中并且长度大于0时才对标记体求值。&nbsp;<BR>ifParameterNull&nbsp;只有在一个指定的请求参数不包含在这个请求中或者长度等于0时才对标记体求值。&nbsp;<BR>iterate&nbsp;为一个指定集合中的每个元素重复一次标记体（可以是一个Collection，一个Iterator，一个Map，或者一个对象数组）。这个标记在Java2环境中代替了&nbsp;enumerate&nbsp;标记。&nbsp;<BR>link&nbsp;生成一个超联接，当没有cookie支持时自动应用URL编程来维护session状态。&nbsp;<BR>parameter&nbsp;处理指定请求参数的值，适当地过滤HTML中有特殊含义的字符。&nbsp;<BR>property&nbsp;显示一个表单中命名的bean属性&nbsp;--&nbsp;在属性应该是只读时使用这个标记而不是&nbsp;text&nbsp;标记。&nbsp;<BR>3.3.4&nbsp;自动表单验证<BR>除了上面描述的表单和bean的交互外，如果你的bean知道怎样验证它接收的输入字段，Struts还提供一种附加的机制。为了利用这个特性，使你的bean类实现&nbsp;ValidatingActionForm&nbsp;接口，而不是&nbsp;ActionForm&nbsp;接口。一个&nbsp;ValidatingActionForm&nbsp;增加了一个附加的方法签名：&nbsp;<BR>public&nbsp;String[]&nbsp;validate()<BR>对于一个被controller&nbsp;servlet在bean属性已经组装但是在相应的行为类的&nbsp;perform()&nbsp;方法被调用之前调用的方法，validate()&nbsp;方法有以下可选项：&nbsp;<BR>执行适当的验证发现没有错误&nbsp;--&nbsp;返回&nbsp;null&nbsp;或者一个非0长度字符串数组，并且controller&nbsp;servlet将继续调用适当的&nbsp;Action&nbsp;类的&nbsp;perform()&nbsp;方法。&nbsp;<BR>执行适当的验证发现有错误&nbsp;--&nbsp;返回一个内容为应该被显示的出错消息关键字（进入应用程序的MessageResources&nbsp;包）的字符串数组。controller&nbsp;servlet将作为适合于&nbsp;&lt;struts:errors&gt;&nbsp;标记使用的请求属性保存这个数组，并且将控制重定向回输入表单（由这个&nbsp;ActionMapping&nbsp;的&nbsp;inputForm&nbsp;属性标识）。&nbsp;<BR>正如以前提到的，这个特性完全是可选的。如果你的form&nbsp;bean&nbsp;仅仅实现了&nbsp;ActionForm&nbsp;接口，controller&nbsp;servlet将假设任何请求的验证由action类完成。&nbsp;<BR>3.4&nbsp;其它的表示技术<BR>尽管你的应用程序的外表和感觉可以完全基于标准的JSP能力和Struts的定制标记库构建，你也应该考虑展开其它改进组件重用、减少管理负担或者减少出错的技术。在下面的部分讨论几个可选的技术。&nbsp;<BR>3.4.1&nbsp;特定于应用程序的定制标记<BR>在使用Struts库提供的定制标记之外，很容易建立特定于你创建的应用程序的标记来帮助建立用户界面。Struts包括的例子程序用建立以下仅用于实现这个应用程序的标记演示了这个原则：&nbsp;<BR>checkLogon&nbsp;-&nbsp;检查一个特殊的会话对象的存在，如果不存在将控制重定向到注册页面。这是用来捕捉这样的情况，用户在你的应用程序执行的中间把一个页面做成书签并且试图跳过注册，或者用户的会话超时。&nbsp;<BR>linkSubscription&nbsp;-&nbsp;为一个详细的定单页面生成一个超联接，它将需要的主关键字值作为一个请求属性传递。这在列出与一个用户相关的定单并提供编辑或删除定单的联接时使用。&nbsp;<BR>linkUser&nbsp;-&nbsp;为一个用户的一个具体的页面生成一个超联接，它将它将需要的主关键字值作为一个请求属性传递。&nbsp;<BR>这些标记的源代码在&nbsp;src/example&nbsp;目录中，在包&nbsp;org.apache.struts.example&nbsp;里，还带有一些其它的用在这个应用程序中的Java类。&nbsp;<BR>3.4.2&nbsp;有包含文件的页面组件<BR>在一个JSP文件（包含定制标记和beans用来访问请求的动态数据）中创建完整的表示是一种非常普通的设计方法，在Struts包括的例子程序中被采用。然而很多应用程序要求在单独一个页面中显示你的应用程序的多个逻辑上独立的部分。&nbsp;<BR>举例来说，一个入口应用程序可以在入口的主页面上有一些或者全部以下的功能：&nbsp;<BR><BR>访问这个入口的一个搜索引擎。&nbsp;<BR>一个或更多的“提供新闻”的显示，含有按照用户的注册信息定制的感兴趣的标题。&nbsp;<BR>访问与这个入口相关的讨论的主题。&nbsp;<BR>如果你的入口提供免费邮件帐号，还要有一个“邮件等待”的提示。&nbsp;<BR>如果你能够将工作划分开，分配不同的开发者去做不同的片段，那么这个站点不同片段的开发就会更加简单。然后，你可以使用JSP技术的&nbsp;include&nbsp;能力来将这些片段组合进一个单独的页面。有两种&nbsp;include&nbsp;可用，依赖于你希望输出的组合发生在什么时间：&nbsp;<BR>include&nbsp;指令&nbsp;（&lt;%@&nbsp;include&nbsp;file="xxxxx"&nbsp;%&gt;）在JSP页面被编译时处理。它用于包括不需要在请求时改变的HTML代码。它把包括进来的文本当作静态文本，很象C或C++中的&nbsp;#include&nbsp;指令。&nbsp;<BR>include&nbsp;行为&nbsp;（&lt;jsp:include&nbsp;page="xxxxx"&nbsp;flush="true"&nbsp;/&gt;）在请求时处理，并且是由服务器透明处理。这意味着你可以通过把它嵌套在一个类似ifParameterEquals的标记中有条件地执行include&nbsp;。&nbsp;<BR>3.4.3&nbsp;图片处理组件<BR>一些应用程序要求动态生成图片，就象一个股市报告站点的价格图一样。通常使用两种不同的方法来实现这个需求：&nbsp;<BR>处理一个执行一个servlet请求的URL的超联接。这个servlet将使用一个图象库来生成图片，设置适当的content类型（例如&nbsp;image/gif），并且将图片的字节流发送回浏览器。浏览器就会象从一个静态文件中接收到的一样显示图片。&nbsp;<BR>处理HTML代码需要下载一个创建请求的图象的Java&nbsp;applet。你可以通过为在处理的代码中的这个applet设置适当的初始化参数配置这个图象，或者你可以让这个applet与服务器建立自己联接来接收这些参数。&nbsp;<BR>4.&nbsp;创建Controller组件<BR>4.1&nbsp;概述<BR>现在我们理解了怎样构造你的应用程序的Model和View组件，现在是集中到&nbsp;Controller&nbsp;组件的时候了。Struts包括一个实现映射一个请求URI到一个行为类的主要功能的servlet。因此你的与Controller有关的主要责任是：&nbsp;<BR>为每一个可能接收的逻辑请求写一个&nbsp;Action&nbsp;类（也就是，一个&nbsp;Action&nbsp;接口的实现）&nbsp;<BR>写一个定义类名和与每个可能的映射相关的其它信息的&nbsp;ActionMapping&nbsp;类（也就是，一个&nbsp;ActionMapping&nbsp;接口的实现）&nbsp;<BR>写行为映射配置文件（用XML）用来配置controller&nbsp;servlet。&nbsp;<BR>为你的应用程序更新web应用程序展开描述符文件（用XML）用来包括必需的Struts组件。&nbsp;<BR>给你的应用程序添加适当的Struts组件。&nbsp;<BR>4.2&nbsp;Action类<BR>Action&nbsp;接口定义一个单一的必须由一个&nbsp;Action&nbsp;类实现的方法，就象下面这样：&nbsp;<BR>public&nbsp;ActionForward&nbsp;perform(ActionServlet&nbsp;servlet,<BR>ActionMapping&nbsp;mapping,<BR>ActionForm&nbsp;form,<BR>HttpServletRequest&nbsp;request,<BR>HttpServletResponse&nbsp;response)<BR>throws&nbsp;IOException,&nbsp;ServletException;<BR>一个&nbsp;Action&nbsp;类的目标是处理这个请求，然后返回一个标识JSP页面的&nbsp;ActionForward&nbsp;对象，控制应该重定向这个JSP页面以生成相应的响应。在&nbsp;Model&nbsp;2&nbsp;设计模式中，一个典型的&nbsp;Action&nbsp;类将在它的&nbsp;perform()&nbsp;方法中实现下面的逻辑：&nbsp;<BR>验证用户session的当前状态（例如，检查用户已经成功地注册）。如果&nbsp;Action&nbsp;类发现没有注册存在，请求应该重定向到显示用户名和口令用于注册的JSP页面。应该这样做是因为用户可能试图从“中间”（也就是，从一个书签）进入你的应用程序，或者因为session已经超时并且servlet容器创建了一个新的session。&nbsp;<BR>如果验证还没有发生（由于使用一个实现&nbsp;ValidatingActionForm&nbsp;接口的form&nbsp;bean），验证这个&nbsp;form&nbsp;bean&nbsp;的属性是必须的。如果发现一个问题，当作一个请求属性保存合适的出错信息关键字，然后将控制重定向回输入表单这样错误可以被纠正。&nbsp;<BR>执行要求的处理来处理这个请求（例如在数据库里保存一行）。这可以用嵌入&nbsp;Action&nbsp;类本身的代码来完成，但是通常应该调用一个商业逻辑bean的一个合适的方法来执行。&nbsp;<BR>更新将用来创建下一个用户界面页面的服务器端对象（典型情况下是request范围或session范围beans，定义你需要在多长时间内保持这些项目可获得）。&nbsp;<BR>返回一个标识生成响应的JSP页面的适当的&nbsp;ActionForward&nbsp;对象，基于新近更新的beans。典型情况下，你将通过在你接收到的&nbsp;ActionMapping&nbsp;对象（如果你使用一个局部于与这个映射上的逻辑名）或者在controller&nbsp;servlet&nbsp;本身（如果你使用一个全局于应用程序的逻辑名）上调用&nbsp;findForward()&nbsp;得到一个对这样一个对象的引用。&nbsp;<BR>当为&nbsp;Action&nbsp;类编程时要记住的设计要点包括以下这些：&nbsp;<BR>controller&nbsp;servlet仅仅创建一个你的&nbsp;Action&nbsp;类的实例，用于所有的请求。这样你需要编写你的&nbsp;Action&nbsp;类使其能够在一个多线程环境中正确运行，就象你必须安全地编写一个servlet的&nbsp;service()&nbsp;方法一样。&nbsp;<BR>帮助线程安全编程的最重要的原则就是在你的&nbsp;Action&nbsp;类中仅仅使用局部变量而不是实例变量。局部变量创建于一个分配给（由你的JVM）每个请求线程的栈中，所以没有必要担心会共享它们。&nbsp;<BR>尽管不应该，代表你的系统中Model部分的的beans仍有可能抛出违例。你应该在你的&nbsp;perform()&nbsp;方法的逻辑中捕捉所有这样的违例，并且通过执行以下语句将它们记录在应用程序的日志文件中（包括相应的栈跟踪信息）：&nbsp;<BR>servlet.log("Error&nbsp;message&nbsp;text",&nbsp;exception);<BR>作为一个通用的规则，分配很少的资源并在来自同一个用户（在用户的session中）的请求间保持它们会导致可伸缩性的问题。你应该在将控制重定向到适当的View组件前努力释放这样的资源（例如数据库联接）&nbsp;--&nbsp;甚至在你调用的一个bean抛出了一个违例时。&nbsp;<BR>另外，你将会想要防止出现非常大的&nbsp;Action&nbsp;类。最简单的实现途径是将你的功能逻辑嵌入到&nbsp;Action&nbsp;类本身，而不是将其写在独立的商业逻辑beans中。除了使&nbsp;Action&nbsp;类难于理解和维护外，这种方法也使得难于重用这些商业逻辑代码，因为代码被嵌入到一个组件（Action&nbsp;类）中并被捆绑运行于web应用程序环境中。&nbsp;<BR>包括在Struts中的例子程序某种程度上延伸了这个设计原则，因为商业逻辑本身是嵌入到&nbsp;Action&nbsp;类中的。这应该被看作是在这个样本应用程序设计中的一个bug，而不是一个Struts体系结构中的固有特性，或者是一个值得仿效的方法。&nbsp;<BR><BR>4.3&nbsp;ActionMapping实现<BR>为了成功地运行，Struts的controller&nbsp;servlet需要知道关于每个URI该怎样映射到一个适当的&nbsp;Action&nbsp;类的几件事。需要了解的知识封装在一个叫做&nbsp;ActionMapping&nbsp;的Java接口中，它有以下属性：&nbsp;<BR>actionClass&nbsp;-&nbsp;用于这个映射的&nbsp;Action&nbsp;类完整的Java类名。第一次一个特定的映射被使用，一个这个类的实例将被创建并为以后重用而保存。&nbsp;<BR>formAttribute&nbsp;-&nbsp;session范围的bean的名字，当前的这个映射的&nbsp;ActionForm&nbsp;被保存在这个bean之下。如果这个属性没有被定义，没有&nbsp;ActionForm&nbsp;被使用。&nbsp;<BR>formClass&nbsp;-&nbsp;用于这个映射的&nbsp;ActionForm&nbsp;类完整的Java类名。如果你在使用对form&nbsp;beans的支持，这个类的一个实例将被创建并保存（在当前的用户会话中）&nbsp;<BR>path&nbsp;-&nbsp;匹配选择这个映射的请求的URI路径。看下面如何匹配的例子。&nbsp;<BR>Struts在一个叫做&nbsp;ActionMappingBase&nbsp;的类中包括了一个&nbsp;ActionMapping&nbsp;接口的方便的实现。如果你不需要为你自己的映射定义任何附加的属性，尽管把这个类作为你的&nbsp;ActionMapping&nbsp;类好了，就向下面部分描述的那样配置。然而，定义一个&nbsp;ActionMapping&nbsp;实现（多半是扩展&nbsp;ActionMappingBase&nbsp;类）来包含附加的属性也是可能的。controller&nbsp;servlet知道怎样自动配置这些定制属性，因为它使用Struts的Digester模块来读配置文件。&nbsp;<BR>包括在Struts的例子程序中，这个特性用来定义两个附加的属性：&nbsp;<BR><BR>failure&nbsp;-&nbsp;如果Action类检测到它接收的输入字段的一些问题，控制应该被重定向到的上下文相关的URI。典型情况下是请求发向的JSP页面名，它将引起表单被重新显示（包含Action类设置的出错消息和大部分最近的来自ActionForm&nbsp;bean的输入值）。&nbsp;<BR>success&nbsp;-&nbsp;如果Action类成功执行请求的功能，控制应该被重定向到的上下文相关的URI。典型情况下是准备这个应用程序的会话流的下一个页面的JSP页面名。&nbsp;<BR>使用这两个额外的属性，例子程序中的&nbsp;Action&nbsp;类几乎完全独立于页面设计者使用的实际的JSP页面名。这个页面可以在重新设计时被重命名，然而几乎不会影响到&nbsp;Action&nbsp;类本身。如果“下一个”JSP页面的名字被硬编码到&nbsp;Action&nbsp;类中，所有的这些类也需要被修改。&nbsp;<BR>4.4&nbsp;Action映射配置文件<BR>controller&nbsp;servlet怎样知道你想要得到的映射？写一个简单地初始化新的&nbsp;ActionMapping&nbsp;实例并且调用所有适当的set方法的小的Java类是可能的（但是很麻烦）。为了使这个处理简单些，Struts包括一个Digester模块能够处理一个想得到的映射的基于XML的描述，同时创建适当的对象。看&nbsp;API&nbsp;文档&nbsp;以获得关于Digester更多的信息。&nbsp;<BR>开发者的责任是创建一个叫做&nbsp;action.xml&nbsp;的XML文件，并且把它放在你的应用程序的WEB-INF目录中。（注意这个文件并不需要&nbsp;DTD，因为实际使用的属性对于不同的用户可以是不同的）最外面的XML元素必须是&lt;action-mappings&gt;，在这个元素之中是嵌入的0个或更多的&nbsp;&lt;action&gt;&nbsp;元素&nbsp;--&nbsp;每一个对应于你希望定义的一个映射。&nbsp;<BR><BR>来自例子程序的&nbsp;action.xml&nbsp;文件包括“注册”功能的以下映射条目，我们用来说明这个需求：&nbsp;<BR><BR>&lt;action-mappings&gt;<BR><BR>&lt;forward&nbsp;name="logon"&nbsp;path="/logon.jsp"/&gt;<BR><BR>&lt;action&nbsp;path="/logon"<BR>actionClass="org.apache.struts.example.LogonAction"<BR>formAttribute="logonForm"<BR>formClass="org.apache.struts.example.LogonForm"<BR>inputForm="/logon.jsp"&gt;<BR>&lt;forward&nbsp;name="success"&nbsp;path="/mainMenu.jsp"/&gt;<BR>&lt;/action&gt;<BR><BR>&lt;/action-mappings&gt;<BR>就象你所看到的，这个映射匹配路径&nbsp;/logon&nbsp;（实际上，因为例子程序使用扩展匹配，你在一个JSP页面指定的请求的URI结束于/logon.do）。当接收到一个匹配这个路径的请求时，一个&nbsp;LogonAction&nbsp;类的实例将被创建（仅仅在第一次）并被使用。controller&nbsp;servlet将在关键字&nbsp;logonForm&nbsp;下查找一个session范围的bean，如果需要就为指定的类创建并保存一个bean。&nbsp;<BR>这个&nbsp;action&nbsp;元素也定义了一个逻辑名“success”，它在&nbsp;LogonAction&nbsp;类中被用来标识当一个用户成功注册时使用的页面。象这样使用一个逻辑名允许将&nbsp;action&nbsp;类隔离于任何由于重新设计位置而可能发生的页面名改变。&nbsp;<BR><BR>这是第二个在任何&nbsp;action&nbsp;之外宣告的&nbsp;forward&nbsp;元素，这样它就可以被所有的action全局地获得。在这个情况下，它为注册页面定义了一个逻辑名。当你调用&nbsp;mapping.findForward()&nbsp;时在你的&nbsp;action&nbsp;代码中，Struts首先查找这个action本地定义的逻辑名。如果没有找到，Struts会自动为你查找全局定义的逻辑名。&nbsp;<BR><BR>4.5&nbsp;Web应用程序展开描述符<BR>设置应用程序最后的步骤是配置应用程序展开描述符（保存在文件WEB-INF/web.xml中）以包括所有必需的Struts组件。作为一个指南使用例子程序的展开描述符，我们看到下面的条目需要被创建或修改。&nbsp;<BR>4.5.1&nbsp;配置Action&nbsp;Servlet实例<BR>添加一个条目定义action&nbsp;servlet本身，同时包括适当的初始化参数。这样一个条目看起来象是这样：&nbsp;<BR>&lt;servlet&gt;<BR>&lt;servlet-name&gt;action&lt;/servlet-name&gt;<BR>&lt;servlet-class&gt;org.apache.struts.action.ActionServlet&lt;/servlet-class&gt;<BR>&lt;init-p<BR>aram&gt;<BR>&lt;param-name&gt;application&lt;/param-name&gt;<BR>&lt;param-value&gt;org.apache.struts.example.ApplicationResources&lt;/param-value&gt;<BR>&lt;/init-param&gt;<BR>&lt;init-param&gt;<BR>&lt;param-name&gt;config&lt;/param-name&gt;<BR>&lt;param-value&gt;/WEB-INF/action.xml&lt;/param-value&gt;<BR>&lt;/init-param&gt;<BR>&lt;init-param&gt;<BR>&lt;param-name&gt;debug&lt;/param-name&gt;<BR>&lt;param-value&gt;2&lt;/param-value&gt;<BR>&lt;/init-param&gt;<BR>&lt;init-param&gt;<BR>&lt;param-name&gt;mapping&lt;/param-name&gt;<BR>&lt;param-value&gt;org.apache.struts.example.ApplicationMapping&lt;/param-value&gt;<BR>&lt;/init-param&gt;<BR>&lt;load-on-startup&gt;2&lt;/load-on-startup&gt;<BR>&lt;/servlet&gt;<BR>controller&nbsp;servlet支持的初始化参数在下面描述，拷贝自&nbsp;ActionServlet&nbsp;类的&nbsp;Javadocs&nbsp;。方括号描述如果你没有为那个初始化参数提供一个值时假设的缺省值。&nbsp;<BR>application&nbsp;-&nbsp;应用程序资源包基类的Java类名。[NONE].&nbsp;<BR>config&nbsp;-&nbsp;包含配置信息的XML资源的上下文相关的路径。[/WEB-INF/action.xml]&nbsp;<BR>debug&nbsp;-&nbsp;这个servlet的调试级别，它控制记录多少信息到日志中。[0]&nbsp;<BR>digester&nbsp;-&nbsp;我们在&nbsp;initMapping()&nbsp;中利用的Digester的调试级别，它记录到System.out而不是servlet的日志中。[0]&nbsp;<BR>forward&nbsp;-&nbsp;使用的ActionForward实现的Java类名。[org.apache.struts.action.ActionForward]&nbsp;<BR>mapping&nbsp;-&nbsp;使用的ActionMapping实现的Java类名。[org.apache.struts.action.ActionMappingBase]&nbsp;<BR>nocache&nbsp;-&nbsp;如果设置为&nbsp;true，增加HTTP头信息到所有响应中使浏览器对于生成或重定向到的任何响应不做缓冲。[false]&nbsp;<BR>null&nbsp;-&nbsp;如果设置为&nbsp;true，设置应用程序资源使得如果未知的消息关键字被使用则返回&nbsp;null。否则，一个包括不欢迎的消息关键字的出错消息将被返回。[true]&nbsp;<BR>4.5.2&nbsp;配置Action&nbsp;Servlet映射<BR>有两种通常的方法来定义将被controller&nbsp;servlet处理的URL&nbsp;--&nbsp;前缀匹配和扩展匹配。每种方法的一个适当的映射条目将在下面被描述。&nbsp;<BR>前缀匹配意思是你想让所有以一个特殊值开头（在上下文路径部分之后）的URL传递给这个servlet。这样一个条目看起来可以象是这样：&nbsp;<BR><BR>&lt;servlet-mapping&gt;<BR>&lt;servlet-name&gt;action&lt;/servlet-name&gt;<BR>&lt;url-pattern&gt;/execute/*&lt;/url-pattern&gt;<BR>&lt;/servlet-mapping&gt;<BR>它意味着一个匹配前面描述的&nbsp;/logon&nbsp;路径的请求的URL看起来象是这样：&nbsp;<BR><IMG src="http://www.matrix.org.cn/article/images/small/url.gif" align=absMiddle></FONT><A href="http://www.mycompany.com/myapplication/execute/logon" target=_blank><FONT face=宋体 color=#002c99>http://www.mycompany.com/myapplication/execute/logon</FONT></A><BR><FONT face=宋体>这里&nbsp;/myapplicationis&nbsp;是你的应用程序展开所在的上下文路径。&nbsp;<BR>另一方面，扩展映射基于URL以一个跟着定义的一组字符的句点结束的事实而将URL匹配到action&nbsp;servlet&nbsp;。例如，JSP处理servlet映射到&nbsp;*.jsp&nbsp;模式这样它在每个JSP页面请求时被调用。为了使用&nbsp;*.do&nbsp;扩展（它意味着“做某件事”）映射条目看起来应该象是这样：&nbsp;<BR><BR>&lt;servlet-mapping&gt;<BR>&lt;servlet-name&gt;action&lt;/servlet-name&gt;<BR>&lt;url-pattern&gt;*.do&lt;/url-pattern&gt;<BR>&lt;/servlet-mapping&gt;<BR>并且一个匹配以前描述的&nbsp;/logon&nbsp;路径的请求的URI可以看起来象是这样：&nbsp;<BR><IMG src="http://www.matrix.org.cn/article/images/small/url.gif" align=absMiddle></FONT><A href="http://www.mycompany.com/myapplication/logon.do" target=_blank><FONT face=宋体 color=#002c99>http://www.mycompany.com/myapplication/logon.do</FONT></A><BR><FONT face=宋体>4.5.3&nbsp;配置Struts标记库<BR>下一步，你必须添加一个定义Struts标记库的条目。这个条目看起来应该象是这样：&nbsp;<BR>&lt;taglib&gt;<BR>&lt;taglib-uri&gt;/WEB-INF/struts.tld&lt;/taglib-uri&gt;<BR>&lt;taglib-location&gt;/WEB-INF/struts.tld&lt;/taglib-location&gt;<BR>&lt;/taglib&gt;<BR>它告诉JSP系统到哪里去找这个库的标记库描述符（在你的应用程序的WEB-INF目录，而不是在外部互联网上的某个地方）。&nbsp;<BR>4.5.4&nbsp;添加Struts组件到你的应用程序中<BR>为了在你的应用程序运行时使用Struts，你必须将&nbsp;struts.tld&nbsp;文件拷贝到你的&nbsp;WEB-INF&nbsp;目录，将&nbsp;struts.jar&nbsp;文件拷贝到你的&nbsp;WEB-INF/lib&nbsp;。&nbsp;</FONT><BR><BR><B><BR><BR></B><img src ="http://www.blogjava.net/happyfish/aggbug/1621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happyfish/" target="_blank">小鱼儿</a> 2005-03-02 22:48 <a href="http://www.blogjava.net/happyfish/archive/2005/03/02/1621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习spring：</title><link>http://www.blogjava.net/happyfish/archive/2005/03/02/1619.html</link><dc:creator>小鱼儿</dc:creator><author>小鱼儿</author><pubDate>Wed, 02 Mar 2005 14:44:00 GMT</pubDate><guid>http://www.blogjava.net/happyfish/archive/2005/03/02/1619.html</guid><wfw:comment>http://www.blogjava.net/happyfish/comments/1619.html</wfw:comment><comments>http://www.blogjava.net/happyfish/archive/2005/03/02/1619.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/happyfish/comments/commentRss/1619.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/happyfish/services/trackbacks/1619.html</trackback:ping><description><![CDATA[学习spring：<BR><BR>　　(1) spring下载包中doc目录下的MVC-step-by-step和sample目录下的例子都是比较好的spring开发的例子。 <BR><BR>　　(2) AppFuse集成了目前最流行的几个开源轻量级框架或者工具 Ant,XDoclet,Spring,Hibernate(iBATIS),JUnit,Cactus,StrutsTestCase,Canoo's WebTest,Struts Menu,Display Tag Library,OSCache,JSTL,Struts 。<BR><BR>　　通过AppFuse源代码来学习spring。<BR><BR>AppFuse网站：http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse<BR><BR>　　(3)Spring 开发指南(夏昕)（http://www.xiaxin.net/Spring_Dev_Guide.rar）<BR><BR>　　一本spring的入门书籍,里面介绍了反转控制和依赖注射的概念，以及spring的bean管理，spring的MVC，spring和hibernte，iBatis的结合。<BR><BR>　　(4) spring学习的中文论坛<BR><BR>　　SpringFramework中文论坛(http://spring.jactiongroup.net)<BR><BR>　　Java视线论坛(http://forum.javaeye.com)的spring栏目<BR><BR>　　2、利用Spring框架编程，console打印出log4j:WARN Please initialize the log4j system properly？<BR><BR>　　说明你的log4j.properties没有配置。请把log4j.properties放到工程的classpath中，eclipse的classpath为bin目录，由于编译后src目录下的文件会拷贝到bin目录下，所以你可以把log4j.properties放到src目录下。<BR><BR>　　这里给出一个log4j.properties的例子：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>log4j.rootLogger=DEBUG,stdout<BR>log4j.appender.stdout=org.apache.log4j.ConsoleAppender<BR>log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<BR>log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n</TD></TR></TBODY></TABLE><BR>　　3、出现 java.lang.NoClassDefFoundError?<BR><BR>　　一般情况下是由于你没有把必要的jar包放到lib中。<BR><BR>　　比如你要采用spring和hibernate（带事务支持的话），你除了spring.jar外还需要hibernat.jar、aopalliance.jar、cglig.jar、jakarta-commons下的几个jar包。<BR><BR>http://www.springframework.org/download.html下载spring开发包，提供两种zip包<BR>spring-framework-1.1.3-with-dependencies.zip和spring-framework-1.1.3.zip，我建议你下载spring-framework-1.1.3-with-dependencies.zip。这个zip解压缩后比后者多一个lib目录，其中有hibernate、j2ee、dom4j、aopalliance、jakarta-commons等常用包。<BR><BR>　　4、java.io.FileNotFoundException: Could not open class path resource [....hbm.xml],提示找不到xml文件？<BR><BR>　　原因一般有两个：<BR><BR>　　(1)该xml文件没有在classpath中。 <BR><BR>　　(2)applicationContext-hibernate.xml中的xml名字没有带包名。比如：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"＞<BR>＜property name="dataSource"＞＜ref bean="dataSource"/＞＜/property＞<BR>＜property name="mappingResources"＞<BR>　＜list＞<BR>　　＜value＞User.hbm.xml＜/value＞<BR>　　错，改为： <BR>　　＜value＞com/yz/spring/domain/User.hbm.xml＜/value＞<BR>　＜/list＞<BR>＜/property＞<BR>＜property name="hibernateProperties"＞<BR>＜props＞ <BR>　＜prop key="hibernate.dialect"＞ net.sf.hibernate.dialect.MySQLDialect ＜/prop＞ <BR>　＜prop key="hibernate.show_sql"＞true＜/prop＞ <BR>＜/props＞ <BR>＜/property＞<BR>＜/bean＞</TD></TR></TBODY></TABLE><BR>　　5、org.springframework.beans.NotWritablePropertyException: Invalid property 'postDao' of bean class？<BR><BR>　　出现异常的原因是在application-xxx.xml中property name的错误。<BR><BR>　　＜property name="...."＞ 中name的名字是与bean的set方法相关的，而且要注意大小写。<BR><BR>　　比如<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>public class PostManageImpl extends BaseManage implements PostManage {<BR>　private PostDAO dao = null;<BR>　public void setPostDAO(PostDAO postDAO){<BR>　　this.dao = postDAO;<BR>　}<BR>}</TD></TR></TBODY></TABLE><BR>　　那么xml的定义应该是：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜bean id="postManage" parent="txProxyTemplate"＞<BR>＜property name="target"＞<BR>　＜bean class="com.yz.spring.service.implement.PostManageImpl"＞<BR>　　＜property name="postDAO"＞＜ref bean="postDAO"/＞＜/property＞ 对<BR>　　＜property name="dao"＞＜ref bean="postDAO"/＞＜/property＞ 错<BR>　＜/bean＞<BR>＜/property＞<BR>＜/bean＞</TD></TR></TBODY></TABLE><BR>　　6、Spring中如何实现事务管理？<BR><BR>　　首先，如果使用mysql，确定mysql为InnoDB类型。<BR><BR>　　事务管理的控制应该放到商业逻辑层。你可以写个处理商业逻辑的JavaBean，在该JavaBean中调用DAO，然后把该Bean的方法纳入spring的事务管理。<BR><BR>　　比如：xml文件定义如下：<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜bean id="txProxyTemplate" abstract="true"<BR>class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"＞<BR>＜property name="transactionManager"＞＜ref bean="transactionManager"/＞＜/property＞<BR>＜property name="transactionAttributes"＞<BR>＜props＞<BR>＜prop key="save*"＞PROPAGATION_REQUIRED＜/prop＞<BR>＜prop key="remove*"＞PROPAGATION_REQUIRED＜/prop＞<BR>＜prop key="*"＞PROPAGATION_REQUIRED＜/prop＞<BR>＜/props＞<BR>＜/property＞<BR>＜/bean＞<BR><BR>＜bean id="userManage" parent="txProxyTemplate"＞<BR>　＜property name="target"＞<BR>　　＜bean class="com.yz.spring.service.implement.UserManageImpl"＞<BR>　　　＜property name="userDAO"＞＜ref bean="userDAO"/＞＜/property＞<BR>　　＜/bean＞<BR>　＜/property＞<BR>＜/bean＞</TD></TR></TBODY></TABLE><BR>　　com.yz.spring.service.implement.UserManageImpl就是我们的实现商业逻辑的JavaBean。我们通过parent元素声明其事务支持。<BR><BR>　　7、如何管理Spring框架下更多的JavaBean？<BR><BR>　　JavaBean越多，spring配置文件就越大，这样不易维护。为了使配置清晰，我们可以将JavaBean分类管理，放在不同的配置文件中。 应用启动时将所有的xml同时加载。<BR><BR>　　比如：<BR><BR>　　DAO层的JavaBean放到applicationContext-hibernate.xml中，商业逻辑层的JavaBean放到applicationContext-service.xml中。然后启动类中调用以下代码载入所有的ApplicationContext。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>String[] paths = {"com/yz/spring/dao/hibernate/applicationContext-hibernate.xml",<BR>"com/yz/spring/service/applicationContext-service.xml"};<BR>ctx = new ClassPathXmlApplicationContext(paths);</TD></TR></TBODY></TABLE><BR>　　8、web应用中如何加载ApplicationContext？<BR><BR>　　可以通过定义web.xml，由web容器自动加载。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜servlet＞<BR>＜servlet-name＞context＜/servlet-name＞<BR>＜servlet-class＞org.springframework.web.context.ContextLoaderServlet＜/servlet-class＞<BR>＜load-on-startup＞1＜/load-on-startup＞<BR>＜/servlet＞<BR><BR>＜context-param＞<BR>＜param-name＞contextConfigLocation＜/param-name＞<BR>＜param-value＞/WEB-INF/applicationContext-hibernate.xml＜/param-value＞<BR>＜param-value＞/WEB-INF/applicationContext-service.xml＜/param-value＞<BR>＜/context-param＞</TD></TR></TBODY></TABLE><BR>　　9、在spring中如何配置的log4j?<BR><BR>　　在web.xml中加入以下代码即可。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>＜context-param＞<BR>＜param-name＞log4jConfigLocation＜/param-name＞<BR>＜param-value＞/WEB-INF/log4j.properties＜/param-value＞<BR>＜/context-param＞</TD></TR></TBODY></TABLE><BR>　　10、Spring框架入门的编程问题解决了，我该如何更深地领会Spring框架呢？<BR><BR>　　这两本书你该去看看。这两本书是由Spring的作者Rod Johnson编写的。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>Expert One on one J2EE Design and Development<BR>Expert One on one J2EE Development Without EJB</TD></TR></TBODY></TABLE><BR>　　你也该看看martinfowler的Inversion of Control Containers and the Dependency Injection pattern。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>http://www.martinfowler.com/articles/injection.html</TD></TR></TBODY></TABLE>　<BR>　　再好好研读一下spring的文档。<BR><BR>
<TABLE borderColor=#ffcc66 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>http://www.jactiongroup.net/reference/html/index.html（中文版，未全部翻译）</TD></TR></TBODY></TABLE><BR><img src ="http://www.blogjava.net/happyfish/aggbug/1619.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/happyfish/" target="_blank">小鱼儿</a> 2005-03-02 22:44 <a href="http://www.blogjava.net/happyfish/archive/2005/03/02/1619.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>