隨筆-51  評論-14  文章-0  trackbacks-0

          總算將一個(gè)項(xiàng)目勉強(qiáng)上線,也是第一次我獨(dú)立完成的這么多任務(wù),框架設(shè)計(jì)、框架搭建、代碼編寫、測試、數(shù)據(jù)庫創(chuàng)建、表結(jié)構(gòu)設(shè)計(jì)……除了頁面和詳細(xì)設(shè)計(jì)我都做了個(gè)遍,雖然很倉促也犯了很多錯(cuò)誤,但是整個(gè)過程走下來,發(fā)現(xiàn)自己真的學(xué)到不少東西。在這個(gè)空檔期寫個(gè)小總結(jié),以便以后使用 :)

           現(xiàn)在框架真是多的要死,也沒有什么真正能一統(tǒng)天下的東西,每個(gè)人的著眼點(diǎn)和技術(shù)習(xí)慣都不同,在剛接到項(xiàng)目的時(shí)候,老大就要我自己去確定框架。當(dāng)時(shí)我正沉迷于TapeStry+Spring+iBatis開發(fā)的暢快之中,當(dāng)時(shí)真想直接將自己的東西移植過去,但是一想公司陸續(xù)會有其他人進(jìn)來加入到項(xiàng)目中,那么TSS這個(gè)框架肯定很難找到合適的人選,而且自己在研究TSS的過程中也發(fā)現(xiàn)由于文檔的缺乏,遇到問題的解決就是一個(gè)很嚴(yán)重的問題,最終只能棄用。雖然我很喜歡T4,但是它實(shí)在不讓人放心,只好期待Howard能給我們不斷帶來驚喜,真正成為繼Struts、WebWork之后的最優(yōu)選擇。有時(shí)間我還會繼續(xù)學(xué)習(xí)T4,并做一下總結(jié)。

          經(jīng)過當(dāng)時(shí)的考慮,我只得放棄TSS,最終選擇自己相對熟悉的Struts+Spring+Hibernate,說是熟悉,那是因?yàn)橐郧暗捻?xiàng)目是用這個(gè),有網(wǎng)友戲稱SSH是庸俗組合,呵呵,庸俗就庸俗吧,我想自己能把這套東西搞好也會有相當(dāng)?shù)碾y度的(現(xiàn)在證明這個(gè)選擇是對的,出了問題有人問,項(xiàng)目組的其他人也都是玩這套東西的,維護(hù)擴(kuò)展都方便)。

           

          具體細(xì)節(jié)就不再描繪了,做軟件的都知道問題無法解決是多么的折磨人,這其中的酸甜苦辣只有經(jīng)歷過的人才知道,技術(shù)上的問題是遇到一個(gè)解決一個(gè),實(shí)在覺得解決不了或者沒有把握,利馬換其他想法,這個(gè)很重要,實(shí)現(xiàn)的方法有很多,即便不是最優(yōu)的解決方案,但是節(jié)省的大量的時(shí)間,在工期緊的時(shí)候一定要權(quán)衡的去考慮,否則后果不堪設(shè)想。

          總體框架(SSH)需要4個(gè)重要的配置文件:

          1.web.xml

           

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE web-app
          PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
          "http://java.sun.com/dtd/web-app_2_3.dtd"
          >
          <web-app>
              
          <display-name>sample</display-name>
              
          <context-param> 
                  
          <param-name>contextConfigLocation</param-name> 
                  
          <param-value>/WEB-INF/applicationContext.xml</param-value> 
              
          </context-param> 
              
          <!--OpenSessionInViewFilter配置,其實(shí)是一個(gè)又繁瑣性能又低的東西,以后再也不想用到-->
              
          <filter>
                  
          <filter-name>OpenSessionInViewFilter</filter-name>
                  
          <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
                  
          <!-- singleSession默認(rèn)為true,若設(shè)為false則等于沒用OpenSessionInView --> 
                  
          <init-param> 
                      
          <param-name>singleSession</param-name> 
                      
          <param-value>true</param-value>
                  
          </init-param>
              
          </filter>
              
          <filter-mapping> 
                  
          <filter-name>OpenSessionInViewFilter</filter-name> 
                  
          <url-pattern>/*</url-pattern> 
              
          </filter-mapping>
              
          <!--encoding-->
              
          <filter>
                  
          <filter-name>Set Character Encoding</filter-name>
                  
          <filter-class>com.shpcims.util.SetCharacterEncodingFilter</filter-class>
                  
          <init-param>
                      
          <param-name>encoding</param-name>
                      
          <param-value>utf-8</param-value> 
                  
          </init-param>
              
          </filter>
              
          <filter-mapping>
                  
          <filter-name>Set Character Encoding</filter-name>
                  
          <servlet-name>action</servlet-name>
              
          </filter-mapping>
              
          <!--Spring Context listener-->
              
          <listener> 
                  
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
              
          </listener>

              
              
          <servlet>
                  
          <servlet-name>action</servlet-name>
                  
          <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
                  
          <init-param>
                      
          <param-name>config</param-name>
                      
          <param-value>/WEB-INF/struts-config.xml</param-value>
                  
          </init-param>
                  
          <init-param>
                      
          <param-name>debug</param-name>
                      
          <param-value>3</param-value>
                  
          </init-param>
                  
          <init-param>
                      
          <param-name>detail</param-name>
                      
          <param-value>3</param-value>
                  
          </init-param>
                  
          <load-on-startup>1</load-on-startup>
              
          </servlet>
              
          <servlet-mapping>
              
          <servlet-name>action</servlet-name>
                  
          <url-pattern>*.do</url-pattern>
              
          </servlet-mapping>
              
              
              
          <welcome-file-list>
                  
          <welcome-file>index.jsp</welcome-file>
              
          </welcome-file-list>
              
              
          <taglib>
                  
          <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
                  
          <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
              
          </taglib>
              
          <taglib>
                  
          <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
                  
          <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
              
          </taglib>
              
          <taglib>
                  
          <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
                  
          <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
              
          </taglib>
              
          <taglib>
                  
          <taglib-uri>/WEB-INF/struts-tiles.tld</taglib-uri>
                  
          <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>
              
          </taglib>
              
          <taglib>
                  
          <taglib-uri>/WEB-INF/CustomTag.tld</taglib-uri>
                  
          <taglib-location>/WEB-INF/tags/CustomTag.tld</taglib-location>
              
          </taglib>
          </web-app>

          2.Struts-config.xml

          <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"
          >
          <struts-config>
              
              
          <!-- forms -->
              
          <form-beans>
                  
          <form-bean name="loginForm" type="com.shpcims.web.login.form.LoginForm" />    </form-beans>
              
          <global-forwards>
                  
          <forward name="web_report" path="/reporter"/>
                  
          <forward name="report_fail" path="/WEB-INF/jsp/SystemError.jsp"/>
              
          </global-forwards>
              
              
          <!-- actions -->
              
          <action-mappings>
                  
          <action path="/LoginAction"
                          type
          ="org.springframework.web.struts.DelegatingActionProxy"
                          scope
          ="request"
                          name
          ="loginForm"
                          validate
          ="true"
                          input
          ="/index.jsp">
                      
          <forward name="success"     path="/CreditInfoPreAction.do" />
                      
          <forward name="fail"         path="/index.jsp" />
                  
          </action>
                  
              
          </action-mappings>
              
              
          <!-- Custmoer Controller for Authentication -->
              
          <controller>
                 
          <set-property property="processorClass" value="com.shpcims.framework.CustomerRequestProcessor" />
              
          </controller>
              
              
          <!-- Message-resources -->
              
          <message-resources parameter="ApplicationResources" />
              
              
          <!-- plug-in -->
              
          <!-- tiles template -->
              
          <plug-in className="org.apache.struts.tiles.TilesPlugin" >
                  
          <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />
                  
          <set-property property="definitions-debug" value="2" />
                  
          <set-property property="definitions-parser-details" value="2" />
                  
          <set-property property="definitions-parser-validate" value="true" />
              
          </plug-in>
              
          <!-- spring plug-in -->
              
          <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
                  
          <set-property property="contextConfigLocation" value="/WEB-INF/beans.xml" />
              
          </plug-in>    
              
          <!-- Validator plugin -->
              
          <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
                  
          <set-property
                      
          property="pathnames"
                          value
          ="/WEB-INF/validaterule/validator-rules.xml,
                         /WEB-INF/validaterule/validation.xml
                  "
          />
              
          </plug-in>
          </struts-config>

          3.applicationContext.xml

           

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
           
          <beans>
              
          <!-- service -->
              
          <bean id="chartService" parent="baseTransactionProxy">
                  
          <property name="target">
                      
          <bean class="com.shpcims.service.ChartServiceImpl">
                      
          </bean>
                  
          </property>
              
          </bean>    
              
              
          <!-- dao -->
              
          <bean id="customDao" class="com.shpcims.dao.CustomDaoImpl">
                  
          <property name="sessionFactory" ref="sessionFactory" />
              
          </bean>
          <!-- 配置sessionFactory, 注意這里引入的包的不同 -->
              
          <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                  
          <property name="dataSource" ref="dataSource" />
                  
          <!-- mappingResources -->
                  
          <property name="mappingResources">
                      
          <list>
                          
          <value>com/shpcims/model/Area.hbm.xml</value>            </list>
                  
          </property>
                  
          <property name="hibernateProperties">
                      
          <props>
                          
          <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
                          
          <!-- 開發(fā)期間為true -->
                          
          <prop key="hibernate.show_sql">true</prop>
                      
          </props>
                  
          </property>
              
          </bean>
              
              
          <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
                    abstract
          ="true">
                  
          <property name="proxyTargetClass" value="true" />
                  
          <property name="transactionManager" ref="transactionManager"/>
                  
          <property name="transactionAttributes">
                      
          <props>
                          
          <prop key="update*">PROPAGATION_REQUIRED</prop>
                          
          <prop key="insert*">PROPAGATION_REQUIRED</prop>
                          
          <prop key="create*">PROPAGATION_REQUIRED</prop>
                          
          <prop key="assign*">PROPAGATION_REQUIRED</prop>
                          
          <prop key="reassign*">PROPAGATION_REQUIRED</prop>
                          
          <prop key="delete*">PROPAGATION_REQUIRED</prop>
                          
          <prop key="select*">PROPAGATION_REQUIRED</prop>
                          
          <prop key="remove*">PROPAGATION_REQUIRED</prop>
                          
          <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                          
          <prop key="add*">PROPAGATION_REQUIRED</prop>
                          
          <prop key="delete*">PROPAGATION_REQUIRED</prop>
                      
          </props>
                  
          </property>
              
          </bean>
              
              
          <bean id="calculateJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
                  
          <property name="targetObject">
                      
          <ref bean="gradeCalculateService" />
                  
          </property>
                  
          <property name="targetMethod">
                      
          <value>calcuateCreditLevel</value>
                  
          </property>
              
          </bean>
              
              
          <bean id="cronCalculateTigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
                  
          <property name="jobDetail">
                      
          <ref bean="calculateJob"/>
                  
          </property>
                  
          <property name="cronExpression">
                      
          <value>0 0 0 1,15 * ?</value>
                  
          </property>
              
          </bean>
              
              
          <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
                  
          <property name="triggers">
                      
          <list>
                          
          <ref bean="cronCalculateTigger"/>
                      
          </list>
                  
          </property>
              
          </bean>
              
              
          <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
                  
          <property name="driverClassName">
                      
          <value>net.sourceforge.jtds.jdbc.Driver</value>
                  
          </property>
                  
          <property name="url">
                      
          <value>jdbc:jtds:sqlserver://192.168.0.16:1433/SHPCIMS</value>
                  
          </property>
                  
          <property name="username">
                      
          <value>sqlserver</value>
                  
          </property>
                  
          <property name="password">
                      
          <value>sqlserver</value>
                  
          </property>
              
          </bean>
              
              
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                  
          <property name="dataSource" ref="dataSource" />
              
          </bean>
              
              
          <!-- init properties 
              <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                  <property name="location">
                      <value>init.properties</value>
                  </property>
              </bean>
          -->
              
              
          <!-- use to resolve hibernate lazy load --> 
              
          <bean id="hibernateLazyResolver" class="com.shpcims.util.HibernateLazyResolver"> 
                  
          <property name="sessionFactory"><ref local="sessionFactory"/></property> 
              
          </bean> 
              
              
          <!-- log advice -->
              
          <bean name="logger" class="com.shpcims.framework.LogAdvice">
                  
          <property name="systemManagerService" ref="systemManagerService" />
              
          </bean>
              
          <bean name="beforeLogAdvice" class="com.shpcims.framework.BeforeLogAdvice">
                  
          <property name="systemManagerService" ref="systemManagerService" />
              
          </bean>
          </beans>
          4.beans.xml
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
           
          <beans>
              
          <!-- action -->
              
          <bean name="/LoginAction" class="com.shpcims.web.login.action.LoginAction" singleton="false">
                  
          <property name="systemManagerService" ref="systemManagerService" />
              
          </bean>
              
          <bean name="autoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
                  
          <property name="beanNames">
                      
          <list>
                          
          <value>/LoginAction</value>            
                                                                          
          </list>
                  
          </property>
                  
          <property name="interceptorNames">
                      
          <list>
                          
          <value>logger</value>
                          
          <value>beforeLogAdvice</value>
                      
          </list>
                  
          </property>
                  
          <property name="proxyTargetClass" value="true"/>
              
          </bean>
          </beans>

          4個(gè)文件中的大多數(shù)配置都是很普通的,只在這記錄一些比較容易出問題的地方,

          web.xml中配置了OpenSessionInViewFilter,這個(gè)東西是我在整個(gè)框架構(gòu)建中浪費(fèi)最多時(shí)間也是出現(xiàn)問題最多的地方,后來和項(xiàng)目組同事討論,最終在新的項(xiàng)目中放棄了對這爛東西的使用,如果使用延遲加載,那么所有需要加載的東西應(yīng)該在Dao中使用Hibernate.initialize(object)強(qiáng)制加載,使得持久化操作保持在Dao層中完成,徹底拋棄OpenSesionInViewFilter。HOHO

          Spring ContextListner 的加載仍然放在web.xml里面進(jìn)行,盡管在Struts中使用了ContextLoaderPlugin,但僅僅是在加載StrutsAction的時(shí)候才使用到,而整個(gè)SpringContext的初始化仍然是放在web.xml里面進(jìn)行。個(gè)人覺得這樣做肯定有很多好處,但是目前仍不能說出真正的緣由。如此配置的初衷還是因?yàn)橛玫搅薕penSessionInViewFilter,因?yàn)槿绻赟truts中去初始化Spring,OpenSessionInViewFilter根本跑不起來,因?yàn)樗旧硎窃趙eb.xml中初始化的,而且需要ContextListner 的支持。必須配置在web.xml中,此時(shí)仍使用ContextLoaderPlugin來加載就會出現(xiàn)Spring被加載兩次的情況,結(jié)果造成OpenSessionInViewFilter失效。盡管現(xiàn)在不再使用那個(gè)Filter,配置卻仍然這樣保持下來,我覺得仍然可以避免一些問題,畢竟配置在Struts下面就被Struts綁死了,那么好像是 Struts在控制整體,違背了框架搭建的初衷,也無法使Spring發(fā)揮自己最大的功力。

          Struts-config.xml中有3個(gè)需要注意的地方,第一個(gè)是使用DelegatingActionProxy,我曾經(jīng)對我項(xiàng)目組的同事每個(gè)人都解釋了一遍為什么要使用這個(gè)東東,真是痛苦的要死。但是這個(gè)東西一直都被認(rèn)為是Struts+Spring最好的配置方式,其他的諸如使用WebLoadContext那種方式好像都無法帶來這樣的好處。我覺得這樣用的好處是:就如它的名字一樣,Proxy,Struts在使用它的時(shí)候根本不知道它的存在,幾乎感覺不到影響,只是把配置文件寫到beans.xml中去了。第二個(gè)好處是Struts的線程安全問題,如此配置新的線程不再共享同一個(gè)Action,更高深的東西我也說不清楚了 :(。第三個(gè)好處就是方便的使用AOP,這個(gè)是我最喜歡的了,有了這個(gè)Proxy,StrutsAction才真正的成為Spring轄區(qū)的一部分,方便的使用AOP,我不知道沒有AOP我需要多寫幾千行代碼,這對項(xiàng)目的及時(shí)完工真是不知道作出多少貢獻(xiàn),也使得框架更加優(yōu)雅,極盡贊美之詞也不為過。:P

          第二個(gè)注意的地方是使用了Tiles框架,盡管后來美工給我Frame框架的時(shí)候造成了很多麻煩,可我仍然挺喜歡Tiles,心想如果我在用T4的時(shí)候能那么輕易的使用Tiles當(dāng)時(shí)真的就用TSS也說不一定哦。Tiles里面基礎(chǔ)配置沒什么可說的,tiles-defs.xml、layout.jsp,頁面上的使用寫正確配置就可以了,但是在使用Tiles的時(shí)候遇到一個(gè)預(yù)加載JS的需求,要不是手頭有以前項(xiàng)目的代碼,估計(jì)就玩完了


          <tiles:getAsString name="javascript" ignore="true"/>

          <SCRIPT language="JavaScript">
          <!--
          function init(){
              
          if(window.subinit){
                  subinit();
              }

          }

          <tiles:insert attribute="fw_script_block" ignore="true" />
          //-->
          </SCRIPT>
          <link href="css/portal.css" rel="stylesheet" type="text/css">
          </HEAD>
          <BODY onload="init()" style="overflow-x:hidden;overflow-y:hidden">

          看上去很普通的代碼,但是其中使用了tiles的一個(gè)樹型 ignore="true", 才真正使得預(yù)加載JS變得更加方便和可控制,這樣我就不用在每個(gè)布局模板上都寫上一個(gè)沒有意義的空方法在里面咯。

          第三個(gè)問題是使用Validation框架,盡管以前使用過,但是自己用的時(shí)候才知道配置起來沒那么簡單,最初我采用Struts-1.2.9版本,沒想到Validation不能用,后來在網(wǎng)上發(fā)現(xiàn)Validation用的包不全是Struts自帶的,版本不統(tǒng)一導(dǎo)致了Validation問題多多,折磨我好多天,最終不得不放棄Struts1.2.9而降級到1.2.8,才使得問題得以解決。

          applicationContext.xml中的配置也相對要穩(wěn)定一些,需要什么加什么就好了,當(dāng)時(shí)我為了將JUnit分離出來還特地請教了一位高人,JUnit分離其實(shí)有很大的意義,它不但真正意義上脫離了Web環(huán)境還使得測試數(shù)據(jù)和真實(shí)數(shù)據(jù)的分離。利用好JUnit絕對是提高開發(fā)效率的一件法寶,難怪有很多大師級的人物都說編寫測試用例要比編寫代碼挑戰(zhàn)大得多。但是項(xiàng)目最終的遺留問題讓我被迫放棄了這個(gè)JUnit分離:(,原因是我無法解決相對路徑的查找,項(xiàng)目中大量用到了Socket、線程、任務(wù)計(jì)劃這種東西,使得相對路徑的問題多多,沒辦法我只能盡量縮減配置文件的數(shù)目,不知道有沒有更好的解決方案。

           



          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1028413

          posted on 2008-03-29 16:49 Hank1026 閱讀(510) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 山西省| 安吉县| 抚宁县| 临城县| 嵊州市| 宜春市| 乌苏市| 梁平县| 清徐县| 邵阳市| 翁牛特旗| 广西| 襄樊市| 西藏| 余江县| 绵竹市| 阿瓦提县| 卓资县| 兰考县| 齐河县| 澄迈县| 马龙县| 平果县| 英德市| 祁阳县| 东阳市| 石景山区| 阳泉市| 托里县| 丰都县| 湖口县| 遵化市| 安顺市| 顺昌县| 大名县| 马鞍山市| 连南| 大丰市| 巨野县| 民勤县| 嘉荫县|