国产亚洲精品资在线,亚洲免费人成在线视频观看,亚洲一区动漫卡通在线播放http://m.tkk7.com/rain1102/category/37665.html<br/><font color="green" style="font-family: 華文行楷;font-size:16px;">子曰:危邦不入,亂邦不居。天下有道則見,無道則隱。</font><font color="#3C1435"></font>zh-cnFri, 20 Feb 2009 10:09:59 GMTFri, 20 Feb 2009 10:09:59 GMT60Object Graph Navigation Language--OGNL訪問靜態(tài)方法和類變量http://m.tkk7.com/rain1102/archive/2006/12/26/90106.htmlEric.ZhouEric.ZhouTue, 26 Dec 2006 06:56:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/26/90106.htmlhttp://m.tkk7.com/rain1102/comments/90106.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/26/90106.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/90106.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/90106.html       除了使用標(biāo)準(zhǔn)的OGNL格式調(diào)用靜態(tài)方法和靜態(tài)屬性之外,WebWork還可以不指定完整的包名,而是通過使用vs前綴(vs代表Value Stack,就是值棧)調(diào)用保存于值棧中的類的靜態(tài)屬性和靜態(tài)方法??梢允褂胿s告知WebWork使用存儲于棧頂?shù)念悓ο螅瑥亩媪税ˊexamples.test.Muppet):@vs@OG_MUPPET或者vs@OG_MUPPET()。
  同時,也可以在vs之后指定一數(shù)字,例如vs1,從而指明選擇了值棧中更深一層的對象。

Eric.Zhou 2006-12-26 14:56 發(fā)表評論
]]>
通過PreResultListener在result執(zhí)行之前獲得回調(diào)控制http://m.tkk7.com/rain1102/archive/2006/12/25/89895.htmlEric.ZhouEric.ZhouMon, 25 Dec 2006 06:30:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/25/89895.htmlhttp://m.tkk7.com/rain1102/comments/89895.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/25/89895.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/89895.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/89895.html開發(fā)interceptor的時候,了解action已經(jīng)執(zhí)行完畢而result還沒有開始執(zhí)行的時間點往往很重要的。譬如在異常處理方面就是如此:在action處理的過程中,由于后臺的處理,出現(xiàn)的異常很可能是系統(tǒng)異常;而在result處理的過程中,異常則可能出現(xiàn)在為用戶呈現(xiàn)的頁面的時候,而不是由于系統(tǒng)問題。
下面給出了ExceptionInterceptor的代碼,該interceptor會在result開始執(zhí)行之前與之后以不同的方式處理異常。在result開始執(zhí)行之前,可以改變用于從action配置中查詢result的返回碼,而在webwork應(yīng)用程序中,使用Action.ERROR是一個常用的實踐技巧:將Action.ERROR映射至向用戶提示錯誤的頁面。所以,需要捕獲異常并返回Action.ERROR。在result開始執(zhí)行之后,來自interceptor的返回碼就不再那樣重要了,但是仍然可以獲得由beforeResult()方法回傳給result code,并且可以返回它。在以下離子中需要注意的一點是:由于interceptor必須是無狀態(tài)的,因此它為每一個ActionInvocation創(chuàng)建一個新的ExceptionHandler,可以保存該ActionInvocation的狀態(tài)。
ExceptionInterceptor:在result前后以不同的方式處理異常
/**
 * @filename ExceptionInterceptor.java
 * @author Rain_zhou
 * @version ExceptionInterceptor,下午01:05:50
 */
package com.founder.study.forum.interceptor;

import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.interceptor.Interceptor;

/**
 * @author Rain_zhou
 *
 */
public class ExceptionInterceptor implements Interceptor {

 /* (non-Javadoc)
  * @see com.opensymphony.xwork.interceptor.Interceptor#destroy()
  */
 public void destroy() {
  // TODO Auto-generated method stub

 }

 /* (non-Javadoc)
  * @see com.opensymphony.xwork.interceptor.Interceptor#init()
  */
 public void init() {
  // TODO Auto-generated method stub

 }

 /* (non-Javadoc)
  * @see com.opensymphony.xwork.interceptor.Interceptor#intercept(com.opensymphony.xwork.ActionInvocation)
  */
 public String intercept(ActionInvocation arg0) throws Exception {
  // TODO Auto-generated method stub
  ExceptionHandler handler=new ExceptionHandler(arg0);
  return handler.invoke();
 }

}



/**
 * @filename ExceptionHandler.java
 * @author Rain_zhou
 * @version ExceptionHandler,下午01:07:04
 */
package com.founder.study.forum.interceptor;

import com.founder.study.forum.helper.NoLimitException;
import com.opensymphony.xwork.Action;
import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.interceptor.PreResultListener;

/**
 * @author Rain_zhou
 *
 */
public class ExceptionHandler implements PreResultListener {

 private ActionInvocation invocation;
 private boolean beforeResult=true;
 private String result=Action.ERROR;
 
 public ExceptionHandler(ActionInvocation invocation){
  this.invocation=invocation;
  invocation.addPreResultListener(this);
 }
 
 String invoke(){
  try{
   result=invocation.invoke();
  }catch(Exception e){
   if(beforeResult){
    return Action.ERROR;
   }else{
    return result;
   }
  }
  return result;
 }
 /* (non-Javadoc)
  * @see com.opensymphony.xwork.interceptor.PreResultListener#beforeResult(com.opensymphony.xwork.ActionInvocation, Java.lang.String)
  */
 public void beforeResult(ActionInvocation arg0, String arg1) {
  // TODO Auto-generated method stub

  beforeResult=false;
  result=arg1;
 }

}



Eric.Zhou 2006-12-25 14:30 發(fā)表評論
]]>
WebWork中的ComponentManager接口http://m.tkk7.com/rain1102/archive/2006/12/25/89857.htmlEric.ZhouEric.ZhouMon, 25 Dec 2006 03:49:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/25/89857.htmlhttp://m.tkk7.com/rain1102/comments/89857.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/25/89857.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/89857.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/89857.html在WebWork 中,每一個作用域(請求、會話或者應(yīng)用程序)都有一個ComponentManager--Manager(CM)與它相關(guān)聯(lián)。每個CM都會有一個父CM,而在決定如何管理和應(yīng)用資源的時候,CM將會詢問父CM。請求作用域CM有一個會話作用域CM,而會話作用域CM則有一個應(yīng)用程序作用域CM它自己的父CM。
這意味著應(yīng)用一個對象到請求作用域CM必須保證該對象能夠獲取屬于會話或者應(yīng)用程序作用域的資源。每個作用域的CM都存放于屬性map中,該map可以通過ServletRequest對象、HttpSession對象或者ServletContext對象的setAttribute()和getAttribute()方法進行訪問。

Eric.Zhou 2006-12-25 11:49 發(fā)表評論
]]>
webwork中的aware接口http://m.tkk7.com/rain1102/archive/2006/12/25/89816.htmlEric.ZhouEric.ZhouMon, 25 Dec 2006 01:23:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/25/89816.htmlhttp://m.tkk7.com/rain1102/comments/89816.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/25/89816.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/89816.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/89816.htmlwebwork所支持的通用aware接口列示如下:
1、ParametersAware 指明action需要HTTP請求參數(shù)map。
2、ServletRequestAware 指明action需要ServletRequest對象。
3、SessionAware 指明action需要HttpSession對象。
4、ApplicationAware 指明action需要ServletContext對象。

Eric.Zhou 2006-12-25 09:23 發(fā)表評論
]]>
Acegi簡介http://m.tkk7.com/rain1102/archive/2006/12/19/88847.htmlEric.ZhouEric.ZhouTue, 19 Dec 2006 08:40:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/19/88847.htmlhttp://m.tkk7.com/rain1102/comments/88847.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/19/88847.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/88847.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/88847.html       安全涉及到兩個不同的概念,認證和授權(quán)。前者是關(guān)于確認用戶是否確實是他們所宣稱的身份。授權(quán)則是關(guān)于確認用戶是否有允許執(zhí)行一個特定的操作。
       在Acegi安全系統(tǒng)中,需要被認證的用戶,系統(tǒng)或代理稱為"Principal"。Acegi安全系統(tǒng)和其他的安全系統(tǒng)不同,它并沒有角色和用戶組的概念。
Acegi系統(tǒng)設(shè)計
  關(guān)鍵組件
      Acegi安全系統(tǒng)包含以下七個關(guān)鍵的功能組件:
        1 Authentication對象,包含了Principal,Credential和Principal的授權(quán)信息。同時還可以包含關(guān)于發(fā)起認證請求的客戶的其他信息,如IP地址。
        2 ContextHolder對象,使用ThreadLocal儲存Authentication對象的地方。
        3 AuthenticationManager,用于認證ContextHolder中的Authentication對象。
        4 AccessDecissionManager,用于授權(quán)一個特定的操作。
        5 RunAsManager,當(dāng)執(zhí)行特定的操作時,用于選擇性地替換Authentication對象。
        6 Secure Object攔截器,用于協(xié)調(diào)AuthenticationManager,AccessDecissionManager,RunAsManager和特定操作的執(zhí)行。
        7 ObjectDefinitionSource,包含了特定操作的授權(quán)定義。
      這七個關(guān)鍵的功能組件的關(guān)系如下圖所示(圖中灰色部分是關(guān)鍵組件):


安全管理對象
       Acegi安全系統(tǒng)目前支持兩類安全管理對象。
       第一類的安全管理對象管理AOP Alliance的MethodInvocation,開發(fā)人員可以用它來保護Spring容器中的業(yè)務(wù)對象。為了使Spring管理的Bean可以作為MethodInvocation來使用,Bean可以通過ProxyFactoryBean和BeanNameAutoProxyCreator來管理,就像在Spring的事務(wù)管理一樣使用。
       第二類是FilterInvocation。它用過濾器(Filter)來創(chuàng)建,并簡單地包裝了HTTP的ServletRequest,ServletResponse和FilterChain。FilterInvocation可以用來保護HTTP資源。通常,開發(fā)人員并不需要了解它的工作機制,因為他們只需要將Filter加入web.xml,Acegi安全系統(tǒng)就可以工作了。

安全配置參數(shù)
       每個安全管理對象都可以描述數(shù)量不限的各種安全認證請求。例如,MethodInvocation對象可以描述帶有任意參數(shù)的任意方法的調(diào)用,而FilterInvocation可以描述任意的HTTP URL。
       Acegi安全系統(tǒng)需要記錄應(yīng)用于每個認證請求的安全配置參數(shù)。例如,對于BankManager.getBalance(int accountNumber)方法和BankManager.approveLoan(int applicationNumber)方法,它們需要的認證請求的安全配置很不相同。
       為了保存不同的認證請求的安全配置,需要使用配置參數(shù)。從實現(xiàn)的視角來看,配置參數(shù)使用ConfigAttribute接口來表示。Acegi安全系統(tǒng)提供了ConfigAttribute接口的一個實現(xiàn),SecurityConfig,它把配置參數(shù)保存為一個字符串。
       ConfigAttributeDefinition類是ConfigAttribute對象的一個簡單的容器,它保存了和特定請求相關(guān)的ConfigAttribute的集合。
       當(dāng)安全攔截器收到一個安全認證請求時,需要決定應(yīng)用哪一個配置參數(shù)。換句話說,它需要找出應(yīng)用于這個請求的ConfigAttributeDefinition對象。這個查找的過程是由ObjectDefinitionSource接口來處理的。這個接口的主要方法是public ConfigAttributeDefinition getAttributes(Object object),其中Object參數(shù)是一個安全管理對象。因為安全管理對象包含有認證請求的詳細信息,所以O(shè)bjectDefinitionSource接口的實現(xiàn)類可以從中獲得所需的詳細信息,以查找相關(guān)的ConfigAttributeDefiniton對象。


Acegi如何工作
       為了說明Acegi安全系統(tǒng)如何工作,我們設(shè)想一個使用Acegi的例子。通常,一個安全系統(tǒng)需要發(fā)揮作用,它必須完成以下的工作:
      1 首先,系統(tǒng)從客戶端請求中獲得Principal和Credential;
      2 然后系統(tǒng)認證Principal和Credential信息;
      3 如果認證通過,系統(tǒng)取出Principal的授權(quán)信息;
      4 接下來,客戶端發(fā)起操作請求;
      5 系統(tǒng)根據(jù)預(yù)先配置的參數(shù)檢查Principal對于該操作的授權(quán);
      6 如果授權(quán)檢查通過則執(zhí)行操作,否則拒絕。
      那么,Acegi安全系統(tǒng)是如何完成這些工作的呢?首先,我們來看看Acegi安全系統(tǒng)的認證和授權(quán)的相關(guān)類:
      安全攔截器的抽象基類,它包含有兩個管理類,AuthenticationManager和AccessDecisionManager。AuthenticationManager用于認證ContextHolder中的Authentication對象(包含了Principal,Credential和Principal的授權(quán)信息);AccessDecissionManager則用于授權(quán)一個特定的操作。

      下面來看一個MethodSecurityInterceptor的例子:
      <bean id="bankManagerSecurity" 
                     class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
             <property name="validateConfigAttributes">
                    <value>true</value>
            </property>
            <property name="authenticationManager">
                   <ref bean="authenticationManager"/>
            </property>
            <property name="accessDecisionManager">
                  <ref bean="accessDecisionManager"/>
            </property>
            <property name="objectDefinitionSource">
                  <value>
                     net.sf.acegisecurity.context.BankManager.delete*=
                             ROLE_SUPERVISOR,RUN_AS_SERVER
                     net.sf.acegisecurity.context.BankManager.getBalance=
                             ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_
                  </value>
            </property>
      </bean>

      上面的配置文件中,MethodSecurityInterceptor是AbstractSecurityInterceptor的一個實現(xiàn)類。它包含了兩個管理器,authenticationManager和accessDecisionManager。這兩者的配置如下:
      
<bean id="authenticationDao" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
               <property name="dataSource"><ref bean="dataSource"/></property>
      </bean>
      <bean id="daoAuthenticationProvider"
                     class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
               <property name="authenticationDao"><ref bean="authenticationDao"/></property>
      </bean>
      <bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
               <property name="providers">
                      <list><ref bean="daoAuthenticationProvider"/></list>
               </property>
      </bean>
      <bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
      <bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
               <property name="allowIfAllAbstainDecisions"><value>false</value></property>
               <property name="decisionVoters">
                      <list><ref bean="roleVoter"/></list>
               </property>
      </bean>


       準(zhǔn)備工作做好了,現(xiàn)在我們來看看Acegi安全系統(tǒng)是如何實現(xiàn)認證和授權(quán)機制的。以使用HTTP BASIC認證的應(yīng)用為例子,它包括下面的步驟:
       1. 用戶登錄系統(tǒng),Acegi從acegisecurity.ui子系統(tǒng)的安全攔截器(如BasicProcessingFilter)中得到用戶的登錄信息(包括Principal和Credential)并放入Authentication對象,并保存在ContextHolder對象中;
       2. 安全攔截器將Authentication對象交給AuthenticationManager進行身份認證,如果認證通過,返回帶有Principal授權(quán)信息的Authentication對象。此時ContextHolder對象的Authentication對象已擁有Principal的詳細信息;
       3. 用戶登錄成功后,繼續(xù)進行業(yè)務(wù)操作;
       4. 安全攔截器(bankManagerSecurity)收到客戶端操作請求后,將操作請求的數(shù)據(jù)包裝成安全管理對象(FilterInvocation或MethodInvocation對象);
       5. 然后,從配置文件(ObjectDefinitionSource)中讀出相關(guān)的安全配置參數(shù)ConfigAttributeDefinition;
       6. 接著,安全攔截器取出ContextHolder中的Authentication對象,把它傳遞給AuthenticationManager進行身份認證,并用返回值更新ContextHolder的Authentication對象;
       7. 將Authentication對象,ConfigAttributeDefinition對象和安全管理對象(secure Object)交給AccessDecisionManager,檢查Principal的操作授權(quán);
       8. 如果授權(quán)檢查通過則執(zhí)行客戶端請求的操作,否則拒絕;

AccessDecisionVoter
       注意上節(jié)的accessDecisionManager是一個AffirmativeBased類,它對于用戶授權(quán)的投票策略是,只要通過其中的一個授權(quán)投票檢查,即可通過;它的allowIfAllAbstainDecisions屬性值是false,意思是如果所有的授權(quán)投票是都是棄權(quán),則通不過授權(quán)檢查。
       Acegi安全系統(tǒng)包括了幾個基于投票策略的AccessDecisionManager,上節(jié)的RoleVoter就是其中的一個投票策略實現(xiàn),它是AccessDecisionVoter的一個子類。AccessDecisionVoter的具體實現(xiàn)類通過投票來進行授權(quán)決策,AccessDecisionManager則根據(jù)投票結(jié)果來決定是通過授權(quán)檢查,還是拋出AccessDeniedException例外。
       AccessDecisionVoter接口共有三個方法:
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config);
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
       其中的vote方法返回int返回值,它們是AccessDecisionVoter的三個靜態(tài)成員屬性:ACCESS_ABSTAIN,,ACCESS_DENIED和ACCESS_GRANTED,它們分別是棄權(quán),否決和贊成。
       Acegi安全系統(tǒng)中,使用投票策略的AccessDecisionManager共有三個具體實現(xiàn)類:AffirmativeBased、ConsensusBased和UnanimousBased。它們的投票策略是,AffirmativeBased類只需有一個投票贊成即可通過;ConsensusBased類需要大多數(shù)投票贊成即可通過;而UnanimousBased類需要所有的投票贊成才能通過。
       RoleVoter類是一個Acegi安全系統(tǒng)AccessDecisionVoter接口的實現(xiàn)。如果ConfigAttribute以ROLE_開頭,RoleVoter則進行投票。如果GrantedAuthority的getAutority方法的String返回值匹配一個或多個以ROLE_開頭的ConfigAttribute,則投票通過,否則不通過。如果沒有以ROLE_開頭的ConfigAttribute,RoleVoter則棄權(quán)。

安全攔截器
  攔截器如何工作
  MethodInvocation攔截器
  FilterInvocation攔截器
認證
  認證請求
  認證管理器
  Authentication Provider
授權(quán)
  Access Decision Manager
  Voting Decision Manager
  授權(quán)管理推薦
ContextHolder的用戶接口
  用戶接口目標(biāo)
  HTTP會話認證
  HTTP Basic認證

1、Log4j的概念
   Log4j中有三個主要的組件,它們分別是Logger、Appender和Layout,Log4j 允許開發(fā)人員定義多個Logger,每個Logger擁有自己的名字,Logger之間通過名字來表明隸屬關(guān)系。有一個Logger稱為Root,它永遠 存在,且不能通過名字檢索或引用,可以通過Logger.getRootLogger()方法獲得,其它Logger通過 Logger.getLogger(String name)方法。
   Appender則是用來指明將所有的log信息存放到什么地方,Log4j中支持多種appender,如 console、files、GUI components、NT Event Loggers等,一個Logger可以擁有多個Appender,也就是你既可以將Log信息輸出到屏幕,同時存儲到一個文件中。
   Layout的作用是控制Log信息的輸出方式,也就是格式化輸出的信息。
   Log4j中將要輸出的Log信息定義了5種級別,依次為DEBUG、INFO、WARN、ERROR和FATAL,當(dāng)輸出時,只有級別高過配置中規(guī)定的 級別的信息才能真正的輸出,這樣就很方便的來配置不同情況下要輸出的內(nèi)容,而不需要更改代碼,這點實在是方便啊。

2、Log4j的配置文件
  雖然可以不用配置文件,而在程序中實現(xiàn)配置,但這種方法在如今的系統(tǒng)開發(fā)中顯然是不可取的,能采用配置文件的地方一定一定要用配置文件。Log4j支持兩 種格式的配置文件:XML格式和Java的property格式,本人更喜歡后者,首先看一個簡單的例子吧,如下:

 log4j.rootLogger=debug, stdout, R
  log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

  # Pattern to output the caller's file name and line number.
  log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

  log4j.appender.R=org.apache.log4j.RollingFileAppender
  log4j.appender.R.File=example.log
  log4j.appender.R.MaxFileSize=100KB

  # Keep one backup file
  log4j.appender.R.MaxBackupIndex=1

  log4j.appender.R.layout=org.apache.log4j.PatternLayout
  log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
        

  首先,是設(shè)置root,格式為 log4j.rootLogger=[level],appenderName, ...,其中l(wèi)evel就是設(shè)置需要輸出信息的級別,后面是appender的輸出的目的地,appenderName就是指定日志信息輸出到哪個地方。您可以同時指定多個輸出目的地。配置日志信息輸出目的地Appender,其語法為
  log4j.appender.appenderName = fully.qualified.name.of.appender.class
  log4j.appender.appenderName.option1 = value1
  ...
  log4j.appender.appenderName.option = valueN
Log4j提供的appender有以下幾種:
  org.apache.log4j.ConsoleAppender(控制臺)
  org.apache.log4j.FileAppender(文件)
  org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個日志文件)
  org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產(chǎn)生新文件)
  org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)
配置日志信息的格式(布局),其語法為:
  log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
  log4j.appender.appenderName.layout.option1 = value1
  ....
  log4j.appender.appenderName.layout.option = valueN
Log4j提供的layout有以下幾種:
  org.apache.log4j.HTMLLayout(以HTML表格形式布局),
  org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
  org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串),
  org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時間、線程、類別等等信息)

3、Log4j在程序中的使用
  要在自己的類中使用Log4j,首先聲明一個靜態(tài)變量Logger logger=Logger.getLog("classname");在使用之前,用PropertyConfigurator.configure ("配置文件")配置一下,現(xiàn)在就可以使用了,用法如下:logger.debug("debug message")或者logger.info("info message"),看下面一個小例子:

 import com.foo.Bar;
  import org.apache.log4j.Logger;
  import org.apache.log4j.PropertyConfigurator;
  public class MyApp {
    static Logger logger = Logger.getLogger(MyApp.class.getName());
    public static void main(String[] args) {
      // BasicConfigurator replaced with PropertyConfigurator.
      PropertyConfigurator.configure(args[0]);
      logger.info("Entering application.");
      Bar bar = new Bar();
      bar.doIt();
      logger.info("Exiting application.");
    }
  }



[簡介]

對于一個典型的Web應(yīng)用,完善的認證和授權(quán)機制是必不可少的,在SpringFramework中,Juergen Hoeller提供的范例JPetStore給了一些這方面的介紹,但還遠遠不夠,Acegi是一個專門為SpringFramework提供安全機制的 項目,全稱為Acegi Security System for Spring,當(dāng)前版本為0.5.1,就其目前提供的功能,應(yīng)該可以滿足絕大多數(shù)應(yīng)用的需求。

本文的主要目的是希望能夠說明如何在基于Spring構(gòu)架的Web應(yīng)用中使用Acegi,而不是詳細介紹其中的每個接口、每個類。注意,即使對已經(jīng)存在的Spring應(yīng)用,通過下面介紹的步驟,也可以馬上享受到Acegi提供的認證和授權(quán)。

[基礎(chǔ)工作]
在你的Web應(yīng)用的lib中添加Acegi下載包中的acegi-security.jar

[web.xml]
實現(xiàn)認證和授權(quán)的最常用的方法是通過filter,Acegi亦是如此,通常Acegi需要在web.xml添加以下5個filter:

<filter>
  <filter-name>Acegi Channel Processing Filter</filter-name>
  <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
  <init-param>
    <param-name>targetClass</param-name>
    <param-value>net.sf.acegisecurity.securechannel.ChannelProcessingFilter</param-value>
  </init-param>
</filter>
<filter>
  <filter-name>Acegi Authentication Processing Filter</filter-name>
  <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
  <init-param>
    <param-name>targetClass</param-name>
    <param-value>net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter</param-value>
  </init-param>
</filter>
<filter>
  <filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
  <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
  <init-param>
    <param-name>targetClass</param-name>
    <param-value>net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter</param-value>
  </init-param>
</filter>
<filter>
  <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
  <filter-class>net.sf.acegisecurity.ui.AutoIntegrationFilter</filter-class>
</filter>
<filter>
  <filter-name>Acegi HTTP Request Security Filter</filter-name>
  <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
  <init-param>
    <param-name>targetClass</param-name>
    <param-value>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</param-value>
  </init-param>
</filter>


最先引起迷惑的是net.sf.acegisecurity.util.FilterToBeanProxy,Acegi自己的文檔上解釋是: “What  FilterToBeanProxy does is delegate the Filter's methods through to a bean which is obtained from the
Spring application context. This enables the bean to benefit from the Spring application context lifecycle support and configuration flexibility.”,如希望深究的話,去看看源代碼應(yīng)該不難理解。

再下來就是添加filter-mapping了:
<filter-mapping>
  <filter-name>Acegi Channel Processing Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>Acegi Authentication Processing Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>Acegi HTTP Request Security Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>


這里,需要注意以下兩點:
1) 這幾個filter的順序是不能更改的,順序不對將無法正常工作;
2) 如果你的應(yīng)用不需要安全傳輸,如https,則將"Acegi Channel Processing Filter"相關(guān)內(nèi)容注釋掉即可;
3) 如果你的應(yīng)用不需要Spring提供的遠程訪問機制,如Hessian and Burlap,將"Acegi HTTP BASIC Authorization
Filter"相關(guān)內(nèi)容注釋掉即可。

[applicationContext.xml]
接下來就是要添加applicationContext.xml中的內(nèi)容了,從剛才FilterToBeanFactory的解釋可以看出,真正的filter都
在Spring的applicationContext中管理:

1) 首先,你的數(shù)據(jù)庫中必須具有保存用戶名和密碼的table,Acegi要求table的schema必須如下:

CREATE TABLE users (
    username VARCHAR(50) NOT NULL PRIMARY KEY,
    password VARCHAR(50) NOT NULL,
    enabled BIT NOT NULL
);
CREATE TABLE authorities (
    username VARCHAR(50) NOT NULL,
    authority VARCHAR(50) NOT NULL
);
CREATE UNIQUE INDEX ix_auth_username ON authorities ( username, authority );
ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users
(username);


2) 添加訪問你的數(shù)據(jù)庫的datasource和Acegi的jdbcDao,如下:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
  <property name="url"><value>${jdbc.url}</value></property>
  <property name="username"><value>${jdbc.username}</value></property>
  <property name="password"><value>${jdbc.password}</value></property>
</bean>
<bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
  <property name="dataSource"><ref bean="dataSource"/></property>
</bean>


3) 添加DaoAuthenticationProvider:

<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
  <property name="authenticationDao"><ref bean="authenticationDao"/></property>
  <property name="userCache"><ref bean="userCache"/></property>
</bean>

<bean id="userCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
  <property name="minutesToIdle"><value>5</value></property>
</bean>


如果你需要對密碼加密,則在daoAuthenticationProvider中加入:<property name="passwordEncoder"><ref
bean="passwordEncoder"/></property>,Acegi提供了幾種加密方法,詳細情況可看包
net.sf.acegisecurity.providers.encoding

4) 添加authenticationManager:

<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
  <property name="providers">
    <list>
      <ref bean="daoAuthenticationProvider"/>
    </list>
   </property>
</bean>


5) 添加accessDecisionManager:

<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
  <property name="allowIfAllAbstainDecisions">
    <value>false</value>
  </property>
  <property name="decisionVoters">
    <list><ref bean="roleVoter"/></list>
  </property>
</bean>
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>


6) 添加authenticationProcessingFilterEntryPoint:

<bean id="authenticationProcessingFilterEntryPoint" 
class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
  <property name="loginFormUrl"><value>/acegilogin.jsp</value></property>
  <property name="forceHttps"><value>false</value></property>
</bean>


其中acegilogin.jsp是登陸頁面,一個最簡單的登錄頁面如下:

<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
<%@ page import="net.sf.acegisecurity.ui.AbstractProcessingFilter" %>
<%@ page import="net.sf.acegisecurity.AuthenticationException" %>
<html>
  <head>
    <title>Login</title>
  </head>

  <body>
    <h1>Login</h1>
    <form action="<c:url value='j_acegi_security_check'/>" method="POST">
      <table>
        <tr><td>User:</td><td><input type='text' name='j_username'></td></tr>
        <tr><td>Password:</td><td><input type='password' name='j_password'></td></tr>
        <tr><td colspan='2'><input name="submit" type="submit"></td></tr>
        <tr><td colspan='2'><input name="reset" type="reset"></td></tr>
      </table>
    </form>
  </body>
</html>


7) 添加filterInvocationInterceptor:

<bean id="filterInvocationInterceptor" 
class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
  <property name="authenticationManager">
    <ref bean="authenticationManager"/>
  </property>
  <property name="accessDecisionManager">
    <ref bean="accessDecisionManager"/>
  </property>
  <property name="objectDefinitionSource">
    <value>
      CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
      \A/sec/administrator.*\Z=ROLE_SUPERVISOR
      \A/sec/user.*\Z=ROLE_TELLER
    </value>
  </property>
</bean>


這里請注意,要objectDefinitionSource中定義哪些頁面需要權(quán)限訪問,需要根據(jù)自己的應(yīng)用需求進行修改,我上面給出
的定義的意思是這樣的:
a. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON意思是在比較請求路徑時全部轉(zhuǎn)換為小寫
b. \A/sec/administrator.*\Z=ROLE_SUPERVISOR意思是只有權(quán)限為ROLE_SUPERVISOR才能訪問/sec/administrator*的頁面
c. \A/sec/user.*\Z=ROLE_TELLER意思是只有權(quán)限為ROLE_TELLER的用戶才能訪問/sec/user*的頁面

8) 添加securityEnforcementFilter:

<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
  <property name="filterSecurityInterceptor">
    <ref bean="filterInvocationInterceptor"/>
  </property>
  <property name="authenticationEntryPoint">
    <ref bean="authenticationProcessingFilterEntryPoint"/>
  </property>
</bean>


9) 添加authenticationProcessingFilter:

<bean id="authenticationProcessingFilter" 
class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
  <property name="authenticationManager">
    <ref bean="authenticationManager"/>
  </property>
  <property name="authenticationFailureUrl">
    <value>/loginerror.jsp</value>
  </property>
  <property name="defaultTargetUrl">
    <value>/</value>
  </property>
  <property name="filterProcessesUrl">
    <value>/j_acegi_security_check</value>
  </property>
</bean>

其中authenticationFailureUrl是認證失敗的頁面。

10) 如果需要一些頁面通過安全通道的話,添加下面的配置:

<bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter">
  <property name="channelDecisionManager">
    <ref bean="channelDecisionManager"/>
  </property>
  <property name="filterInvocationDefinitionSource">
    <value>
      CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
      \A/sec/administrator.*\Z=REQUIRES_SECURE_CHANNEL
      \A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL
      \A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL
      \A.*\Z=REQUIRES_INSECURE_CHANNEL
    </value>
  </property>
</bean>

<bean id="channelDecisionManager" class="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl">
  <property name="channelProcessors">
    <list>
      <ref bean="secureChannelProcessor"/>
      <ref bean="insecureChannelProcessor"/>
    </list>
  </property>
</bean>
<bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/>
<bean id="insecureChannelProcessor" class="net.sf.acegisecurity.securechannel.InsecureChannelProcessor"/>


[缺少了什么?]
Acegi目前提供了兩種"secure object",分別對頁面和方法進行安全認證管理,我這里介紹的只是利用
FilterSecurityInterceptor對訪問頁面的權(quán)限控制,除此之外,Acegi還提供了另外一個Interceptor――
MethodSecurityInterceptor,它結(jié)合runAsManager可實現(xiàn)對對象中的方法的權(quán)限控制,使用方法可參看Acegi自帶的文檔
和contact范例。

[最后要說的]
本來以為只是說明如何使用Acegi而已,應(yīng)該非常簡單,但真正寫起來才發(fā)現(xiàn)想要條理清楚的理順?biāo)行枰腷ean還是很
困難的,但愿我沒有遺漏太多東西,如果我的文章有什么遺漏或錯誤的話,還請參看Acegi自帶的quick-start范例,但請
注意,這個范例是不能直接拿來用的。
分析和學(xué)習(xí)Spring中的jpetstore用戶管理
  存在用戶的系統(tǒng),必然需要用戶的登錄和認證,今天就通過分析Spring中自帶的jpetstore的例子來學(xué)習(xí)一下如何實現(xiàn)在Spring構(gòu)架的系統(tǒng)中用戶登錄。
1、首先從注冊用戶開始,先看看jpetstore-servlet.xml中關(guān)于注冊用戶的bean定義,從定義命名中就可以看出下面這段就是注冊用戶的:
  
<bean name="/shop/newAccount.do" class="org.springframework.samples.jpetstore.web.spring.AccountFormController">
    <property name="petStore"><ref bean="petStore"/></property>
    <property name="validator"><ref bean="accountValidator"/></property>
    <property name="successView"><value>index</value></property>
  </bean>

1). formView呢?從AccountFormController的構(gòu)造函數(shù)中得到,原來為EditAccountForm;  
2). EditoAccountForm.jsp中顯得非常亂,其實沒有多少難理解的地方,最主要的是這個form既是添加新用戶的,又是編輯用戶信息的,所以顯得有點亂糟糟的。
2、添加好了新用戶,接下來看看如何登錄,在jpetstore-servlet中發(fā)現(xiàn)這兩個相關(guān)bean定義,如下:
  
<bean name="/shop/signon.do" class="org.springframework.samples.jpetstore.web.spring.SignonController">
    <property name="petStore"><ref bean="petStore"/></property>
  </bean>
  <bean name="/shop/signonForm.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
    <property name="viewName"><value>SignonForm</value></property>
  </bean>

1). 第二個bean是在運行時用戶輸入用戶名和密碼的form,叫做SignonForm,對于這個 ParameterizableViewController,用文檔里的話說這是最簡單的Controller,其作用就是在運行中指向 Controller而不是直接指向jsp文件,僅此而已。
2). SignonForm.jsp,里面就是一個簡單的form,其action就是第一個bean,即/shop/signon.do,最需要注意的是 signonForwardAction,其主要作用是forward到需要輸入用戶名和密碼的那個頁面上去,這個變量哪里來的呢?看看下面:
  
<bean id="secureHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="interceptors">
      <list>
        <ref bean="signonInterceptor"/>
      </list>
    </property>
    <property name="urlMap">
      <map>
        <entry key="/shop/editAccount.do"><ref local="secure_editAccount"/></entry>
        <entry key="/shop/listOrders.do"><ref local="secure_listOrders"/></entry>
        <entry key="/shop/newOrder.do"><ref local="secure_newOrder"/></entry>
        <entry key="/shop/viewOrder.do"><ref local="secure_viewOrder"/></entry>
      </map>
    </property>
  </bean>

  原來,上面的signonInterceptor實現(xiàn)了preHandle,因此在請求上面的map頁面時,首先要經(jīng)過這個Interceptor,看看 SignonInterceptor的源碼,原來在其中為signon.jsp賦予一個signonForwardAction對象,呵呵,總算明白了。
3). 接下來去學(xué)習(xí)一下SignonController,其主體部分中可以看出,首先取出用戶輸入的username和password,然后到數(shù)據(jù)庫中驗證 有沒有這個用戶,如果沒有這個用戶,返回各錯誤頁面;如果成功,首先生成一個UserSession對象,在request的session加入這個 userSession,注意這部分代碼中給出了PagedListHolder分頁的簡單使用方法,關(guān)于分頁顯示,以后再學(xué)習(xí)吧。
3、登錄成功后,就可以根據(jù)不同的用戶設(shè)施不同的行為了,取得用戶信息,無非就是從session取出userSession即可。

Eric.Zhou 2006-12-19 16:40 發(fā)表評論
]]>
WSH(webwork+spring+hibernate)+mysqlhttp://m.tkk7.com/rain1102/archive/2006/12/19/88796.htmlEric.ZhouEric.ZhouTue, 19 Dec 2006 06:55:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/19/88796.htmlhttp://m.tkk7.com/rain1102/comments/88796.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/19/88796.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/88796.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/88796.html web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "<web-app>
    <display-name>Third Team</display-name>

<!--   <filter>
  <filter-name>Set Character Encoding</filter-name>
  <filter-class>com.founder.study.forum.helper.FilterChar</filter-class>
  <init-param>
   <param-name>encoding</param-name>
   <param-value>UTF-8</param-value>
  </init-param>
 </filter>-->
    <filter>
        <filter-name>webwork</filter-name>
        <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
    </filter>
<!--   <filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 <filter-mapping>
  <filter-name>Set Character Encoding</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>-->
    <filter-mapping>
        <filter-name>webwork</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
    <!--
        This typically isn't required, as the taglib is included in webwork.jar.
        If you really need a taglib configuration within web.xml, copy webwork/src/java/META-INF/taglib.tld
        to the WEB-INF directory as webwork.tld.
     -->
    <taglib>
        <taglib-uri>webwork</taglib-uri>
        <taglib-location>/WEB-INF/lib/webwork-2.2.4.jar</taglib-location>
    </taglib>
    <!-- <taglib>
  <taglib-uri>sitemesh-decorator</taglib-uri>
  <taglib-location>/WEB-INF/sitemesh-decorator.tld</taglib-location>
 </taglib>
 <taglib>
  <taglib-uri>sitemesh-page</taglib-uri>
  <taglib-location>/WEB-INF/sitemesh-page.tld</taglib-location>
 </taglib>-->
</web-app>

xwork.xml
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "
http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">

<xwork>
 <include file="webwork-default.xml" />
   
 <package name="default" extends="webwork-default">
    
     <interceptors>
         <interceptor-stack name="modelParamsStack">
           <interceptor-ref name="model-driven" />
            <interceptor-ref name="params" />
         </interceptor-stack>
     </interceptors>
    
  
 </package>
</xwork>

webwork.properties
webwork.objectFactory = spring
webwork.devMode = true
webwork.tag.altSyntax=true
webwork.locale=zh_CN
webwork.i18n.encoding=UTF-8
webwork.custom.i18n.resources=com.founder.study.forum.resource.ApplicationResources

jdbc.properties
# Properties file with JDBC-related settings.
# Applied by PropertyPlaceholderConfigurer from "applicationContext-*.xml".
# Targeted at system administrators, to avoid touching the context XML files.

jdbc.driverClassName=org.gjt.mm.mysql.Driver
jdbc.url=jdbc:mysql://localhost:3306/forum?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root


hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "

<beans default-autowire="byName">
<!-- JDBC Config /author Jerome_mao-->
 <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location" value="/WEB-INF/jdbc.properties" />
 </bean>
<!-- Config DateSource /author Jerome_mao-->
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="${jdbc.driverClassName}" />
  <property name="url" value="${jdbc.url}" />
  <property name="username" value="${jdbc.username}" />
  <property name="password" value="${jdbc.password}" />
 </bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" singleton="true">
 <property name="dataSource">
  <ref local="dataSource" />
 </property>
   <property name="mappingResources">
  <list>
   <value>com/founder/study/forum/model/Threadgroups.hbm.xml</value>
   <value>com/founder/study/forum/model/User.hbm.xml</value>
   <value>com/founder/study/forum/model/Userrole.hbm.xml</value>
  </list>
 </property>
<property name="hibernateProperties">
  <props>
   <prop key="hibernate.dialect">${hibernate.dialect}</prop>
   <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<!--   <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>-->
  </props>
</property> 
</bean>
 
 <!-- Hibernate transaction processing /author Jerome_mao-->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
 <property name="sessionFactory">
  <ref local="sessionFactory" />
 </property>
</bean>

<!-- commerce logic service config -->
<!-- User Service  /author Jerome_mao-->
<bean id="userService" class="com.founder.study.forum.service.impl.UserServiceImpl">
 <property name="userDAO">
  <ref bean="userDAO"/>
 </property>
</bean>
<!-- Data persistent layer  -->
<!-- User login   /author Jerome_mao -->
<bean id="userDAO" class="com.founder.study.forum.dao.hibernate.UserDAOHibernate">
 <property name="sessionFactory">
  <ref local="sessionFactory" />
 </property>
</bean>
<bean id="forumService" class="com.founder.study.forum.service.impl.ForumServiceImpl">
  <property name="forumTypeDAO">
    <ref local="forumTypeDAO"/>
  </property>
</bean>
<bean id="forumTypeDAO" class="com.founder.study.forum.dao.hibernate.ForumTypeDAOHibernate">
  <property name="sessionFactory">
    <ref local="sessionFactory"/>
  </property>
</bean>
<bean id="messageService" class="com.founder.study.forum.service.impl.MessageServiceImpl">
  <property name="messageTypeDAO">
    <ref local="messageTypeDAO"/>
  </property>
</bean>
<bean id="messageTypeDAO" class="com.founder.study.forum.dao.hibernate.MessageTypeDAOHibernate">
   <property name="sessionFactory">
     <ref local="sessionFactory"/>
   </property>
</bean>
<bean id="adminService" class="com.founder.study.forum.service.impl.AdminServiceImpl">
  <property name="adminDAO">
    <ref local="adminDAO"/>
  </property>
</bean>
<bean id="adminDAO" class="com.founder.study.forum.dao.hibernate.AdminDAOHibernate">
   <property name="sessionFactory">
     <ref local="sessionFactory"/>
   </property>
</bean>
</beans>



Eric.Zhou 2006-12-19 14:55 發(fā)表評論
]]>
配置瀏覽器(webwork--config-browser.xml)http://m.tkk7.com/rain1102/archive/2006/12/19/88681.htmlEric.ZhouEric.ZhouTue, 19 Dec 2006 01:39:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/19/88681.htmlhttp://m.tkk7.com/rain1102/comments/88681.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/19/88681.html#Feedback1http://m.tkk7.com/rain1102/comments/commentRss/88681.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/88681.html、將webwork-configbrowser.jar文件放入WEB-INF/lib目錄.
第二、在xwork.xml中增加:<include file="config-browser.xml"/>
第三、在velocity.properties中添加velocimacro.library屬性.
      velocimacro.library=webwork.vm,tigris-macros.vm
最后,啟動服務(wù)器,瀏覽http://localhost:8080/config-browser/actionNames.action


Eric.Zhou 2006-12-19 09:39 發(fā)表評論
]]>
WebWork - webwork-default.xmlhttp://m.tkk7.com/rain1102/archive/2006/12/19/88671.htmlEric.ZhouEric.ZhouTue, 19 Dec 2006 00:58:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/19/88671.htmlhttp://m.tkk7.com/rain1102/comments/88671.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/19/88671.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/88671.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/88671.htmlA base configuration file named webwork-default.xml is included in the webwork jar file. This file may be included at the top of your xwork.xml file to include the standard configuration settings without having to copy them, like so:

								<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN""http://www.opensymphony.com/xwork/xwork-1.0.dtd">
								<xwork>
								<include file="webwork-default.xml"/>
								<package name="default" extends="webwork-default">
    ...
    </package></xwork>

The contents of webwork-default.xml are here:

								<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN""http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
								<xwork>
								<package name="webwork-default">
								<result-types>
								<result-type name="chain" class="com.opensymphony.xwork.ActionChainResult"/>
								<result-type name="dispatcher" class="com.opensymphony.webwork.dispatcher.ServletDispatcherResult" default="true"/>
								<result-type name="freemarker" class="com.opensymphony.webwork.views.freemarker.FreemarkerResult"/>
								<result-type name="httpheader" class="com.opensymphony.webwork.dispatcher.HttpHeaderResult"/>
								<result-type name="jasper" class="com.opensymphony.webwork.views.jasperreports.JasperReportsResult"/>
								<result-type name="redirect" class="com.opensymphony.webwork.dispatcher.ServletRedirectResult"/>
								<result-type name="redirect-action" class="com.opensymphony.webwork.dispatcher.ServletActionRedirectResult"/>
								<result-type name="stream" class="com.opensymphony.webwork.dispatcher.StreamResult"/>
								<result-type name="tiles" class="com.opensymphony.webwork.views.tiles.TilesResult"/>
								<result-type name="velocity" class="com.opensymphony.webwork.dispatcher.VelocityResult"/>
								<result-type name="xslt" class="com.opensymphony.webwork.views.xslt.XSLTResult"/>
								<result-type name="plaintext" class="com.opensymphony.webwork.dispatcher.PlainTextResult" />
								
										<!-- Results necessary when using 'browse server' and 'upload' feature of Richtexteditor -->
								
								<result-type name="richtexteditorGetFolders" class="com.opensymphony.webwork.views.jsp.ui.RichtexteditorGetFoldersResult" />
								<result-type name="richtexteditorGetFoldersAndFiles" class="com.opensymphony.webwork.views.jsp.ui.RichtexteditorGetFoldersAndFilesResult" />
								<result-type name="richtexteditorCreateFolder" class="com.opensymphony.webwork.views.jsp.ui.RichtexteditorCreateFolderResult" />
								<result-type name="richtexteditorFileUpload" class="com.opensymphony.webwork.views.jsp.ui.RichtexteditorFileUploadResult" />
								</result-types>
								<interceptors>
								<interceptor name="alias" class="com.opensymphony.xwork.interceptor.AliasInterceptor"/>
								<interceptor name="autowiring" class="com.opensymphony.xwork.spring.interceptor.ActionAutowiringInterceptor"/>
								<interceptor name="chain" class="com.opensymphony.xwork.interceptor.ChainingInterceptor"/>
								<interceptor name="component" class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>
								<interceptor name="conversionError" class="com.opensymphony.webwork.interceptor.WebWorkConversionErrorInterceptor"/>
								<interceptor name="createSession" class="com.opensymphony.webwork.interceptor.CreateSessionInterceptor" />
								<interceptor name="debugging" class="com.opensymphony.webwork.interceptor.debugging.DebuggingInterceptor" />
								<interceptor name="external-ref" class="com.opensymphony.xwork.interceptor.ExternalReferencesInterceptor"/>
								<interceptor name="execAndWait" class="com.opensymphony.webwork.interceptor.ExecuteAndWaitInterceptor"/>
								<interceptor name="exception" class="com.opensymphony.xwork.interceptor.ExceptionMappingInterceptor"/>
								<interceptor name="fileUpload" class="com.opensymphony.webwork.interceptor.FileUploadInterceptor"/>
								<interceptor name="i18n" class="com.opensymphony.xwork.interceptor.I18nInterceptor"/>
								<interceptor name="logger" class="com.opensymphony.xwork.interceptor.LoggingInterceptor"/>
								<interceptor name="model-driven" class="com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"/>
								<interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
								<interceptor name="prepare" class="com.opensymphony.xwork.interceptor.PrepareInterceptor"/>
								<interceptor name="static-params" class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>
								<interceptor name="scope" class="com.opensymphony.webwork.interceptor.ScopeInterceptor"/>
								<interceptor name="servlet-config" class="com.opensymphony.webwork.interceptor.ServletConfigInterceptor"/>
								<interceptor name="sessionAutowiring" class="com.opensymphony.webwork.spring.interceptor.SessionContextAutowiringInterceptor"/>
								<interceptor name="timer" class="com.opensymphony.xwork.interceptor.TimerInterceptor"/>
								<interceptor name="token" class="com.opensymphony.webwork.interceptor.TokenInterceptor"/>
								<interceptor name="token-session" class="com.opensymphony.webwork.interceptor.TokenSessionStoreInterceptor"/>
								<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
								<interceptor name="workflow" class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"/>
								
										<!-- Basic stack -->
								
								<interceptor-stack name="basicStack">
								<interceptor-ref name="exception"/>
								<interceptor-ref name="servlet-config"/>
								<interceptor-ref name="prepare"/>
								<interceptor-ref name="static-params"/>
								<interceptor-ref name="params"/>
								<interceptor-ref name="conversionError"/>
								</interceptor-stack>
								
										<!-- Sample validation and workflow stack -->
								
								<interceptor-stack name="validationWorkflowStack">
								<interceptor-ref name="basicStack"/>
								<interceptor-ref name="validation"/>
								<interceptor-ref name="workflow"/>
								</interceptor-stack>
								
										<!-- Sample file upload stack -->
								
								<interceptor-stack name="fileUploadStack">
								<interceptor-ref name="fileUpload"/>
								<interceptor-ref name="basicStack"/>
								</interceptor-stack>

            <!-- Sample WebWork Inversion of Control stack
                 Note: WebWork's IoC is deprecated - please
                 look at alternatives such as Spring -->
            <interceptor-stack name="componentStack"><interceptor-ref name="component"/><interceptor-ref name="basicStack"/></interceptor-stack><!-- Sample model-driven stack  --><interceptor-stack name="modelDrivenStack"><interceptor-ref name="model-driven"/><interceptor-ref name="basicStack"/></interceptor-stack><!-- Sample action chaining stack --><interceptor-stack name="chainStack"><interceptor-ref name="chain"/><interceptor-ref name="basicStack"/></interceptor-stack><!-- Sample i18n stack --><interceptor-stack name="i18nStack"><interceptor-ref name="i18n"/><interceptor-ref name="basicStack"/></interceptor-stack>

            <!-- Sample execute and wait stack.
                 Note: execAndWait should always be the *last* interceptor. -->
            <interceptor-stack name="executeAndWaitStack"><interceptor-ref name="basicStack"/><interceptor-ref name="execAndWait"/></interceptor-stack>

            <!-- An example of the params-prepare-params trick. This stack
                 is exactly the same as the defaultStack, except that it
                 includes one extra interceptor before the prepare interceptor:
                 the params interceptor.

                 This is useful for when you wish to apply parameters directly
                 to an object that you wish to load externally (such as a DAO
                 or database or service layer), but can't load that object
                 until at least the ID parameter has been loaded. By loading
                 the parameters twice, you can retrieve the object in the
                 prepare() method, allowing the second params interceptor to
                 apply the values on the object. -->
            <interceptor-stack name="paramsPrepareParamsStack"><interceptor-ref name="exception"/><interceptor-ref name="alias"/><interceptor-ref name="params"/><interceptor-ref name="servlet-config"/><interceptor-ref name="prepare"/><interceptor-ref name="i18n"/><interceptor-ref name="chain"/><interceptor-ref name="model-driven"/><interceptor-ref name="fileUpload"/><interceptor-ref name="static-params"/><interceptor-ref name="params"/><interceptor-ref name="conversionError"/><interceptor-ref name="validation"><param name="excludeMethods">input,back,cancel</param></interceptor-ref><interceptor-ref name="workflow"><param name="excludeMethods">input,back,cancel</param></interceptor-ref></interceptor-stack>

            <!-- A complete stack with all the common interceptors in place.
                 Generally, this stack should be the one you use, though it
                 may do more than you need. Also, the ordering can be
                 switched around (ex: if you wish to have your servlet-related
                 objects applied before prepare() is called, you'd need to move
                 servlet-config interceptor up.

                 This stack also excludes from the normal validation and workflow
                 the method names input, back, and cancel. These typically are
                 associated with requests that should not be validated.
                 -->
            <interceptor-stack name="defaultStack"><interceptor-ref name="exception"/><interceptor-ref name="alias"/><interceptor-ref name="servlet-config"/><interceptor-ref name="prepare"/><interceptor-ref name="i18n"/><interceptor-ref name="chain"/><interceptor-ref name="debugging"/><interceptor-ref name="model-driven"/><interceptor-ref name="fileUpload"/><interceptor-ref name="static-params"/><interceptor-ref name="params"/><interceptor-ref name="conversionError"/><interceptor-ref name="validation"><param name="excludeMethods">input,back,cancel,browse</param></interceptor-ref><interceptor-ref name="workflow"><param name="excludeMethods">input,back,cancel,browse</param></interceptor-ref></interceptor-stack>

            <!-- The completeStack is here for backwards compatibility for
                 applications that still refer to the defaultStack by the
                 old name -->
            <interceptor-stack name="completeStack"><interceptor-ref name="defaultStack"/></interceptor-stack></interceptors><default-interceptor-ref name="defaultStack"/></package></xwork>

This file defines all of the default bundled results and interceptors and many interceptor stacks which you can use either as-is or as a basis for your own application-specific interceptor stacks. Notice the name of the package is "webwork-default".



Eric.Zhou 2006-12-19 08:58 發(fā)表評論
]]>
webwok中property-driven與model-drivenhttp://m.tkk7.com/rain1102/archive/2006/12/14/87801.htmlEric.ZhouEric.ZhouThu, 14 Dec 2006 12:17:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/14/87801.htmlhttp://m.tkk7.com/rain1102/comments/87801.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/14/87801.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/87801.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/87801.html本文的前提是,你愿意將頁面數(shù)據(jù)封裝為一個對象(是否封裝還得看實際情況,如果頁面數(shù)據(jù)特別少也沒這個必要)。

封裝頁面數(shù)據(jù)是否使用ModelDrivenInterceptor有時候還真與個人使用習(xí)慣有點關(guān)系

看下面的實現(xiàn)action1:

public class VoteAction implements Action, ModelDriven {
。。。。。
   /**
     * 封裝請求傳入的信息
     */
    private Vote vote = new Vote();
。。。。。
/**
     *
     * @author weip
     * @time 19:36:40 2006-5-14
     * @return Object
     */
    public Object getModel() {

        return vote;
    }
}
一個使用ModelDrivenInterceptor的action

還有另一種實現(xiàn)action2

public class VoteAction implements Action{
。。。。。
   /**
     * 封裝請求傳入的信息
     */
    private Vote vote = new Vote();
。。。。。
/**
     *
     * @author weip
     * @time 19:36:40 2006-5-14
     * @return Object
     */
    public Object getVote () {

        return vote;
    }
}

action1和action2效果完全一樣,只不過實現(xiàn)起來還是有少許差別
1) action1 需要配置ModelDrivenInterceptor,且實現(xiàn)ModelDriven 接口(如果沒有實現(xiàn)此接口,那么配置ModelDrivenInterceptor沒有任何意義),頁面的傳值很簡單<input type="text" name="type" />
這樣就可以將type的值注入到vote的type屬性
2)action2不需要配置ModelDrivenInterceptor,但頁面?zhèn)髦瞪晕⒙闊┮稽c
<input type="text" name="vote.type" />

如果使用form提交也無所謂,但如果使用url的方式就很累了。到底如何選擇就要看情況了,好像也無關(guān)緊要

Eric.Zhou 2006-12-14 20:17 發(fā)表評論
]]>
優(yōu)雅的解決web布局的問題 -- sitemesh的使用http://m.tkk7.com/rain1102/archive/2006/12/14/87799.htmlEric.ZhouEric.ZhouThu, 14 Dec 2006 12:12:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/14/87799.htmlhttp://m.tkk7.com/rain1102/comments/87799.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/14/87799.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/87799.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/87799.htmlwebwork的開發(fā)團隊opensymphony提供了一種優(yōu)雅的解決頁面布局的方法sitemesh。
sitemesh應(yīng)用Decorator模式,用filter截取request和response,把頁面組件head,content,banner
結(jié)合為一個完整的視圖。通常我們都是用include標(biāo)簽在每個jsp頁面中來不斷的包含各種header,
stylesheet, scripts and footer,現(xiàn)在,在sitemesh的幫助下,我們可以開心的刪掉他們了

下邊是創(chuàng)建一個簡單實例的步驟:
1,新建一個標(biāo)準(zhǔn)的web工程叫sitemesh
在WebRoot下新建一個index.jsp,內(nèi)容如下

1 <% @ page contentType = " text/html; charset=utf-8 " %>
2 this  is index.jsp.
3 it ' s a simple page 

接著在webRoot下新建幾個目錄
style2
login
shared
在login下建立目錄style3
然後把index.jsp分別復(fù)制到style2,login/style3,shared下
現(xiàn)在訪問下邊的鏈接:
http://localhost:8080/sitemesh/index.jsp
http://localhost:8080/sitemesh/style2/index.jsp
http://localhost:8080/sitemesh/login/style3/index.jsp
http://localhost:8080/sitemesh/shared/index.jsp
得到的結(jié)果是一樣的,那我們?nèi)绾巫屵@四個相同的index.jsp有不同的樣式呢。除了每個里邊加入include
還有個解決辦法,就是sitemesh
2,在http://www.opensymphony.com下載sitemesh-2.2.1.jar,sitemesh-decorator.tld,sitemesh-page.tld
三個文件。
復(fù)制sitemesh.jar到WEB-INF/lib下,
復(fù)制sitemesh-decorator.tld,sitemesh-page.tld到WEB-INF下
把下邊這部分加入web.xml
------------------------------------------------------------------------------
<filter>
  <filter-name>sitemesh</filter-name>
  <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>sitemesh</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<taglib>
  <taglib-uri>sitemesh-decorator</taglib-uri>
  <taglib-location>/WEB-INF/sitemesh-decorator.tld</taglib-location>
</taglib>

<taglib>
  <taglib-uri>sitemesh-page</taglib-uri>
  <taglib-location>/WEB-INF/sitemesh-page.tld</taglib-location>
</taglib>
--------------------------------------------------------------------------------
在WEB-INF下建立一個decorators.xml,內(nèi)容如下
excludes代表不使用的部分
其它三個是匹配url,使用style
--------------------------------------------------------------------------
<decorators defaultdir="/decorators">
    <excludes>
        <pattern>/shared/*</pattern>   
    </excludes>
    <decorator name="style1" page="style1.jsp">
        <pattern>/*</pattern>
    </decorator>
    <decorator name="style2" page="style2.jsp">
        <pattern>/style2/*</pattern>
    </decorator>
   
    <decorator name="style3" page="style3.jsp">
        <pattern>/*/style3/*</pattern>
    </decorator>
</decorators>
--------------------------------------------------------------------------
在WebRoot下新建一個目錄decorators
然後在下邊建立三個jsp文件,內(nèi)容如下
------------------------------------------------------------------
<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>
<html>
  <head>
    <title><decorator:title default="裝飾器頁面..." /></title>
    <decorator:head />
  </head>
  <body>
    <p><font color="red">this is style2's header</font></p>
    <hr>
    <decorator:body />
    <hr>
    <p><font color="red">this is style1's footer</font></p>
  </body>
</html>
------------------------------------------------------------------

<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>

<html>
  <head>
    <title><decorator:title default="裝飾器頁面..." /></title>
    <decorator:head />
  </head>
  <body>
    <p><font color="green">this is style2's header</font></p>
    <hr>
    <decorator:body />
    <hr>
    <p><font color="green">this is style2's footer</font></p>
  </body>
</html>

------------------------------------------------------------------
<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>

<html>
  <head>
    <title><decorator:title default="裝飾器頁面..." /></title>
    <decorator:head />
  </head>
  <body>
    <p><font color="blue">this is style3's header</font></p>
    <hr>
    <decorator:body />
    <hr>
    <p><font color="blue">this is style3's footer</font></p>
  </body>
</html>
------------------------------------------------------------------
再次訪問
http://localhost:8080/sitemesh/index.jsp
http://localhost:8080/sitemesh/style2/index.jsp
http://localhost:8080/sitemesh/login/style3/index.jsp
http://localhost:8080/sitemesh/shared/index.jsp
看到變化了吧。這只是個簡單的展示,仔細思考一下你的需求,你能作出更好的布局方式。
sitemesh真不錯。重要是學(xué)習(xí)簡單20分種就搞定了

Eric.Zhou 2006-12-14 20:12 發(fā)表評論
]]>
WebWork教程- Interceptor(攔截器)http://m.tkk7.com/rain1102/archive/2006/12/14/87781.htmlEric.ZhouEric.ZhouThu, 14 Dec 2006 11:16:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/14/87781.htmlhttp://m.tkk7.com/rain1102/comments/87781.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/14/87781.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/87781.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/87781.html WebWork 教程 - Interceptor( 攔截器 )
Interceptor (攔截器)將 Action 共用的行為獨立出來,在 Action 執(zhí)行前后運行。這也就是我們所說的 AOP Aspect Oriented Programming ,面向切面編程),它是分散關(guān)注的編程方法,它將通用需求功能從不相關(guān)類之中分離出來;同時,能夠使得很多類共享一個行為,一旦行為發(fā)生變化,不必修改很多類,只要修改這個行為就可以。
 
Interceptor 將很多功能從我們的 Action 中獨立出來,大量減少了我們 Action 的代碼,獨立出來的行為具有很好的重用性。 XWork 、 WebWork 的許多功能都是有 Interceptor 實現(xiàn),可以在配置文件中組裝 Action 用到的 Interceptor ,它會按照你指定的順序,在 Action 執(zhí)行前后運行。 Interceptor 在框架中的應(yīng)用如下圖所示
 
 
當(dāng)你提交對 Aciton (默認是 .action 結(jié)尾的 Url )的請求時, ServletDispatcher 會根據(jù)你的請求,去調(diào)度并執(zhí)行相應(yīng)的 Action 。在 Action 執(zhí)行之前,調(diào)用被 Interceptor 截取, Interceptor Action 執(zhí)行前后運行。
 
我們在用戶注冊的例子中就使用了取得 Request 請求參數(shù)的攔截器,配置文件中 <interceptor-ref name="params"/> 將攔截器 params 組裝到 RegisterAction 中。“ params ”在我們的 webwork-default.xml 配置文件中有定義, webwork-default.xml 中攔截器的定義如下:
 
<interceptors>
            <interceptor name="timer" class="com.opensymphony.xwork.interceptor.TimerInterceptor"/>
            <interceptor name="logger" class="com.opensymphony.xwork.interceptor.LoggingInterceptor"/>
            <interceptor name="chain" class="com.opensymphony.xwork.interceptor.ChainingInterceptor"/>
            <interceptor name="static-params" class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>
            <interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
            <interceptor name="model-driven" class="com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"/>
            <interceptor name="component" class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>
            <interceptor name="token" class="com.opensymphony.webwork.interceptor.TokenInterceptor"/>
            <interceptor name="token-session" class="com.opensymphony.webwork.interceptor.TokenSessionStoreInterceptor"/>
            <interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
            <interceptor name="workflow" class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"/>
            <interceptor name="servlet-config" class="com.opensymphony.webwork.interceptor.ServletConfigInterceptor"/>
            <interceptor name="prepare" class="com.opensymphony.xwork.interceptor.PrepareInterceptor"/>
            <interceptor name="conversionError" class="com.opensymphony.webwork.interceptor.WebWorkConversionErrorInterceptor"/>
            <interceptor-stack name="defaultStack">
                <interceptor-ref name="static-params"/>
                <interceptor-ref name="params"/>
                <interceptor-ref name="conversionError"/>
            </interceptor-stack>
            <interceptor-stack name="validationWorkflowStack">
                <interceptor-ref name="defaultStack"/>
                <interceptor-ref name="validation"/>
                <interceptor-ref name="workflow"/>
            </interceptor-stack>
        </interceptors>
這些都時有框架提供的默認的 Interceptor ,下面我來看看 Interceptor 使用的步驟:
1、   創(chuàng)建一個自己需要的 Interceptor 類,它必需實現(xiàn)
com.opensymphony.xwork.interceptor.Interceptor
接口,具體的開發(fā)見下面的 Interceptor 的原理。
2、   在配置文件( xwork..xml )中申明這個 Interceptor 類,它放在標(biāo)簽 <interceptor /> 中,同是 <interceptor /> 標(biāo)簽嵌入在 <interceptors /> 標(biāo)簽內(nèi)部。
3、   創(chuàng)建 Interceptor 棧,使用標(biāo)簽: <interceptor-stack /> , 讓一組 Interceptor 可以按次序調(diào)用。(可選)
4、   指定 Action 所要用到的 Interceptor (前面申明過的),可以用 <interceptor-ref /> <default-interceptor-ref /> 標(biāo)簽。前面的標(biāo)簽指定某個 Action 所用到的 Interceptor ,如果 Action 沒有被用 <interceptor-ref /> 指定 Interceptor ,它將使用 <default-interceptor-ref /> 指定的 Interceptor
框架中給我們提供了很多實用的 Interceptor ,它的定義上面已經(jīng)給出,它的具體功能如下:
l          timer :記錄 Action 執(zhí)行的時間,并做為日志信息輸出;
l          logger :在日志信息中輸出要執(zhí)行的 Action 信息;
l          chain :將前一個執(zhí)行結(jié)束的 Action 屬性設(shè)置到當(dāng)前的 Action 中。它被用在 ResultType 為“ chain ”指定結(jié)果的 Action 中,該結(jié)果 Action 對象會從 OgnlValueStack 中獲得前一個 Action 對應(yīng)的屬性,它實現(xiàn) Action 鏈之間的數(shù)據(jù)傳遞;
l          static-params :將 xwork.xml 配置文件里定義的 Action 參數(shù),設(shè)置到對應(yīng)的 Action 中。 Action 參數(shù)使用 <param /> 標(biāo)簽,是 <action /> 標(biāo)簽的直接子元素。我們這里定義的 Action 類必需實現(xiàn) com.opensymphony.xwork.config.entities . Parameterizable 接口;
l          params :將 Request 請求的參數(shù)設(shè)置到相應(yīng) Action 對象的屬性中,用戶注冊例子用到過這個攔截器;
l          model-driven :如果 Action 實現(xiàn) ModelDriven 接口,它將 getModel() 取得的模型對象存入 OgnlValueStack 中;
l          component :激活組件功能支持,讓注冊過的組件在當(dāng)前 Action 中可用,即為 Action 提供 IoC (依賴倒轉(zhuǎn)控制)框架的支持;
l          token :核對當(dāng)前 Action 請求( request )的有效標(biāo)識,防止重復(fù)提交 Action 請求 (request) 。
l          token-session :功能同上,但是當(dāng)提交無效的 Action 請求標(biāo)識時,它會將請求數(shù)據(jù)保存到 session 中。
l          validation :實現(xiàn)使用 xml 配置文件( {Action}-validation.xml )對 Action 屬性值進行驗證,詳細請看后面介紹的驗證框架。
l          workflow :調(diào)用 Action 類的驗證功能,假設(shè) Action 使用 ValidationAware 實現(xiàn)驗證( ActionSupport 提供此功能),如果驗證沒有通過, workflow 會將請求返回到 input 視圖( Action <result /> 中定義的)。
l          servlet-config :提供 Action 直接對 HttpServletRequest HttpServletResponse JavaServlet api 的訪問, Action 要實現(xiàn)相應(yīng)的接口,例如: ServletRequestAware ServletResponseAware 。如果必需要提供對 JavaServlet api 的訪問,我們建議使用 ServletActionContext ,在前面 ActionContext 章節(jié)中有介紹。
l          prepare :在 Action 執(zhí)行之前調(diào)用 Action prepare() 方法,這個方法是用來準(zhǔn)備 Action 執(zhí)行之前要做的工作。它要求我們的 Action 必需實現(xiàn) com.opensymphony.xwork . Preparable 接口
conversionError :用來處理框架進行類型轉(zhuǎn)化 (Type Conversion) 時的出錯信息。它將存儲在 ActionContext 中的類型轉(zhuǎn)化( Type Conversion )錯誤信息轉(zhuǎn)化成相應(yīng)的 Action 字段的錯誤信息,保存在堆棧中。根據(jù)需要,可以將這些錯誤信息在視圖中顯示出來。
 
Interceptor 的原理
下面我們來看看 Interceptor 是如何實現(xiàn)在 Action 執(zhí)行前后調(diào)用的:
Action Interceptor 在框架中的執(zhí)行,是由 ActionInvocation 對象調(diào)用的。它是用方法: String invoke() throws Exception; 來實現(xiàn)的,它首先會依次調(diào)用 Action 對應(yīng)的 Interceptor ,執(zhí)行完成所有的 Interceptor 之后,再去調(diào)用 Action 的方法,代碼如下:
if (interceptors.hasNext()) {
Interceptor interceptor = (Interceptor) interceptors.next();
resultCode = interceptor.intercept(this);
} else {
     if (proxy.getConfig().getMethodName() == null) {
resultCode = getAction().execute();
} else {
        resultCode = invokeAction(getAction(), proxy.getConfig());
}
}
它會在攔截器棧中遍歷 Interceptor ,調(diào)用 Interceptor 方法:
String intercept(ActionInvocation invocation) throws Exception; 。
我們一直都提到, Interceptor 是在 Action 前后執(zhí)行,可是從上面的代碼我們看到的卻是執(zhí)行完所有 Interceptor intercept () 方法之后再去調(diào)用我們的 Action 。“在 Action 前后執(zhí)行”是如何實現(xiàn)的呢?我們來看看抽象類 AroundInterceptor intercept () 實現(xiàn):
public String intercept(ActionInvocation invocation) throws Exception {
        String result = null;
 
        before(invocation);
        result = invocation.invoke();
        after(invocation, result);
 
        return result;
    }
原來在 intercept () 方法又對 ActionInvocation invoke() 方法進行遞歸調(diào)用, ActionInvocation 循環(huán)嵌套在 intercept () 中,一直到語句 result = invocation.invoke(); 執(zhí)行結(jié)束,即: Action 執(zhí)行完并返回結(jié)果 result ,這時 Interceptor 對象會按照剛開始執(zhí)行的逆向順序依次執(zhí)行結(jié)束。這樣 before () 方法將在 Action 執(zhí)行前調(diào)用, after () 方法在 Action 執(zhí)行之后運行


Eric.Zhou 2006-12-14 19:16 發(fā)表評論
]]>
WebWork教程-驗證框架http://m.tkk7.com/rain1102/archive/2006/12/14/87780.htmlEric.ZhouEric.ZhouThu, 14 Dec 2006 11:13:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/14/87780.htmlhttp://m.tkk7.com/rain1102/comments/87780.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/14/87780.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/87780.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/87780.html 驗證框架
WebWork 提供了在 Action 執(zhí)行之前,對輸入數(shù)據(jù)的驗證功能,它使用了其核心 XWork 的驗證框架。提供了如下功能:
1、   可配置的驗證文件。它的驗證文件是一個獨立的 XML 配置文件,對驗證的添加、修改只需更改配置文件,無需編譯任何的 Class 。
2、   驗證文件和被驗證的對象完全解藕。驗證對象是普通的 JavaBean 就可以了(可以是 FormBean 、域?qū)ο蟮龋?,它們不需實現(xiàn)任何額外的方法或繼承額外的類。
3、   多種不同的驗證方式。因為它驗證功能是可以繼承的,所以可以用多種不同的方式指定驗證文件,比如:通過父類的 Action 、通過 Action 、通過 Action 的方法、通過 Action 所使用的對象,等等。
4、   強大的表達式驗證。它使用了 OGNL 的表達式語言,提供強大的表達式驗證功能。
5、   同時支持服務(wù)器端和客戶端驗證。
為用戶注冊添加驗證功能
下面我們來看看如何為用戶注冊添加驗證功能:
1、   注冊我們的驗證類型
WebWork 為不同的驗證要求提供不同的驗證類型。一個驗證類型,一般是有一個類來提供。這個類必須實現(xiàn)接口: com.opensymphony.xwork.validator.Validator ,但我們在寫自己的驗證類型時,無需直接實現(xiàn) Validator 接口,它有抽象類可供直接使用如 ValidatorSupport 、 FieldValidatorSupport 等。
驗證類型在使用之前,必須要在 ValidatorFactory com.opensymphony.xwork.validator . ValidatorFactory )中 注冊??梢杂卸N方法實現(xiàn)驗證類型的注冊。一、寫程序代碼進行注冊,它使用 ValidatorFactory 類的靜態(tài)方法: registerValidator(String name, String className) 。 二、使用配置文件 validators.xml 進行注冊,要求把文件 validators.xml 放到 ClassPath 的跟目錄中( /WEB-INF/classes )。但在實際開發(fā)中,一般都使用第二中注冊方法。我們的驗證類型注冊如下:
<validators>
    <validator name="required" class="com.opensymphony.xwork.validator.validators.RequiredFieldValidator"/>
    <validator name="requiredstring" class="com.opensymphony.xwork.validator.validators.RequiredStringValidator"/>
    <validator name="int" class="com.opensymphony.xwork.validator.validators.IntRangeFieldValidator"/>
    <validator name="date" class="com.opensymphony.xwork.validator.validators.DateRangeFieldValidator"/>
    <validator name="expression" class="com.opensymphony.xwork.validator.validators.ExpressionValidator"/>
    <validator name="fieldexpression" class="com.opensymphony.xwork.validator.validators.FieldExpressionValidator"/>
    <validator name="email" class="com.opensymphony.xwork.validator.validators.EmailValidator"/>
    <validator name="url" class="com.opensymphony.xwork.validator.validators.URLValidator"/>
    <validator name="visitor" class="com.opensymphony.xwork.validator.validators.VisitorFieldValidator"/>
    <validator name="conversion" class="com.opensymphony.xwork.validator.validators.ConversionErrorFieldValidator"/>
    <validator name="stringlength" class="com.opensymphony.xwork.validator.validators.StringLengthFieldValidator"/>
</validators>
注冊驗證類型的配置文件非常簡單。它使用標(biāo)簽 <validator > 提供名-值對的形式注冊。這樣我們的驗證文件就可以直接引用它的名字。
2、   開啟 Action 的驗證功能
  如果 Action 要使用驗證框架的驗證功能,它必須在配置文件中指定攔截器“ validation ”,它的定義如下:
<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/> 。
我們的驗證文件必須以 ActionName-validation.xml 格式命名,它必須被放置到與這個 Action 相同的包中。你也可以為這個 Action 通過別名的方式指定驗證文件,它的命名格式為: ActionName-aliasname-validation.xml 。“ ActionName ”是我們 Action 的類名;“ aliasname ”是我們在配置文件( xwork.xml )中定義這個 Action 所用到的名稱。這樣,同一個 Action 類,在配置文件中的不同定義就可以對應(yīng)不同的驗證文件。驗證框架也會根據(jù) Action 的繼承結(jié)構(gòu)去查找 Action 的父類驗證文件,如果找到它會去執(zhí)行這個父類的驗證。
 
3、   實現(xiàn)我們的驗證文件: RegisterActionSupport-validation.xml
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd">
<validators>
    <field name="user.username">
    <field-validator type="requiredstring">
            <message>You must enter a value for username.</message>
        </field-validator>
    </field>
    <field name="user.password">
    <field-validator type="requiredstring">
            <message>You must enter a value for password.</message>
        </field-validator>
        <field-validator type="fieldexpression">
            <param name="expression">user.password == verifyPassword</param>
            <message>Passwords don't match.</message>
        </field-validator>
    </field>
    <field name="user.email">
    <field-validator type="email">
            <message>You must enter a valid email.</message>
        </field-validator>
    </field>
    <field name="user.age">
    <field-validator type="int">
            <param name="min">6</param>
            <param name="max">100</param>
            <message>Age must be between ${min} and ${max}, current value is ${user.age}.</message>
        </field-validator>
    </field>
</validators>
說明:
1 )、 <field > 標(biāo)簽代表一個字段,它的屬性“ name ”和頁面輸入框的“ name ”屬性必需完全一致,其實它也就是我們的表達式語言。
2 )、 <field-validator > 標(biāo)簽定義我們的驗證規(guī)則, type 屬性的值就是就是我們前面定義的驗證類型。
3 )、驗證文件中,字段的數(shù)據(jù)是通過表達式語言從我們的值堆棧( OgnlValueStack )中取得,一般是 Action Model 對象。例如:我們的字段“ user.age ”,它會通過 Action getUser().getAge() 來取得用戶輸入的年齡,再來根據(jù)驗證的類型“ int ”和最大值最小值的參數(shù)來判斷輸入的數(shù)據(jù)是否能通過驗證。
4 )、不管驗證是否通過,我們的 Action 都會執(zhí)行,但如果驗證沒有通過,它不會調(diào)用 Action execute() 方法。
 
4、   顯示 Action 的驗證錯誤信息
如果用戶輸入的數(shù)據(jù)驗證沒有通過,我們需重新返回輸入頁面,并給出錯誤信息提示。攔截器棧“ validationWorkflowStack ”為我們實現(xiàn)了這個功能。它首先驗證用戶輸入的數(shù)據(jù),如果驗證沒有通過將不執(zhí)行我們 Action execute() 方法,而是將請求重新返回到輸入頁面。
我們的 xwork.xml 配置文件如下:
<action name="registerSupport" class="example.register.RegisterActionSupport">
            <result name="success" type="dispatcher">
                <param name="location">/register-result.jsp</param>
            </result>
            <result name="input" type="dispatcher">
                <param name="location">/registerSupport.jsp</param>
            </result>
            <interceptor-ref name="validationWorkflowStack"/>
        </action>
 
通過接口 ValidationAware , 我們可以獲得類級別或字段級別的驗證錯誤信息,這個錯誤信息也就是我們驗證文件中 <message> 標(biāo)簽里的數(shù)據(jù)。 ActionSupport 類已實現(xiàn)了此接口,這樣在應(yīng)用中我們的 Action 只要繼承 ActionSupport 類就可以了。 RegisterActionSupport .java 代碼如下:
package example.register;
 
import com.opensymphony.xwork.ActionSupport;
 
public class RegisterActionSupport extends ActionSupport {
 
    private User user= new User();
    private String verifyPassword;
   
    public User getUser(){
        returnthis.user;
    }
   
    public String execute(){
        // 在這里調(diào)用用戶注冊的業(yè)務(wù)邏輯,比如:將注冊信息存儲到數(shù)據(jù)庫
        return SUCCESS;
    }
 
    public String getVerifyPassword(){
        returnthis.verifyPassword;
    }
   
    publicvoid setVerifyPassword(String verPassword){
        this.verifyPassword = verPassword;
    }
}
我們 WebWork UI 標(biāo)簽庫直接提供了驗證錯誤信息顯示功能。如果字段級別的驗證沒有通過,它會在輸入框上方顯示驗證文件定義的錯誤提示信息。我們將用戶輸入的頁面更改如下:
registerSupport.jsp
<%@ taglib uri="webwork" prefix="ww" %>
<html>
<head><title>Register Example</title></head>
<body>
<table border=0 width=97%>
<tr><td align="left">
    <ww:form name="'test'" action="'/example/registerSupport.action'" method="'POST'">
            <ww:textfield label="'Username'" name="'user.username'" required="true"/>
            <ww:textfield label="'Password'" name="'user.password'" required="true"/>
            <ww:textfield label="'VerifyPassword'" name="'verifyPassword'" required="true"/>
            <ww:textfield label="'Email'" name="'user.email'" required="true"/>
            <ww:textfield label="'Age'" name="'user.age'" required="true"/>
            <ww:submit value="'Submit'"/>
         </ww:form>
</td></tr>
</table>
</body>
</html>
我們上面的例子使用的是服務(wù)器端驗證。 WebWork 也為我們提供了方便的客戶端驗證。它將驗證自動生成 JavaScript 腳本。如果要使用客戶端驗證只需改變相應(yīng)的驗證類型就可以了(輸入頁面的表單必需使用 <ww:form> 標(biāo)簽,并設(shè)置屬性“ validate="true" ”)。具體的驗證類型可以在 WebWork 的包 com.opensymphony.webwork.validators 中找到。


Eric.Zhou 2006-12-14 19:13 發(fā)表評論
]]>
WebWork-ActionContext(Action上下文)http://m.tkk7.com/rain1102/archive/2006/12/13/87573.htmlEric.ZhouEric.ZhouWed, 13 Dec 2006 11:44:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/13/87573.htmlhttp://m.tkk7.com/rain1102/comments/87573.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/13/87573.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/87573.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/87573.html ActionContext 介紹
Web 應(yīng)用程序開發(fā)中,除了將請求參數(shù)自動設(shè)置到 Action 的字段中,我們往往也需要在 Action 里直接獲取請求 (Request) 或會話( Session )的一些信息 , 甚至需要直接對 JavaServlet Http 的請求( HttpServletRequest )、響應(yīng) (HttpServletResponse) 操作。
我們需要在 Action 中取得 request 請求參數(shù)“ username ”的值:
ActionContext context = ActionContext.getContext();
Map params = context.getParameters();
String username = (String) params.get(“username”);
ActionContext com.opensymphony.xwork.ActionContext )是 Action 執(zhí)行時的上下文,上下文可以看作是一個容器(其實我們這里的容器就是一個 Map 而已),它存放放的是 Action 在執(zhí)行時需要用到的對象
 
一般情況,我們的 ActionContext 都是通過: ActionContext context = (ActionContext) actionContext.get(); 來獲取的。我們再來看看這里的 actionContext 對象的創(chuàng)建: static ThreadLocal actionContext = new ActionContextThreadLocal(); , ActionContextThreadLocal 是實現(xiàn) ThreadLocal 的一個內(nèi)部類。 ThreadLocal 可以命名為“線程局部變量”,它為每一個使用該變量的線程都提供一個變量值的副本,使每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本沖突。這樣,我們 ActionContext 里的屬性只會在對應(yīng)的當(dāng)前請求線程中可見,從而保證它是線程安全的。
 
 
下面我們看看怎么通過 ActionContext 取得我們的 HttpSession
Map session = ActionContext.getContext().getSession() ;
 
ServletActionContext
ServletActionContext com.opensymphony.webwork. ServletActionContext ),這個類直接繼承了我們上面介紹的 ActionContext ,它提供了直接與 JavaServlet 相關(guān)對象訪問的功能,它可以取得的對象有:
1、   javax.servlet.http.HttpServletRequest HTTPservlet 請求對象
2、   javax.servlet.http.HttpServletResponse; HTTPservlet 相應(yīng)對象
3、   javax.servlet.ServletContext Servlet 上下文信息
4、   javax.servlet.ServletConfig Servlet 配置對象
5、   javax.servlet.jsp.PageContext Http 頁面上下文
 
 
下面我們看看幾個簡單的例子,讓我們了解如何從 ServletActionContext 里取得 JavaServlet 的相關(guān)對象:
1、   取得 HttpServletRequest 對象:
HttpServletRequest request = ServletActionContext. getRequest();
2、   取得 HttpSession 對象:
HttpSession session = ServletActionContext. getRequest().getSession();
 
ServletActionContext ActionContext 有著一些重復(fù)的功能,在我們的 Action 中,該如何去抉擇呢?我們遵循的原則是:如果 ActionContext 能夠?qū)崿F(xiàn)我們的功能,那最好就不要使用 ServletActionContext ,讓我們的 Action 盡量不要直接去訪問 JavaServlet 的相關(guān)對象。在使用 ActionContext 時有一點要注意:不要在 Action 的構(gòu)造函數(shù)里使用 ActionContext.getContext() ,因為這個時候 ActionContext 里的一些值也許沒有設(shè)置,這時通過 ActionContext 取得的值也許是 null 。


Eric.Zhou 2006-12-13 19:44 發(fā)表評論
]]>
WebWork介紹-Action篇http://m.tkk7.com/rain1102/archive/2006/12/13/87539.htmlEric.ZhouEric.ZhouWed, 13 Dec 2006 09:28:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/13/87539.htmlhttp://m.tkk7.com/rain1102/comments/87539.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/13/87539.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/87539.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/87539.html閱讀全文

Eric.Zhou 2006-12-13 17:28 發(fā)表評論
]]>
webwork中文件上傳實現(xiàn)http://m.tkk7.com/rain1102/archive/2006/12/13/87534.htmlEric.ZhouEric.ZhouWed, 13 Dec 2006 09:16:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/13/87534.htmlhttp://m.tkk7.com/rain1102/comments/87534.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/13/87534.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/87534.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/87534.html step1:
頁面定義如下
    <form action="upload.do" enctype="multipart/form-data" method="post">
            <input type="file" name="doc"/>
             ......................... 省略
   </form>

step2
    action 如下
    public class UploadAction extends ActionSupport {
          .....................................
          private File doc;//doc與頁面取一樣的名字

          public void setDoc(File doc) {
                 this.doc = doc;
         }

         //當(dāng)然還可以使用以下的咚咚
  /*
     * public void setDocContentType(String docContentType) {
     * this.docContentType = docContentType; }
     *
     *//**
         *
         * @author weip
         * @time 0:23:24 2006-5-11
         * @param docFileName
         */
    /*
     * public void setDocFileName(String docFileName) { this.docFileName =
     * docFileName; }
     */

    /**
     *
     */
    /*
     * private String docContentType;
     *
     *//**
         *
         */
    /*
     * private String docFileName;
     */

.............................................................

   }

當(dāng)程序進入到action當(dāng)中時,你可以開始處理上面代碼中的doc,此時文件已上傳到服務(wù)器中的一個臨時目錄(同時被注入到action中就是你看到的 doc),此臨時目錄由webwork.properties指定,你必須將此文件拷貝到你需要的目錄,否則action執(zhí)行完畢,此文件會被刪除,準(zhǔn)確說是攔截器的后處理刪除了臨時文件,這一段結(jié)論的前提是你使用攔截器處理上傳

step3
處理配置文件,配置攔截器

<action name="upload" class="com.mofile.baby.web.action.signup.UploadAction">
          
            <result name="success" type="freemarker">/page/signup/uploadfile.htm</result>
            <interceptor-ref name="fileUpload"/>
            <interceptor-ref name="defaultWebStack"/>
         
  </action>

step4
對于webwork.properties的一些處理
webwork in action上推薦使用webwork.multipart.parser=jakarta而不是默認的 pell,如果使用前者,不要忘了在你的lib中加入commons-fileupload.jar


需要注意的問題:
你在使用
fileUpload傳攔截器的時候應(yīng)該避免使用execAndWait攔截器,否則很有可能會出現(xiàn)空指針,因為execAndWait攔截器會在另一個線程處理action,而原來的線程會刪掉臨時文件,所以當(dāng)你在action中處理文件的時候很有可能文件已被刪掉,雖然這并非一定會出現(xiàn),但畢竟不安全

Eric.Zhou 2006-12-13 17:16 發(fā)表評論
]]>
webwork.propertieshttp://m.tkk7.com/rain1102/archive/2006/12/12/87328.htmlEric.ZhouEric.ZhouTue, 12 Dec 2006 11:28:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/12/87328.htmlhttp://m.tkk7.com/rain1102/comments/87328.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/12/87328.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/87328.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/87328.html### Webwork default properties ###(can be overridden by a webwork.properties file in the root of the classpath) ### ### Specifies the Configuration used to configure webwork ### one could extend com.opensymphony.webwork.config.Configuration ### to build one's customize way of getting the configurations parameters into webwork # webwork.configuration=com.opensymphony.webwork.config.DefaultConfiguration ### This can be used to set your default locale and encoding scheme # webwork.locale=en_US webwork.i18n.encoding=UTF-8 ### if specified, the default object factory can be overridden here ### Note: short-hand notation is supported in some cases, such as "spring" ### Alternatively, you can provide a com.opensymphony.xwork.ObjectFactory subclass name here # webwork.objectFactory = spring ### specifies the autoWiring logic when using the SpringObjectFactory. ### valid values are: name, type, auto, and constructor (name is the default) webwork.objectFactory.spring.autoWire = name ### indicates to the webwork-spring integration if Class instances should be cached ### this should, until a future Spring release makes it possible, be left as true ### unless you know exactly what you are doing! ### valid values are: true, false (true is the default) webwork.objectFactory.spring.useClassCache = true ### if specified, the default object type determiner can be overridden here ### Note: short-hand notation is supported in some cases, such as "tiger" or "notiger" ### Alternatively, you can provide a com.opensymphony.xwork.util.ObjectTypeDeterminer implementation name here ### Note: if you have the xwork-tiger.jar within your classpath, GenericsObjectTypeDeterminer is used by default ### To disable tiger support use the "notiger" property value here. #webwork.objectTypeDeterminer = tiger #webwork.objectTypeDeterminer = notiger ### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data # webwork.multipart.parser=cos # webwork.multipart.parser=pell webwork.multipart.parser=jakarta # uses javax.servlet.context.tempdir by default webwork.multipart.saveDir= webwork.multipart.maxSize=2097152 ### Load custom property files (does not override webwork.properties!) # webwork.custom.properties=application,com/webwork/extension/custom ### How request URLs are mapped to and from actions webwork.mapper.class=com.opensymphony.webwork.dispatcher.mapper.DefaultActionMapper ### Used by the DefaultActionMapper ### You may provide a comma separated list, e.g. webwork.action.extension=action,jnlp,do webwork.action.extension=action ### Used by FilterDispatcher ### If true than WW serves static content from inside its jar. ### If false than the static content must be available at <context_path>/webwork webwork.serve.static=true ### use alternative syntax that requires %{} in most places ### to evaluate expressions for String attributes for tags webwork.tag.altSyntax=true ### when set to true, WebWork will act much more friendly for developers. This ### includes: ### - webwork.i18n.reload = true ### - webwork.configuration.xml.reload = true ### - raising various debug or ignorable problems to errors ### For example: normally a request to foo.action?someUnknownField=true should ### be ignored (given that any value can come from the web and it ### should not be trusted). However, during development, it may be ### useful to know when these errors are happening and be told of ### them right away. webwork.devMode = false ### when set to true, resource bundles will be reloaded on _every_ request. ### this is good during development, but should never be used in production webwork.i18n.reload=false ### Standard UI theme ### Change this to reflect which path should be used for JSP control tag templates by default webwork.ui.theme=xhtml webwork.ui.templateDir=template #sets the default template type. Either ftl, vm, or jsp webwork.ui.templateSuffix=ftl ### Configuration reloading ### This will cause the configuration to reload xwork.xml when it is changed webwork.configuration.xml.reload=false ### Location of velocity.properties file. defaults to velocity.properties # webwork.velocity.configfile = velocity.properties ### Comma separated list of VelocityContext classnames to chain to the WebWorkVelocityContext # webwork.velocity.contexts = ### used to build URLs, such as the UrlTag webwork.url.http.port = 80 webwork.url.https.port = 443 ### possible values are: none, get or all webwork.url.includeParams = get ### Load custom default resource bundles # webwork.custom.i18n.resources=testmessages,testmessages2 ### workaround for some app servers that don't handle HttpServletRequest.getParameterMap() ### often used for WebLogic, Orion, and OC4J webwork.dispatcher.parametersWorkaround = false ### configure the Freemarker Manager class to be used ### Allows user to plug-in customised Freemarker Manager if necessary ### MUST extends off com.opensymphony.webwork.views.freemarker.FreemarkerManager #webwork.freemarker.manager.classname=com.opensymphony.webwork.views.freemarker.FreemarkerManager ### See the WebWorkBeanWrapper javadocs for more information webwork.freemarker.wrapper.altMap=true ### configure the XSLTResult class to use stylesheet caching. ### Set to true for developers and false for production. webwork.xslt.nocache=false

Eric.Zhou 2006-12-12 19:28 發(fā)表評論
]]>
webwork+spring+hibernate架構(gòu)目錄結(jié)構(gòu)http://m.tkk7.com/rain1102/archive/2006/12/11/86877.htmlEric.ZhouEric.ZhouMon, 11 Dec 2006 05:21:00 GMThttp://m.tkk7.com/rain1102/archive/2006/12/11/86877.htmlhttp://m.tkk7.com/rain1102/comments/86877.htmlhttp://m.tkk7.com/rain1102/archive/2006/12/11/86877.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/86877.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/86877.html

     轉(zhuǎn)自http://m.tkk7.com/black_zerg/archive/2005/05/30/5327.html 

       src 目錄下為 Java 源碼

dao    負責(zé)數(shù)據(jù)訪問對象的定義和實現(xiàn)

  其中 Dao 結(jié)尾為接口, Impl 結(jié)尾為實現(xiàn)。目前一般用 hibernate 做實現(xiàn)。
domain 實體對象

logic   針對實體對象封裝的邏輯

  這里 service 是外觀接口, serviceimpl 是實現(xiàn),考慮目前情況簡單,并沒有進一步分離邏輯,業(yè)務(wù)邏輯都在 impl 中完成。

web    界面相關(guān)的 Java

  common 是一些常用類,如處理中文問題的 filter.

  displaytag 中放了 displaytag 相關(guān)的類,多為 wrapper.

  webwork 中都是對應(yīng)的 action

其中 BaseAction 是基本的抽象類,基本后續(xù)開發(fā)應(yīng)繼承此類

CrudAction 是為了一般的 Crud 工作而作的一個抽象類,可以繼承用來簡化工作。

CaseDispatcher 負責(zé)菜單點擊后分發(fā)到相關(guān) Action ,同時處理權(quán)限和 session 工作。
 
其他 action 按模塊進行了組織

左邊是 webroot 的結(jié)構(gòu)

 

 

重要的配置文件有:

Spring

applicationContext.xml

applicationContext-db.xml

Webwork

xwork.xml

webwork.properties

i18n

 labels.properties

log4j

 log4j.properties

displaytag

 displaytag.properties

dbConnect

 jdbc.properties

 

關(guān)于一些技術(shù)難點和細節(jié):

1.  各框架連接: spring hibernate 使用 spring hibernate 支持。 Spring webwork 使用 autoware 的攔截機制自動裝配。

2.  列表的問題,采用 displaytag 。功能強大,使用簡潔,可實現(xiàn)排序和數(shù)據(jù)導(dǎo)出。

3.  數(shù)據(jù)下載,使用 displaytag 自帶的 excel 下載

4.  文件上傳,使用 webwork 提供的解決方案,用攔截機制實現(xiàn)。

5. jsp 代碼組織方面,我們使用 taglib css 技術(shù)使 jsp 中頁面邏輯減少到最小,一般情況完全可以不使用 <% %> script 。同時我們使用兩個 include 來包含常用的 taglib 定義, js 引用和 html 結(jié)構(gòu),使 jsp 代碼非常簡潔。

6.  中文問題 我們使用 filter 來解決頁面 gbk Java 程序 unicode 的轉(zhuǎn)換,同時通過正確的設(shè)置數(shù)據(jù)庫連接 url 完成和數(shù)據(jù)庫之間的交互。

7.  I18n 國際化。我們要求在 jsp 代碼中不出現(xiàn)中文,所有提示信息都通過資源文件 labels.properties 來完成。頁面中可以使用 jstl webwork 標(biāo)簽來調(diào)用。

8.  界面驗證問題。使用 webwork validate 機制用 xml 定義,或在 action 中代碼判斷。



Eric.Zhou 2006-12-11 13:21 發(fā)表評論
]]>
主站蜘蛛池模板: 亚洲成A人片在线观看WWW| 爱情岛论坛网亚洲品质自拍| 亚洲成在人天堂在线| 成人性做爰aaa片免费看| 国产亚洲美女精品久久久2020| 免费在线观看一区| 亚洲国产精品综合久久网络| 羞羞视频免费网站入口| 亚洲AⅤ优女AV综合久久久| 香蕉视频免费在线播放| 中文字幕亚洲一区二区三区| 三年片免费高清版 | 亚洲综合激情九月婷婷 | 成年人免费视频观看| 亚洲变态另类一区二区三区| 日韩视频免费一区二区三区| 激情吃奶吻胸免费视频xxxx| 亚洲无人区午夜福利码高清完整版| 两个人看的www视频免费完整版| 亚洲a一级免费视频| 毛片基地免费观看| 国产午夜亚洲精品不卡电影| 亚洲一级Av无码毛片久久精品| 波多野结衣免费一区视频| 亚洲精品综合久久中文字幕| 男人的好免费观看在线视频| 亚洲av无码日韩av无码网站冲 | 亚洲成在人天堂在线| 欧美男同gv免费网站观看| 黄页网址在线免费观看| 久久亚洲免费视频| 妞干网免费观看视频| 国产特黄一级一片免费| 亚洲精品在线网站| 亚洲成人影院在线观看| 久草福利资源网站免费| 亚洲av无码一区二区三区四区| 亚洲永久精品ww47| 天天干在线免费视频| 99精品视频免费| 亚洲国产成人无码AV在线|