﻿<?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-CONAN ZONE-文章分类-Spring</title><link>http://www.blogjava.net/conans/category/32512.html</link><description>你越挣扎我就越兴奋</description><language>zh-cn</language><lastBuildDate>Sat, 17 Apr 2010 11:08:29 GMT</lastBuildDate><pubDate>Sat, 17 Apr 2010 11:08:29 GMT</pubDate><ttl>60</ttl><item><title>Spring Security 3应用的11个步骤</title><link>http://www.blogjava.net/conans/articles/318053.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Mon, 12 Apr 2010 05:36:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/318053.html</guid><description><![CDATA[<ol>
    <li>
    <strong>Spring Security</strong><br />
    11个步骤为应用程序添加安全防护<br />
    </li>
    <li>
    <strong>历史与现状</strong><br />
    自2003年出现的Spring扩展插件Acegi Security发展而来。<br />
    目前最新版本为3.x，已成为Spring的一部分。<br />
    为J2EE企业应用程序提供可靠的安全性服务。<br />
    </li>
    <li>
    <strong>Authentication vs. Authorization</strong><br />
    区分概念验证与授权<br />
    验证<br />
    这个用户是谁？<br />
    用户身份可靠吗？<br />
    授权<br />
    某用户A是否可以访问资源R<br />
    某用户A是否可以执行M操作<br />
    某用户A是否可以对资源R执行M操作<br />
    </li>
    <li>
    <strong>SS中的验证特点</strong><br />
    支持多种验证方式<br />
    支持多种加密格式<br />
    支持组件的扩展和替换<br />
    可以本地化输出信息<br />
    </li>
    <li>
    <strong>SS中的授权特点</strong><br />
    支持多种仲裁方式<br />
    支持组件的扩展和替换<br />
    支持对页面访问、方法访问、对象访问的授权。<br />
    </li>
    <li>
    <strong>SS核心安全实现</strong><br />
    Web安全<br />
    通过配置Servlet Filter激活SS中的过滤器链<br />
    实现Session一致性验证<br />
    实现免登陆验证（Remember-Me验证）<br />
    提供一系列标签库进行页面元素的安全控制<br />
    方法安全<br />
    通过AOP模式实现安全代理<br />
    Web安全与方法安全均可以使用表达式语言定义访问规则<br />
    </li>
    <li>
    <strong>配置SS</strong><br />
    配置Web.xml，应用安全过滤器<br />
    配置Spring，验证与授权部分<br />
    在web页面中获取用户身份<br />
    在web页面中应用安全标签库<br />
    实现方法级安全<br />
    </li>
    <li>
    <strong>1：配置web.xml</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Cfilter%3E%0A%3Cfilter-name%3EspringSecurityFilterChain%3C%2Ffilter-name%3E%0A%3Cfilter-class%3Eorg.springframework.web.filter.DelegatingFilterProxy%3C%2Ffilter-class%3E%0A%3C%2Ffilter%3E%0A%3Cfilter-mapping%3E%0A%3Cfilter-name%3EspringSecurityFilterChain%3C%2Ffilter-name%3E%0A%3Curl-pattern%3E%2F*%3C%2Furl-pattern%3E%0A%3C%2Ffilter-mapping%3E%0A%3Ccontext-param%3E%0A%3Cparam-name%3EcontextConfigLocation%3C%2Fparam-name%3E%0A%3Cparam-value%3Eclasspath%3Aspring.xml%3C%2Fparam-value%3E%0A%3C%2Fcontext-param%3E%0A%3Clistener%3E%0A%3Clistener-class%3E%0Aorg.springframework.web.context.ContextLoaderListener%0A%3C%2Flistener-class%3E%0A%3C%2Flistener%3E%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>&lt;filter&gt;&nbsp;&nbsp;</li>
        <li>&lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;&nbsp;&nbsp;</li>
        <li>&lt;filter-class&gt;org.springframework.web.filter.DelegatingFilterProxy&lt;/filter-class&gt;&nbsp;&nbsp;</li>
        <li>&lt;/filter&gt;&nbsp;&nbsp;</li>
        <li>&lt;filter-mapping&gt;&nbsp;&nbsp;</li>
        <li>&lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;&nbsp;&nbsp;</li>
        <li>&lt;url-pattern&gt;/*&lt;/url-pattern&gt;&nbsp;&nbsp;</li>
        <li>&lt;/filter-mapping&gt;&nbsp;&nbsp;</li>
        <li>&lt;context-param&gt;&nbsp;&nbsp;</li>
        <li>&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;&nbsp;&nbsp;</li>
        <li>&lt;param-value&gt;classpath:spring.xml&lt;/param-value&gt;&nbsp;&nbsp;</li>
        <li>&lt;/context-param&gt;&nbsp;&nbsp;</li>
        <li>&lt;listener&gt;&nbsp;&nbsp;</li>
        <li>&lt;listener-class&gt;&nbsp;&nbsp;</li>
        <li>org.springframework.web.context.ContextLoaderListener&nbsp;&nbsp;</li>
        <li>&lt;/listener-class&gt;&nbsp;&nbsp;</li>
        <li>&lt;/listener&gt;&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">&lt;filter&gt;
    &lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;
    &lt;filter-class&gt;org.springframework.web.filter.DelegatingFilterProxy&lt;/filter-class&gt;
    &lt;/filter&gt;
    &lt;filter-mapping&gt;
    &lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;
    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
    &lt;/filter-mapping&gt;
    &lt;context-param&gt;
    &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
    &lt;param-value&gt;classpath:spring.xml&lt;/param-value&gt;
    &lt;/context-param&gt;
    &lt;listener&gt;
    &lt;listener-class&gt;
    org.springframework.web.context.ContextLoaderListener
    &lt;/listener-class&gt;
    &lt;/listener&gt;
    </pre>
    &nbsp;</li>
    <li>
    <strong>2：Spring配置文件中设置命名空间</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3Cbeans%3Abeansxmlns%3D%22http%3A%2F%2Fwww.springframework.org%2Fschema%2Fsecurity%22%0Axmlns%3Abeans%3D%22http%3A%2F%2Fwww.springframework.org%2Fschema%2Fbeans%22%20xmlns%3Axsi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%22%0Axsi%3AschemaLocation%3D%22http%3A%2F%2Fwww.springframework.org%2Fschema%2Fbeans%0Ahttp%3A%2F%2Fwww.springframework.org%2Fschema%2Fbeans%2Fspring-beans-3.0.xsd%0Ahttp%3A%2F%2Fwww.springframework.org%2Fschema%2Fsecurity%0Ahttp%3A%2F%2Fwww.springframework.org%2Fschema%2Fsecurity%2Fspring-security-3.0.xsd%22%3E%0A%3C%2Fbeans%3Abeans%3E%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"?&gt;&nbsp;&nbsp;</li>
        <li>&lt;beans:beansxmlns="http://www.springframework.org/schema/security"&nbsp;&nbsp;</li>
        <li>xmlns:beans="http://www.springframework.org/schema/beans"&nbsp;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&nbsp;&nbsp;</li>
        <li>xsi:schemaLocation="http://www.springframework.org/schema/beans&nbsp;&nbsp;</li>
        <li>http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&nbsp;&nbsp;</li>
        <li>http://www.springframework.org/schema/security&nbsp;&nbsp;</li>
        <li>http://www.springframework.org/schema/security/spring-security-3.0.xsd"&gt;&nbsp;&nbsp;</li>
        <li>&lt;/beans:beans&gt;&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
    &lt;beans:beansxmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.0.xsd"&gt;
    &lt;/beans:beans&gt;
    </pre>
    <strong>&nbsp;</strong>
    </li>
    <li>
    <strong>3：配置最基本的验证与授权</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Chttp%20auto-config%3D%22true%22%3E%0A%3Cintercept-url%20pattern%3D%22%2F**%22%20access%3D%22ROLE_USER%22%20%2F%3E%0A%3C%2Fhttp%3E%0A%3Cauthentication-manager%3E%0A%3Cauthentication-provider%3E%0A%3Cuser-service%3E%0A%3Cuser%20name%3D%22tom%22%20password%3D%22123%22%20authorities%3D%22ROLE_USER%2C%20ROLE_A%22%20%2F%3E%0A%3Cuser%20name%3D%22jerry%22%20password%3D%22123%22%20authorities%3D%22ROLE_USER%2C%20ROLE_B%22%20%2F%3E%0A%3C%2Fuser-service%3E%0A%3C%2Fauthentication-provider%3E%0A%3C%2Fauthentication-manager%3E%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>&lt;http&nbsp;auto-config="true"&gt;&nbsp;&nbsp;</li>
        <li>&lt;intercept-url&nbsp;pattern="/**"&nbsp;access="ROLE_USER"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;/http&gt;&nbsp;&nbsp;</li>
        <li>&lt;authentication-manager&gt;&nbsp;&nbsp;</li>
        <li>&lt;authentication-provider&gt;&nbsp;&nbsp;</li>
        <li>&lt;user-service&gt;&nbsp;&nbsp;</li>
        <li>&lt;user&nbsp;name="tom"&nbsp;password="123"&nbsp;authorities="ROLE_USER,&nbsp;ROLE_A"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;user&nbsp;name="jerry"&nbsp;password="123"&nbsp;authorities="ROLE_USER,&nbsp;ROLE_B"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;/user-service&gt;&nbsp;&nbsp;</li>
        <li>&lt;/authentication-provider&gt;&nbsp;&nbsp;</li>
        <li>&lt;/authentication-manager&gt;&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">&lt;http auto-config="true"&gt;
    &lt;intercept-url pattern="/**" access="ROLE_USER" /&gt;
    &lt;/http&gt;
    &lt;authentication-manager&gt;
    &lt;authentication-provider&gt;
    &lt;user-service&gt;
    &lt;user name="tom" password="123" authorities="ROLE_USER, ROLE_A" /&gt;
    &lt;user name="jerry" password="123" authorities="ROLE_USER, ROLE_B" /&gt;
    &lt;/user-service&gt;
    &lt;/authentication-provider&gt;
    &lt;/authentication-manager&gt;
    </pre>
    &nbsp;</li>
    <li>
    <strong>4：通过数据库验证用户身份</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Cauthentication-manager%3E%0A%3Cauthentication-provider%3E%0A%3Cpassword-encoder%20hash%3D%E2%80%9Cmd5%E2%80%9D%2F%3E%0A%3Cjdbc-user-service%20data-source-ref%3D%22dataSource%22%2F%3E%0A%3C%2Fauthentication-provider%3E%0A%3C%2Fauthentication-manager%3E%0A%E6%95%B0%E6%8D%AE%E8%A1%A8%E7%BB%93%E6%9E%84%E8%A7%81SS%E8%AF%B4%E6%98%8E%E6%89%8B%E5%86%8C%E9%99%84%E5%BD%95A%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>&lt;authentication-manager&gt;&nbsp;&nbsp;</li>
        <li>&lt;authentication-provider&gt;&nbsp;&nbsp;</li>
        <li>&lt;password-encoder&nbsp;hash=&#8220;md5&#8221;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;jdbc-user-service&nbsp;data-source-ref="dataSource"/&gt;&nbsp;&nbsp;</li>
        <li>&lt;/authentication-provider&gt;&nbsp;&nbsp;</li>
        <li>&lt;/authentication-manager&gt;&nbsp;&nbsp;</li>
        <li>数据表结构见SS说明手册附录A&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">&lt;authentication-manager&gt;
    &lt;authentication-provider&gt;
    &lt;password-encoder hash=&#8220;md5&#8221;/&gt;
    &lt;jdbc-user-service data-source-ref="dataSource"/&gt;
    &lt;/authentication-provider&gt;
    &lt;/authentication-manager&gt;
    数据表结构见SS说明手册附录A
    </pre>
    &nbsp;</li>
    <li>
    <strong>5：完善web页面验证规则</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Chttp%20auto-config%3D%22true%22%3E%0A%3Cintercept-url%20pattern%3D%22%2Fjs%2F**%22%20filters%3D%22none%22%2F%3E%0A%3Cintercept-url%20pattern%3D%22%2Fcss%2F**%22%20filters%3D%22none%22%2F%3E%0A%3Cintercept-url%20pattern%3D%22%2Fimages%2F**%22%20filters%3D%22none%22%2F%3E%0A%3Cintercept-url%20pattern%3D%22%2Fa.jsp%22%20access%3D%22ROLE_A%22%20%2F%3E%0A%3Cintercept-url%20pattern%3D%22%2Fb.jsp%22%20access%3D%22ROLE_B%22%20%2F%3E%0A%3Cintercept-url%20pattern%3D%22%2Fc.jsp%22%20access%3D%22ROLE_A%2C%20ROLE_B%22%20%2F%3E%0A%3Cintercept-url%20pattern%3D%22%2F**%22%20access%3D%22ROLE_USER%22%20%2F%3E%0A%3C%2Fhttp%3E%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>&lt;http&nbsp;auto-config="true"&gt;&nbsp;&nbsp;</li>
        <li>&lt;intercept-url&nbsp;pattern="/js/**"&nbsp;filters="none"/&gt;&nbsp;&nbsp;</li>
        <li>&lt;intercept-url&nbsp;pattern="/css/**"&nbsp;filters="none"/&gt;&nbsp;&nbsp;</li>
        <li>&lt;intercept-url&nbsp;pattern="/images/**"&nbsp;filters="none"/&gt;&nbsp;&nbsp;</li>
        <li>&lt;intercept-url&nbsp;pattern="/a.jsp"&nbsp;access="ROLE_A"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;intercept-url&nbsp;pattern="/b.jsp"&nbsp;access="ROLE_B"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;intercept-url&nbsp;pattern="/c.jsp"&nbsp;access="ROLE_A,&nbsp;ROLE_B"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;intercept-url&nbsp;pattern="/**"&nbsp;access="ROLE_USER"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;/http&gt;&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">&lt;http auto-config="true"&gt;
    &lt;intercept-url pattern="/js/**" filters="none"/&gt;
    &lt;intercept-url pattern="/css/**" filters="none"/&gt;
    &lt;intercept-url pattern="/images/**" filters="none"/&gt;
    &lt;intercept-url pattern="/a.jsp" access="ROLE_A" /&gt;
    &lt;intercept-url pattern="/b.jsp" access="ROLE_B" /&gt;
    &lt;intercept-url pattern="/c.jsp" access="ROLE_A, ROLE_B" /&gt;
    &lt;intercept-url pattern="/**" access="ROLE_USER" /&gt;
    &lt;/http&gt;
    </pre>
    &nbsp;</li>
    <li>
    <strong>6：自定义验证配置</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Chttp%20auto-config%3D%22true%22%3E%0A%3C!--%20%E6%8C%87%E5%AE%9A%E7%99%BB%E9%99%86%E9%A1%B5%E9%9D%A2%E3%80%81%E6%88%90%E5%8A%9F%E9%A1%B5%E9%9D%A2%E3%80%81%E5%A4%B1%E8%B4%A5%E9%A1%B5%E9%9D%A2--%3E%0A%3Cform-login%20login-page%3D%22%2Flogin.jsp%22%20default-target-url%3D%22%2Findex.jsp%22%20authentication-failure-url%3D%22%2Flogin.jsp%22%20%2F%3E%0A%3C!--%20%E5%B0%9D%E8%AF%95%E8%AE%BF%E9%97%AE%E6%B2%A1%E6%9C%89%E6%9D%83%E9%99%90%E7%9A%84%E9%A1%B5%E9%9D%A2%E6%97%B6%E8%B7%B3%E8%BD%AC%E7%9A%84%E9%A1%B5%E9%9D%A2%20--%3E%0A%3Caccess-denied-handler%20error-page%3D%22%2FaccessDenied.jsp%22%2F%3E%0A%3C!--%20%E4%BD%BF%E7%94%A8%E8%AE%B0%E4%BD%8F%E7%94%A8%E6%88%B7%E5%90%8D%E3%80%81%E5%AF%86%E7%A0%81%E5%8A%9F%E8%83%BD%EF%BC%8C%E6%8C%87%E5%AE%9A%E6%95%B0%E6%8D%AE%E6%BA%90%E5%92%8C%E5%8A%A0%E5%AF%86%E7%9A%84key%20--%3E%0A%3Cremember-me%20data-source-ref%3D%22dataSource%22%20%2F%3E%0A%3C!--%20logout%E9%A1%B5%E9%9D%A2%EF%BC%8Clogout%E5%90%8E%E6%B8%85%E9%99%A4session%20--%3E%0A%3Clogout%20invalidate-session%3D%22true%22%20logout-success-url%3D%22%2Flogin.jsp%22%20%2F%3E%0A%3C!--%20session%20%E5%A4%B1%E6%95%88%E5%90%8E%E8%B7%B3%E8%BD%AC%E7%9A%84%E9%A1%B5%E9%9D%A2%EF%BC%8C%E6%9C%80%E5%A4%A7%E7%99%BB%E9%99%86%E6%AC%A1%E6%95%B0%20--%3E%0A%3Csession-management%20invalid-session-url%3D%22%2FsessionTimeout.htm%22%3E%0A%3Cconcurrency-control%20max-sessions%3D%221%22%20expired-url%3D%22%2FsessionTimeout.htm%22%20%2F%3E%0A%3C%2Fsession-management%3E%0A%3C%2Fhttp%3E%0A%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8SS%E8%87%AA%E5%B8%A6%E7%9A%84%E7%99%BB%E9%99%86%E9%A1%B5%E9%9D%A2%E4%BD%9C%E4%B8%BAlogin.jsp%E7%9A%84%E6%A8%A1%E6%9D%BF%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>&lt;http&nbsp;auto-config="true"&gt;&nbsp;&nbsp;</li>
        <li>&lt;!--&nbsp;指定登陆页面、成功页面、失败页面--&gt;&nbsp;&nbsp;</li>
        <li>&lt;form-login&nbsp;login-page="/login.jsp"&nbsp;default-target-url="/index.jsp"&nbsp;authentication-failure-url="/login.jsp"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;!--&nbsp;尝试访问没有权限的页面时跳转的页面&nbsp;--&gt;&nbsp;&nbsp;</li>
        <li>&lt;access-denied-handler&nbsp;error-page="/accessDenied.jsp"/&gt;&nbsp;&nbsp;</li>
        <li>&lt;!--&nbsp;使用记住用户名、密码功能，指定数据源和加密的key&nbsp;--&gt;&nbsp;&nbsp;</li>
        <li>&lt;remember-me&nbsp;data-source-ref="dataSource"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;!--&nbsp;logout页面，logout后清除session&nbsp;--&gt;&nbsp;&nbsp;</li>
        <li>&lt;logout&nbsp;invalidate-session="true"&nbsp;logout-success-url="/login.jsp"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;!--&nbsp;session&nbsp;失效后跳转的页面，最大登陆次数&nbsp;--&gt;&nbsp;&nbsp;</li>
        <li>&lt;session-management&nbsp;invalid-session-url="/sessionTimeout.htm"&gt;&nbsp;&nbsp;</li>
        <li>&lt;concurrency-control&nbsp;max-sessions="1"&nbsp;expired-url="/sessionTimeout.htm"&nbsp;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;/session-management&gt;&nbsp;&nbsp;</li>
        <li>&lt;/http&gt;&nbsp;&nbsp;</li>
        <li>可以使用SS自带的登陆页面作为login.jsp的模板&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">&lt;http auto-config="true"&gt;
    &lt;!-- 指定登陆页面、成功页面、失败页面--&gt;
    &lt;form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp" /&gt;
    &lt;!-- 尝试访问没有权限的页面时跳转的页面 --&gt;
    &lt;access-denied-handler error-page="/accessDenied.jsp"/&gt;
    &lt;!-- 使用记住用户名、密码功能，指定数据源和加密的key --&gt;
    &lt;remember-me data-source-ref="dataSource" /&gt;
    &lt;!-- logout页面，logout后清除session --&gt;
    &lt;logout invalidate-session="true" logout-success-url="/login.jsp" /&gt;
    &lt;!-- session 失效后跳转的页面，最大登陆次数 --&gt;
    &lt;session-management invalid-session-url="/sessionTimeout.htm"&gt;
    &lt;concurrency-control max-sessions="1" expired-url="/sessionTimeout.htm" /&gt;
    &lt;/session-management&gt;
    &lt;/http&gt;
    可以使用SS自带的登陆页面作为login.jsp的模板
    </pre>
    </li>
    <li>
    <strong>7：本地化消息输出</strong><br />
    拷贝本地化资源文件后，在配置文件中加载该文件：<br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3C!--%20%E5%8A%A0%E8%BD%BD%E9%94%99%E8%AF%AF%E4%BF%A1%E6%81%AF%E8%B5%84%E6%BA%90%E6%96%87%E4%BB%B6%20--%3E%0A%3Cbeans%3Abean%20id%3D%22messageSource%22%20%0Aclass%3D%22org.springframework.context.support.ReloadableResourceBundleMessageSource%22%3E%0A%3Cbeans%3Aproperty%20name%3D%22basename%22%20value%3D%22classpath%3Amessages%22%2F%3E%0A%3C%2Fbeans%3Abean%3E%0A%E8%B5%84%E6%BA%90%E6%96%87%E4%BB%B6%E5%9C%A8SS%E6%A0%B8%E5%BF%83%E5%8C%85%EF%BC%9Aspring-security-core-3.0.2.RELEASE.jar%E7%9A%84orgspringframeworksecurity%E7%9B%AE%E5%BD%95%E4%B8%AD%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>&lt;!--&nbsp;加载错误信息资源文件&nbsp;--&gt;&nbsp;&nbsp;</li>
        <li>&lt;beans:bean&nbsp;id="messageSource"&nbsp;&nbsp;&nbsp;</li>
        <li>class="org.springframework.context.support.ReloadableResourceBundleMessageSource"&gt;&nbsp;&nbsp;</li>
        <li>&lt;beans:property&nbsp;name="basename"&nbsp;value="classpath:messages"/&gt;&nbsp;&nbsp;</li>
        <li>&lt;/beans:bean&gt;&nbsp;&nbsp;</li>
        <li>资源文件在SS核心包：spring-security-core-3.0.2.RELEASE.jar的orgspringframeworksecurity目录中&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">&lt;!-- 加载错误信息资源文件 --&gt;
    &lt;beans:bean id="messageSource"
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource"&gt;
    &lt;beans:property name="basename" value="classpath:messages"/&gt;
    &lt;/beans:bean&gt;
    资源文件在SS核心包：spring-security-core-3.0.2.RELEASE.jar的orgspringframeworksecurity目录中
    </pre>
    &nbsp;</li>
    <li>
    <strong>8：在web页面中获取用户信息</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%E6%96%B9%E5%BC%8F%E4%B8%80%EF%BC%9AJava%E4%BB%A3%E7%A0%81%0AAuthentication%20auth%20%3D%20SecurityContextHolder.getContext().getAuthentication()%3B%0ACollection%3CGrantedAuthority%3E%20col%20%3D%20auth.getAuthorities()%3B%0A%E6%96%B9%E5%BC%8F%E4%BA%8C%EF%BC%9A%E6%A0%87%E7%AD%BE%E5%BA%93%0A%3C%25%40%20taglib%20prefix%3D%22sec%22%20uri%3D%22http%3A%2F%2Fwww.springframework.org%2Fsecurity%2Ftags%22%20%25%3E%0A%3Csec%3Aauthentication%20property%3D%22name%E2%80%9C%2F%3E%0A%3Csec%3Aauthentication%20property%3D%22authorities%E2%80%9C%2F%3E%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>方式一：Java代码&nbsp;&nbsp;</li>
        <li>Authentication&nbsp;auth&nbsp;=&nbsp;SecurityContextHolder.getContext().getAuthentication();&nbsp;&nbsp;</li>
        <li>Collection&lt;GrantedAuthority&gt;&nbsp;col&nbsp;=&nbsp;auth.getAuthorities();&nbsp;&nbsp;</li>
        <li>方式二：标签库&nbsp;&nbsp;</li>
        <li>&lt;%@&nbsp;taglib&nbsp;prefix="sec"&nbsp;uri="http://www.springframework.org/security/tags"&nbsp;%&gt;&nbsp;&nbsp;</li>
        <li>&lt;sec:authentication&nbsp;property="name&#8220;/&gt;&nbsp;&nbsp;</li>
        <li>&lt;sec:authentication&nbsp;property="authorities&#8220;/&gt;&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">方式一：Java代码
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    Collection&lt;GrantedAuthority&gt; col = auth.getAuthorities();
    方式二：标签库
    &lt;%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %&gt;
    &lt;sec:authentication property="name&#8220;/&gt;
    &lt;sec:authentication property="authorities&#8220;/&gt;
    </pre>
    &nbsp;</li>
    <li>
    <strong>9：在web页面进行元素安全控制</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%E6%96%B9%E5%BC%8F%E4%B8%80%0A%3Csec%3AauthorizeifAnyGranted%3D%22ROLE_A%22%3E%0A%3Ca%20href%3D%22a.jsp%22%3E%E4%BD%A0%E5%8F%AF%E4%BB%A5%E8%AE%BF%E9%97%AEa.jsp%3C%2Fa%3E%0A%3C%2Fsec%3Aauthorize%3E%0A%3Csec%3AauthorizeifNotGranted%3D%22ROLE_A%22%3E%0A%E4%BD%A0%E4%B8%8D%E5%8F%AF%E4%BB%A5%E8%AE%BF%E9%97%AEa.jsp%0A%3C%2Fsec%3Aauthorize%3E%0A%E6%96%B9%E5%BC%8F%E4%BA%8C%0A%3Csec%3Aauthorizeurl%3D%22%2Fa.jsp%22%3E%0A%3Ca%20href%3D%22a.jsp%22%3E%E4%BD%A0%E5%8F%AF%E4%BB%A5%E8%AE%BF%E9%97%AEa.jsp%3C%2Fa%3E%0A%3C%2Fsec%3Aauthorize%3E%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>方式一&nbsp;&nbsp;</li>
        <li>&lt;sec:authorizeifAnyGranted="ROLE_A"&gt;&nbsp;&nbsp;</li>
        <li>&lt;a&nbsp;href="a.jsp"&gt;你可以访问a.jsp&lt;/a&gt;&nbsp;&nbsp;</li>
        <li>&lt;/sec:authorize&gt;&nbsp;&nbsp;</li>
        <li>&lt;sec:authorizeifNotGranted="ROLE_A"&gt;&nbsp;&nbsp;</li>
        <li>你不可以访问a.jsp&nbsp;&nbsp;</li>
        <li>&lt;/sec:authorize&gt;&nbsp;&nbsp;</li>
        <li>方式二&nbsp;&nbsp;</li>
        <li>&lt;sec:authorizeurl="/a.jsp"&gt;&nbsp;&nbsp;</li>
        <li>&lt;a&nbsp;href="a.jsp"&gt;你可以访问a.jsp&lt;/a&gt;&nbsp;&nbsp;</li>
        <li>&lt;/sec:authorize&gt;&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">方式一
    &lt;sec:authorizeifAnyGranted="ROLE_A"&gt;
    &lt;a href="a.jsp"&gt;你可以访问a.jsp&lt;/a&gt;
    &lt;/sec:authorize&gt;
    &lt;sec:authorizeifNotGranted="ROLE_A"&gt;
    你不可以访问a.jsp
    &lt;/sec:authorize&gt;
    方式二
    &lt;sec:authorizeurl="/a.jsp"&gt;
    &lt;a href="a.jsp"&gt;你可以访问a.jsp&lt;/a&gt;
    &lt;/sec:authorize&gt;
    </pre>
    &nbsp;</li>
    <li>
    <strong>10：全局方法安全控制</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Cglobal-method-security%20pre-post-annotations%3D%22enabled%22%3E%0A%3Cprotect-pointcut%20expression%3D%22execution(*%20com.xasxt.*Service.add*(..))%22%20access%3D%22ROLE_A%22%2F%3E%0A%3Cprotect-pointcut%20expression%3D%22execution(*%20com.xasxt.*Service.delete*(..))%22%20access%3D%22ROLE_B%22%2F%3E%0A%3C%2Fglobal-method-security%3E%0A%E6%AD%A4%E5%A4%84%E4%BD%BF%E7%94%A8%E4%BA%86AspectJ%E4%B8%AD%E5%B8%B8%E7%94%A8%E7%9A%84%E5%88%87%E5%85%A5%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%88%E7%99%BE%E5%BA%A6%EF%BC%9AAspectJ%20execution%EF%BC%89%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>&lt;global-method-security&nbsp;pre-post-annotations="enabled"&gt;&nbsp;&nbsp;</li>
        <li>&lt;protect-pointcut&nbsp;expression="execution(*&nbsp;com.xasxt.*Service.add*(..))"&nbsp;access="ROLE_A"/&gt;&nbsp;&nbsp;</li>
        <li>&lt;protect-pointcut&nbsp;expression="execution(*&nbsp;com.xasxt.*Service.delete*(..))"&nbsp;access="ROLE_B"/&gt;&nbsp;&nbsp;</li>
        <li>&lt;/global-method-security&gt;&nbsp;&nbsp;</li>
        <li>此处使用了AspectJ中常用的切入点表达式（百度：AspectJ&nbsp;execution）&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">&lt;global-method-security pre-post-annotations="enabled"&gt;
    &lt;protect-pointcut expression="execution(* com.xasxt.*Service.add*(..))" access="ROLE_A"/&gt;
    &lt;protect-pointcut expression="execution(* com.xasxt.*Service.delete*(..))" access="ROLE_B"/&gt;
    &lt;/global-method-security&gt;
    此处使用了AspectJ中常用的切入点表达式（百度：AspectJ execution）
    </pre>
    &nbsp;</li>
    <li>
    <strong>11：使用注解进行方法安全控制</strong><br />
    <div>
    <div>
    <div>Java代码 <embed src="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20class%20DemoService%20%7B%0A%40PreAuthorize(%22hasRole(%26apos%3BROLE_A%26apos%3B)%22)%0Apublic%20void%20methodA()%20%7B%0A%7D%0A%40PreAuthorize(%22hasAnyRole(%26apos%3BROLE_A%2C%20ROLE_B%26apos%3B)%22)%0Apublic%20void%20methodB()%20%7B%0A%7D%0A%7D%0AhasRole%E4%B8%8EhasAnyRole%E4%B8%BASS%E9%80%9A%E7%94%A8%E5%86%85%E7%BD%AE%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%88google%20%3A%20spring%20security%20Common%20Built-In%20Expressions%EF%BC%89%0A" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="15" width="14"></div>
    </div>
    <ol start="1">
        <li>public&nbsp;class&nbsp;DemoService&nbsp;{&nbsp;&nbsp;</li>
        <li>@PreAuthorize("hasRole(&amp;apos;ROLE_A&amp;apos;)")&nbsp;&nbsp;</li>
        <li>public&nbsp;void&nbsp;methodA()&nbsp;{&nbsp;&nbsp;</li>
        <li>}&nbsp;&nbsp;</li>
        <li>@PreAuthorize("hasAnyRole(&amp;apos;ROLE_A,&nbsp;ROLE_B&amp;apos;)")&nbsp;&nbsp;</li>
        <li>public&nbsp;void&nbsp;methodB()&nbsp;{&nbsp;&nbsp;</li>
        <li>}&nbsp;&nbsp;</li>
        <li>}&nbsp;&nbsp;</li>
        <li>hasRole与hasAnyRole为SS通用内置表达式（google&nbsp;:&nbsp;spring&nbsp;security&nbsp;Common&nbsp;Built-In&nbsp;Expressions）&nbsp;&nbsp;</li>
    </ol>
    </div>
    <pre style="display: none;" name="code" class="java">public class DemoService {
    @PreAuthorize("hasRole(&amp;apos;ROLE_A&amp;apos;)")
    public void methodA() {
    }
    @PreAuthorize("hasAnyRole(&amp;apos;ROLE_A, ROLE_B&amp;apos;)")
    public void methodB() {
    }
    }
    hasRole与hasAnyRole为SS通用内置表达式（google : spring security Common Built-In Expressions）
    </pre>
    &nbsp;</li>
    <li>
    <strong>12：下一步做什么？？？</strong><br />
    采用更安全的验证方式<br />
    采用安全的数据传输方式<br />
    实现动态授权<br />
    自定义验证与授权部件<br />
    实现数据级安全</li>
</ol>
<img src ="http://www.blogjava.net/conans/aggbug/318053.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2010-04-12 13:36 <a href="http://www.blogjava.net/conans/articles/318053.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再析在spring框架中解决多数据源的问题</title><link>http://www.blogjava.net/conans/articles/285674.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Mon, 06 Jul 2009 05:45:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/285674.html</guid><description><![CDATA[<span>在前面我写了《<a linkindex="29" href="http://www.javaeye.com/blog/72486">如何在</a></span><span><a>spring</a></span><span><a>框架中解决多数据源的问题</a>》，通过设计模式中的</span><span>Decorator</span><span>模式在</span><span>spring</span><span>框架中解决多数据源的问题，得到了许多网友的关注。在与网友探讨该问题的过程中，我发现我的方案并不完善，它只解决了一部分问题。</span>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span>总结多数据源的问题，其实它需要分为以下三种情况：各个数据源的数据结构不同、各个数据源的数据结构相同、各个数据源的数据结构部分相同又有部分不同。对于第二种情况，各个数据源的数据结构相同，我们使用一个</span><span>sessionFactory</span><span>，而在</span><span>sessionFactory</span><span>中通过</span><span>MultiDataSource</span><span>来动态切换数据源，应当是一个不错的方案，既解决了多个</span><span>sessionFactory</span><span>对相同的值对象重复装载对内存的浪费，又使数据源的切换对客户程序透明，简化了代码的实现和对客户程序的影响。但是，对于第一种情况，各个数据源的数据结构不同，运用这样的方案存在潜在风险。</span></p>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span>对于各个数据源的数据结构不同的情况，使用一个</span><span>sessionFactory</span><span>而在这个</span><span>sessionFactory</span><span>中动态切换数据源，可能造成数据访问的张冠李戴。譬如，数据源</span><span>A</span><span>有表</span><span>T</span><span>而数据源</span><span>B</span><span>没有，可能造成客户程序在访问表</span><span>T</span><span>的时候却尝试去连接数据源</span><span>B</span><span>，
因为客户程序访问哪个数据源是在程序运行期间由客户程序决定的，因此这样的错误是很难发现的。也许客户程序的一个不经意的错误就可能造成错误。解决这个问
题的方法有两个：一是严格要求客户程序不要写错，这当然是可以做到的，但作为框架设计者，另一个解决方法是在框架中就避免出现这样的情况。因此我祭出了</span><span>MultiSessionFactory</span><span>的方案来解决各个数据源的数据结构不同的多数据源问题。</span></p>
<h2><span>问题的分析</span></h2>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span>与</span><span>MultiDataSource</span><span>的方案一样，</span><span>MultiSessionFactory</span><span>同样是在</span><span>spring</span><span>框架下调用</span><span>ApplicationContext</span><span>的</span><span>getBean()</span><span>方法而不会另外创建</span><span>beanFacoty</span><span>，也同样使用</span><span>Decorator</span><span>模式来处理切换的问题。</span><span>MultiSessionFactory</span><span>的对象关系如图：</span></p>
<p class="MsoNormal" style="text-indent: 26.25pt;"></p>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span><img src="http://www.javaeye.com/upload/picture/pic/3974/10f6052e-a238-46fd-b6d3-b62321b2c51d.jpg" alt="" height="387" width="563" /></span></p>
<span>在该方案中，</span><span>SessionFactory</span><span>就是</span><span>Hibernate</span><span>的</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">org.hibernate.SessionFactory</span><span>接口，</span><span>Decorator</span><span>就是</span><span>MultiSessionFactory</span><span>，</span><span>SessionFactory1</span><span>和</span><span>SessionFactory2</span><span>往往是</span><span>spring</span><span>的</span><span style="font-size: 10pt; font-family: 'Courier New';">org.springframework.orm.hibernate3.LocalSessionFactoryBean</span><span>。细心的朋友可能会注意，实际上</span><span style="font-size: 10pt; font-family: 'Courier New';">LocalSessionFactoryBean</span><span>并不是</span><span>SessionFactory</span><span>的实现，这个方案是否有问题呢？这个问题其实也一直困扰了我好久，最后我发现，我们通过</span><span>ApplicationContext</span><span>的</span><span>getBean()</span><span>得到一个</span><span style="font-size: 10pt; font-family: 'Courier New';">LocalSessionFactoryBean</span><span>的时候其实并不是真正地得到了它，而是得到了一个</span><span>SessionFactory</span><span>，因为</span><span>spring</span><span>为</span><span style="font-size: 10pt; font-family: 'Courier New';">LocalSessionFactoryBean</span><span>重写了</span><span>getObject()</span><span>，使其返回的是</span><span>SessionFactory</span><span>。一个简单的明证就是，</span><span>HibernateDaoSupport</span><span>的</span><span>sessionFactory</span><span>属性的类型是</span><span>SessionFactory</span><span>，而我们在</span><span>spring</span><span>配置的时候注入的却是</span><span style="font-size: 10pt; font-family: 'Courier New';">LocalSessionFactoryBean</span><span>。</span><span style="font-size: 10pt; font-family: 'Courier New';">
<h2><span>方案的实现</span></h2>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span>在整个这个方案中，我们需要实现的只有</span><span>MultiSessionFactory</span><span>类和我们可爱的</span><span>Spserver</span><span>，总共就两个类，然后呢就是一些</span><span>spring</span><span>的配置，就完成了。</span></p>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span>MultiSessionFactory</span><span>实现了</span><span>SessionFactory</span><span>，同时为了得到</span><span>AplicationContext</span><span>而实现了</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">ApplicationContextAware</span><span>。</span><span>MultiSessionFactory</span><span>的代码如下：</span></p>
<div class="code_title">java 代码</div>
<span>
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;MultiSessionFactory&nbsp;</span><span class="keyword">implements</span><span>&nbsp;SessionFactory,&nbsp;ApplicationContextAware&nbsp;{ &nbsp;&nbsp;</span></span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">long</span><span>&nbsp;serialVersionUID&nbsp;=&nbsp;2064557324203496378L; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;Log&nbsp;log&nbsp;=&nbsp;LogFactory.getLog(MultiSessionFactory.</span><span class="keyword">class</span><span>); &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;ApplicationContext&nbsp;applicationContext&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;SessionFactory&nbsp;sessionFactory&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;ApplicationContext&nbsp;getApplicationContext()&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;applicationContext; &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setApplicationContext(ApplicationContext&nbsp;applicationContext)&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.applicationContext&nbsp;=&nbsp;applicationContext; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;SessionFactory&nbsp;getSessionFactory(String&nbsp;sessionFactoryName)&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.debug(</span><span class="string">"sessionFactoryName:"</span><span>+sessionFactoryName); &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>(sessionFactoryName==</span><span class="keyword">null</span><span>||sessionFactoryName.equals(</span><span class="string">""</span><span>)){ &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;sessionFactory; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;(SessionFactory)</span><span class="keyword">this</span><span>.getApplicationContext().getBean(sessionFactoryName); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span class="keyword">catch</span><span>(NoSuchBeanDefinitionException&nbsp;ex){ &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;DaoException(</span><span class="string">"There&nbsp;is&nbsp;not&nbsp;the&nbsp;sessionFactory&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;SessionFactory&nbsp;getSessionFactory()&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sessionFactoryName&nbsp;=&nbsp;SpObserver.getSp(); &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;getSessionFactory(sessionFactoryName); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setSessionFactory(SessionFactory&nbsp;sessionFactory)&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.sessionFactory&nbsp;=&nbsp;sessionFactory; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;SessionFactory接口需要实现的方法 </span><span>&nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>...... &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p class="MsoNormal" style="text-indent: 26.25pt;">MultiSessionFactory<span>的完整代码见我提供的附件。</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">setSessionFactory()</span><span>实际上是设定的默认</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">sessionFactory</span><span>，它在</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">spring</span><span>装载的时候调用，其对应的数据源应当是主数据源，即项目初始化中需要读取初始化数据的数据源。在任何多数据源项目中，都应当有一个存放初始化数据、系统维护数据、用户权限数据的数据源，这就是主数据源。因此</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">MultiSessionFactory</span><span>的配置应当这样写：</span></p>
<span>
<div class="code_title">xml 代码</div>
</span><span>
<div class="dp-highlighter">
<ol class="dp-xml">
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"sessionFactory"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.htxx.service.dao.MultiSessionFactory"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"sessionFactory"</span><span class="tag">&gt;</span><span class="tag">&lt;</span><span class="tag-name">ref</span><span>&nbsp;</span><span class="attribute">bean</span><span>=</span><span class="attribute-value">"hostSessionFactory"</span><span class="tag">/&gt;<span class="tag"><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;</span></span> </span></li>
    <li class="alt"><span class="tag"><span class="tag-name"><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span> </span></li>
</ol>
</div>
<p class="MsoNormal" style="text-indent: 26.25pt;">SpServer<span>的写法与<a linkindex="30" href="http://www.javaeye.com/blog/72486">《如何在</a></span><span style="font-size: 10.5pt; font-family: 'Times New Roman';"><a>spring</a></span><span><a>框架中解决多数据源的问题》</a>中的一样，我就不再累赘了。</span></p>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span>另外，在</span><span>spring</span><span>配置中配置多个数据源，每个数据源对应一个</span><span>sessionFactory</span><span>，这个对应的</span><span>sessionFactory</span><span>中的值对象应当是该数据源的值对象。客户程序在执行数据访问前，通过调用</span><span>SpServer</span><span>的</span><span>putSp()</span><span>方法，告诉</span><span>MultiSessionFactory</span><span>需要切换到哪个</span><span>sessionFactory</span><span>，然后执行数据访问。这样，不同数据源的值对象通过放在不同的</span><span>sessionFactory</span><span>中，避免了张冠李戴的情况。具体的示例见附件的</span><span>MultiSessionFactoryTest</span><span>。</span></p>
<h2><span>另外的方案</span></h2>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span>也许有些朋友对以上方案还不满意，因为在执行数据访问前毕竟还要多做一步指定</span><span>sessionFactory</span><span>的工作。实际上，对于各个数据源的数据结构不同的项目，一个值对象应当使用哪个数据源有一个非常确定的对应关系。如果通过配置文件将值对象与它的</span><span>sessionFactory</span><span>对应起来，那么我们在执行数据访问的时候传递的是哪个值对象，</span><span>MultiSessionFactory</span><span>马上就可以去找到对应的</span><span>sessionFactory</span><span>。这个方案你可以通过</span><span>AOP</span><span>来制作一个拦截器拦截所有诸如</span><span>save()</span><span>、</span><span>delete()</span><span>、</span><span>get()</span><span>、</span><span>load()</span><span>等方法来实现，也可以扩展</span><span>HibernateDaoSupport</span><span>来实现。这样的方案使客户程序甚至都不用知道他是在操作的一个多数据源系统。当然，这个方案感兴趣的朋友可以自己去实现。</span></p>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span>另外，在这个方案中的核心是运用</span><span>Decorator</span><span>设计模式来解决切换</span><span>sessionFactory</span><span>的目的，即</span><span>MultiSessionFactory</span><span>的实现。至于通过什么方式来通知</span><span>MultiSessionFactory</span><span>应当切换到哪个</span><span>SessionFactory</span><span>，可以根据不同项目的情况自由选择。我在这里给大家提供了通过</span><span>SpOberver</span><span>和建立值对象与</span><span>sessionFactory</span><span>关系的配置文件这两个方案，你也可以有自己的方案解决。</span></p>
<h2><span>第三种情况的解决方案</span></h2>
<p class="MsoNormal" style="text-indent: 26.25pt;"><span>前面我已经给出了第一种和第二种情况的解决方案：各个数据源的数据结构不同的情况用</span><span>MultiSessionFactory</span><span>解决；各个数据源的数据结构相同的情况用</span><span>MultiDataSource</span><span>解决。那么第三种情况，各个数据源的数据结构部分相同又有部分不同，又应当如何解决呢？当然是将</span><span>MultiSessionFactory</span><span>和</span><span>MultiDataSource</span><span>结合起来解决。对于数据结构不同的部分，其分别创建各自的</span><span>sessionFactory</span><span>然后通过</span><span>MultiSessionFactory</span><span>来切换，而对于数据结构相同的部分，建立共同的</span><span>sessionFactory</span><span>和多个不同的</span><span>dataSource</span><span>然后通过</span><span>MultiDataSource</span><span>来切换就可以了。</span></p>
<span>还有的朋友问到这样的方案其事务处理和二级缓存的情况。这个方案是在</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">spring</span><span>框架下的解决方案，其事务处理的能力也是由</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">spring</span><span>的能力来决定的。目前</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">spring</span><span>要处理跨数据库的事务处理是通过</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">JTA</span><span>来实现的，这种方式在该方案中同样可以实现，朋友们可以试一试。另外，本方案能使用二级缓存吗？当然可以。对于</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">MultiSessionFactory</span><span>当然没有任何问题，它通过不同的</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">sessionFactory</span><span>分离开了不同的数据源和值对象，我们可以毫无顾忌地使用。对于</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">MultiDataSource</span><span>来说，就有点问题了。</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">MultiDataSource</span><span>使多个数据源使用共同的</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">sessionFactory</span><span>，因此它仿佛就是将多个数据源在逻辑上合并为一个数据源。正因为如此，我们需要保证对于同一个表在所有数据源中都要主键唯一。什么意思呢？数据源</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">A</span><span>和数据源</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">B</span><span>都有表</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">T</span><span>，如果数据源</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">A</span><span>中的表</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">T</span><span>拥有</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">ID</span><span>为</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">001</span><span>的一条数据，那么在数据源</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">B</span><span>的表</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">T</span><span>中就不能有</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">ID</span><span>为</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">001</span><span>的记录。如果你总是通过</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">MultiDataSource</span><span>来执行表的插入操作，并且使用uuid.hex生成主键，这当然不会有问题。但如果你有通过其它方式插入表的操作，你应当保证这样的唯一性。另外，对于查询的操作，缓存中存放的既可能是数据源</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">A</span><span>的数据，也可能是数据源</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">B</span><span>的数据，因此你应当对数据有一个规划。对于表</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">T</span><span>的数据，哪些应当插入到数据源</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">A</span><span>中，哪些应当插入到</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">B</span><span>中，应当有一个定义。假如是通过不同单位来决定插入哪个数据源，那么在查询数据源</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">A</span><span>的表</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">T</span><span>是，应当增加条件只查询数据源</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">A</span><span>应当有的单位而排除调其它单位。如此这样，你只要注意到这两个问题，你就可以放心大胆地使用二级缓存。</span></span></span></span>
<img src ="http://www.blogjava.net/conans/aggbug/285674.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-07-06 13:45 <a href="http://www.blogjava.net/conans/articles/285674.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何在spring框架中解决多数据源的问题</title><link>http://www.blogjava.net/conans/articles/285673.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Mon, 06 Jul 2009 05:43:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/285673.html</guid><description><![CDATA[<p class="MsoNormal" style="text-indent: 17.95pt;"><span><span>在我们的项目中遇到这样一个问题：我们的项目需要连接多个数据库，而且不同的客户在每次访问中根据需要会去访问不同的数据库。我们以往在</span><span>spring</span><span>和</span><span>hibernate</span><span>框架中总是配置一个数据源，因而</span><span>sessionFactory</span><span>的</span><span>dataSource</span><span>属性总是指向这个数据源并且恒定不变，所有</span><span>DAO</span><span>在使用</span><span>sessionFactory</span><span>的时候都是通过这个数据源访问数据库。但是现在，由于项目的需要，我们的</span><span>DAO</span><span>在访问</span><span>sessionFactory</span><span>的时候都不得不在多个数据源中不断切换，问题就出现了：如何让</span><span>sessionFactory</span><span>在执行数据持久化的时候，根据客户的需求能够动态切换不同的数据源？我们能不能在</span><span>spring</span><span>的框架下通过少量修改得到解决？是否有什么设计模式可以利用呢？</span></span>&nbsp;&nbsp; </p>
<h2><span>问题的分析</span></h2>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>我首先想到在</span><span>spring</span><span>的</span><span>applicationContext</span><span>中配置所有的</span><span>dataSource</span><span>。这些</span><span>dataSource</span><span>可能是各种不同类型的，比如不同的数据库：</span><span>Oracle</span><span>、</span><span>SQL Server</span><span>、</span><span>MySQL</span><span>等，也可能是不同的数据源：比如</span><span>apache </span><span>提供的</span><span>org.apache.commons.dbcp.BasicDataSource</span><span>、</span><span>spring</span><span>提供的</span><span>org.springframework.jndi.JndiObjectFactoryBean</span><span>等。然后</span><span>sessionFactory</span><span>根据客户的每次请求，将</span><span>dataSource</span><span>属性设置成不同的数据源，以到达切换数据源的目的。</span></p>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>但是，我很快发现一个问题：当多用户同时并发访问数据库的时候会出现资源争用的问题。这都是&#8220;单例模式&#8221;惹的祸。众所周知，我们在使用</span><span>spring</span><span>框架的时候，在</span><span>beanFactory</span><span>中注册的</span><span>bean</span><span>基本上都是采用单例模式，即</span><span>spring</span><span>在启动的时候，这些</span><span>bean</span><span>就装载到内存中，并且每个</span><span>bean</span><span>在整个项目中只存在一个对象。正因为只存在一个对象，对象的所有属性，更准确说是实例变量，表现得就如同是个静态变量（实际上&#8220;静态&#8221;与&#8220;单例&#8221;往往是非常相似的两个东西，我们常常用&#8220;静态&#8221;来实现&#8220;单例&#8221;）。拿我们的问题来说，</span><span>sessionFactory</span><span>在整个项目中只有一个对象，它的实例变量</span><span>dataSource</span><span>也就只有一个，就如同一个静态变量一般。如果不同的用户都不断地去修改</span><span>dataSource</span><span>的值，必然会出现多用户争用一个变量的问题，对系统产生隐患。</span></p>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>通过以上的分析，解决多数据源访问问题的关键，就集中在</span><span>sessionFactory</span><span>在执行数据持久化的时候，能够通过某段代码去根据客户的需要动态切换数据源，并解决资源争用的问题。</span></p>
<h2><span>问题的解决</span></h2>
<h4 style="margin-left: 21pt; text-indent: -21pt;"><span><span>(一)<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>采用</span><span>Decorator</span><span>设计模式</span></h4>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>要解决这个问题，我的思路锁定在了这个</span><span>dataSource</span><span>上了。如果</span><span>sessionFactory</span><span>指向的</span><span>dataSource</span><span>可以根据客户的需求去连接客户所需要的真正的数据源，即提供动态切换数据源的功能，那么问题就解决了。那么我们怎么做呢？去修改那些我们要使用的</span><span>dataSource</span><span>源码吗？这显然不是一个好的方案，我们希望我们的修改与原</span><span>dataSource</span><span>代码是分离的。根据以上的分析，使用</span><span>GoF</span><span>设计模式中的</span><span>Decorator</span><span>模式（装饰者模式）应当是我们可以选择的最佳方案。</span></p>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>什么是&#8220;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">Decorator</span><span>模式&#8221;？简单点儿说就是当我们需要修改原有的功能，但我们又不愿直接去修改原有的代码时，设计一个</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">Decorator</span><span>套在原有代码外面。当我们使用</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">Decorator</span><span>的时候与原类完全一样，当</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">Decorator</span><span>的某些功能却已经修改为了我们需要修改的功能。</span><span style="font-size: 10.5pt; font-family: 'Times New Roman';">Decorator</span><span>模式的结构如图。</span></p>
<p class="MsoNormal" align="center"><span><img src="http://fangang.javaeye.com/upload/picture/pic/3753/0a7ad179-b609-4fb5-ae49-d266f0fb9ee5.jpg" alt="" height="183" width="480" /></span></p>
<p class="MsoNormal"><span><span><span>我们本来需要修改图中所有具体的</span><span>Component</span><span>类的一些功能，但却并不是去直接修改它们的代码，而是在它们的外面增加一个</span><span>Decorator</span><span>。</span><span>Decorator</span><span>与具体的</span><span>Component</span><span>类都是继承的</span><span>AbstractComponent</span><span>，因此它长得和具体的</span><span>Component</span><span>类一样，也就是说我们在使用</span><span>Decorator</span><span>的时候就如同在使用</span><span>ConcreteComponentA</span><span>或者</span><span>ConcreteComponentB</span><span>一样，甚至那些使用</span><span>ConcreteComponentA</span><span>或者</span><span>ConcreteComponentB</span><span>的客户程序都不知道它们用的类已经改为了</span><span>Decorator</span><span>，但是</span><span>Decorator</span><span>已经对具体的</span><span>Component</span><span>类的部分方法进行了修改，执行这些方法的结果已经不同了。</span></span></span></p>
<h4 style="margin-left: 21pt; text-indent: -21pt;"><span><span>(二)<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>设计</span><span>MultiDataSource</span><span>类</span></h4>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>现在回到我们的问题，我们需要对</span><span>dataSource</span><span>的功能进行变更，但又不希望修改</span><span>dataSource</span><span>中的任何代码。我这里指的</span><span>dataSource</span><span>是所有实现</span><span>javax.sql.DataSource</span><span>接口的类，我们常用的包括</span><span>apache </span><span>提供的</span><span>org.apache.commons.dbcp.BasicDataSource</span><span>、</span><span>spring</span><span>提供的</span><span>org.springframework.jndi.JndiObjectFactoryBean</span><span>等，这些类我们不可能修改它们本身，更不可能对它们一个个地修改以实现动态分配数据源的功能，同时，我们又希望使用</span><span>dataSource</span><span>的</span><span>sessionFactory</span><span>根本就感觉不到这样的变化。</span><span>Decorator</span><span>模式就正是解决这个问题的设计模式。</span></p>
<p class="MsoNormal"><span>首先写一个</span><span>Decorator</span><span>类，我取名叫</span><span>MultiDataSource，通过它来动态切换数据源</span><span>。同时在配置文件中将sessionFactory的dataSource属性由原来的某个具体的dataSource改为MultiDataSource。如图：</span></p>
<p class="MsoNormal" align="center"><span><img src="http://fangang.javaeye.com/upload/picture/pic/3751/e853e195-11a9-4836-9e3c-83db72d6ed39.jpg" alt="" height="283" width="480" /></span></p>
<span>对比原<span>Decorator</span><span>模式，</span><span>AbstractComponent</span><span>是一个抽象类，但在这里我们可以将这个抽象类用接口来代替，即</span><span>DataSource</span><span>接口，而</span><span>ConcreteComponent</span><span>就是那些</span><span>DataSource</span><span>的实现类，如</span><span>BasicDataSource</span><span>、</span><span>JndiObjectFactoryBean</span><span>等。</span>MultiDataSource</span><span>封装了具体的dataSource，并实现了数据源动态切换：<br />
</span>
<div class="code_title">java 代码</div>
<span>
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;MultiDataSource&nbsp;</span><span class="keyword">implements</span><span>&nbsp;DataSource&nbsp;{ &nbsp;&nbsp;</span></span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;DataSource&nbsp;dataSource&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span class="keyword">public</span><span>&nbsp;MultiDataSource(DataSource&nbsp;dataSource){ &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.dataSource&nbsp;=&nbsp;dataSource; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/*&nbsp;(non-Javadoc) </span>&nbsp; </li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;javax.sql.DataSource#getConnection() </span>&nbsp;</span> </li>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;Connection&nbsp;getConnection()&nbsp;</span><span class="keyword">throws</span><span>&nbsp;SQLException&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;getDataSource().getConnection(); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//其它DataSource接口应当实现的方法 </span><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;DataSource&nbsp;getDataSource(){ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">this</span><span>.dataSource; &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setDataSource(DataSource&nbsp;dataSource)&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.dataSource&nbsp;=&nbsp;dataSource; &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
<p class="MsoNormal" style="text-indent: 17.95pt;">客户在发出请求的时候，将dataSourceName放到request中，然后把request中的数据源名通过调用new <span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">MultiDataSource(dataSource)</span><span>时可以告诉</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">MultiDataSource</span><span>客户需要的数据源，就可以实现动态切换数据源了。但细心的朋友会发现这在单例的情况下就是问题的，因为</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">MultiDataSource</span><span>在系统中只有一个对象，它的实例变量</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">dataSource</span><span>也只有一个，就如同一个静态变量一般。正因为如此，</span><span>单例模式让许多设计模式都不得不需要更改，这将在我的《&#8220;单例&#8221;更改了我们的设计模式》中详细讨论。那么，我们在单例模式下如何设计呢？</span></p>
<h4 style="margin-left: 21pt; text-indent: -21pt;"><span><span>(三)<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>单例模式下的</span><span>MultiDataSource</span></h4>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>在单例模式下，由于我们在每次调用</span><span>MultiDataSource</span><span>的方法的时候，</span><span>dataSource</span><span>都可能是不同的，所以我们不能将</span><span>dataSource</span><span>放在实例变量</span><span>dataSource</span><span>中，最简单的方式就是在方法</span><span>getDataSource()</span><span>中增加参数，告诉</span><span>MultiDataSource</span><span>我到底调用的是哪个</span><span>dataSource</span><span>：</span></p>
<span>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;DataSource&nbsp;getDataSource(String&nbsp;dataSourceName){ &nbsp;&nbsp;</span></span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.debug(</span><span class="string">"dataSourceName:"</span><span>+dataSourceName); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>(dataSourceName==</span><span class="keyword">null</span><span>||dataSourceName.equals(</span><span class="string">""</span><span>)){ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">this</span><span>.dataSource; &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;(DataSource)</span><span class="keyword">this</span><span>.applicationContext.getBean(dataSourceName); &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span class="keyword">catch</span><span>(NoSuchBeanDefinitionException&nbsp;ex){ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;DaoException(</span><span class="string">"There&nbsp;is&nbsp;not&nbsp;the&nbsp;dataSource&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
</ol>
</div>
<p class="MsoNormal" style="text-indent: 17.95pt;">值得一提的是，我需要的数据源已经都在<span>spring</span><span>的配置文件中注册，</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">dataSourceName</span><span>就是其对应的</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">id</span><span>。</span></p>
<span>
<div class="code_title">xml 代码</div>
<div class="dp-highlighter">
<ol class="dp-xml">
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dataSource1"</span><span>&nbsp;&nbsp;</span></span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.apache.commons.dbcp.BasicDataSource"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"driverClassName"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">value</span><span class="tag">&gt;</span><span>oracle.jdbc.driver.OracleDriver</span><span class="tag"><span class="tag-name">value</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag"><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;</span></span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;...... &nbsp;&nbsp;</span> </li>
    <li class="alt"><span class="tag"><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </span></li>
    <li><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dataSource2"</span><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.apache.commons.dbcp.BasicDataSource"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"driverClassName"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">value</span><span class="tag">&gt;</span><span>oracle.jdbc.driver.OracleDriver</span><span class="tag"><span class="tag-name">value</span><span class="tag">&gt;</span><span>&nbsp;</span></span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag"><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span>&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;...... &nbsp;&nbsp;</span> </li>
    <li><span class="tag"><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span>&nbsp;</span> </li>
</ol>
</div>
<p class="MsoNormal" style="text-indent: 17.95pt;">为了得到<span>spring</span><span>的</span><span>ApplicationContext</span><span>，</span><span>MultiDataSource</span><span>类必须实现接口</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">org.springframework.context.ApplicationContextAware</span><span>，并且实现方法：</span></p>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">private</span><span>&nbsp;ApplicationContext&nbsp;applicationContext&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></span> </li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setApplicationContext(ApplicationContext&nbsp;applicationContext)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;BeansException&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.applicationContext&nbsp;=&nbsp;applicationContext; &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
</ol>
</div>
<p class="MsoNormal" style="text-indent: 17.95pt;">如此这样，我就可以通过<strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">this</span></strong><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">.</span><span style="font-size: 10pt; color: #0000c0; font-family: 'Courier New';">applicationContext</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">.getBean(dataSourceName)</span><span>得到</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">dataSource</span><span>了。</span></p>
<h4 style="margin-left: 21pt; text-indent: -21pt;"><span><span>(四)<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>通过线程传递</span><span>dataSourceName</span></h4>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>查看以上设计，</span><span>MultiDataSource</span><span>依然无法运行，因为用户在发出请求时，他需要连接什么数据库，其数据源名是放在</span><span>request</span><span>中的，要将</span><span>request</span><span>中的数据源名传给</span><span>MultiDataSource</span><span>，需要经过</span><span>BUS</span><span>和</span><span>DAO</span><span>，也就是说为了把数据源名传给</span><span>MultiDataSource</span><span>，</span><span>BUS</span><span>和</span><span>DAO</span><span>的所有方法都要增加</span><span>dataSourceName</span><span>的参数，这是我们不愿看到的。写一个类，通过线程的方式跳过</span><span>BUS</span><span>和</span><span>DAO</span><span>直接传递给</span><span>MultiDataSource</span><span>是一个不错的设计：</span></p>
<p class="MsoNormal" style="text-indent: 17.95pt;" align="center"><span><img src="http://fangang.javaeye.com/upload/picture/pic/3752/58696c8a-fd62-4a7f-b6f1-1973c1ef7954.jpg" alt="" height="146" width="480" /></span></p>
<span>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;SpObserver&nbsp;{ &nbsp;&nbsp;</span></span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;ThreadLocal&nbsp;local&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;ThreadLocal(); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;putSp(String&nbsp;sp)&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local.set(sp); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;String&nbsp;getSp()&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;(String)local.get(); &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
<p class="MsoNormal" style="text-indent: 17.95pt;">做一个<span>filter</span><span>，每次客户发出请求的时候就调用</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">SpObserver.<em>petSp</em>(</span><span>dataSourceName</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">)</span><span>，将</span><span>request</span><span>中的</span><span>dataSourceName</span><span>传递给</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">SpObserver</span><span>对象。</span><span>最后修改</span><span>MultiDataSource</span><span>的方法</span><span>getDataSource()</span><span>：</span></p>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;DataSource&nbsp;getDataSource(){ &nbsp;&nbsp;</span></span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sp&nbsp;=&nbsp;SpObserver.getSp(); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;getDataSource(sp); &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
</ol>
</div>
<p class="MsoNormal" style="text-indent: 17.95pt;">完整的<span>MultiDataSource</span><span>代码在附件中。</span></p>
<h4 style="margin-left: 21pt; text-indent: -21pt;"><span><span>(五)<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>动态添加数据源</span></h4>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>通过以上方案，我们解决了动态分配数据源的问题，但你可能提出疑问：方案中的数据源都是配置在</span><span>spring</span><span>的</span><span>ApplicationContext</span><span>中，如果我在程序运行过程中动态添加数据源怎么办？这确实是一个问题，而且在我们的项目中也确实遇到。</span><span>spring</span><span>的</span><span>ApplicationContext</span><span>是在项目启动的时候加载的。加载以后，我们如何动态地加载新的</span><span>bean</span><span>到</span><span>ApplicationContext</span><span>中呢？我想到如果用</span><span>spring</span><span>自己的方法解决这个问题就好了。所幸的是，在查看</span><span>spring</span><span>的源代码后，我找到了这样的代码，编写了</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">DynamicLoadBean</span><span>类，只要</span><span>调用<span>loadBean()</span><span>方法，就可以将某个或某几个配置文件中的</span><span>bean</span><span>加载到</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">ApplicationContext</span><span>中（见附件）。不通过配置文件直接加载对象，在</span><span style="font-size: 10pt; color: #000000; font-family: 'Courier New';">spring</span><span>的源码中也有，感兴趣的朋友可以自己研究。</span></span></p>
<h4 style="margin-left: 21pt; text-indent: -21pt;"><span><span>(六)<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>在</span><span>spring</span><span>中配置</span></h4>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>在完成了所有这些设计以后，我最后再唠叨一句。我们应当在</span><span>spring</span><span>中做如下配置：</span></p>
<span>
<div class="code_title">xml 代码</div>
<div class="dp-highlighter">
<ol class="dp-xml">
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dynamicLoadBean"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.htxx.service.dao.DynamicLoadBean"</span><span class="tag">&gt;</span><span class="tag"><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span> </span></li>
    <li><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dataSource"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.htxx.service.dao.MultiDataSource"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"dataSource"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">ref</span><span>&nbsp;</span><span class="attribute">bean</span><span>=</span><span class="attribute-value">"dataSource1"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag"><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag"><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"sessionFactory"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.orm.hibernate3.LocalSessionFactoryBean"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"dataSource"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">ref</span><span>&nbsp;</span><span class="attribute">bean</span><span>=</span><span class="attribute-value">"dataSource"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag"><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...... &nbsp;&nbsp;</span> </li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag"><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span> </span></li>
</ol>
</div>
<p class="MsoNormal" style="text-indent: 17.95pt;">其中<span>dataSource</span><span>属性实际上更准确地说应当是</span><span>defaultDataSource</span><span>，即</span><span>spring</span><span>启动时以及在客户没有指定数据源时应当指定的默认数据源。</span> </p>
<h2><span>该方案的优势</span></h2>
<p>&nbsp;</p>
<span>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>以上方案与其它方案相比，它有哪些优势呢？</span></p>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>首先，这个方案完全是在</span><span>spring</span><span>的框架下解决的，数据源依然配置在</span><span>spring</span><span>的配置文件中，</span><span>sessionFactory</span><span>依然去配置它的</span><span>dataSource</span><span>属性，它甚至都不知道</span><span>dataSource</span><span>的改变。唯一不同的是在真正的</span><span>dataSource</span><span>与</span><span>sessionFactory</span><span>之间增加了一个</span><span>MultiDataSource</span><span>。</span></p>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>其次，实现简单，易于维护。这个方案虽然我说了这么多东西，其实都是分析，真正需要我们写的代码就只有</span><span>MultiDataSource</span><span>、</span><span>SpObserver</span><span>两个类。</span><span>MultiDataSource</span><span>类真正要写的只有</span><span>getDataSource()</span><span>和</span><span>getDataSource(sp)</span><span>两个方法，而</span><span>SpObserver</span><span>类更简单了。实现越简单，出错的可能就越小，维护性就越高。</span></p>
<p class="MsoNormal" style="text-indent: 17.95pt;"><span>最后，这个方案可以使单数据源与多数据源兼容。这个方案完全不影响</span><span>BUS</span><span>和</span><span>DAO</span><span>的编写。如果我们的项目在开始之初是单数据源的情况下开发，随着项目的进行，需要变更为多数据源，则只需要修改</span><span>spring</span><span>配置，并少量修改</span><span>MVC</span><span>层以便在请求中写入需要的数据源名，变更就完成了。如果我们的项目希望改回单数据源，则只需要简单修改配置文件。这样，为我们的项目将增加更多的弹性。</span></p>
<p class="MsoNormal" style="text-indent: 17.95pt;"><strong>特别说明：实例中的
DynamicLoadBean在web环境下运行会出错，需要将类中AbstractApplicationContext改为
org.springframework.context.ConfigurableApplicationContext。</strong></p>
</span></span></span></span></span></span><br />
<span><br />
</span>
<img src ="http://www.blogjava.net/conans/aggbug/285673.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-07-06 13:43 <a href="http://www.blogjava.net/conans/articles/285673.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Security 2 配置精讲</title><link>http://www.blogjava.net/conans/articles/253454.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 05 Feb 2009 14:01:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/253454.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 搭建基础环境 首先我们为示例搭建基本的开发环境，环境的搭建方式，可以参考我的另外一篇文章：http://www.javaeye.com/wiki/struts2/1321-struts2-development-environment-to-build 整个环境的搭建包括：创建合适的目录结构、加入了合适的Library，加入了基本的Jetty启动类、加入基本的配置文件等。最终的项目...&nbsp;&nbsp;<a href='http://www.blogjava.net/conans/articles/253454.html'>阅读全文</a><img src ="http://www.blogjava.net/conans/aggbug/253454.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-02-05 22:01 <a href="http://www.blogjava.net/conans/articles/253454.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring,hibernate,struts的面试笔试题（含答案）</title><link>http://www.blogjava.net/conans/articles/249547.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Fri, 02 Jan 2009 07:13:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/249547.html</guid><description><![CDATA[<div class="blog_content">Hibernate工作原理及为什么要用？<br />
原理：<br />
1.读取并解析配置文件<br />
2.读取并解析映射信息，创建SessionFactory<br />
3.打开Sesssion<br />
4.创建事务Transation<br />
5.持久化操作<br />
6.提交事务<br />
7.关闭Session<br />
8.关闭SesstionFactory<br />
<br />
为什么要用：<br />
1. 对JDBC访问数据库的代码做了封装，大大简化了数据访问层繁琐的重复性代码。<br />
<br />
2. Hibernate是一个基于JDBC的主流持久化框架，是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作<br />
<br />
3. hibernate使用Java反射机制，而不是字节码增强程序来实现透明性。<br />
<br />
4. hibernate的性能非常好，因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库，从一对一到多对多的各种复杂关系。<br />
<br />
2． Hibernate是如何延迟加载?<br />
1. Hibernate2延迟加载实现：a)实体对象 b)集合（Collection）<br />
<br />
2. Hibernate3 提供了属性的延迟加载功能<br />
<br />
当Hibernate在查询数据的时候，数据并没有存在与内存中，当程序真正对数据的操作时，对象才存在与内存中，就实现了延迟加载，他节省了服务器的内存开销，从而提高了服务器的性能。<br />
<br />
3．Hibernate中怎样实现类之间的关系?(如：一对多、多对多的关系)<br />
<br />
类与类之间的关系主要体现在表与表之间的关系进行操作，它们都市对对象进行操作，我们程序中把所有的表与类都映射在一起，它们通过配置文件中的many-to-one、one-to-many、many-to-many、<br />
<br />
4． 说下Hibernate的缓存机制<br />
<br />
1. 内部缓存存在Hibernate中又叫一级缓存，属于应用事物级缓存<br />
<br />
2. 二级缓存：<br />
a) 应用及缓存<br />
b) 分布式缓存<br />
条件：数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非 关键数据<br />
c) 第三方缓存的实现<br />
<br />
5． Hibernate的查询方式<br />
Sql、Criteria,object comptosition<br />
Hql：<br />
1、 属性查询<br />
2、 参数查询、命名参数查询<br />
3、 关联查询<br />
4、 分页查询<br />
5、 统计函数<br />
<br />
6． 如何优化Hibernate？<br />
1.使用双向一对多关联，不使用单向一对多<br />
2.灵活使用单向一对多关联<br />
3.不用一对一，用多对一取代<br />
4.配置对象缓存，不使用集合缓存<br />
5.一对多集合使用Bag,多对多集合使用Set<br />
6. 继承类使用显式多态<br />
7. 表字段要少，表关联不要怕多，有二级缓存撑腰<br />
<br />
<br />
7． Struts工作机制？为什么要使用Struts？<br />
工作机制：<br />
Struts的工作流程:<br />
在web应用启动时就会加载初始化ActionServlet,ActionServlet从<br />
struts-config.xml文件中读取配置信息,把它们存放到各种配置对象<br />
当ActionServlet接收到一个客户请求时,将执行如下流程.<br />
-(1)检索和用户请求匹配的ActionMapping实例,如果不存在,就返回请求路径无效信息;<br />
-(2)如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中;<br />
-(3)根据配置信息决定是否需要表单验证.如果需要验证,就调用ActionForm的validate()方法;<br />
-(4)如果ActionForm的validate()方法返回null或返回一个不包含ActionMessage的ActuibErrors对象, 就表示表单验证成功;<br />
-(5)ActionServlet根据ActionMapping所包含的映射信息决定将请求转发给哪个Action,如果相应的 Action实例不存在,就先创建这个实例,然后调用Action的execute()方法;<br />
-(6)Action的execute()方法返回一个ActionForward对象,ActionServlet在把客户请求转发给 ActionForward对象指向的JSP组件;<br />
-(7)ActionForward对象指向JSP组件生成动态网页,返回给客户;<br />
<br />
为什么要用：<br />
JSP、Servlet、JavaBean技术的出现给我们构建强大的企业应用系统提供了可能。但用这些技术构建的系统非常的繁乱，所以在此之上，我们需要一个规则、一个把这些技术组织起来的规则，这就是框架，Struts便应运而生。<br />
<br />
基于Struts开发的应用由3类组件构成：控制器组件、模型组件、视图组件<br />
<br />
8． Struts的validate框架是如何验证的？<br />
在struts配置文件中配置具体的错误提示，再在FormBean中的validate()方法具体调用。<br />
<br />
9． 说下Struts的设计模式<br />
MVC模式: web应用程序启动时就会加载并初始化ActionServler。用户提交表单时，一个配置好的ActionForm对象被创建，并被填入表单相应的数据，ActionServler根据Struts-config.xml文件配置好的设置决定是否需要表单验证，如果需要就调用ActionForm的 Validate（）验证后选择将请求发送到哪个Action，如果Action不存在，ActionServlet会先创建这个对象，然后调用 Action的execute（）方法。Execute（）从ActionForm对象中获取数据，完成业务逻辑，返回一个ActionForward对象，ActionServlet再把客户请求转发给ActionForward对象指定的jsp组件，ActionForward对象指定的jsp生成动态的网页，返回给客户。<br />
<br />
10． spring工作机制及为什么要用?<br />
1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。<br />
2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller.<br />
3.DispatcherServlet请请求提交到目标Controller<br />
4.Controller进行业务逻辑处理后，会返回一个ModelAndView<br />
5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象<br />
6.视图对象负责渲染返回给客户端。<br />
<br />
为什么用：<br />
{AOP 让开发人员可以创建非行为性的关注点，称为横切关注点，并将它们插入到应用程序代码中。使用 AOP 后，公共服务 （比如日志、持久性、事务等）就可以分解成方面并应用到域对象上，同时不会增加域对象的对象模型的复杂性。<br />
IOC 允许创建一个可以构造对象的应用环境，然后向这些对象传递它们的协作对象。正如单词 倒置 所表明的，IOC 就像反 过来的 JNDI。没有使用一堆抽象工厂、服务定位器、单元素（singleton）和直接构造（straight construction），每一个对象都是用其协作对象构造的。因此是由容器管理协作对象（collaborator）。<br />
Spring即使一个AOP框架，也是一IOC容器。 Spring 最好的地方是它有助于您替换对象。有了 Spring，只要用 JavaBean 属性和配置文件加入依赖性（协作对象）。然后可以很容易地在需要时替换具有类似接口的协作对象。}<br />
<br />
<br />
<br />
<br />
Spring 框架是一个分层架构，由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上，核心容器定义了创建、配置和管理 bean 的方式，如图 1 所示。<br />
<br />
组成 Spring 框架的每个模块（或组件）都可以单独存在，或者与其他一个或多个模块联合实现。每个模块的功能如下：<br />
<br />
☆ 核心容器：核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory，它是工厂模式的实现。BeanFactory 使用控制反转 （IOC）模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。<br />
<br />
☆ Spring 上下文：Spring 上下文是一个配置文件，向 Spring 框架提供上下文信息。Spring 上下文包括企业服务，例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。<br />
<br />
☆ Spring AOP：通过配置管理特性，Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以，可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP，不用依赖 EJB 组件，就可以将声明性事务管理集成到应用程序中。<br />
<br />
☆ Spring DAO：JDBC DAO 抽象层提供了有意义的异常层次结构，可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理，并且极大地降低了需要编写的异常代码数量（例如打开和关闭连接）。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。<br />
<br />
☆ Spring ORM：Spring 框架插入了若干个 ORM 框架，从而提供了 ORM 的对象关系工具，其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。<br />
<br />
☆ Spring Web 模块：Web 上下文模块建立在应用程序上下文模块之上，为基于 Web 的应用程序提供了上下文。所以，Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。<br />
<br />
☆ Spring MVC 框架：MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口，MVC 框架变成为高度可配置的，MVC 容纳了大量视图技术，其中包括 JSP、Velocity、Tiles、iText 和 POI。<br />
<br />
Spring 框架的功能可以用在任何 J2EE 服务器中，大多数功能也适用于不受管理的环境。Spring 的核心要点是：支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问，这样的对象可以在不同 J2EE 环境 （Web 或 EJB）、独立应用程序、测试环境之间重用。<br />
<br />
IOC 和 AOP<br />
<br />
控制反转模式（也称作依赖性介入）的基本概念是：不创建对象，但是描述创建它们的方式。在代码中不直接与对象和服务连接，但在配置文件中描述哪一个组件需要哪一项服务。容器（在 Spring 框架中是 IOC 容器） 负责将这些联系在一起。<br />
<br />
在典型的 IOC 场景中，容器创建了所有对象，并设置必要的属性将它们连接在一起，决定什么时间调用方法。下表列出了 IOC 的一个实现模式。<br />
<br />
<br />
<br />
<br />
Spring 框架的 IOC 容器采用类型 2 和类型3 实现。<br />
<br />
<br />
面向方面的编程<br />
<br />
面向方面的编程，即 AOP，是一种编程技术，它允许程序员对横切关注点或横切典型的职责分界线的行为（例如日志和事务管理）进行模块化。AOP 的核心构造是方面，它将那些影响多个类的行为封装到可重用的模块中。<br />
<br />
AOP 和 IOC 是补充性的技术，它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中，可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中，可以反过来将日志服务模块化，并以声明的方式将它们应用到需要日志的组件上。当然，优势就是 Java 类不需要知道日志服务的存在，也不需要考虑相关的代码。所以，用 Spring AOP 编写的应用程序代码是松散耦合的。<br />
<br />
AOP 的功能完全集成到了 Spring 事务管理、日志和其他各种特性的上下文中。<br />
<br />
IOC 容器<br />
<br />
Spring 设计的核心是 org.springframework.beans 包，它的设计目标是与 JavaBean 组件一起使用。这个包通常不是由用户直接使用，而是由服务器将其用作其他多数功能的底层中介。下一个最高级抽象是 BeanFactory 接口，它是工厂设计模式的实现，允许通过名称创建和检索对象。BeanFactory 也可以管理对象之间的关系。<br />
<br />
BeanFactory 支持两个对象模型。<br />
<br />
□ 单态 模型提供了具有特定名称的对象的共享实例，可以在查询时对其进行检索。Singleton 是默认的也是最常用的对象模型。对于无状态服务对象很理想。<br />
<br />
□ 原型 模型确保每次检索都会创建单独的对象。在每个用户都需要自己的对象时，原型模型最适合。<br />
<br />
bean 工厂的概念是 Spring 作为 IOC 容器的基础。IOC 将处理事情的责任从应用程序代码转移到框架。正如我将在下一个示例中演示的那样，Spring 框架使用 JavaBean 属性和配置数据来指出必须设置的依赖关系。<br />
<br />
BeanFactory 接口<br />
<br />
因为 org.springframework.beans.factory.BeanFactory 是一个简单接口，所以可以针对各种底层存储方法实现。最常用的 BeanFactory 定义是 XmlBeanFactory，它根据 XML 文件中的定义装入 bean，如清单 1 所示。<br />
<br />
清单 1. XmlBeanFactory<br />
<br />
BeanFactory factory = new XMLBeanFactory(new FileInputSteam("mybean.xml"));<br />
<br />
在 XML 文件中定义的 Bean 是被消极加载的，这意味在需要 bean 之前，bean 本身不会被初始化。要从 BeanFactory 检索 bean，只需调用 getBean() 方法，传入将要检索的 bean 的名称即可，如清单 2 所示。<br />
<br />
清单 2. getBean()<br />
<br />
MyBean mybean = (MyBean) factory.getBean("mybean");<br />
<br />
每个 bean 的定义都可以是 POJO （用类名和 JavaBean 初始化属性定义） 或 FactoryBean。FactoryBean 接口为使用 Spring 框架构建的应用程序添加了一个间接的级别。<br />
<br />
IOC 示例<br />
<br />
理解控制反转最简单的方式就是看它的实际应用。在对由三部分组成的 Spring 系列 的第 1 部分进行总结时，我使用了一个示例，演示了如何通过 Spring IOC 容器注入应用程序的依赖关系（而不是将它们构建进来）。<br />
<br />
我用开启在线信用帐户的用例作为起点。对于该实现，开启信用帐户要求用户与以下服务进行交互：<br />
<br />
☆ 信用级别评定服务，查询用户的信用历史信息。<br />
<br />
☆ 远程信息链接服务，插入客户信息，将客户信息与信用卡和银行信息连接起来，以进行自动借记（如果需要的话）。<br />
<br />
☆ 电子邮件服务，向用户发送有关信用卡状态的电子邮件。<br />
<br />
三个接口<br />
<br />
对于这个示例，我假设服务已经存在，理想的情况是用松散耦合的方式把它们集成在一起。以下清单显示了三个服务的应用程序接口。<br />
<br />
清单 3. CreditRatingInterface<br />
<br />
public interface CreditRatingInterface {<br />
public boolean getUserCreditHistoryInfo<wbr>rmation(ICustomer iCustomer);<br />
}<br />
<br />
清单 3 所示的信用级别评定接口提供了信用历史信息。它需要一个包含客户信息的 Customer 对象。该接口的实现是由 CreditRating 类提供的。<br />
<br />
清单 4. CreditLinkingInterface<br />
<br />
public interface CreditLinkingInterface {<br />
<br />
public String getUrl();<br />
public void setUrl(String url);<br />
public void linkCreditBankAccount() throws Exception ;<br />
<br />
}<br />
<br />
信用链接接口将信用历史信息与银行信息（如果需要的话）连接在一起，并插入用户的信用卡信息。信用链接接口是一个远程服务，它的查询是通过 getUrl() 方法进行的。URL 由 Spring 框架的 bean 配置机制设置，我稍后会讨论它。该接口的实现是由 CreditLinking 类提供的。<br />
<br />
清单 5. EmailInterface<br />
<br />
public interface EmailInterface {<br />
<br />
public void sendEmail(ICustomer iCustomer);<br />
public String getFromEmail();<br />
public void setFromEmail(String fromEmail) ;<br />
public String getPassword();<br />
public void setPassword(String password) ;<br />
public String getSmtpHost() ;<br />
public void setSmtpHost(String smtpHost);<br />
public String getUserId() ;<br />
public void setUserId(String userId);</div>
<div class="blog_content">转自网络。</div>
<img src ="http://www.blogjava.net/conans/aggbug/249547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-01-02 15:13 <a href="http://www.blogjava.net/conans/articles/249547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring中使用proxool作数据源连接池的配置</title><link>http://www.blogjava.net/conans/articles/232264.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Fri, 03 Oct 2008 14:06:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/232264.html</guid><description><![CDATA[很奇怪，很多人都说proxool很好，<br />
但是搜索spring中配置proxool作 数据源连接池的资料却几乎找不到详细点的。<br />
<br />
因此自己整理如下：<br />
<br />
&nbsp; 先下载:<br />
&nbsp; <br />
&nbsp; http://surfnet.dl.sourceforge.net/sourceforge/proxool/proxool-0.9.0RC2.zip<br />
<br />
<br />
&nbsp; web.xml<br />
<br />
-------------------------<br />
<br />
<br />
&nbsp; &lt;servlet&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;proxoolServletConfigurator&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;org.logicalcobwebs.proxool.configuration.ServletConfigurator&lt;/servlet-class&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;xmlFile&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;WEB-INF/proxool.xml&lt;/param-value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&nbsp; &lt;/servlet&gt;<br />
&nbsp; &lt;servlet&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;proxooladmin&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;org.logicalcobwebs.proxool.admin.servlet.AdminServlet&lt;/servlet-class&gt;<br />
&nbsp; &lt;/servlet&gt;<br />
&nbsp; &lt;servlet-mapping&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;proxooladmin&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/proxooladmin&lt;/url-pattern&gt;<br />
&nbsp; &lt;/servlet-mapping&gt;<br />
<br />
<br />
-------------------------<br />
<br />
&nbsp; proxool.xml<br />
<br />
-------------------------<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;proxool-config&gt;<br />
&nbsp; &lt;proxool&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;alias&gt;blogdb&lt;/alias&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;driver-url&gt;jdbc:oracle:thin:@127.0.0.1:1521:ORADB&lt;/driver-url&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;driver-class&gt;oracle.jdbc.driver.OracleDriver&lt;/driver-class&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;driver-properties&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="user" value="lizongbo"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="password" value="password"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/driver-properties&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;maximum-connection-count&gt;10&lt;/maximum-connection-count&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;house-keeping-test-sql&gt;select 1 from dual&lt;/house-keeping-test-sql&gt;<br />
&nbsp; &lt;/proxool&gt;<br />
&lt;/proxool-config&gt;<br />
<br />
spring里：<br />
两种配置：<br />
a:&nbsp; &lt;!-- 与上面的proxool以及web.xml里结合使用--&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="mainDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="driverClassName"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;value&gt;org.logicalcobwebs.proxool.ProxoolDriver&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="url"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;value&gt;proxool.blogdb&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
<br />
b:&lt;!-- 单独的类似dbcp的使用--&gt;<br />
&nbsp; &lt;bean id="mainDataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource" destroy-method="close"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="driver"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;oracle.jdbc.driver.OracleDriver&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="driverUrl"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;jdbc:oracle:thin:lizongbo/password@127.0.0.1:1521:ORADB&lt;/value&gt;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&lt;!--用户名和密码写在一起才调用成功,不然会报 调用无效的参数 错误，下面设置用户名和密码的property好像是无效的，其它数据库也是这样<br />
&nbsp;比如mysql的也要把用户名和密码写在url里：&lt;property name="driverUrl" value="jdbc:mysql://localhost:3306/blogdb?user=lizongbo&amp;amp;password=lizongbo" /&gt;<br />
&nbsp;--&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="user"&gt; &lt;!-- 必须在这里也设置，但是 proxool却不使用它，或许是个bug--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;lizongbo&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="password"&gt; &lt;!-- 必须在这里也设置，但是 proxool却不使用它，或许是个bug--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;lizongbo&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="alias"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;lizongbo&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="houseKeepingSleepTime"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;90000&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="prototypeCount"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;5&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="maximumConnectionCount"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;100&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="minimumConnectionCount"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;10&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="trace"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;true&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;property name="verbose"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;true&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;/bean&gt;<br />
<img src ="http://www.blogjava.net/conans/aggbug/232264.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-10-03 22:06 <a href="http://www.blogjava.net/conans/articles/232264.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> OpenSessionInView详解</title><link>http://www.blogjava.net/conans/articles/213755.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 09 Jul 2008 11:12:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/213755.html</guid><description><![CDATA[<font color="#000000">OpenSessionInView详解 关键字: <a title="Spring" href="http://www.google.cn/search?sbi=基金&amp;amp;amp;q=基金&amp;amp;amp;sbb=搜索&amp;amp;amp;sa=搜索&amp;amp;amp;client=pub-6430022987645146&amp;amp;amp;forid=1&amp;amp;amp;prog=aff&amp;amp;amp;ie=GB2312&amp;amp;amp;oe=GB2312&amp;amp;amp;hl=zh-CN" target="_blank">Spring</a> OpenSessionInView OpenSessionInViewFilter是Spring提供的一个针对Hibernate的一个支持类，其主要意思是在发起一个页面请求时打开Hibernate的Session，一直保持这个Session，直到这个请求结束，具体是通过一个Filter来实现的。 由于Hibernate引入了Lazy Load特性，使得脱离Hibernate的Session周期的对象如果再想通过getter方法取到其关联对象的值，Hibernate会抛出一个LazyLoad的Exception。所以为了解决这个问题，Spring引入了这个Filter，使得Hibernate的Session的生命周期变长。 首先分析一下它的源码，可以发现，它所实现的功能其实比较简单： Java代码</font>
<p>&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">&nbsp;&nbsp;1</span>&nbsp;<span style="color: #000000">SessionFactory&nbsp;sessionFactory&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;lookupSessionFactory(request);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;&nbsp;2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;&nbsp;3</span>&nbsp;<span style="color: #000000">Session&nbsp;session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;&nbsp;4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;&nbsp;5</span>&nbsp;<span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;participate&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;&nbsp;9</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(isSingleSession())&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;11</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;single&nbsp;session&nbsp;mode&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;13</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(TransactionSynchronizationManager.hasResource(sessionFactory))&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;14</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;15</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;Do&nbsp;not&nbsp;modify&nbsp;the&nbsp;Session:&nbsp;just&nbsp;set&nbsp;the&nbsp;participate&nbsp;flag.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;17</span>&nbsp;<span style="color: #000000">participate&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;19</span>&nbsp;<span style="color: #000000">}&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;21</span>&nbsp;<span style="color: #000000">logger.debug(</span><span style="color: #000000">"</span><span style="color: #000000">Opening&nbsp;single&nbsp;&lt;A&nbsp;title=Hibernate&nbsp;href=</span><span style="color: #000000">"</span><span style="color: #000000">http:</span><span style="color: #008000">//</span><span style="color: #008000">www.google.cn/search?sbi=基金&amp;amp;amp;q=基金&amp;amp;amp;sbb=搜索&amp;amp;amp;sa=搜索&amp;amp;amp;client=pub-6430022987645146&amp;amp;amp;forid=1&amp;amp;amp;prog=aff&amp;amp;amp;ie=GB2312&amp;amp;amp;oe=GB2312&amp;amp;amp;hl=zh-CN&nbsp;"&nbsp;target=_blank&gt;Hibernate&lt;/A&gt;&nbsp;Session&nbsp;in&nbsp;OpenSessionInViewFilter");&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;22</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;23</span>&nbsp;<span style="color: #000000">session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;getSession(sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;24</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;25</span>&nbsp;<span style="color: #000000">TransactionSynchronizationManager.bindResource(sessionFactory,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;SessionHolder(session));&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;26</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;27</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;28</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;29</span>&nbsp;<span style="color: #000000">}&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;30</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;31</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;deferred&nbsp;close&nbsp;mode&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;32</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;33</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(SessionFactoryUtils.isDeferredCloseActive(sessionFactory))&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;34</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;35</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;Do&nbsp;not&nbsp;modify&nbsp;deferred&nbsp;close:&nbsp;just&nbsp;set&nbsp;the&nbsp;participate&nbsp;flag.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;36</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;37</span>&nbsp;<span style="color: #000000">participate&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;38</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;39</span>&nbsp;<span style="color: #000000">}&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;40</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;41</span>&nbsp;<span style="color: #000000">SessionFactoryUtils.initDeferredClose(sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;42</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;43</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;44</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;45</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;46</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;47</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;48</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;49</span>&nbsp;<span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;50</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;51</span>&nbsp;<span style="color: #000000">filterChain.doFilter(request,&nbsp;response);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;52</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;53</span>&nbsp;<span style="color: #000000">}&nbsp;</span><span style="color: #0000ff">finally</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;54</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;55</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #000000">!</span><span style="color: #000000">participate)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;56</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;57</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(isSingleSession())&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;58</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;59</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;single&nbsp;session&nbsp;mode&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;60</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;61</span>&nbsp;<span style="color: #000000">TransactionSynchronizationManager.unbindResource(sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;62</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;63</span>&nbsp;<span style="color: #000000">logger.debug(</span><span style="color: #000000">"</span><span style="color: #000000">Closing&nbsp;single&nbsp;&lt;A&nbsp;title=Hibernate&nbsp;href=</span><span style="color: #000000">"</span><span style="color: #000000">http:</span><span style="color: #008000">//</span><span style="color: #008000">www.google.cn/search?sbi=基金&amp;amp;amp;q=基金&amp;amp;amp;sbb=搜索&amp;amp;amp;sa=搜索&amp;amp;amp;client=pub-6430022987645146&amp;amp;amp;forid=1&amp;amp;amp;prog=aff&amp;amp;amp;ie=GB2312&amp;amp;amp;oe=GB2312&amp;amp;amp;hl=zh-CN&nbsp;"&nbsp;target=_blank&gt;Hibernate&lt;/A&gt;&nbsp;Session&nbsp;in&nbsp;OpenSessionInViewFilter");&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;64</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;65</span>&nbsp;<span style="color: #000000">closeSession(session,&nbsp;sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;66</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;67</span>&nbsp;<span style="color: #000000">}</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;68</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;69</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;deferred&nbsp;close&nbsp;mode&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;70</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;71</span>&nbsp;<span style="color: #000000">SessionFactoryUtils.processDeferredClose(sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;72</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;73</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;74</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;75</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;76</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;77</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;78</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;79</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;80</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;81</span>&nbsp;<span style="color: #000000">SessionFactory&nbsp;sessionFactory&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;lookupSessionFactory(request);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;82</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;83</span>&nbsp;<span style="color: #000000">Session&nbsp;session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;84</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;85</span>&nbsp;<span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;participate&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;86</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;87</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;88</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;89</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(isSingleSession())&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;90</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;91</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;single&nbsp;session&nbsp;mode&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;92</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;93</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(TransactionSynchronizationManager.hasResource(sessionFactory))&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;94</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;95</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;Do&nbsp;not&nbsp;modify&nbsp;the&nbsp;Session:&nbsp;just&nbsp;set&nbsp;the&nbsp;participate&nbsp;flag.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;96</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;97</span>&nbsp;<span style="color: #000000">participate&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;98</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">&nbsp;99</span>&nbsp;<span style="color: #000000">}&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">100</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">101</span>&nbsp;<span style="color: #000000">logger.debug(</span><span style="color: #000000">"</span><span style="color: #000000">Opening&nbsp;single&nbsp;&lt;A&nbsp;title=Hibernate&nbsp;href=</span><span style="color: #000000">"</span><span style="color: #000000">http:</span><span style="color: #008000">//</span><span style="color: #008000">www.google.cn/search?sbi=基金&amp;amp;amp;q=基金&amp;amp;amp;sbb=搜索&amp;amp;amp;sa=搜索&amp;amp;amp;client=pub-6430022987645146&amp;amp;amp;forid=1&amp;amp;amp;prog=aff&amp;amp;amp;ie=GB2312&amp;amp;amp;oe=GB2312&amp;amp;amp;hl=zh-CN&nbsp;"&nbsp;target=_blank&gt;Hibernate&lt;/A&gt;&nbsp;Session&nbsp;in&nbsp;OpenSessionInViewFilter");&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">102</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">103</span>&nbsp;<span style="color: #000000">session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;getSession(sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">104</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">105</span>&nbsp;<span style="color: #000000">TransactionSynchronizationManager.bindResource(sessionFactory,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;SessionHolder(session));&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">106</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">107</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">108</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">109</span>&nbsp;<span style="color: #000000">}&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">110</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">111</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;deferred&nbsp;close&nbsp;mode&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">112</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">113</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(SessionFactoryUtils.isDeferredCloseActive(sessionFactory))&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">114</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">115</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;Do&nbsp;not&nbsp;modify&nbsp;deferred&nbsp;close:&nbsp;just&nbsp;set&nbsp;the&nbsp;participate&nbsp;flag.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">116</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">117</span>&nbsp;<span style="color: #000000">participate&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">118</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">119</span>&nbsp;<span style="color: #000000">}&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">120</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">121</span>&nbsp;<span style="color: #000000">SessionFactoryUtils.initDeferredClose(sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">122</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">123</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">124</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">125</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">126</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">127</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">128</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">129</span>&nbsp;<span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">130</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">131</span>&nbsp;<span style="color: #000000">filterChain.doFilter(request,&nbsp;response);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">132</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">133</span>&nbsp;<span style="color: #000000">}&nbsp;</span><span style="color: #0000ff">finally</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">134</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">135</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #000000">!</span><span style="color: #000000">participate)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">136</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">137</span>&nbsp;<span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(isSingleSession())&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">138</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">139</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;single&nbsp;session&nbsp;mode&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">140</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">141</span>&nbsp;<span style="color: #000000">TransactionSynchronizationManager.unbindResource(sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">142</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">143</span>&nbsp;<span style="color: #000000">logger.debug(</span><span style="color: #000000">"</span><span style="color: #000000">Closing&nbsp;single&nbsp;&lt;A&nbsp;title=Hibernate&nbsp;href=</span><span style="color: #000000">"</span><span style="color: #000000">http:</span><span style="color: #008000">//</span><span style="color: #008000">www.google.cn/search?sbi=基金&amp;amp;amp;q=基金&amp;amp;amp;sbb=搜索&amp;amp;amp;sa=搜索&amp;amp;amp;client=pub-6430022987645146&amp;amp;amp;forid=1&amp;amp;amp;prog=aff&amp;amp;amp;ie=GB2312&amp;amp;amp;oe=GB2312&amp;amp;amp;hl=zh-CN&nbsp;"&nbsp;target=_blank&gt;Hibernate&lt;/A&gt;&nbsp;Session&nbsp;in&nbsp;OpenSessionInViewFilter");&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">144</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">145</span>&nbsp;<span style="color: #000000">closeSession(session,&nbsp;sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">146</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">147</span>&nbsp;<span style="color: #000000">}</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">148</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">149</span>&nbsp;<span style="color: #008000">//</span><span style="color: #008000">&nbsp;deferred&nbsp;close&nbsp;mode&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">150</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">151</span>&nbsp;<span style="color: #000000">SessionFactoryUtils.processDeferredClose(sessionFactory);&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">152</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">153</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">154</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">155</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">156</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;<br />
</span><span style="color: #008080">157</span>&nbsp;<span style="color: #000000">}&nbsp;&nbsp;</span></div>
<br />
在上述代码中，首先获得SessionFactory，然后通过SessionFactory获得一个Session。然后执行真正的Action代码，最后根据情况将Hibernate的Session进行关闭。整个思路比较清晰。 注意，在这里有个2个Tips： 1）通过getSession()获得的这个Session做了一次 session.setFlushMode(FlushMode.NEVER); 有关FlushMode可以参考一下这篇文章。http://www2.matrix.org.cn/resource/article/2006-10-08/Hibernate+FlushMode+NEVER_312bca85-5699-11db-91a0-d98dff0aec60.html 2）Spring对拿到的Session做了一次绑定到当前线程的做法，使得这个Session是线程安全的。 从上述代码其实可以得到一些对我们的开发有帮助的结论： 1）如果使用了OpenSessionInView模式，那么Spring会帮助你管理Session的开和关，从而你在你的DAO中通过HibernateDaoSupport拿到的getSession()方法，都是绑定到当前线程的线程安全的Session，即拿即用，最后会由Filter统一关闭。 2）由于拿到的Hibernate的Session被设置了session.setFlushMode(FlushMode.NEVER); 所以，除非你直接调用session.flush()，否则Hibernate session无论何时也不会flush任何的状态变化到数据库。因此，数据库事务的配置非常重要。（我们知道，在调用org.hibernate.Transaction.commit()的时候会触发session.flush()）我曾经见过很多人在使用OpenSessionInView模式时，都因为没有正确配置事务，导致了底层会抛出有关FlushMode.NEVER的异常。 OpenSessionInView这个模式使用比较简单，也成为了大家在Web开发中经常使用的方法，不过它有时候会带来一些意想不到的问题，这也是在开发中需要注意的。 1. 在Struts＋Spring＋Hibernate环境中，由于配置的问题导致的模式失效 这个问题以前论坛曾经讨论过，可以参考一下下面这个帖子： http://www.javaeye.com/topic/15057 2. OpenSessionInView的效率问题 这个问题也有人在论坛提出过，Robbin曾经做过具体的测试，可以具体参考一下下面这个帖子： http://www.javaeye.com/topic/17501 3. 由于使用了OpenSessionInView模式后造成了内存和数据库连接问题 这个问题是我在生产环境中碰到的一个问题。由于使用了OpenSessionInView模式，Session的生命周期变得非常长。虽然解决了Lazy Load的问题，但是带来的问题就是Hibernate的一级缓存，也就是Session级别的缓存的生命周期会变得非常长，那么如果你在你的Service层做大批量的数据操作时，其实这些数据会在缓存中保留一份，这是非常耗费内存的。还有一个数据库连接的问题，存在的原因在于由于数据库的Connection是和Session绑在一起的，所以，Connection也会得不到及时的释放。因而当系统出现业务非常繁忙，而计算量又非常大的时候，往往数据连接池的连接数会不够。这个问题我至今非常头痛，因为有很多客户对数据连接池的数量会有限制，不会给你无限制的增加下去。 4. 使用了OpenSessionInView模式以后取数据的事务问题 在使用了OpenSessionInView以后，其实事务的生命周期比Session的生命周期来得短，就以为着，其实有相当一部分的查询是不被纳入到事务的范围内的，此时是否会读到脏数据？这个问题我至今不敢确认，有经验的朋友请指教一下。 最后提一下OpenSessionInView模式的一些替代方案，可以使用OpenSessionInViewInterceptor来代替这个Filter，此时可以使用Spring的AOP配置，将这个Interceptor配置到你所需要的层次上去。另外就是只能使用最古老的Hibernate.initialize()方法进行初始化了。
<img src ="http://www.blogjava.net/conans/aggbug/213755.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-07-09 19:12 <a href="http://www.blogjava.net/conans/articles/213755.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【翻译】spring配置全书(上)</title><link>http://www.blogjava.net/conans/articles/213465.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Tue, 08 Jul 2008 15:03:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/213465.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 作者简介： &nbsp; Craig Walls 是 Texas-based 公司的软件开发人员，有着超过 13 年的开发经验，涉及的领域有通信，金融，零售，教育以及软件业等。他是 Spring Framework 的狂热拥护者，频繁的在当地 local user groups 讨论组和相关会议上演讲 Spring ，并且他的 Blog 上也有很多关于 Spring 的内容。 &nbs...&nbsp;&nbsp;<a href='http://www.blogjava.net/conans/articles/213465.html'>阅读全文</a><img src ="http://www.blogjava.net/conans/aggbug/213465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-07-08 23:03 <a href="http://www.blogjava.net/conans/articles/213465.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转载）spring+hibernate避免延迟加载异常 </title><link>http://www.blogjava.net/conans/articles/212420.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 03 Jul 2008 12:30:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/212420.html</guid><description><![CDATA[<p>在hibernate中，延迟加载是1个非常大的优点，但有时候却给我们带来一些小麻烦，在后台查询结束后，session已经关闭，但在前台显示的时候，如果存在关联关系就会产生延迟加载异常。<br />
解决办法是客户端每次请求就分配1个session,将请求结果返回给客户端，并完成展现后关闭session。<br />
实现这个功能非常简单，在web.xml中加入以下配置<br />
</p>
<blockquote>&lt;filter&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-class&gt;org.springframework.orm.hibernate3.support.OpenSessionInViewFilter &lt;/filter-class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;singleSession&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;true&lt;/param-value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<br />
&lt;/filter&gt;<br />
&lt;filter-mapping&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;*.do&lt;/url-pattern&gt;<br />
&nbsp; &lt;/filter-mapping&gt;</blockquote>
<p><br />
使用spring提供这个过滤器就可以实现session的集中管理了，所有以.do结尾的请求都自动分配了1个session,并且在这个请求过程中都使用这个session.</p>
<img src ="http://www.blogjava.net/conans/aggbug/212420.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-07-03 20:30 <a href="http://www.blogjava.net/conans/articles/212420.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Application Platform - SpringSource的应用服务器发布</title><link>http://www.blogjava.net/conans/articles/210659.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 25 Jun 2008 11:43:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/210659.html</guid><description><![CDATA[<div class="blog_content">2008年的5.1劳动节，SpringSource发布了策划已久的开源应用服务器－SpringSource Application Platform。JavaEye的新闻频道也有报道： <br />
<br />
<a href="http://www.javaeye.com/news/2113" target="_blank">SpringSource 宣布发布 SpringSource Application Platform Beta</a> <br />
<br />
总体来说，Spring的Application Platform就是一个根据Rod Johnson自己对于Java企业应用开发的理解，自行制订了一套应用服务器的标准，并且开发了这样一个专用的应用服务器出来。但是Spring的应用服务器也有自己的一些特色，让我们简单看看： <br />
<br />
<img src="http://blog.springsource.com/main/wp-content/uploads/2008/04/architecture.png" _counted="undefined"  alt="" /> <br />
<br />
这是Spring应用服务器的结构图。他的底层是用Equinox这个OSGi框架来搭建的，我们知道Equinox为底层框架搭建的应用软件还有Eclipse，他的特点是高度的模块化，可定制化和在线的部署和卸载，以及模块的版本管理、依赖管理等功能。 <br />
<br />
Spring在Equinox的基础之上开发了DMK这样一个框架，即动态模块内核(Dynamic Module Kernel)，DMK封装了Equinox的很多底层操作，向上提供了更加方便的API和管理平台。 <br />
<br />
在DMK之上，所有的功能统统以模块的方式运行在DMK之上，例如Tomcat就是以模块的方式部署在Spring应用服务器上，此外还集成了应用发布模块、系统管理模块等等。所有的模块都可以以标准的方式部署到Spring应用服务器上面，具体模块的信息，可以看看Spring应用服务器的repository目录下面的文件。 <br />
<br />
Spring应用服务器给我的感觉和JBoss应用服务器很像。JBoss也是类似这样的结构，JBoss最核心的底层是JBoss Microkernel，即微内核，这个MicroKernel提供了JMX的接口，而JBoss应用服务器的所有其他功能，都是通过标准的JMX来插入到MicroKernel之上的，例如Tomcat、Hibernate3、EJB、Transaction，DB Pool等等，都是标准的SAR模块包。 <br />
<br />
他们之间比较大的不同在于Spring应用服务器底层使用的是OSGi结构来进行模块化的管理和部署，而JBoss使用的是基于JMX的模块化管理。使用OSGi的一大好处就是可以在线的热部署和卸载，并且可以提供良好的模块版本管理。 <br />
<br />
Spring应用服务器我从我初步的接触来看，我觉得有一些比较有特色的地方： <br />
<br />
一、轻量级和模块化 <br />
<br />
Spring应用服务器本质上就是基于Equinox的Spring DMK，这DMK本身是很小的，在DMK上面可以部署各种各样的功能模块来扩展应用服务器的功能，模块化程度非常高，内核本身是很轻量级的。 <br />
<br />
看Spring Applicaiton Platform自己的文档上面说，如果去掉Tomcat模块的话，启动应用服务器只占15MB内存(能用来干啥？)，其实目前Spring应用服务器并没有提供很多功能模块上来，只是一个web模块、一个部署模块和一个管理监控模块。但是计划在2.0版本增加更多的模块、例如群集支持模块、SOA模块等等。 <br />
<br />
二、在线的热部署和卸载 <br />
<br />
得益于Equinox，可以在服务器运行期增加功能模块、部署新的Web应用，或者更新、卸载Web应用，所有的这些操作都可以Online进行。这恐怕是比传统的Java应用服务器最领先的特色了。 <br />
<br />
三、库的版本管理和依赖 <br />
<br />
jar包的版本冲突和依赖是传统Java应用很头疼的一个方面，Spring应用服务器提出了自己的一套库版本管理和库依赖管理的机制，具体的原理我还没有仔细的研究，貌似也是利用了OSGi的功能。 <br />
<br />
总结： <br />
<br />
Spring应用服务器和Spring框架并没有什么直接的关系。你用其他框架开发的Web应用也可以部署到spring应用服务器上来，只是Spring应用服务器提供了很多可能你觉得不错的功能，吸引你使用spring的应用服务器，而不是tomcat或者jboss。但是Spring应用服务器并不符合Java EE的标准，因此可以看成是一个完全无视JCP的应用服务器，也是Rod Johnson大胆甩开标准进军应用服务器市场的尝试。 </div>
<img src ="http://www.blogjava.net/conans/aggbug/210659.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-25 19:43 <a href="http://www.blogjava.net/conans/articles/210659.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring和struts2的整合</title><link>http://www.blogjava.net/conans/articles/209888.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Sun, 22 Jun 2008 11:00:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/209888.html</guid><description><![CDATA[<table style="table-layout: fixed">
    <tbody>
        <tr>
            <td>
            <div class="cnt">
            <div class="cnt">在Struts2中整合Spring的IoC支持是一件十分简单的事情。让我们一步一步来实现：<br />
            1）复制struts2-spring-plugin-x-x-x.jar和相应的spring.jar到/WEB-INF/lib目录下。<br />
            2）在struts.properties中设置struts.objectFactory属性值<br />
            <div style="border-right: #3c78b5 1px dashed; border-top: #3c78b5 1px dashed; margin: 10px; border-left: #3c78b5 1px dashed; line-height: 13px; border-bottom: #3c78b5 1px dashed">
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; border-bottom: #3c78b5 1px dashed; background-color: #f0f0f0; text-align: center"><strong>struts.properties</strong></div>
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; background-color: #f0f0f0; text-align: left">
            <pre>struts.objectFactory = spring
            </pre>
            </div>
            </div>
            或者是在XML文件中进行常量配置<br />
            <div style="border-right: #3c78b5 1px dashed; border-top: #3c78b5 1px dashed; margin: 10px; border-left: #3c78b5 1px dashed; line-height: 13px; border-bottom: #3c78b5 1px dashed">
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; border-bottom: #3c78b5 1px dashed; background-color: #f0f0f0; text-align: center"><strong>struts.xml</strong></div>
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; background-color: #f0f0f0; text-align: left">
            <pre>&lt;struts&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;constant name="struts.objectFactory" value="spring" /&gt;
            &lt;/struts&gt;
            </pre>
            </div>
            </div>
            3）配置Spring监听器<br />
            <div style="border-right: #3c78b5 1px dashed; border-top: #3c78b5 1px dashed; margin: 10px; border-left: #3c78b5 1px dashed; line-height: 13px; border-bottom: #3c78b5 1px dashed">
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; border-bottom: #3c78b5 1px dashed; background-color: #f0f0f0; text-align: center"><strong>web.xml</strong></div>
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; background-color: #f0f0f0; text-align: left">
            <pre>&lt;listener&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener<span class="code-tag">&lt;/listener-class&gt;
            &lt;/listener&gt;
            </span>
            </pre>
            </div>
            </div>
            通过Spring配置来注册对象<br />
            <div style="border-right: #3c78b5 1px dashed; border-top: #3c78b5 1px dashed; margin: 10px; border-left: #3c78b5 1px dashed; line-height: 13px; border-bottom: #3c78b5 1px dashed">
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; border-bottom: #3c78b5 1px dashed; background-color: #f0f0f0; text-align: center"><strong>applicationContext.xml</strong></div>
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; background-color: #f0f0f0; text-align: left">
            <pre>&lt;?xml version=<span class="code-quote">"1.0"</span> encoding="UTF-8"?&gt;
            &lt;!DOCTYPE beans PUBLIC
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "-//SPRING//DTD BEAN//EN"
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
            &lt;beans default-autowire="byName"&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="personManager" class="com.acme.PersonManager"/&gt;
            &lt;/beans&gt;
            </pre>
            </div>
            </div>
            当然你也可以拥有更多的Spring配置文件。在web.xml中进行下列设置，从而使Spring的ApplicationContext通过匹配所给定模式的文件来初始化对象<br />
            <div style="border-right: #3c78b5 1px dashed; border-top: #3c78b5 1px dashed; margin: 10px; border-left: #3c78b5 1px dashed; line-height: 13px; border-bottom: #3c78b5 1px dashed">
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; background-color: #f0f0f0; text-align: left">
            <pre>&lt;!-- 用来定位Spring XML文件的上下文配置 --&gt;
            &lt;context-param&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;contextConfigLocation<span class="code-tag">&lt;/param-name&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml&lt;/param-value&gt;
            &lt;/context-param&gt;
            </span>
            </pre>
            </div>
            </div>
            4）修改你的Struts配置文件<br />
            <div style="border-right: #3c78b5 1px dashed; border-top: #3c78b5 1px dashed; margin: 10px; border-left: #3c78b5 1px dashed; line-height: 13px; border-bottom: #3c78b5 1px dashed">
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; border-bottom: #3c78b5 1px dashed; background-color: #f0f0f0; text-align: center"><strong>struts.xml</strong></div>
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; background-color: #f0f0f0; text-align: left">
            <pre>&lt;!DOCTYPE struts PUBLIC
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "http://struts.apache.org/dtds/struts-2.0.dtd"&gt;
            &lt;struts&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;include file="struts-default.xml"/&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;package name="default" extends="struts-default"&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action name="foo" class="com.acme.Foo"&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;result&gt;foo.ftl&lt;/result&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/action&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/package&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;package name="secure" namespace="/secure" extends="default"&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action name="bar" class="bar"&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;result&gt;bar.ftl&lt;/result&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/action&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/package&gt;
            &lt;/struts&gt;
            </pre>
            </div>
            </div>
            默认情况下，Spring从下面的文件中寻找为bar所做的配置<br />
            <div style="border-right: #3c78b5 1px dashed; border-top: #3c78b5 1px dashed; margin: 10px; border-left: #3c78b5 1px dashed; line-height: 13px; border-bottom: #3c78b5 1px dashed">
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; border-bottom: #3c78b5 1px dashed; background-color: #f0f0f0; text-align: center"><strong>applicationConext.xml</strong></div>
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; background-color: #f0f0f0; text-align: left">
            <pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
            &lt;!DOCTYPE beans PUBLIC
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "-//SPRING//DTD BEAN//EN"
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
            &lt;beans default-autowire="byName"&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="bar" class="com.my.BarClass" singleton="false"/&gt;
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...
            &lt;/beans&gt;
            </pre>
            </div>
            </div>
            5）好了，现在你的Struts2和Spring就能正常的一起工作了。有几个配置技术点需要详细说明下：装配模式。你可以通过设置修改struts.properties中下列属性的值来改变装配模式。<br />
            <div style="border-right: #3c78b5 1px dashed; border-top: #3c78b5 1px dashed; margin: 10px; border-left: #3c78b5 1px dashed; line-height: 13px; border-bottom: #3c78b5 1px dashed">
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; background-color: #f0f0f0; text-align: left">
            <pre class="code-java">struts.objectFactory.spring.autoWire = type
            </pre>
            </div>
            </div>
            该参数可供选择的设置值有<br />
            <table style="margin: 5px; border-collapse: collapse">
                <tbody>
                    <tr>
                        <th style="border-right: #ccc 1px solid; padding-right: 4px; border-top: #ccc 1px solid; padding-left: 4px; padding-bottom: 3px; border-left: #ccc 1px solid; padding-top: 3px; border-bottom: #ccc 1px solid; background-color: #f0f0f0; text-align: center">name</th>
                        <td style="border-right: #ccc 1px solid; padding-right: 4px; border-top: #ccc 1px solid; padding-left: 4px; padding-bottom: 3px; border-left: #ccc 1px solid; padding-top: 3px; border-bottom: #ccc 1px solid">按照你的action的属性的名字和Spring里的bean的名字匹配，如果匹配就自动装配。这是<strong>缺省的</strong></td>
                    </tr>
                    <tr>
                        <th style="border-right: #ccc 1px solid; padding-right: 4px; border-top: #ccc 1px solid; padding-left: 4px; padding-bottom: 3px; border-left: #ccc 1px solid; padding-top: 3px; border-bottom: #ccc 1px solid; background-color: #f0f0f0; text-align: center">type</th>
                        <td style="border-right: #ccc 1px solid; padding-right: 4px; border-top: #ccc 1px solid; padding-left: 4px; padding-bottom: 3px; border-left: #ccc 1px solid; padding-top: 3px; border-bottom: #ccc 1px solid">按照你的action的属性的类型，在Spring注册的bean中查找，如果相同就自动装配。这需要你在Spring中仅注册了一个此类型的bean</td>
                    </tr>
                    <tr>
                        <th style="border-right: #ccc 1px solid; padding-right: 4px; border-top: #ccc 1px solid; padding-left: 4px; padding-bottom: 3px; border-left: #ccc 1px solid; padding-top: 3px; border-bottom: #ccc 1px solid; background-color: #f0f0f0; text-align: center">auto</th>
                        <td style="border-right: #ccc 1px solid; padding-right: 4px; border-top: #ccc 1px solid; padding-left: 4px; padding-bottom: 3px; border-left: #ccc 1px solid; padding-top: 3px; border-bottom: #ccc 1px solid">Spring会试图自动监测来找到最好的方法自动装配你的action</td>
                    </tr>
                    <tr>
                        <th style="border-right: #ccc 1px solid; padding-right: 4px; border-top: #ccc 1px solid; padding-left: 4px; padding-bottom: 3px; border-left: #ccc 1px solid; padding-top: 3px; border-bottom: #ccc 1px solid; background-color: #f0f0f0; text-align: center">constructor</th>
                        <td style="border-right: #ccc 1px solid; padding-right: 4px; border-top: #ccc 1px solid; padding-left: 4px; padding-bottom: 3px; border-left: #ccc 1px solid; padding-top: 3px; border-bottom: #ccc 1px solid">Spring会自动装配bean的构造函数的参数</td>
                    </tr>
                </tbody>
            </table>
            是否使用类缓存。你可以通过设置修改struts.properties中下列属性的值来改变是否使用Spring自身的类缓存机制。可以设定的值为true或false，默认为true。<br />
            <div style="border-right: #3c78b5 1px dashed; border-top: #3c78b5 1px dashed; margin: 10px; border-left: #3c78b5 1px dashed; line-height: 13px; border-bottom: #3c78b5 1px dashed">
            <div style="padding-right: 3px; padding-left: 3px; padding-bottom: 3px; padding-top: 3px; background-color: #f0f0f0; text-align: left">
            <pre>struts.objectFactory.spring.useClassCache = false
            </pre>
            </div>
            </div>
            </div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
 <img src ="http://www.blogjava.net/conans/aggbug/209888.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-22 19:00 <a href="http://www.blogjava.net/conans/articles/209888.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>