﻿<?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-大道至简-文章分类-Spring</title><link>http://www.blogjava.net/hellotony/category/11936.html</link><description>道生一，一生二，二生三，三生万物。万物负阴而抱阳，冲气以为和。</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:30:34 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:30:34 GMT</pubDate><ttl>60</ttl><item><title>Spring入门(zt)</title><link>http://www.blogjava.net/hellotony/articles/50752.html</link><dc:creator>Tony</dc:creator><author>Tony</author><pubDate>Tue, 06 Jun 2006 05:20:00 GMT</pubDate><guid>http://www.blogjava.net/hellotony/articles/50752.html</guid><wfw:comment>http://www.blogjava.net/hellotony/comments/50752.html</wfw:comment><comments>http://www.blogjava.net/hellotony/articles/50752.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hellotony/comments/commentRss/50752.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hellotony/services/trackbacks/50752.html</trackback:ping><description><![CDATA[
		<p>
				<font face="Arial" size="2">Spring是一个非常优秀的轻量级框架，通过Spring的IoC容器，我们的关注点便放到了需要实现的业务逻辑上。对AOP的支持则能让我们动
态增强业务方法。编写普通的业务逻辑Bean是非常容易而且易于测试的，因为它能脱离J2EE容器（如Servlet，JSP环境）单独进行单元测试。最
后的一步便是在Spring框架中将这些业务Bean以XML配置文件的方式组织起来，它们就按照我们预定的目标正常工作了！非常容易！</font>
		</p>
		<p>
				<font face="Arial" size="2">本文将给出一个基本的Spring入门示例，并演示如何使用Spring的AOP将复杂的业务逻辑分离到每个方面中。</font>
		</p>
		<p>
				<font face="Arial" size="2">1．开发环境配置<br />2．编写Bean接口及其实现<br />3．在Spring中配置Bean并获得Bean的实例<br />4．编写Advisor以增强ServiceBean<br />5．总结</font>
		</p>
		<h3>
				<font face="Arial" size="2">1．开发环境配置</font>
		</h3>
		<p>
				<font face="Arial" size="2">首先，需要正确配置Java环境。推荐安装JDK1.4.2，并正确配置环境变量：</font>
		</p>
		<p>
				<font face="Arial" size="2">JAVA_HOME=&lt;JDK安装目录&gt;<br />CLASSPATH=.<br />Path=%JAVA_HOME%\bin;……</font>
		</p>
		<p>
				<font face="Arial" size="2">我们将使用免费的Eclipse 3.1作为IDE。新建一个Java
Project，将Spring的发布包spring.jar以及commons-logging-1.0.4.jar复制到Project目录下，并在
Project &gt; Properties中配置好Java Build Path：</font>
		</p>
		<p>
				<font face="Arial" size="2">
						<img onmousewheel="return bbimg(this)" alt="" src="http://www.crackj2ee.com/Article/UploadFiles/200604/20060402192206665.jpg" onload="javascript:resizepic(this)" border="undefined" height="362" width="550" />
				</font>
		</p>
		<h3>
				<font face="Arial" size="2">2．编写Bean接口及其实现</font>
		</h3>
		<p>
				<font face="Arial" size="2">我们实现一个管理用户的业务Bean。首先定义一个ServiceBean接口，声明一些业务方法：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">/**<br /> * Copyright_2006, Liao Xuefeng<br /> * Created on 2006-3-9<br /> * For more information, please visit: </font>
				<font face="Arial" size="2">
						<a href="http://www.crackj2ee.com/">
								<font color="#0066ff">http://www.crackj2ee.com</font>
						</a>
						<br />
				</font>
				<font color="#0066ff" face="Arial" size="2"> */<br />package com.crackj2ee.example.spring;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">/**<br /> * Interface of service facade.<br /> * <br /> * @author Xuefeng<br /> */<br />public interface ServiceBean {<br />    void addUser(String username, String password);<br />    void deleteUser(String username);<br />    boolean findUser(String username);<br />    String getPassword(String username);<br />}</font>
		</pre>
		<p>
				<font face="Arial" size="2">然后在MyServiceBean中实现接口：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">/**<br /> * Copyright_2006, Liao Xuefeng<br /> * Created on 2006-3-9<br /> * <br /> * For more information, please visit: </font>
				<font face="Arial" size="2">
						<a href="http://www.crackj2ee.com/">
								<font color="#0066ff">http://www.crackj2ee.com</font>
						</a>
						<br />
				</font>
				<font color="#0066ff" face="Arial" size="2"> */<br />package com.crackj2ee.example.spring;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">import java.util.*;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">public class MyServiceBean implements ServiceBean {</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    private String dir;<br />    private Map map = new HashMap();</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    public void setUserDir(String dir) {<br />        this.dir = dir;<br />        System.out.println("Set user dir to: " + dir);<br />    }</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    public void addUser(String username, String password) {<br />        if(!map.containsKey(username))<br />            map.put(username, password);<br />        else<br />            throw new RuntimeException("User already exist.");<br />    }</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    public void deleteUser(String username) {<br />        if(map.remove(username)==null)<br />            throw new RuntimeException("User not exist.");<br />    }</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    public boolean findUser(String username) {<br />        return map.containsKey(username);<br />    }</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    public String getPassword(String username) {<br />        return (String)map.get(username);<br />    }<br />}</font>
		</pre>
		<p>
				<font face="Arial" size="2">为了简化逻辑，我们使用一个Map保存用户名和口令。</font>
		</p>
		<p>
				<font face="Arial" size="2">现在，我们已经有了一个业务Bean。要测试它非常容易，因为到目前为止，我们还没有涉及到Spring容器，也没有涉及到任何Web容器（假定这是一个Web应用程序关于用户管理的业务Bean）。完全可以直接进行Unit测试，或者，简单地写个main方法测试：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">/**<br /> * Copyright_2006, Liao Xuefeng<br /> * Created on 2006-3-9<br /> * For more information, please visit: </font>
				<font face="Arial" size="2">
						<a href="http://www.crackj2ee.com/">
								<font color="#0066ff">http://www.crackj2ee.com</font>
						</a>
						<br />
				</font>
				<font color="#0066ff" face="Arial" size="2"> */<br />package com.crackj2ee.example.spring;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">public class Main {</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    public static void main(String[] args) throws Exception {<br />        ServiceBean service = new MyServiceBean();<br />        service.addUser("bill", "hello");<br />        service.addUser("tom", "goodbye");<br />        service.addUser("tracy", "morning");<br />        System.out.println("tom's password is: " + service.getPassword("tom"));<br />        if(service.findUser("tom")) {<br />            service.deleteUser("tom");<br />        }<br />    }<br />}</font>
		</pre>
		<p>
				<font face="Arial" size="2">执行结果：<br /><img onmousewheel="return bbimg(this)" alt="" src="http://www.crackj2ee.com/Article/UploadFiles/200604/20060402192408916.jpg" onload="javascript:resizepic(this)" border="undefined" height="178" width="550" /></font>
		</p>
		<h3>
				<font face="Arial" size="2">3．在Spring中配置Bean并获得Bean的实例</font>
		</h3>
		<p>
				<font face="Arial" size="2">我们已经在一个main方法中实现了业务，不过，将对象的生命周期交给容器管理是更好的办法，我们就不必为初始化对象和销毁对象进行硬编码，从而获得更大的灵活性和可测试性。</font>
		</p>
		<p>
				<font face="Arial" size="2">想要把ServiceBean交给Spring来管理，我们需要一个XML配置文件。新建一个beans.xml，放到src目录下，确保在classpath中能找到此配置文件，输入以下内容：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" <br />"</font>
				<font face="Arial" size="2">
						<a href="http://www.springframework.org/dtd/spring-beans.dtd">
								<font color="#0066ff">http://www.springframework.org/dtd/spring-beans.dtd</font>
						</a>
				</font>
				<font color="#0066ff" face="Arial" size="2">"&gt;<br />&lt;beans&gt;<br />    &lt;bean id="service" class="com.crackj2ee.example.spring.MyServiceBean" /&gt;<br />&lt;/beans&gt;</font>
		</pre>
		<p>
				<font face="Arial" size="2">以上XML声明了一个id为service的Bean，默认地，Spring为每个声明的Bean仅创建一个实例，并通过id来引用这个Bean。下面，我们修改main方法，让Spring来管理业务Bean：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">/**<br /> * Copyright_2006, Liao Xuefeng<br /> * Created on 2006-3-9<br /> * For more information, please visit: </font>
				<font face="Arial" size="2">
						<a href="http://www.crackj2ee.com/">
								<font color="#0066ff">http://www.crackj2ee.com</font>
						</a>
						<br />
				</font>
				<font color="#0066ff" face="Arial" size="2"> */<br />package com.crackj2ee.example.spring;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">import org.springframework.beans.factory.xml.XmlBeanFactory;<br />import org.springframework.core.io.ClassPathResource;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">public class Main {</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    public static void main(String[] args) throws Exception {<br />        // init factory:<br />        <font color="#ff0000">XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));</font><br />        // use service bean:<br />        ServiceBean service = (ServiceBean)factory.getBean("service");<br />        service.addUser("bill", "hello");<br />        service.addUser("tom", "goodbye");<br />        service.addUser("tracy", "morning");<br />        System.out.println("tom's password is \"" + service.getPassword("tom") + "\"");<br />        if(service.findUser("tom")) {<br />            service.deleteUser("tom");<br />        }<br />        // close factory:<br />        <font color="#ff0000">factory.destroySingletons();</font><br />    }<br />}</font>
		</pre>
		<p>
				<font face="Arial" size="2">执行结果：<br /> <img onmousewheel="return bbimg(this)" alt="" src="http://www.crackj2ee.com/Article/UploadFiles/200604/20060402192443792.jpg" onload="javascript:resizepic(this)" border="undefined" height="177" width="550" /></font>
		</p>
		<p>
				<font face="Arial" size="2">由于我们要通过main方法启动Spring环境，因此，首先需要初始化一个BeanFactory。红色部分是初始化Spring的BeanFactory的典型代码，只需要保证beans.xml文件位于classpath中。</font>
		</p>
		<p>
				<font face="Arial" size="2">然后，在BeanFactory中通过id查找，即可获得相应的Bean的实例，并将其适当转型为合适的接口。</font>
		</p>
		<p>
				<font face="Arial" size="2">接着，实现一系列业务操作，在应用程序结束前，让Spring销毁所有的Bean实例。</font>
		</p>
		<p>
				<font face="Arial" size="2">对比上一个版本的Main，可以看出，最大的变化是不需要自己管理Bean的生命周期。另一个好处是在不更改实现类的前提下，动态地为应用程序增加功能。</font>
		</p>
		<h3>
				<font face="Arial" size="2">4．编写Advisor以增强ServiceBean</font>
		</h3>
		<p>
				<font face="Arial" size="2">所谓AOP即是将分散在各个方法处的公共代码提取到一处，并通过类似拦截器的机制实现代码的动态织入。可以简单地想象成，在某个方法的调用前、返回
前、调用后和抛出异常时，动态插入自己的代码。在弄清楚Pointcut、Advice之类的术语前，不如编写一个最简单的AOP应用来体验一下。</font>
		</p>
		<p>
				<font face="Arial" size="2">考虑一下通常的Web应用程序都会有日志记录，我们来编写一个LogAdvisor，对每个业务方法调用前都作一个记录：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">/**<br /> * Copyright_2006, Liao Xuefeng<br /> * Created on 2006-3-9<br /> * For more information, please visit: </font>
				<font face="Arial" size="2">
						<a href="http://www.crackj2ee.com/">
								<font color="#0066ff">http://www.crackj2ee.com</font>
						</a>
						<br />
				</font>
				<font color="#0066ff" face="Arial" size="2"> */<br />package com.crackj2ee.example.spring;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">import java.lang.reflect.Method;<br />import org.springframework.aop.MethodBeforeAdvice;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">public class LogAdvisor implements MethodBeforeAdvice {<br />    public void before(Method m, Object[] args, Object target) throws Throwable {<br />        System.out.println("[Log] " + target.getClass().getName() + "." + m.getName() + "()");<br />    }<br />}</font>
		</pre>
		<p>
				<font face="Arial" size="2">然后，修改beans.xml：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" <br />"</font>
				<font face="Arial" size="2">
						<a href="http://www.springframework.org/dtd/spring-beans.dtd">
								<font color="#0066ff">http://www.springframework.org/dtd/spring-beans.dtd</font>
						</a>
				</font>
				<font color="#0066ff" face="Arial" size="2">"&gt;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">&lt;beans&gt;<br />    &lt;bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" /&gt;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    &lt;bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" /&gt;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    &lt;bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;<br />        &lt;property name="proxyInterfaces"&gt;&lt;value&gt;com.crackj2ee.example.spring.ServiceBean&lt;/value&gt;&lt;/property&gt;<br />        &lt;property name="target"&gt;&lt;ref local="serviceTarget"/&gt;&lt;/property&gt;<br />        &lt;property name="interceptorNames"&gt;<br />            &lt;list&gt;<br />                &lt;value&gt;logAdvisor&lt;/value&gt;<br />            &lt;/list&gt;<br />        &lt;/property&gt;<br />    &lt;/bean&gt;<br />&lt;/beans&gt;</font>
		</pre>
		<p>
				<font face="Arial" size="2">注意观察修改后的配置文件，我们使用了一个ProxyFactoryBean作为service来与客户端打交道，而真正的业务Bean即
MyServiceBean被声明为serviceTarget并作为参数对象传递给ProxyFactoryBean，proxyInterfaces
指定了返回的接口类型。对于客户端而言，将感觉不出任何变化，但却动态加入了LogAdvisor，关系如下：<br /> <img onmousewheel="return bbimg(this)" alt="" src="http://www.crackj2ee.com/Article/UploadFiles/200604/20060402192529808.jpg" onload="javascript:resizepic(this)" border="undefined" /></font>
		</p>
		<p>
				<font face="Arial" size="2">运行结果如下，可以很容易看到调用了哪些方法：<br /> <img onmousewheel="return bbimg(this)" alt="" src="http://www.crackj2ee.com/Article/UploadFiles/200604/20060402192542603.jpg" onload="javascript:resizepic(this)" border="undefined" height="320" width="550" /></font>
		</p>
		<p>
				<font face="Arial" size="2">要截获指定的某些方法也是可以的。下面的例子将修改getPassword()方法的返回值：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">/**<br /> * Copyright_2006, Liao Xuefeng<br /> * Created on 2006-3-9<br /> * For more information, please visit: </font>
				<font face="Arial" size="2">
						<a href="http://www.crackj2ee.com/">
								<font color="#0066ff">http://www.crackj2ee.com</font>
						</a>
						<br />
				</font>
				<font color="#0066ff" face="Arial" size="2"> */<br />package com.crackj2ee.example.spring;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">import org.aopalliance.intercept.MethodInterceptor;<br />import org.aopalliance.intercept.MethodInvocation;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">public class PasswordAdvisor implements MethodInterceptor {<br />    public Object invoke(MethodInvocation invocation) throws Throwable {<br />        Object ret = invocation.proceed();<br />        if(ret==null)<br />            return null;<br />        String password = (String)ret;<br />        StringBuffer encrypt = new StringBuffer(password.length());<br />        for(int i=0; i&lt;password.length(); i++)<br />            encrypt.append('*');<br />        return encrypt.toString();<br />    }<br />}</font>
		</pre>
		<p>
				<font face="Arial" size="2">这个PasswordAdvisor将截获ServiceBean的getPassword()方法的返回值，并将其改为"***"。继续修改beans.xml：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" <br />"</font>
				<font face="Arial" size="2">
						<a href="http://www.springframework.org/dtd/spring-beans.dtd">
								<font color="#0066ff">http://www.springframework.org/dtd/spring-beans.dtd</font>
						</a>
				</font>
				<font color="#0066ff" face="Arial" size="2">"&gt;<br />&lt;beans&gt;<br />    &lt;bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" /&gt;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    &lt;bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" /&gt;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    &lt;bean id="passwordAdvisorTarget" class="com.crackj2ee.example.spring.PasswordAdvisor" /&gt;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    &lt;bean id="passwordAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt;<br />        &lt;property name="advice"&gt;<br />            &lt;ref local="passwordAdvisorTarget"/&gt;<br />        &lt;/property&gt;<br />        &lt;property name="patterns"&gt;<br />            &lt;list&gt;<br />                &lt;value&gt;.*getPassword&lt;/value&gt;<br />            &lt;/list&gt;<br />        &lt;/property&gt;<br />    &lt;/bean&gt;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">    &lt;bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;<br />        &lt;property name="proxyInterfaces"&gt;&lt;value&gt;com.crackj2ee.example.spring.ServiceBean&lt;/value&gt;&lt;/property&gt;<br />        &lt;property name="target"&gt;&lt;ref local="serviceTarget"/&gt;&lt;/property&gt;<br />        &lt;property name="interceptorNames"&gt;<br />            &lt;list&gt;<br />                &lt;value&gt;logAdvisor&lt;/value&gt;<br />                &lt;value&gt;passwordAdvisor&lt;/value&gt;<br />            &lt;/list&gt;<br />        &lt;/property&gt;<br />    &lt;/bean&gt;<br />&lt;/beans&gt;</font>
		</pre>
		<p>
				<font face="Arial" size="2">利用Spring提供的一个RegexMethodPointcutAdvisor可以非常容易地指定要截获的方法。运行结果如下，可以看到返回结果变为"******"：<br /> <img onmousewheel="return bbimg(this)" alt="" src="http://www.crackj2ee.com/Article/UploadFiles/200604/20060402192623904.jpg" onload="javascript:resizepic(this)" border="undefined" height="333" width="550" /></font>
		</p>
		<p>
				<font face="Arial" size="2">还需要继续增强ServiceBean？我们编写一个ExceptionAdvisor，在业务方法抛出异常时能做一些处理：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">/**<br /> * Copyright_2006, Liao Xuefeng<br /> * Created on 2006-3-9<br /> * For more information, please visit: </font>
				<font face="Arial" size="2">
						<a href="http://www.crackj2ee.com/">
								<font color="#0066ff">http://www.crackj2ee.com</font>
						</a>
						<br />
				</font>
				<font color="#0066ff" face="Arial" size="2"> */<br />package com.crackj2ee.example.spring;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">import org.springframework.aop.ThrowsAdvice;</font>
		</pre>
		<pre>
				<font color="#0066ff" face="Arial" size="2">public class ExceptionAdvisor implements ThrowsAdvice {<br />    public void afterThrowing(RuntimeException re) throws Throwable {<br />        System.out.println("[Exception] " + re.getMessage());<br />    }<br />}</font>
		</pre>
		<p>
				<font face="Arial" size="2">将此Advice添加到beans.xml中，然后在业务Bean中删除一个不存在的用户，故意抛出异常：</font>
		</p>
		<pre>
				<font color="#0066ff" face="Arial" size="2">service.deleteUser("not-exist");</font>
		</pre>
		<p>
				<font face="Arial" size="2">再次运行，注意到ExceptionAdvisor记录下了异常：<br /> <img onmousewheel="return bbimg(this)" alt="" src="http://www.crackj2ee.com/Article/UploadFiles/200604/20060402192701196.jpg" onload="javascript:resizepic(this)" border="undefined" height="216" width="550" /></font>
		</p>
		<h3>
				<font face="Arial" size="2">5．总结</font>
		</h3>
		<p>
				<font face="Arial" size="2">利用Spring非常强大的IoC容器和AOP功能，我们能实现非常灵活的应用，让Spring容器管理业务对象的生命周期，利用AOP增强功能，却不影响业务接口，从而避免更改客户端代码。</font>
		</p>
		<p>
				<font face="Arial" size="2">为了实现这一目标，必须始终牢记：面向接口编程。而Spring默认的AOP代理也是通过Java的代理接口实现的。虽然Spring也可以用CGLIB实现对普通类的代理，但是，业务对象只要没有接口，就会变得难以扩展、维护和测试。</font>
		</p>
<img src ="http://www.blogjava.net/hellotony/aggbug/50752.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hellotony/" target="_blank">Tony</a> 2006-06-06 13:20 <a href="http://www.blogjava.net/hellotony/articles/50752.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring+hibernate连接mysql（转自oksonic）</title><link>http://www.blogjava.net/hellotony/articles/22262.html</link><dc:creator>Tony</dc:creator><author>Tony</author><pubDate>Fri, 02 Dec 2005 08:42:00 GMT</pubDate><guid>http://www.blogjava.net/hellotony/articles/22262.html</guid><wfw:comment>http://www.blogjava.net/hellotony/comments/22262.html</wfw:comment><comments>http://www.blogjava.net/hellotony/articles/22262.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hellotony/comments/commentRss/22262.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hellotony/services/trackbacks/22262.html</trackback:ping><description><![CDATA[<font size="2">测试部件<br>mysql5.0.x&nbsp; <br>mysql-connector-java-3.1.11-bin.jar&nbsp; <br>mysql-connector-java-3.1.8-bin.jar<br>tomcat5.5.x<br>hibernate3<br><br>配置文件：<br></font><font size="2"><font color="#0000ff"><font color="#008000">&lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;<br></font>&nbsp;&nbsp;&lt;property name="driverClassName"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="url"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;value&gt;jdbc:mysql://192.168.1.5/oksonic&lt;/value&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="username"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;value&gt;root&lt;/value&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="password"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;value&gt;Super sonic&lt;/value&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&lt;/bean&gt;<br><br></font><font color="#000000">关键部份在第一行，现在的配置是使用了</font></font><font size="2"><font color="#000000"><font color="#0000ff">mysql-connector-java-3.1.11-bin.jar</font>&nbsp;，<br>如果将驱动文件换为</font><font color="#0000ff">mysql-connector-java-3.1.8-bin.jar</font></font><font color="#000000" size="2">，的话服务启动后读取配置文件信息到此部份后就会出错，而后面的配置信息将全部放弃。<br>这时可以将第一行的内容改为以下内容：<br><font color="#0000ff">&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;</font></font><img src ="http://www.blogjava.net/hellotony/aggbug/22262.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hellotony/" target="_blank">Tony</a> 2005-12-02 16:42 <a href="http://www.blogjava.net/hellotony/articles/22262.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts+Spring+Hibernate练习(完整)(转自oksonic)</title><link>http://www.blogjava.net/hellotony/articles/22261.html</link><dc:creator>Tony</dc:creator><author>Tony</author><pubDate>Fri, 02 Dec 2005 08:41:00 GMT</pubDate><guid>http://www.blogjava.net/hellotony/articles/22261.html</guid><wfw:comment>http://www.blogjava.net/hellotony/comments/22261.html</wfw:comment><comments>http://www.blogjava.net/hellotony/articles/22261.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hellotony/comments/commentRss/22261.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hellotony/services/trackbacks/22261.html</trackback:ping><description><![CDATA[<div><font size="2">工具：</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;Eclipse3.1、MyEclipse4.03、Tomcat5.5.9、Properties Editor插件、MySql4.1.13</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">新建工程：名称为 login</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">创建Struts框架</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">创建 index.jsp，增加一链接指向 login.jsp</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">按下Ctrl + N，创建 login.jsp、LoginAction，使用MyEclipse的向导就可以了，<strong>记得选对正确的版本</strong></font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">在ActionForm配置页中选择类型为动态Form，并继承于DynaValidatorForm，新增两个属性：username、
password，在创建jsp文件打上钩，将路径改为/login.jsp，然后下一步，改LoginAction的Input
source改为/login.jsp，点击完成</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">按下Ctrl + N 创建一个forwards，<strong>记得选对正确的版本</strong></font></div>
<div><font size="2">name 输入 indexGo</font></div>
<div><font size="2">路径选择 /index.jsp</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2"><strong>配置validator</strong></font></div>
<div><font size="2">先添加Struts插件，使用向导</font></div>
<div><font size="2">Plugin class : org.apache.struts.validator.ValidatorPlugIn</font></div>
<div><font size="2">Property : pathnames</font></div>
<div><font size="2">Value : </font><font color="#008000" size="2">/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml</font></div>
<div><font size="2">这里需要两个xml文件</font></div>
<div><font color="#000000" size="2">现在创建“</font><font color="#000000" size="2">validation.xml</font><font color="#000000" size="2">”</font><font size="2">&nbsp;文件</font></div>
<div><font size="2">&nbsp;</font></div>
<div>
<div><font size="2">在这里说明一点，我使用MyEclipse创建的Struts框架中缺少了validator-rules.xml文件，需要动拷贝到WEB-INF目录中</font></div>
<div><font size="2">此文件可以到<a href="http://struts.apache.org/"><font color="#8d8c8c">http://struts.apache.org/</font></a>下载</font></div>
<div><font size="2">&nbsp;</font></div></div>
<div><font size="2">文件内容如下：</font></div>
<div><font color="#0000ff" size="2">&lt;form-validation&gt;<br>&nbsp;&lt;formset&gt;<br>&nbsp;&nbsp;&lt;form name="loginForm"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;field property="username" depends="required"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;arg0 key="prompt.username" /&gt;<br>&nbsp;&nbsp;&nbsp;&lt;/field&gt;<br>&nbsp;&nbsp;&nbsp;&lt;field property="password" depends="required"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;arg0 key="prompt.password" /&gt;<br>&nbsp;&nbsp;&nbsp;&lt;/field&gt;<br>&nbsp;&nbsp;&lt;/form&gt;<br>&nbsp;&lt;/formset&gt;<br>&lt;/form-validation&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#000000" size="2"><strong>编辑资源文件</strong>“ApplicationResources.properties”</font></div>
<div><font size="2">增加以下内容</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#0000ff" size="2">prompt.username=User Name<br>prompt.password=User Password</font></div>
<div><font color="#0000ff" size="2">errors.required={0} is required.</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#000000" size="2">再创建中文件资源文件“ApplicationResources_zh_CN.properties”</font></div>
<p><font size="2">增加以下内容 </font></p>
<div><font color="#0000ff" size="2">prompt.username=用户名称<br>prompt.password=登录密码</font></div>
<div><font color="#0000ff" size="2">errors.required={0} 必需填写！</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#000000" size="2">修改struts-config.xml文件</font></div>
<div><font size="2">在以下位置增加绿色字体部份</font></div>
<div><font size="2">&lt;action-mappings &gt;<br>&nbsp;&nbsp;&nbsp; &lt;action<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attribute="loginForm"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; input="/login.jsp"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="loginForm"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path="/login"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scope="request"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#008000" size="2">validate="true"<br></font><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type="com.test.struts.action.LoginAction" /&gt;</font></div>
<div><font size="2">&nbsp; &lt;/action-mappings&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">这里说明提交的数据必需经过验证，而验证则是通过validator框架进行的。</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">修改LoginAction.java文件的execute方法，内容如下</font></div>
<div><font color="#0000ff" size="2">public ActionForward execute(<br>&nbsp;&nbsp;ActionMapping mapping,<br>&nbsp;&nbsp;ActionForm form,<br>&nbsp;&nbsp;HttpServletRequest request,<br>&nbsp;&nbsp;HttpServletResponse response) {<br>&nbsp;&nbsp;DynaValidatorForm loginForm = (DynaValidatorForm) form;<br>&nbsp;&nbsp;<font color="#008000">String username=loginForm.getString("username");<br>&nbsp;&nbsp;String password=loginForm.getString("password");<br>&nbsp;&nbsp;if(username.equals("test")||password.equals("test")){<br>&nbsp;&nbsp;&nbsp;return mapping.findForward("indexGo");<br>&nbsp;&nbsp;}else{<br>&nbsp;&nbsp;&nbsp;return mapping.getInputForward();<br>&nbsp;&nbsp;}<br></font>&nbsp;}</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">现在再修改一下login.jsp</font></div>
<div><font size="2">增加以下绿色字体部份</font></div>
<div><font size="2">&lt;%@ page language="java" </font><font color="#008000" size="2">contentType="text/html; charset=UTF-8"</font><font size="2"> %&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">其中</font><font color="#008000" size="2">charset=UTF-8 </font><font color="#000000" size="2">是使用UTF-8的字符编码，这也是为了支持国际化而使用的。</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">好了，现在可以启动Tomcat进行测试了</font></div>
<div><font size="2"><a href="http://localhost/login/"><font color="#8d8c8c">http://localhost/login/</font></a>&nbsp;这里说明一下，我的Tomcat已经装端口号改为80了，所以就不必使用<a href="http://localhost:8080/login/"><font color="#8d8c8c">http://localhost:8080/login/</font></a>这样的方法了。</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">如果不输入任何数据而直接提交表单的话就可以看到效果了。</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#ff0000" size="2">好了，如果没有什么问题的话就继续往下看吧，如果有问题的话就得往上看了^_^</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">现在创建Spring框架了，在这里我将Spring所有的包全部加载进去，因为我还不知道具体用到哪些类，全部加进去方便点</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">单选框选第二个，这样的话所有的类库和标签等都将拷贝到项目中去，这样方便以后的布署</font></div>
<div><font size="2">下一步后是创建配置文件，将文件放到“WebRoot/WEB-INF”目录下，文件名称为“applicationContext.xml”</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&nbsp;</font></div>
<div>
<div><font size="2">配置struts-config.xml文件，添加（spring）的插件</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#0000ff" size="2">&lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;<br>&nbsp;&nbsp;&nbsp; &lt;set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml" /&gt;<br>&nbsp; &lt;/plug-in&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&nbsp; 
</font><div><font color="#000000" size="2">修改LoginAction配置</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2"><strong><font color="#000000">原：</font></strong></font></div>
<div><font color="#0000ff" size="2">&lt;action<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attribute="loginForm"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; input="/login.jsp"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="loginForm"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path="/login"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scope="request"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validate="true"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type="com.test.struts.action.LoginAction" /&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#0000ff" size="2">&nbsp; &lt;/action-mappings&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#000000" size="2">改为：</font></div>
<div>
<div><font color="#0000ff" size="2">&lt;action<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attribute="loginForm"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; input="/login.jsp"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="loginForm"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path="/login"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scope="request"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validate="true"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type="<font color="#008000">org.springframework.web.struts.DelegatingActionProxy</font>" /&gt;</font></div>
<div><font color="#0000ff" size="2">&nbsp; &lt;/action-mappings&gt;</font></div></div></div></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&nbsp; 
</font><div><font color="#000000" size="2">绿色字体部份为修改内容</font></div>
<div><font color="#000000" size="2">这里将使用spring的代理器来对Action进行控制</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">当提交到/login.do是将控制权交给了spring，然后由spring来决定是否转回到struts的Action</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">现在来配置spring</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#0000ff" size="2">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br>&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "</font><font size="2"><a href="http://www.springframework.org/dtd/spring-beans.dtd"><font color="#0000ff">http://www.springframework.org/dtd/spring-beans.dtd</font></a></font><font color="#0000ff" size="2">"&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#0000ff" size="2">&lt;beans&gt;<br>&nbsp;<font color="#008000">&lt;bean name="/login" class="com.test.struts.action.LoginAction" singleton="false"&gt;&lt;/bean&gt;</font></font></div>
<div><font color="#0000ff" size="2">&lt;/beans&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#000000" size="2">绿色字体是关于转交控制权的配置内容</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">属性singleton="false"，指明了Action
的实例获取方式为每次重新创建。解决了Struts中令人诟病的线程安全问题（Struts中，由一个Action实例处理所有的请求，这就导致了类公用
资源在并发请求中的线程同步问题。）（摘自spring开发指南）</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#800080" size="2">这时如果你要进行测试也是可以的，不过为了省点时间就不进行测试了。</font></div>
<div><font size="2">&nbsp; 
</font><div><font size="2"><strong>建立数据库在 </strong></font><font size="2">这里我使用的是mysql4.1.13</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">CREATE TABLE `user` (<br>&nbsp; `ID` int(11) NOT NULL auto_increment,<br>&nbsp; `USERNAME` varchar(50) NOT NULL default '',<br>&nbsp; `PASSWORD` varchar(50) NOT NULL default '',<br>&nbsp; PRIMARY KEY&nbsp; (`ID`)<br>) ENGINE=MyISAM DEFAULT CHARSET=latin1; </font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">添加记录 insert into user (USERNAME,PASSWORD) values ('test','test')</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2"><strong>创建Hibernate框架</strong></font></div>
<div><font size="2">在配置界面中配置数据库的连接部份，重要的是点击链接将jdbc拷贝到lib目录中</font></div>
<div><font size="2">使用MyEclipse的数据Database Explorer工具创建User.hmb.xml、AbstractUser.java、User.java映射文件</font></div>
<div><font size="2">创建完成后可以将自动生成的hibernate.cfg.xml删除</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2"><strong>创建UserDAO.java、UserDAOImp.java</strong></font></div>
<div>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">UserDAO.java<o:p></o:p></span></b></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">public interface UserDAO {<o:p></o:p></span></b></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp; </span>public abstract boolean isValidUser(String username, String password);<o:p></o:p></span></b></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">}<o:p></o:p></span></b></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></b></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">UserDAOImp.java<o:p></o:p></span></b></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">import java.util.List;<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">import org.springframework.orm.hibernate3.support.HibernateDaoSupport;<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">import com.test.Hibernate.SessionFactory;<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">public class UserDAOImp extends HibernateDaoSupport implements UserDAO {<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>private SessionFactory sessionFactory;<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>private static String hql = "from User u where u.username=? ";<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>public boolean isValidUser(String username, String password) {<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>List userList = this.getHibernateTemplate().find(hql, username);</span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (userList.size() &gt; 0) {<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return true;<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return false;<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>}<o:p></o:p></span></font></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><font size="2"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">}<o:p></o:p></span></font></p></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2"><strong>修改LoginAction.java文件</strong>，使用userDao的方法来进行用户验证</font></div>
<div><font size="2">package com.test.struts.action;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">import org.apache.struts.action.Action;<br>import org.apache.struts.action.ActionForm;<br>import org.apache.struts.action.ActionForward;<br>import org.apache.struts.action.ActionMapping;<br>import org.apache.struts.validator.DynaValidatorForm;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#008000" size="2">import com.test.UserDAO;</font></div>
<div><font size="2"><br>public class LoginAction extends Action {</font></div>
<div><font size="2"><br>&nbsp;</font><font color="#008000" size="2">private UserDAO userDAO</font><font size="2">;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#008000" size="2">&nbsp;public UserDAO getUserDAO() {<br>&nbsp;&nbsp;return userDAO;<br>&nbsp;}</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font color="#008000" size="2">&nbsp;public void setUserDAO(UserDAO userDAO) {<br>&nbsp;&nbsp;this.userDAO = userDAO;<br>&nbsp;}</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&nbsp;public ActionForward execute(ActionMapping mapping, ActionForm form,<br>&nbsp;&nbsp;&nbsp;HttpServletRequest request, HttpServletResponse response) {<br>&nbsp;&nbsp;DynaValidatorForm loginForm = (DynaValidatorForm) form;<br>&nbsp;&nbsp;// TODO Auto-generated method stub<br>&nbsp;&nbsp;String username = (String) loginForm.get("username");<br>&nbsp;&nbsp;String password = (String) loginForm.get("password");<br>&nbsp;&nbsp;loginForm.set("password", null);<br>&nbsp;&nbsp;</font><font color="#008000" size="2">if (userDAO.isValidUser(username,password)) {<br>&nbsp;&nbsp;&nbsp;return mapping.findForward("indexGo");<br>&nbsp;&nbsp;} else {<br>&nbsp;&nbsp;&nbsp;return mapping.getInputForward();<br>&nbsp;&nbsp;}<br></font><font size="2">&nbsp;}</font></div>
<div><font size="2">}<br>绿色字体为修改部份</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">现在剩下最后的spring配置了</font></div>
<div><font size="2">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br>&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "<a href="http://www.springframework.org/dtd/spring-beans.dtd"><font color="#8d8c8c">http://www.springframework.org/dtd/spring-beans.dtd</font></a>"&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&lt;beans&gt;<br>&nbsp;&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;<br>&nbsp;&nbsp;&lt;property name="driverClassName"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="url"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;value&gt;jdbc:mysql://localhost/test&lt;/value&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="username"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;value&gt;root&lt;/value&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="password"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;value&gt;root&lt;/value&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&lt;/bean&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&nbsp;&lt;!-- 配置sessionFactory, 注意这里引入的包的不同&nbsp; --&gt;<br>&nbsp;&lt;bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;<br>&nbsp;&nbsp;&lt;property name="dataSource"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;ref local="dataSource" /&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="mappingResources"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;list&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;com/test/Hibernate/User.hbm.xml&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="hibernateProperties"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;props&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="hibernate.dialect"&gt;org.hibernate.dialect.MySQLDialect&lt;/prop&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="hibernate.show_sql"&gt;true&lt;/prop&gt;<br>&nbsp;&nbsp;&nbsp;&lt;/props&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&lt;/bean&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&nbsp;&lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;<br>&nbsp;&nbsp;&lt;property name="sessionFactory"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;ref local="sessionFactory" /&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&lt;/bean&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&nbsp;&lt;bean id="userDAO" class="com.test.UserDAOImp"&gt;<br>&nbsp;&nbsp;&lt;property name="sessionFactory"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;ref local="sessionFactory" /&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&lt;/bean&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&nbsp;&lt;bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;<br>&nbsp;&nbsp;&lt;property name="transactionManager"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;ref bean="transactionManager" /&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="target"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;ref local="userDAO" /&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&nbsp;&lt;property name="transactionAttributes"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;props&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="insert*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="get*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="is*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;<br>&nbsp;&nbsp;&nbsp;&lt;/props&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&lt;/bean&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">&nbsp;&lt;bean name="/login" class="com.test.struts.action.LoginAction" singleton="false"&gt;<br>&nbsp;&nbsp;&lt;property name="userDAO"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;ref bean="userDAOProxy" /&gt;<br>&nbsp;&nbsp;&lt;/property&gt;<br>&nbsp;&lt;/bean&gt;<br>&lt;/beans&gt;</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">现在可以进行测试了！</font></div>
<div><font size="2">&nbsp;</font></div>
<div><font size="2">在编写代码有配置内容时一定要注意 hibernate 和 hibernate3 ，这两个包的名字就只差一个字，千万不要有错，否则找错误可是很难的。</font></div></div></div><img src ="http://www.blogjava.net/hellotony/aggbug/22261.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hellotony/" target="_blank">Tony</a> 2005-12-02 16:41 <a href="http://www.blogjava.net/hellotony/articles/22261.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>轻量级开发成功秘诀：露出水面的Spring</title><link>http://www.blogjava.net/hellotony/articles/20576.html</link><dc:creator>Tony</dc:creator><author>Tony</author><pubDate>Sat, 19 Nov 2005 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/hellotony/articles/20576.html</guid><wfw:comment>http://www.blogjava.net/hellotony/comments/20576.html</wfw:comment><comments>http://www.blogjava.net/hellotony/articles/20576.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hellotony/comments/commentRss/20576.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hellotony/services/trackbacks/20576.html</trackback:ping><description><![CDATA[<font size="2">轻量级容器在为应用程序组织胶水代码方面，提供了一种方法。Spring框架在轻量级容器世界独占鳌头。它内含了轻量级容器、面向方面编程框架和可以轻而易举整合数百种开放源码框架的胶水代码。
<br><br>在 2003 年的时候，三个山地自行车手和我尖叫着冲下一条叫做 Forrest Ridge 的陡峭小径。这条小径因为刚刚重新开放，没有什么宣传，因此德克萨斯州首府奥斯汀只有很少的人知道它。
<br><br>整个秋天，我们都保守这个秘密，享受它带给我们的快乐。而到了今天，我们不得不在这条小径上躲避 20 个以上的车手。因为，秘密公开了！
<br><br>尽管大家发现了这条奇妙的小径对于我和我的朋友而言不是好事，但是，当您的开放源码项目被人发现时，那却是一件令人欣喜若狂的事情。因为从此您就可以更易找到资源、更快修补项目缺陷，并且通常您还可以利用其他的社区资源。
<br><br>现在，Spring 已经被大家所发现。它是最重要的开放源码项目之一，在企业环境的输入输出中扮演了重要角色，以它自己的方式取得了与 Hibernate 类似的辉煌成果。本文向您展示了 Spring 对于轻量级的开发为何意义如此重大。
<br><br>Spring 是什么？
<br><br>您若是一名企业程序开发人员，Spring 会令您事半功倍。但它到底是什么？对于这样的综合性框架，很难轻易找到一个明确的答案。
<br><br>从本质上讲，Spring 是一个轻量级容器。您可以通过 Spring 来利用普通 Java 对象（POJO）编程，使用依赖注入解析 POJO 间的依赖性，然后使用面向方面编程（AOP）将服务与它们相关联。
<br><br>Spring 也提供了许多胶水代码，这使您可以更加轻松地使用 Java 2 平台企业版（J2EE）服务，比如用于事务的
Java 事务 API （JTA）、用于远程控制的远程方法调用（RMI）、用于管理的 Java 管理扩展（JMX）或用于持久性的 Java
数据对象（JDO）。
<br><br>Spring 还为开放源码框架，比如 Hibernate、Tapestry、Struts 和 JavaServer Faces（JSF），提供了胶水代码。注意，虽然有些框架是相互竞争的，但这并不是什么问题，Spring 没有试图只支持一种获胜的框架。
<br><br>使用 Spring，使您能够利用一些服务。例如，Web Flow 可以轻松地处理 Web 页面间的流。类似地，Web MVC 为类似 Struts 的基于 Web 的应用程序提供了模型－视图－控制器（MVC）架构。
<br><br>因此，Spring 支持众多的技术。与企业 JavaBean（EJB）技术一样，Spring 容器让您可使用很多企业服务。但是与 EJB 1.x 和 2.x 不一样，放入容器的是 JavaBean，而不是一些私有组件。
<br><br>与 EJB 脱离的另一方面是，Spring 并不将您限制于少量标准服务，而是让您从大量服务中自由选择，甚至构建您自己的服务。
<br><br>在我看来，Spring 是 Java 社区中最重要的开放源码项目之一。它帮助我们重新定义了 J2EE。在一定程度上由于来自 Spring 技术革新的压力，导致 EJB 3 专家小组构建了一个比 EJB 2.x 更加相似 Spring 的接口。
<br><br>我能够轻易地想像到，在企业级程序开发中，Spring 的使用会变得同 Struts 一样普及。为帮助您了解 Spring 如此重要的原因，让我们一层层剥开它神秘的面纱。<br><br>
              核心容器
<br><br>首先，我们来看看 Spring 的工作原理。在此，我不会为您展示完整的例子，因为您可以找到数不清的 Spring 教程。我使用的是我最新出版的书中的示例应用程序，这里节选示例中的一个片段来向您展示 Spring 可以帮助您所做的事情。
<br><br>这个应用程序简单地为一个称为 RentaBike 的操作维护一个自行车清单。Spring
是此应用程序的“中枢系统”。Spring 的主要容器 ?? 上下文 ??
保存着对所有应用程序主要层和服务的引用。应用程序的主要层是数据库、持久性框架、数据库访问对象和用户界面（UI）控制器及视图层。
<br><br>这个应用程序的 Spring 上下文只是应用程序使用的 bean 的清单。但是，这些 bean 不是必须依赖所有的
Spring 接口，我在这里选择依赖 Spring
是因为要为您展示一些重复的胶水代码（它们将应用程序联系到一起）。在此上下文中，您会发现至少五种类型的元数据：
<br><br>配置
<br><br>因为容器已经进行了一些配置来处理依赖注入（在 Secrets of lightweight development
success, Part 2: How to lighten up your containers
中讲到过），这里有必要也处理其他配置，以便您可以拥有一个方便、一致的策略。
<br><br>应用程序的主要层
<br><br>在 RentaBike 应用程序中，我公开了一个数据访问对象（DAO）层、一个控制器层和一个视图层（参阅清单 1）。我选择将这个 DAO 封装在一个接口中，这样我就能够切换数据访问层来使用不同的持久性策略。
<br><br>外部依赖性
<br><br>例如，我的 DAO 需要一个数据源。Spring 会注入我的 DAO 需要的资源（比如数据源）和平台特定的配置（比如 Hibernate 的会话工厂）。
<br><br>透明服务
<br><br>我们从 EJB 技术中的最大获益之一就是声明性事务。但是您不得不花费大力气得到它们，因为您被强制使用 EJB 接口和重量级 EJB 容器。Spring 让您可以只配置您需要的服务并将它们应用于 POJO。在 Spring 中，您可以使任何方法成为事务型的。
<br><br>数据 
<br><br>通常，消息数据、关于应用程序流的信息和测试数据也可能放置在应用程序上下文中。
<br><br>清单 1. RentaBike 的一部分上下文
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>&lt;beans&gt; <br>  <br> &lt;bean id="rentaBike"<br> class="com.springbook.JDBCRentABike"&gt; <br>   &lt;property name="storeName"&gt; <br>     &lt;value&gt;Bruce's Bikes&lt;/value&gt;  <br>   &lt;/property&gt; <br>   &lt;property name="dataSource"&gt; <br>     &lt;ref bean="dataSource" /&gt;  <br>   &lt;/property&gt; <br> &lt;/bean&gt; <br>  <br><br><br>  &lt;bean id="bikesController" <br>  class="com.springbook.BikesController"&gt; <br>    &lt;property name="facade"&gt; <br>      &lt;ref bean="rentaBike" /&gt;  <br>    &lt;/property&gt; <br>  <br><br><br>  &lt;/bean&gt; <br>    &lt;bean id="dataSource" <br>  class="org.springframework.<br>  jdbc.datasource.DriverManagerDataSource"&gt; <br>      &lt;property name="driverClassName"&gt; <br>      &lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;  <br>    &lt;/property&gt; <br>    &lt;property name="url"&gt; <br>&lt;value&gt;jdbc:mysql://localhost/bikestore&lt;/value&gt;  <br>    &lt;/property&gt; <br>    &lt;property name="username"&gt; <br>      &lt;value&gt;bikestore&lt;/value&gt;  <br>    &lt;/property&gt; <br>  &lt;/bean&gt; <br>  <br>&lt;/beans&gt;</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>如果仔细观察上下文，您会注意到它是由 bean 组成的。这很重要，因为早期的 J2EE 容器强制您使用给定的
API，具体来说是 EJB。每个 bean 都有一套属性。一些属性是字符串和基本类型值。一些是 bean，比如 rentaBike bean
需要的数据源。
<br><br>您不必实现类似 EJB 会话 bean 接口一样的 API。您只要列出 bean 和它们的属性。其中一些属性满足了依赖性。您现在已经得到了较好的透明性，因此只要需要，您可以在容器之外运行您的 bean 或将您的应用程序移动到其他容器中。<br><br>
              用于测试的上下文
<br><br>您还可以在上下文中包括其他类型的bean。例如，使用上下文填充上下文中的简单测试数据或应用程序流 是非常有意义的。在 Spring: A Developer's Notebook 中，我们使用存根（它使用数组列表代替数据库）驱动第一个 UI 实现。
<br><br>假如，我们已经得到一个具有姓名和 email 地址的数据库表。我就可以构建一个简单的存根（具有作为属性的数组列表），然后快速实现一些简单数据访问方法，如清单 2 所示。
<br><br>清单 2. 替换数据库的测试存根
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>public class StubEmailDirectory<br>{ <br>    private List people; <br>    public List getPeople()<br>	{ <br>        return people; <br>    } <br>    public void setPeople(List people)<br>	{ <br>        this.people = people; <br>    } <br>  <br>    public String findEmail(String name)<br>	{ <br>        Person p = findPerson(name); <br>        if (p==null) { <br>             return null; <br>        } <br>        return p.getEmail(); <br>    } <br>. <br>public Person findPerson(String name)<br>{ <br>        if (people==null) { <br>            return null; <br>        } <br>        int size = people.size(); <br>        for(int i=0;i&lt;size;i++)<br>		{ <br>            Person p=(Person)people.get(i); <br>            if(p.getName().equals(name)) <br>			{ <br>                 return p; <br>            } <br>        } <br>        return null; <br>    } <br>}</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>然后，我可以从上下文填充它，如清单 3 所示。
<br><br>清单 3. 上下文中的测试数据
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>&lt;beans&gt; <br>  <br>&lt;bean id="bruce" <br>class="j2life.bus.Person"&gt; <br>        &lt;property name="name"&gt; <br>            &lt;value&gt;Bruce&lt;/value&gt; <br>        &lt;/property&gt; <br>        &lt;property name="email"&gt; <br>            &lt;value&gt;bruce.t@j2life.com <br>            &lt;/value&gt; <br>        &lt;/property&gt; <br>    &lt;/bean&gt; <br>  <br>&lt;bean id="maggie" <br>class="j2life.bus.Person"&gt; <br>        &lt;property name="name"&gt; <br>            &lt;value&gt;Maggie&lt;/value&gt; <br>        &lt;/property&gt; <br>        &lt;property name="email"&gt; <br>            &lt;value&gt;maggie.t@j2life.com <br>            &lt;/value&gt; <br>        &lt;/property&gt; <br>    &lt;/bean&gt; <br>    &lt;bean id="emails"<br>	class="j2life.bus.StubEmailDirectory"&gt; <br>        &lt;property name="people"&gt; <br>            &lt;list&gt; <br>                &lt;ref bean="bruce"/&gt; <br>                &lt;ref bean="maggie"/&gt; <br>            &lt;/list&gt; <br>        &lt;/property&gt; <br>    &lt;/bean&gt; <br>&lt;/beans&gt;</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>当您考虑测试时，从上下文中摘出测试数据常常很有意义。为使测试用例可重复和可验证，您可以从上下文而不是服务摘出不可预知的数据（例
如，系统时间和随机数）。Spring 的上下文使测试更加容易，因为您可以通过不同方法为生产和测试配置应用程序。Spring
的基础是容器，并且这个基础很重要。但容器远不能代表它的全部。
<br><br>优势
<br><br>同我一样，自行车世界冠军 Lance Armstrong 也来自德克萨斯首府奥斯汀。我很多年来，都很喜欢欣赏他的比赛，部分原因在于他从每次登车中得到的优势比世界上任何人得到的都要多。我寻找机会，以从我所做的每件事中得到附加的优势。
<br><br>Spring 通过提供胶水代码，消除麻烦重复的资源管理、配置和应用程序中的繁重工作，使我得到更多的优势。
<br><br>采用持久性。Hibernate 是一套漂亮的持久性替换方案。但像所有持久性框架一样，它强制您管理一些低级的细节（我宁愿不要它们）。清单 4 展示了一个没有 Spring 的 Hibernate 应用程序示例。
<br><br>清单 4. 没有 Spring 的 Hibernate
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>// Configuration code<br><br>Configuration config = <br>new Configuration( ); <br>config.addClass(Bike.class)<br>.addClass(Customer.class). <br>addClass(Reservation.class); <br>SessionFactory mySessionFactory <br>= Configuration.buildSessionFactory( ); <br><br>  <br>public List getBikesOldWay( )<br>throws Exception { <br>  List bikes = null; <br>  Session s = null; <br>  try { <br>    s = mySessionFactory.openSession( ); <br>    bikes = s.find("from Bike"); <br>  }catch (Exception ex) { <br>    //handle exception gracefully <br>  }finally { <br>    s.close( ); <br>  } <br>  return bikes; <br>}</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>清单 5 展示了一个类似的示例，但它使用了 Spring。
<br><br>清单 5. 使用 Spring 的 Hibernate
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>public List getBikes( ) <br>{ <br>  return getHibernateTemplate()<br>  .find("from Bike"); <br>}</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>可以将 Hibernate 模板看作是实现会话处理的方法。尤其要注意您所没有看到的。您不必担心事务，因为 Spring 让您通过声明配置它们。
<br><br>您也不必担心管理资源，因为代码是在模板中。Spring 总是会关闭会话，所以您不必担心。您不必在这个级别上处理异常，因为 Spring 将它们转换为一套通用的未检查异常（unchecked exceptions）。
<br><br>我喜欢未检查异常，因为我可以选择在架构的合适级别上抛出它们。只需提供很少信息来告诉 Hibernate 做什么。Spring 处理剩下的事情。这就是优势。
<br><br>Spring 也通过其他途径建立了优势。通过为其他服务提供同种的胶水代码，Spring
减轻了应用程序编程人员的负担。我几乎再也不必像往常一样重复劳动。我可以更加简单地使用远程控制、事务、安全、持久性和 MVC 代码，因为
Spring 确实做到了“减负”。
<br><br>在这里，我想指出一些不利之处。在我决定使用 Spring 的胶水代码替代自己的胶水代码时，我自己构建了 Spring 框架的依赖关系。通常，我认为付出这种代价非常值得。<br><br>
              AOP
<br><br>我们了解到 AOP 可以将服务与 POJO 相关联以提供更佳的透明性。使用 AOP，可以从代码中消除许多横切关注点。所以，为什么不马上下载 AOP 框架并直接使用它呢？
<br><br>事实上，一些团队就是这么做的。根据我的经验，技术在我们学会使用它之前就已经早早准备好了。当我看到中级和初级程序员使用 AOP 时，我联想到一个拥有强大工具的孩子。
<br><br>正视它：我们当中的绝大多数人在遇到 AOP 时，仍然还像个孩子。因为它使用了面向对象编程，所以我们必须花费一些时间积累相关知识以更有效地使用 AOP。
<br><br>通过 Spring 的辅助训练，我能够使用 AOP。我可以使用一些预打包的方面并观察定义好场景的示例，这样我不需要冒任何风险就可以从 AOP 中收获更多。
<br><br>实际上，在过去可以经常看到类似的策略。Ada 编程语言支持封装，但只有受限的继承性。像 Microsoft? Windows?
编程模型一样的早期窗口环境内部具有 Window 对象、类似 Smalltalk
消息的事件甚至还有继承，但是公开了一个过程编程模型。我认为这种策略对 AOP 是同等重要的。
<br><br>Spring 的重大意义
<br><br>对于那些使用 Spring 的人，Spring 无疑是革命性的。它的一些简单思想引发了影响深远的结果：
<br><br>Spring 有力地开拓了企业级服务容器。使您不再“隶属”于容器提供的 API 或服务。可以使用 Spring 上下文管理预打包的服务，整合第三方服务或自己编写服务。
<br><br>Spring 在可测试性方面有了长足的进步。
<br><br>通过 Spring，能够使用依赖注入将模拟对象插入到难以接触的位置，在容器外运行对象（因为这些对象是 POJO），甚至使用容器提供不可预知的数据。
<br><br>Spring 的胶水代码使得只要编写很少的代码就可以轻松插入企业服务。编写的代码越少，维护和扩展代码时工作量就越少。
<br><br>Spring 代表一个开放源码项目，重新定义了 Java 商业小组开发软件的方式。Spring 对于最新 EJB 规范的影响是不容置疑的，同时也是非常重要的。
<br><br>Spring 已经成为企业轻量级开发的顶梁柱之一。以下的参考资料为您展示如何入门和深入 Spring。在本系列的下一篇文章中，我会为您介绍轻量级开发中的一些替代的持久性方案。
<br><br>祝您所喜爱的开放源码“小径”也被大家所发现。
<br><br></font><img src ="http://www.blogjava.net/hellotony/aggbug/20576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hellotony/" target="_blank">Tony</a> 2005-11-19 16:17 <a href="http://www.blogjava.net/hellotony/articles/20576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何使用Spring更好地处理Struts动作</title><link>http://www.blogjava.net/hellotony/articles/20575.html</link><dc:creator>Tony</dc:creator><author>Tony</author><pubDate>Sat, 19 Nov 2005 08:14:00 GMT</pubDate><guid>http://www.blogjava.net/hellotony/articles/20575.html</guid><wfw:comment>http://www.blogjava.net/hellotony/comments/20575.html</wfw:comment><comments>http://www.blogjava.net/hellotony/articles/20575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hellotony/comments/commentRss/20575.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hellotony/services/trackbacks/20575.html</trackback:ping><description><![CDATA[<font size="2">Struts Recipes 的合著者 George Franciscus将介绍另一个重大的Struts整合窍门，这次是将 Struts
应用程序导入 Spring 框架。请跟随 George，他将向您展示如何改变 Struts 动作，使得管理 Struts 动作就像管理
Spring beans 那样。结果是一个增强的 web 框架，这个框架可以方便地利用 Spring AOP 的优势。
<br><br>您肯定已经听说过控制反转 (IOC) 设计模式，因为很长一段时间以来一直在流传关于它的信息。如果您在任何功能中使用过
Spring 框架，那么您就知道其原理的作用。在本文中，我利用这一原理把一个 Struts 应用程序注入 Spring 框架，您将亲身体会到
IOC 模式的强大。
<br><br>将一个 Struts 应用程序整合进 Spring 框架具有多方面的优点。首先，Spring 是为解决一些关于 JEE
的真实世界问题而设计的，比如复杂性、低性能和可测试性，等等。第二，Spring 框架包含一个 AOP
实现，允许您将面向方面技术应用于面向对象的代码。
<br><br>第三，一些人可能会说 Spring 框架只有处理 Struts 比 Struts 处理自己好。但是这是观点问题，我演示三种将 Struts 应用程序整合到 Spring 框架的方法后，具体由您自己决定使用哪一种。
<br><br>我所演示的方法都是执行起来相对简单的，但是它们却具有明显不同的优点。我为每一种方法创建了一个独立而可用的例子，这样您就可以完全理解每种方法。请参阅 下载 部分获得完整例子源代码。
<br><br>为什么 Spring 这么了不起？
<br><br>Spring 的创立者 Rod
Johnson以一种批判的眼光看待Java企业软件开发，并且提议很多企业难题都能够通过战略地使用 IOC 模式（也称作依赖注入）来解决。当
Rod 和一个具有奉献精神的开放源码开发者团队将这个理论应用于实践时，结果就产生了 Spring 框架。
<br><br>简言之，Spring 是一个轻型的容器，利用它可以使用一个外部 XML 配置文件方便地将对象连接在一起。每个对象都可以通过显示一个 JavaBean 属性收到一个到依赖对象的引用，留给您的简单任务就只是在一个 XML 配置文件中把它们连接好。
<br><br>IOC 和 Spring
<br><br>IOC 是一种使应用程序逻辑外在化的设计模式，所以它是被注入而不是被写入客户机代码中。将 IOC 与接口编程应用结合，就像 Spring 框架那样，产生了一种架构，这种架构能够减少客户机对特定实现逻辑的依赖。
<br><br>依赖注入是一个强大的特性，但是 Spring 框架能够提供更多特性。Spring
支持可插拔的事务管理器，可以给您的事务处理提供更广泛的选择范围。它集成了领先的持久性框架，并且提供一个一致的异常层次结构。Spring
还提供了一种使用面向方面代码代替正常的面向对象代码的简单机制。
<br><br>Spring AOP 允许您使用拦截器
在一个或多个执行点上拦截应用程序逻辑。加强应用程序在拦截器中的日志记录逻辑会产生一个更可读的、实用的代码基础，所以拦截器广泛用于日志记录。您很快
就会看到，为了处理横切关注点，Spring AOP 发布了它自己的拦截器，您也可以编写您自己的拦截器。 <br><br>
              整合 Struts 和 Spring
<br><br>与 Struts 相似，Spring 可以作为一个 MVC 实现。这两种框架都具有自己的优点和缺点，尽管大部分人同意 Struts 在 MVC 方面仍然是最好的。
<br><br>很多开发团队已经学会在时间紧迫的时候利用 Struts 作为构造高品质软件的基础。Struts 具有如此大的推动力，以至于开发团队宁愿整合 Spring 框架的特性，而不愿意转换成 Spring MVC。
<br><br>没必要进行转换对您来说是一个好消息。Spring 架构允许您将 Struts 作为 Web 框架连接到基于 Spring 的业务和持久层。最后的结果就是现在一切条件都具备了。
<br><br>在接下来的小窍门中，您将会了解到三种将 Struts MVC 整合到 Spring 框架的方法。我将揭示每种方法的缺陷并且对比它们的优点。 一旦您了解到所有三种方法的作用，我将会向您展示一个令人兴奋的应用程序，这个程序使用的是这三种方法中我最喜欢的一种。
<br><br>三个小窍门
<br><br>接下来的每种整合技术（或者窍门）都有自己的优点和特点。我偏爱其中的一种，但是我知道这三种都能够加深您对 Struts 和 Spring 的理解。在处理各种不同情况的时候，这将给您提供一个广阔的选择范围。方法如下：
<br><br>使用 Spring 的 ActionSupport 类整合 Structs
<br><br>使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor 
<br><br>将 Struts Action 管理委托给 Spring 框架装载应用程序环境
<br><br>无论您使用哪种技术，都需要使用 Spring 的 ContextLoaderPlugin 为 Struts 的
ActionServlet 装载 Spring 应用程序环境。就像添加任何其他插件一样，简单地向您的 struts-config.xml
文件添加该插件，如下所示：
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>&lt;plug-in className= <br>  "org.springframework.web.<br>  struts.ContextLoaderPlugIn"&gt; <br>    &lt;set-property property= <br>      "contextConfigLocation"<br>	  value="/WEB-INF/beans.xml"/&gt; <br> &lt;/plug-in&gt;</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>前面已经提到过，在下载部分，您能够找到这三个完全可使用的例子的完整源代码。每个例子都为一个书籍搜索应用程序提供一种不同的 Struts 和 Spring 的整合方法。您可以在这里看到例子的要点，但是您也可以下载应用程序以查看所有的细节。
<br><br>窍门 1. 使用 Spring 的 ActionSupport
<br><br>手动创建一个 Spring 环境是一种整合 Struts 和 Spring 的最直观的方式。为了使它变得更简单，Spring
提供了一些帮助。为了方便地获得 Spring 环境，org.springframework.web.struts.ActionSupport
类提供了一个 getWebApplicationContext() 方法。您所做的只是从 Spring 的 ActionSupport 而不是
Struts Action 类扩展您的动作，如清单 1 所示：
<br><br>清单 1. 使用 ActionSupport 整合 Struts
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>package ca.nexcel.books.actions; <br><br>import java.io.IOException; <br><br>import javax.servlet.ServletException; <br>import javax.servlet.http.HttpServletRequest; <br>import javax.servlet.http.HttpServletResponse; <br><br>import org.apache.struts.action.ActionError; <br>import org.apache.struts.action.ActionErrors; <br>import org.apache.struts.action.ActionForm; <br>import org.apache.struts.action.ActionForward; <br>import org.apache.struts.action.ActionMapping; <br>import org.apache.struts.action.DynaActionForm; <br>import org.springframework.<br>context.ApplicationContext; <br>import org.springframework.<br>web.struts.ActionSupport; <br><br>import ca.nexcel.books.beans.Book; <br>import ca.nexcel.books.business.BookService; <br><br>public class SearchSubmit<br>extends ActionSupport {   |(1) <br><br><br>  public ActionForward execute( <br>    ActionMapping mapping, <br>    ActionForm form, <br>    HttpServletRequest request, <br>    HttpServletResponse response) <br>    throws IOException, <br>	ServletException<br>	{ <br><br>    DynaActionForm searchForm <br>	= (DynaActionForm) form; <br>    String isbn = (String) <br>	searchForm.get("isbn"); <br>         <br>    //the old fashion way <br>    //BookService bookService<br>	= new BookServiceImpl(); <br>         <br>    ApplicationContext ctx =  <br>      getWebApplicationContext();   <br>	  |(2) <br>    BookService bookService =  <br>      (BookService) <br>	  ctx.getBean("bookService");  <br>	  |(3) <br>         <br>  Book book = bookService.read(isbn.trim()); <br><br>    if (null == book) <br>	{ <br>      ActionErrors errors = new ActionErrors(); <br>      errors.add(ActionErrors.GLOBAL_ERROR,<br>	  new ActionError <br>        ("message.notfound")); <br>      saveErrors(request, errors); <br>      return mapping.findForward("failure") ; <br>  } <br><br>    request.setAttribute("book", book); <br>    return mapping.findForward("success"); <br>  } <br>}</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>让我们快速思考一下这里到底发生了什么。在 (1) 处，我通过从 Spring 的 ActionSupport 类而不是 Struts 的 Action 类进行扩展，创建了一个新的 Action。
<br><br>在 (2) 处，我使用 getWebApplicationContext() 方法获得一个 ApplicationContext。为了获得业务服务，我使用在 (2) 处获得的环境在 (3) 处查找一个 Spring bean。<br><br>这种技术很简单并且易于理解。不幸的是，它将 Struts 动作与 Spring 框架耦合在一起。如果您想替换掉
Spring，那么您必须重写代码。并且，由于 Struts 动作不在 Spring 的控制之下，所以它不能获得 Spring AOP
的优势。当使用多重独立的 Spring 环境时，这种技术可能有用，但是在大多数情况下，这种方法不如另外两种方法合适。
<br><br>窍门 2. 覆盖 RequestProcessor
<br><br>将 Spring 从 Struts 动作中分离是一个更巧妙的设计选择。分离的一种方法是使用
org.springframework.web.struts.DelegatingRequestProcessor 类来覆盖 Struts 的
RequestProcessor 处理程序，如清单 2 所示：
<br><br>清单 2. 通过 Spring 的 DelegatingRequestProcessor 进行整合
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>&lt;?xml version="1.0"<br>encoding="ISO-8859-1" ?&gt; <br><br>&lt;!DOCTYPE struts-config PUBLIC <br> "-//Apache Software Foundation<br> //DTD Struts Configuration 1.1//EN" <br>"http://jakarta.apache.org<br>/struts/dtds/struts-config_1_1.dtd"&gt; <br><br>&lt;struts-config&gt; <br> &lt;form-beans&gt; <br>    &lt;form-bean name="searchForm"  <br>      type="org.apache.struts.<br>	  validator.DynaValidatorForm"&gt; <br>               &lt;form-property name="isbn"  <br>			   type="java.lang.String"/&gt; <br>    &lt;/form-bean&gt; <br>   <br>  &lt;/form-beans&gt; <br><br> &lt;global-forwards <br> type="org.apache.struts.<br> action.ActionForward"&gt; <br>     &lt;forward   name="welcome"                <br>	 path="/welcome.do"/&gt; <br>     &lt;forward   name="searchEntry"            <br>	 path="/searchEntry.do"/&gt; <br>     &lt;forward   name="searchSubmit"           <br>	 path="/searchSubmit.do"/&gt; <br> &lt;/global-forwards&gt; <br><br> &lt;action-mappings&gt; <br>    &lt;action    path="/welcome" <br>	forward="/WEB-INF/pages/welcome.htm"/&gt; <br>    &lt;action    path="/searchEntry" <br>	forward="/WEB-INF/pages/search.jsp"/&gt; <br>    &lt;action    path="/searchSubmit"  <br>   type="ca.nexcel.books.actions.SearchSubmit" <br>    input="/searchEntry.do" <br>    validate="true" <br>    name="searchForm"&gt; <br>    &lt;forward name="success" <br>	path="/WEB-INF/pages/detail.jsp"/&gt; <br>    &lt;forward name="failure" <br>	path="/WEB-INF/pages/search.jsp"/&gt; <br>    &lt;/action&gt;   <br><br> &lt;/action-mappings&gt; <br><br> &lt;message-resources <br> parameter="ApplicationResources"/&gt; <br><br> &lt;controller <br> processorClass="org.springframework.web.struts. <br>   DelegatingRequestProcessor"/&gt; |(1) <br><br> &lt;plug-in <br> className="org.apache.struts.<br> validator.ValidatorPlugIn"&gt; <br>    &lt;set-property <br>	property="pathnames"  <br>      value="/WEB-INF/validator-rules.xml,<br>	  /WEB-INF/validation.xml"/&gt; <br> &lt;/plug-in&gt; <br><br><br> &lt;plug-in className="org.springframework.<br> web.struts.ContextLoaderPlugIn"&gt; <br>    &lt;set-property <br>	property="csntextConfigLocation" <br>	value="/WEB-INF/beans.xml"/&gt; <br> &lt;/plug-in&gt; <br>  <br>&lt;/struts-config&gt;</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>我利用了 <controller> 标记来用 DelegatingRequestProcessor 覆盖默认的 Struts RequestProcessor。下一步是在我的 Spring 配置文件中注册该动作，如清单 3 所示：
<br><br>清单 3. 在 Spring 配置文件中注册一个动作
<br><br></controller></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>&lt;?xml version="1.0" <br>encoding="UTF-8"?&gt; <br>&lt;!DOCTYPE beans PUBLIC "<br>-//SPRING//DTD BEAN//EN"  <br>  "http://www.springframework.org<br>  /dtd/spring-beans.dtd"&gt; <br><br>&lt;beans&gt; <br>  &lt;bean id="bookService"<br>  class="ca.nexcel.books.<br>  business.BookServiceImpl"/&gt; <br><br>  &lt;bean name="/searchSubmit"  <br>    class="ca.nexcel.books.<br>	actions.SearchSubmit"&gt; |(1) <br>     &lt;property name="bookService"&gt; <br>        &lt;ref bean="bookService"/&gt; <br>     &lt;/property&gt; <br>  &lt;/bean&gt; <br>&lt;/beans&gt;</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>注意：在 (1) 处，我使用名称属性注册了一个 bean，以匹配 struts-config 动作映射名称。SearchSubmit 动作揭示了一个 JavaBean 属性，允许 Spring 在运行时填充属性，如清单 4 所示：
<br><br>清单 4. 具有 JavaBean 属性的 Struts 动作
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>package ca.nexcel.books.actions; <br><br>import java.io.IOException; <br><br>import javax.servlet.ServletException; <br>import javax.servlet.http.HttpServletRequest; <br>import javax.servlet.http.HttpServletResponse; <br><br>import org.apache.struts.action.Action; <br>import org.apache.struts.action.ActionError; <br>import org.apache.struts.action.ActionErrors; <br>import org.apache.struts.action.ActionForm; <br>import org.apache.struts.action.ActionForward; <br>import org.apache.struts.action.ActionMapping; <br>import org.apache.struts.action.DynaActionForm; <br><br>import ca.nexcel.books.beans.Book; <br>import ca.nexcel.books.business.BookService; <br><br>public class SearchSubmit extends Action<br>{ <br>     <br>  private BookService bookService; <br>  public BookService getBookService()<br>  { <br>    return bookService; <br>  } <br><br>  public void setBookService<br>  (BookService bookService) { | (1) <br>    this.bookService = bookService;  <br>  }  <br><br>  public ActionForward execute( <br>    ActionMapping mapping, <br>    ActionForm form, <br>    HttpServletRequest request, <br>    HttpServletResponse response) <br>    throws IOException, ServletException<br>	{ <br><br>    DynaActionForm searchForm =<br>	(DynaActionForm) form; <br>    String isbn = (String) <br>	searchForm.get("isbn"); <br>         <br>  Book book = getBookService().<br>  read(isbn.trim());  |(2) <br><br>    if (null == book) { <br>      ActionErrors errors = new ActionErrors(); <br>      errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound")); <br>      saveErrors(request, errors); <br>      return mapping.findForward("failure") ; <br>  } <br><br>      request.setAttribute("book", book); <br>      return mapping.findForward("success"); <br>  } <br><br>}</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>              
              <p align="center"><font size="2"><br><span class="content01"></span><span class="content01"></span></font>
              
              
		
		</p><font size="2">在清单 4 中，您可以了解到如何创建 Struts 动作。在 (1) 处，我创建了一个 JavaBean
属性。DelegatingRequestProcessor自动地配置这种属性。这种设计使 Struts 动作并不知道它正被 Spring
管理，并且使您能够利用 Sping 的动作管理框架的所有优点。由于您的 Struts 动作注意不到 Spring 的存在，所以您不需要重写您的
Struts 代码就可以使用其他控制反转容器来替换掉 Spring。
<br><br>DelegatingRequestProcessor 方法的确比第一种方法好，但是仍然存在一些问题。如果您使用一个不同的
RequestProcessor，则需要手动整合 Spring 的
DelegatingRequestProcessor。添加的代码会造成维护的麻烦并且将来会降低您的应用程序的灵活性。此外，还有过一些使用一系列命
令来代替 Struts RequestProcessor 的传闻。 这种改变将会对这种解决方法的使用寿命造成负面的影响。
<br><br>窍门 3. 将动作管理委托给 Spring
<br><br>一个更好的解决方法是将 Strut 动作管理委托给 Spring。您可以通过在 struts-config
动作映射中注册一个代理来实现。代理负责在 Spring 环境中查找 Struts 动作。由于动作在 Spring
的控制之下，所以它可以填充动作的 JavaBean 属性，并为应用诸如 Spring 的 AOP 拦截器之类的特性带来了可能。 <br><br>清单 5 中的 Action 类与清单 4 中的相同。但是 struts-config 有一些不同：
<br><br>清单 5. Spring 整合的委托方法
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt; <br><br>&lt;!DOCTYPE <br>struts-config PUBLIC <br>          "-//Apache Software Foundation<br>		  //DTD Struts Configuration 1.1//EN" <br>          "http://jakarta.apache.org<br>		  /struts/dtds/struts-config_1_1.dtd"&gt; <br><br>&lt;struts-config&gt; <br> &lt;form-beans&gt; <br>    &lt;form-bean name="searchForm"  <br>      type="org.apache.struts.<br>	  validator.DynaValidatorForm"&gt; <br>               &lt;form-property name="isbn"    <br>			   type="java.lang.String"/&gt; <br>    &lt;/form-bean&gt; <br>   <br>  &lt;/form-beans&gt; <br><br> &lt;global-forwards <br> type="org.apache.struts.<br> action.ActionForward"&gt; <br>     &lt;forward   name="welcome"                <br>	 path="/welcome.do"/&gt; <br>     &lt;forward   name="searchEntry"            <br>	 path="/searchEntry.do"/&gt; <br>     &lt;forward   name="searchSubmit"           <br>	 path="/searchSubmit.do"/&gt; <br> &lt;/global-forwards&gt; <br><br> &lt;action-mappings&gt; <br>    &lt;action    path="/welcome" <br>	forward="/WEB-INF/pages/welcome.htm"/&gt; <br>    &lt;action    path="/searchEntry" <br>	forward="/WEB-INF/pages/search.jsp"/&gt; <br>    &lt;action    path="/searchSubmit"  <br>             type="org.springframework.<br>			 web.struts.DelegatingActionProxy" |(1) <br>             input="/searchEntry.do" <br>             validate="true" <br>             name="searchForm"&gt; <br>             &lt;forward name="success" <br>			 path="/WEB-INF/pages/detail.jsp"/&gt; <br>             &lt;forward name="failure" <br>			 path="/WEB-INF/pages/search.jsp"/&gt; <br>    &lt;/action&gt;   <br><br> &lt;/action-mappings&gt; <br><br> &lt;message-resources <br> parameter="ApplicationResources"/&gt; <br><br><br> &lt;plug-in className="org.apache.struts.<br> validator.ValidatorPlugIn"&gt; <br>    &lt;set-property  <br>    property="pathnames"  <br>    value="/WEB-INF/validator-rules.xml,<br>	/WEB-INF/validation.xml"/&gt; <br> &lt;/plug-in&gt; <br><br><br> &lt;plug-in  <br>    className="org.springframework.web.<br>	struts.ContextLoaderPlugIn"&gt; <br>    &lt;set-property <br>	property="contextConfigLocation" <br>	value="/WEB-INF/beans.xml"/&gt; <br> &lt;/plug-in&gt; <br><br>  <br>&lt;/struts-config&gt;</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>清单 5 是一个典型的 struts-config.xml 文件，只有一个小小的差别。它注册 Spring
代理类的名称，而不是声明动作的类名，如（1）处所示。DelegatingActionProxy 类使用动作映射名称查找 Spring
环境中的动作。这就是我们使用 ContextLoaderPlugIn 声明的环境。
<br><br>将一个 Struts 动作注册为一个 Spring bean 是非常直观的，如清单 6 所示。我利用动作映射使用 <bean> 标记的名称属性（在这个例子中是 "/searchSubmit"）简单地创建了一个 bean。这个动作的 JavaBean 属性像任何 Spring bean 一样被填充： 
<br><br>清单 6. 在 Spring 环境中注册一个 Struts 动作
<br><br></bean></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br>&lt;!DOCTYPE beans PUBLIC "<br>-//SPRING//DTD BEAN//EN"  <br> "http://www.springframework.<br> org/dtd/spring-beans.dtd"&gt; <br><br>&lt;beans&gt; <br>  &lt;bean id="bookService" <br>  class="ca.nexcel.books.<br>  business.BookServiceImpl"/&gt; <br><br>  &lt;bean name="/searchSubmit"    <br>        class="ca.nexcel.books.<br>		actions.SearchSubmit"&gt; <br>     &lt;property name="bookService"&gt; <br>        &lt;ref bean="bookService"/&gt; <br>     &lt;/property&gt; <br>  &lt;/bean&gt; <br><br>&lt;/beans&gt;</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>              
              <font size="2"><br><br><br>
              动作委托的优点
<br><br>动作委托解决方法是这三种方法中最好的。Struts动作不了解Spring，不对代码作任何改
<br><br>变就可用于非Spring应用程序中。RequestProcessor的改变不会影响它，并且它可以利用 Spring AOP 特性的优点。 
<br><br>动作委托的优点不止如此。一旦让 Spring 控制您的 Struts 动作，您就可以使用 Spring 给动作补充更强的活力。例如，没有 Spring 的话，所有的 Struts 动作都必须是线程安全的。
<br><br>如果您设置 <bean> 标记的 singleton 属性为“false”，那么不管用何种方法，您的应用程序都将在每一个请求上有一个新生成的动作对象。
<br><br>您可能不需要这种特性，但是把它放在您的工具箱中也很好。您也可以利用 Spring 的生命周期方法。例如，当实例化 Struts 动作时，<bean> 标记的 init-method 属性被用于运行一个方法。
<br><br>类似地，在从容器中删除 bean 之前，destroy-method 属性执行一个方法。这些方法是管理昂贵对象的好办法，它们以一种与 Servlet 生命周期相同的方式进行管理。
<br><br>拦截 Struts
<br><br>前面提到过，通过将 Struts 动作委托给 Spring 框架而整合 Struts 和 Spring
的一个主要的优点是：您可以将 Spring 的 AOP 拦截器应用于您的 Struts 动作。通过将 Spring 拦截器应用于 Struts
动作，您可以用最小的代价处理横切关注点。
<br><br>虽然 Spring 提供很多内置拦截器，但是我将向您展示如何创建自己的拦截器并把它应用于一个 Struts 动作。为了使用拦截器，您需要做三件事：
<br><br>创建拦截器。
<br><br>注册拦截器。
<br><br>声明在何处拦截代码。
<br><br>这看起来非常简单的几句话却非常强大。例如，在清单 7 中，我为 Struts 动作创建了一个日志记录拦截器。 这个拦截器在每个方法调用之前打印一句话：
<br><br>清单 7. 一个简单的日志记录拦截器
<br><br></bean></bean></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>package ca.nexcel.books.interceptors; <br><br>import org.springframework.<br>aop.MethodBeforeAdvice; <br><br>import java.lang.reflect.Method; <br><br>public class LoggingInterceptor <br>implements MethodBeforeAdvice <br>{ <br><br>   public void before(Method method, <br>   Object[] objects, Object o)<br>   throws Throwable <br>   { <br>    System.out.println("logging before!"); <br>    } <br>}</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>
<font size="2"><br><br>这个拦截器非常简单。before()方法在拦截点中每个方法之前运行。在本例中，它打印出
<br><br>一句话，其实它可以做您想做的任何事。下一步就是在Spring配置文件中注册这个拦截器
<br><br>，如清单 8 所示：
<br><br>清单 8. 在 Spring 配置文件中注册拦截器
<br><br></font><center><font size="2"><ccid_nobr>
</ccid_nobr></font><table bordercolorlight="black" bordercolordark="#FFFFFF" align="center" border="1" cellpadding="2" cellspacing="0" width="400">
<tbody><tr>
    <td class="code" style="font-size: 9pt;" bgcolor="#e6e6e6">
    <pre><font size="2"><ccid_code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br>&lt;!DOCTYPE beans PUBLIC "-/<br>/SPRING//DTD BEAN//EN"  <br>"http://www.springframework.<br>org/dtd/spring-beans.dtd"&gt; <br><br>&lt;beans&gt; <br>  &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt; <br><br>  &lt;bean name="/searchSubmit"  <br>        class="ca.nexcel.books.actions.SearchSubmit"&gt; <br>     &lt;property name="bookService"&gt; <br>        &lt;ref bean="bookService"/&gt; <br>     &lt;/property&gt; <br>  &lt;/bean&gt; <br><br>  &lt;!--  Interceptors --&gt;  <br>  &lt;bean name="logger"     <br>    class="ca.nexcel.books.interceptors.<br>	LoggingInterceptor"/&gt; |(1) <br><br>  &lt;!-- AutoProxies --&gt; <br>  &lt;bean name="loggingAutoProxy"  <br>        class="org.springframework.aop.<br>		framework.autoproxy. <br>          BeanNameAutoProxyCreator"&gt; |(2) <br>    &lt;property name="beanNames"&gt; <br>          &lt;value&gt;/searchSubmit&lt;/valuesgt; |(3) <br>    &lt;/property&gt; <br>    &lt;property name="interceptorNames"&gt; <br>        &lt;list&gt; <br>          &lt;value&gt;logger&lt;/value&gt; |(4) <br>        &lt;/list&gt; <br>    &lt;/property&gt; <br>   &lt;/bean&gt; <br><br>&lt;/beans&gt;</ccid_code></font></pre> 
   </td>
  </tr>
</tbody></table>
</center>              
              <p align="center"><font size="2"><br></font></p><font size="2">您可能已经注意到了，清单8扩展了清单6中所示的应用程序以包含一个拦截器。具体细节如下：在(1)处，我注册了这个拦截器。(2)处，我创建了一个
bean名称自动代理，它描述如何应用拦截器。还有其他的方法定义拦截点，但是这种方法常见而简便。
<br><br>在 (3) 处，我将 Struts 动作注册为将被拦截的 bean。如果您想要拦截其他的 Struts 动作，则只需要在 "beanNames" 下面创建附加的  标记。
<br><br>在 (4) 处，当拦截发生时，我执行了在 (1) 处创建的拦截器 bean 的名称。这里列出的所有拦截器都应用于“beanNames”。
<br><br>就是这样。就像这个例子所展示的，将您的 Struts 动作置于 Spring 框架的控制之下，为处理您的 Struts 应用程序提供了一系列全新的选择。在本例中，使用动作委托可以轻松地利用 Spring 拦截器提高 Struts 应用程序中的日志记录能力。
<br><br>结束语
<br><br>在本文中，您已经学习了将 Struts 动作整合到 Spring 框架中的三种窍门。使用 Spring 的
ActionSupport 来整合 Struts（第一种窍门中就是这样做的）简单而快捷，但是会将 Struts 动作与 Spring
框架耦合在一起。
<br><br>如果您需要将应用程序移植到一个不同的框架，则需要重写代码。第二种解决方法通过委托 RequestProcessor
巧妙地解开代码的耦合，但是它的可扩展性不强，并且当 Struts 的 RequestProcessor
变成一系列命令时，这种方法就持续不了很长时间。
<br><br>第三种方法是这三种方法中最好的：将 Struts 动作委托给 Spring 框架可以使代码解耦，从而使您可以在您的 Struts 应用程序中利用 Spring 的特性（比如日志记录拦截器）。
<br><br>三种 Struts-Spring 整合窍门中的每一种都被实现成一个完整可用的应用程序。请参阅 下载 部分仔细研究它们。
<br><br>下载
<br><br><a href="http://tech.ccidnet.com/java/j-sr2-requestprocessor.zip">ActionSupport sample code</a>
<br><br><a href="http://tech.ccidnet.com/java/j-sr2-delegate.zip">RequestProcessor sample code</a>
<br><br><a href="http://tech.ccidnet.com/java/j-sr2-actionsupport.zip">Delegate sample code</a>
<br><br></font><img src ="http://www.blogjava.net/hellotony/aggbug/20575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hellotony/" target="_blank">Tony</a> 2005-11-19 16:14 <a href="http://www.blogjava.net/hellotony/articles/20575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>