国产成人精品免费视,日韩久久久久,日韩欧美精品一区二区http://www.aygfsteel.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訪問靜態方法和類變量http://www.aygfsteel.com/rain1102/archive/2006/12/26/90106.htmlEric.ZhouEric.ZhouTue, 26 Dec 2006 06:56:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/26/90106.htmlhttp://www.aygfsteel.com/rain1102/comments/90106.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/26/90106.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/90106.htmlhttp://www.aygfsteel.com/rain1102/services/trackbacks/90106.html       除了使用標準的OGNL格式調用靜態方法和靜態屬性之外,WebWork還可以不指定完整的包名,而是通過使用vs前綴(vs代表Value Stack,就是值棧)調用保存于值棧中的類的靜態屬性和靜態方法。可以使用vs告知WebWork使用存儲于棧頂的類對象,從而代替了包名(@examples.test.Muppet):@vs@OG_MUPPET或者vs@OG_MUPPET()。
  同時,也可以在vs之后指定一數字,例如vs1,從而指明選擇了值棧中更深一層的對象。

Eric.Zhou 2006-12-26 14:56 發表評論
]]>
通過PreResultListener在result執行之前獲得回調控制http://www.aygfsteel.com/rain1102/archive/2006/12/25/89895.htmlEric.ZhouEric.ZhouMon, 25 Dec 2006 06:30:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/25/89895.htmlhttp://www.aygfsteel.com/rain1102/comments/89895.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/25/89895.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/89895.htmlhttp://www.aygfsteel.com/rain1102/services/trackbacks/89895.html開發interceptor的時候,了解action已經執行完畢而result還沒有開始執行的時間點往往很重要的。譬如在異常處理方面就是如此:在action處理的過程中,由于后臺的處理,出現的異常很可能是系統異常;而在result處理的過程中,異常則可能出現在為用戶呈現的頁面的時候,而不是由于系統問題。
下面給出了ExceptionInterceptor的代碼,該interceptor會在result開始執行之前與之后以不同的方式處理異常。在result開始執行之前,可以改變用于從action配置中查詢result的返回碼,而在webwork應用程序中,使用Action.ERROR是一個常用的實踐技巧:將Action.ERROR映射至向用戶提示錯誤的頁面。所以,需要捕獲異常并返回Action.ERROR。在result開始執行之后,來自interceptor的返回碼就不再那樣重要了,但是仍然可以獲得由beforeResult()方法回傳給result code,并且可以返回它。在以下離子中需要注意的一點是:由于interceptor必須是無狀態的,因此它為每一個ActionInvocation創建一個新的ExceptionHandler,可以保存該ActionInvocation的狀態。
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 發表評論
]]>
WebWork中的ComponentManager接口http://www.aygfsteel.com/rain1102/archive/2006/12/25/89857.htmlEric.ZhouEric.ZhouMon, 25 Dec 2006 03:49:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/25/89857.htmlhttp://www.aygfsteel.com/rain1102/comments/89857.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/25/89857.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/89857.htmlhttp://www.aygfsteel.com/rain1102/services/trackbacks/89857.html在WebWork 中,每一個作用域(請求、會話或者應用程序)都有一個ComponentManager--Manager(CM)與它相關聯。每個CM都會有一個父CM,而在決定如何管理和應用資源的時候,CM將會詢問父CM。請求作用域CM有一個會話作用域CM,而會話作用域CM則有一個應用程序作用域CM它自己的父CM。
這意味著應用一個對象到請求作用域CM必須保證該對象能夠獲取屬于會話或者應用程序作用域的資源。每個作用域的CM都存放于屬性map中,該map可以通過ServletRequest對象、HttpSession對象或者ServletContext對象的setAttribute()和getAttribute()方法進行訪問。

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

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


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

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


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

      下面來看一個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的一個實現類。它包含了兩個管理器,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>


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

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

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

1、Log4j的概念
   Log4j中有三個主要的組件,它們分別是Logger、Appender和Layout,Log4j 允許開發人員定義多個Logger,每個Logger擁有自己的名字,Logger之間通過名字來表明隸屬關系。有一個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,當輸出時,只有級別高過配置中規定的 級別的信息才能真正的輸出,這樣就很方便的來配置不同情況下要輸出的內容,而不需要更改代碼,這點實在是方便啊。

2、Log4j的配置文件
  雖然可以不用配置文件,而在程序中實現配置,但這種方法在如今的系統開發中顯然是不可取的,能采用配置文件的地方一定一定要用配置文件。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
        

  首先,是設置root,格式為 log4j.rootLogger=[level],appenderName, ...,其中level就是設置需要輸出信息的級別,后面是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(每天產生一個日志文件)
  org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生新文件)
  org.apache.log4j.WriterAppender(將日志信息以流格式發送到任意指定的地方)
配置日志信息的格式(布局),其語法為:
  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(包含日志產生的時間、線程、類別等等信息)

3、Log4j在程序中的使用
  要在自己的類中使用Log4j,首先聲明一個靜態變量Logger logger=Logger.getLog("classname");在使用之前,用PropertyConfigurator.configure ("配置文件")配置一下,現在就可以使用了,用法如下: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應用,完善的認證和授權機制是必不可少的,在SpringFramework中,Juergen Hoeller提供的范例JPetStore給了一些這方面的介紹,但還遠遠不夠,Acegi是一個專門為SpringFramework提供安全機制的 項目,全稱為Acegi Security System for Spring,當前版本為0.5.1,就其目前提供的功能,應該可以滿足絕大多數應用的需求。

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

[基礎工作]
在你的Web應用的lib中添加Acegi下載包中的acegi-security.jar

[web.xml]
實現認證和授權的最常用的方法是通過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.”,如希望深究的話,去看看源代碼應該不難理解。

再下來就是添加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) 如果你的應用不需要安全傳輸,如https,則將"Acegi Channel Processing Filter"相關內容注釋掉即可;
3) 如果你的應用不需要Spring提供的遠程訪問機制,如Hessian and Burlap,將"Acegi HTTP BASIC Authorization
Filter"相關內容注釋掉即可。

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

1) 首先,你的數據庫中必須具有保存用戶名和密碼的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) 添加訪問你的數據庫的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中定義哪些頁面需要權限訪問,需要根據自己的應用需求進行修改,我上面給出
的定義的意思是這樣的:
a. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON意思是在比較請求路徑時全部轉換為小寫
b. \A/sec/administrator.*\Z=ROLE_SUPERVISOR意思是只有權限為ROLE_SUPERVISOR才能訪問/sec/administrator*的頁面
c. \A/sec/user.*\Z=ROLE_TELLER意思是只有權限為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對訪問頁面的權限控制,除此之外,Acegi還提供了另外一個Interceptor――
MethodSecurityInterceptor,它結合runAsManager可實現對對象中的方法的權限控制,使用方法可參看Acegi自帶的文檔
和contact范例。

[最后要說的]
本來以為只是說明如何使用Acegi而已,應該非常簡單,但真正寫起來才發現想要條理清楚的理順所有需要的bean還是很
困難的,但愿我沒有遺漏太多東西,如果我的文章有什么遺漏或錯誤的話,還請參看Acegi自帶的quick-start范例,但請
注意,這個范例是不能直接拿來用的。
分析和學習Spring中的jpetstore用戶管理
  存在用戶的系統,必然需要用戶的登錄和認證,今天就通過分析Spring中自帶的jpetstore的例子來學習一下如何實現在Spring構架的系統中用戶登錄。
1、首先從注冊用戶開始,先看看jpetstore-servlet.xml中關于注冊用戶的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的構造函數中得到,原來為EditAccountForm;  
2). EditoAccountForm.jsp中顯得非常亂,其實沒有多少難理解的地方,最主要的是這個form既是添加新用戶的,又是編輯用戶信息的,所以顯得有點亂糟糟的。
2、添加好了新用戶,接下來看看如何登錄,在jpetstore-servlet中發現這兩個相關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實現了preHandle,因此在請求上面的map頁面時,首先要經過這個Interceptor,看看 SignonInterceptor的源碼,原來在其中為signon.jsp賦予一個signonForwardAction對象,呵呵,總算明白了。
3). 接下來去學習一下SignonController,其主體部分中可以看出,首先取出用戶輸入的username和password,然后到數據庫中驗證 有沒有這個用戶,如果沒有這個用戶,返回各錯誤頁面;如果成功,首先生成一個UserSession對象,在request的session加入這個 userSession,注意這部分代碼中給出了PagedListHolder分頁的簡單使用方法,關于分頁顯示,以后再學習吧。
3、登錄成功后,就可以根據不同的用戶設施不同的行為了,取得用戶信息,無非就是從session取出userSession即可。

Eric.Zhou 2006-12-19 16:40 發表評論
]]>
WSH(webwork+spring+hibernate)+mysqlhttp://www.aygfsteel.com/rain1102/archive/2006/12/19/88796.htmlEric.ZhouEric.ZhouTue, 19 Dec 2006 06:55:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/19/88796.htmlhttp://www.aygfsteel.com/rain1102/comments/88796.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/19/88796.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/88796.htmlhttp://www.aygfsteel.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 發表評論
]]>
配置瀏覽器(webwork--config-browser.xml)http://www.aygfsteel.com/rain1102/archive/2006/12/19/88681.htmlEric.ZhouEric.ZhouTue, 19 Dec 2006 01:39:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/19/88681.htmlhttp://www.aygfsteel.com/rain1102/comments/88681.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/19/88681.html#Feedback1http://www.aygfsteel.com/rain1102/comments/commentRss/88681.htmlhttp://www.aygfsteel.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
最后,啟動服務器,瀏覽http://localhost:8080/config-browser/actionNames.action


Eric.Zhou 2006-12-19 09:39 發表評論
]]>
WebWork - webwork-default.xmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/19/88671.htmlEric.ZhouEric.ZhouTue, 19 Dec 2006 00:58:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/19/88671.htmlhttp://www.aygfsteel.com/rain1102/comments/88671.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/19/88671.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/88671.htmlhttp://www.aygfsteel.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 發表評論
]]>
webwok中property-driven與model-drivenhttp://www.aygfsteel.com/rain1102/archive/2006/12/14/87801.htmlEric.ZhouEric.ZhouThu, 14 Dec 2006 12:17:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/14/87801.htmlhttp://www.aygfsteel.com/rain1102/comments/87801.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/14/87801.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/87801.htmlhttp://www.aygfsteel.com/rain1102/services/trackbacks/87801.html本文的前提是,你愿意將頁面數據封裝為一個對象(是否封裝還得看實際情況,如果頁面數據特別少也沒這個必要)。

封裝頁面數據是否使用ModelDrivenInterceptor有時候還真與個人使用習慣有點關系

看下面的實現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

還有另一種實現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效果完全一樣,只不過實現起來還是有少許差別
1) action1 需要配置ModelDrivenInterceptor,且實現ModelDriven 接口(如果沒有實現此接口,那么配置ModelDrivenInterceptor沒有任何意義),頁面的傳值很簡單<input type="text" name="type" />
這樣就可以將type的值注入到vote的type屬性
2)action2不需要配置ModelDrivenInterceptor,但頁面傳值稍微麻煩一點
<input type="text" name="vote.type" />

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

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

下邊是創建一個簡單實例的步驟:
1,新建一個標準的web工程叫sitemesh
在WebRoot下新建一個index.jsp,內容如下

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分別復制到style2,login/style3,shared下
現在訪問下邊的鏈接:
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
得到的結果是一樣的,那我們如何讓這四個相同的index.jsp有不同的樣式呢。除了每個里邊加入include
還有個解決辦法,就是sitemesh
2,在http://www.opensymphony.com下載sitemesh-2.2.1.jar,sitemesh-decorator.tld,sitemesh-page.tld
三個文件。
復制sitemesh.jar到WEB-INF/lib下,
復制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,內容如下
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文件,內容如下
------------------------------------------------------------------
<%@ 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真不錯。重要是學習簡單20分種就搞定了

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


Eric.Zhou 2006-12-14 19:16 發表評論
]]>
WebWork教程-驗證框架http://www.aygfsteel.com/rain1102/archive/2006/12/14/87780.htmlEric.ZhouEric.ZhouThu, 14 Dec 2006 11:13:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/14/87780.htmlhttp://www.aygfsteel.com/rain1102/comments/87780.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/14/87780.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/87780.htmlhttp://www.aygfsteel.com/rain1102/services/trackbacks/87780.html 驗證框架
WebWork 提供了在 Action 執行之前,對輸入數據的驗證功能,它使用了其核心 XWork 的驗證框架。提供了如下功能:
1、   可配置的驗證文件。它的驗證文件是一個獨立的 XML 配置文件,對驗證的添加、修改只需更改配置文件,無需編譯任何的 Class
2、   驗證文件和被驗證的對象完全解藕。驗證對象是普通的 JavaBean 就可以了(可以是 FormBean 、域對象等),它們不需實現任何額外的方法或繼承額外的類。
3、   多種不同的驗證方式。因為它驗證功能是可以繼承的,所以可以用多種不同的方式指定驗證文件,比如:通過父類的 Action 、通過 Action 、通過 Action 的方法、通過 Action 所使用的對象,等等。
4、   強大的表達式驗證。它使用了 OGNL 的表達式語言,提供強大的表達式驗證功能。
5、   同時支持服務器端和客戶端驗證。
為用戶注冊添加驗證功能
下面我們來看看如何為用戶注冊添加驗證功能:
1、   注冊我們的驗證類型
WebWork 為不同的驗證要求提供不同的驗證類型。一個驗證類型,一般是有一個類來提供。這個類必須實現接口: com.opensymphony.xwork.validator.Validator ,但我們在寫自己的驗證類型時,無需直接實現 Validator 接口,它有抽象類可供直接使用如 ValidatorSupport FieldValidatorSupport 等。
驗證類型在使用之前,必須要在 ValidatorFactory com.opensymphony.xwork.validator . ValidatorFactory )中 注冊。可以有二種方法實現驗證類型的注冊。一、寫程序代碼進行注冊,它使用 ValidatorFactory 類的靜態方法: registerValidator(String name, String className) 二、使用配置文件 validators.xml 進行注冊,要求把文件 validators.xml 放到 ClassPath 的跟目錄中( /WEB-INF/classes )。但在實際開發中,一般都使用第二中注冊方法。我們的驗證類型注冊如下:
<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>
注冊驗證類型的配置文件非常簡單。它使用標簽 <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 類,在配置文件中的不同定義就可以對應不同的驗證文件。驗證框架也會根據 Action 的繼承結構去查找 Action 的父類驗證文件,如果找到它會去執行這個父類的驗證。
 
3、   實現我們的驗證文件: 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 > 標簽代表一個字段,它的屬性“ name ”和頁面輸入框的“ name ”屬性必需完全一致,其實它也就是我們的表達式語言。
2 )、 <field-validator > 標簽定義我們的驗證規則, type 屬性的值就是就是我們前面定義的驗證類型。
3 )、驗證文件中,字段的數據是通過表達式語言從我們的值堆棧( OgnlValueStack )中取得,一般是 Action Model 對象。例如:我們的字段“ user.age ”,它會通過 Action getUser().getAge() 來取得用戶輸入的年齡,再來根據驗證的類型“ int ”和最大值最小值的參數來判斷輸入的數據是否能通過驗證。
4 )、不管驗證是否通過,我們的 Action 都會執行,但如果驗證沒有通過,它不會調用 Action execute() 方法。
 
4、   顯示 Action 的驗證錯誤信息
如果用戶輸入的數據驗證沒有通過,我們需重新返回輸入頁面,并給出錯誤信息提示。攔截器棧“ validationWorkflowStack ”為我們實現了這個功能。它首先驗證用戶輸入的數據,如果驗證沒有通過將不執行我們 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> 標簽里的數據。 ActionSupport 類已實現了此接口,這樣在應用中我們的 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(){
        // 在這里調用用戶注冊的業務邏輯,比如:將注冊信息存儲到數據庫
        return SUCCESS;
    }
 
    public String getVerifyPassword(){
        returnthis.verifyPassword;
    }
   
    publicvoid setVerifyPassword(String verPassword){
        this.verifyPassword = verPassword;
    }
}
我們 WebWork UI 標簽庫直接提供了驗證錯誤信息顯示功能。如果字段級別的驗證沒有通過,它會在輸入框上方顯示驗證文件定義的錯誤提示信息。我們將用戶輸入的頁面更改如下:
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>
我們上面的例子使用的是服務器端驗證。 WebWork 也為我們提供了方便的客戶端驗證。它將驗證自動生成 JavaScript 腳本。如果要使用客戶端驗證只需改變相應的驗證類型就可以了(輸入頁面的表單必需使用 <ww:form> 標簽,并設置屬性“ validate="true" ”)。具體的驗證類型可以在 WebWork 的包 com.opensymphony.webwork.validators 中找到。


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


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

Eric.Zhou 2006-12-13 17:28 發表評論
]]>
webwork中文件上傳實現http://www.aygfsteel.com/rain1102/archive/2006/12/13/87534.htmlEric.ZhouEric.ZhouWed, 13 Dec 2006 09:16:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/13/87534.htmlhttp://www.aygfsteel.com/rain1102/comments/87534.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/13/87534.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/87534.htmlhttp://www.aygfsteel.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;
         }

         //當然還可以使用以下的咚咚
  /*
     * 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;
     */

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

   }

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

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傳攔截器的時候應該避免使用execAndWait攔截器,否則很有可能會出現空指針,因為execAndWait攔截器會在另一個線程處理action,而原來的線程會刪掉臨時文件,所以當你在action中處理文件的時候很有可能文件已被刪掉,雖然這并非一定會出現,但畢竟不安全

Eric.Zhou 2006-12-13 17:16 發表評論
]]>
webwork.propertieshttp://www.aygfsteel.com/rain1102/archive/2006/12/12/87328.htmlEric.ZhouEric.ZhouTue, 12 Dec 2006 11:28:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/12/87328.htmlhttp://www.aygfsteel.com/rain1102/comments/87328.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/12/87328.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/87328.htmlhttp://www.aygfsteel.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 發表評論
]]>
webwork+spring+hibernate架構目錄結構http://www.aygfsteel.com/rain1102/archive/2006/12/11/86877.htmlEric.ZhouEric.ZhouMon, 11 Dec 2006 05:21:00 GMThttp://www.aygfsteel.com/rain1102/archive/2006/12/11/86877.htmlhttp://www.aygfsteel.com/rain1102/comments/86877.htmlhttp://www.aygfsteel.com/rain1102/archive/2006/12/11/86877.html#Feedback0http://www.aygfsteel.com/rain1102/comments/commentRss/86877.htmlhttp://www.aygfsteel.com/rain1102/services/trackbacks/86877.html

     轉自http://www.aygfsteel.com/black_zerg/archive/2005/05/30/5327.html 

       src 目錄下為 Java 源碼

dao    負責數據訪問對象的定義和實現

  其中 Dao 結尾為接口, Impl 結尾為實現。目前一般用 hibernate 做實現。
domain 實體對象

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

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

web    界面相關的 Java

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

  displaytag 中放了 displaytag 相關的類,多為 wrapper.

  webwork 中都是對應的 action

其中 BaseAction 是基本的抽象類,基本后續開發應繼承此類

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

CaseDispatcher 負責菜單點擊后分發到相關 Action ,同時處理權限和 session 工作。
 
其他 action 按模塊進行了組織

左邊是 webroot 的結構

 

 

重要的配置文件有:

Spring

applicationContext.xml

applicationContext-db.xml

Webwork

xwork.xml

webwork.properties

i18n

 labels.properties

log4j

 log4j.properties

displaytag

 displaytag.properties

dbConnect

 jdbc.properties

 

關于一些技術難點和細節:

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

2.  列表的問題,采用 displaytag 。功能強大,使用簡潔,可實現排序和數據導出。

3.  數據下載,使用 displaytag 自帶的 excel 下載

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

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

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

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

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



Eric.Zhou 2006-12-11 13:21 發表評論
]]>
主站蜘蛛池模板: 秦安县| 三台县| 平远县| 无极县| 孟连| 左云县| 汉源县| 稷山县| 徐闻县| 华亭县| 仁化县| 买车| 宜兴市| 常德市| 长顺县| 临夏市| 平安县| 咸阳市| 兴业县| 当雄县| 炉霍县| 丽江市| 大埔区| 昭觉县| 商水县| 凤城市| 堆龙德庆县| 卢氏县| 赞皇县| 孟津县| 行唐县| 孝感市| 车致| 宜黄县| 自贡市| 汤原县| 濮阳县| 普兰县| 张家口市| 滕州市| 布拖县|