WWW国产亚洲精品久久麻豆,国产成人亚洲精品,亚洲动漫精品无码av天堂http://m.tkk7.com/rain1102/category/37659.html<br/><font color="green" style="font-family: 華文行楷;font-size:16px;">子曰:危邦不入,亂邦不居。天下有道則見,無道則隱。</font><font color="#3C1435"></font>zh-cnSat, 21 Feb 2009 21:41:26 GMTSat, 21 Feb 2009 21:41:26 GMT60Commons-Validatorhttp://m.tkk7.com/rain1102/archive/2008/05/07/198893.htmlEric.ZhouEric.ZhouWed, 07 May 2008 02:50:00 GMThttp://m.tkk7.com/rain1102/archive/2008/05/07/198893.htmlhttp://m.tkk7.com/rain1102/comments/198893.htmlhttp://m.tkk7.com/rain1102/archive/2008/05/07/198893.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/198893.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/198893.html閱讀全文

Eric.Zhou 2008-05-07 10:50 發表評論
]]>
Struts秘籍之第1段:第2.1式:用插件(PlugIn)來進行應用初始化http://m.tkk7.com/rain1102/archive/2008/03/27/189114.htmlEric.ZhouEric.ZhouThu, 27 Mar 2008 11:56:00 GMThttp://m.tkk7.com/rain1102/archive/2008/03/27/189114.htmlhttp://m.tkk7.com/rain1102/comments/189114.htmlhttp://m.tkk7.com/rain1102/archive/2008/03/27/189114.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/189114.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/189114.html問題

在應用啟動時需要裝入應用初始化數據到context 中。

動作要領

創建一個類,實現org.apache.struts.action.PlugIn接口,并且在struts-config.xml文件中指定plug-in元素。下面的XML 片斷展示了一個plug-in 聲明以及一個嵌套的set-property元素來設置定制屬性:

 

<plug-in className="com.oreilly.strutsckbk.CustomPlugin" >

  
<set-property property="customData"

                   value
="Hello from the plugin"/>

</plug-in>

 

動作變化

Struts提供了一個PlugIn接口,你可以用它來創建在應用啟動時初始化的定制服務。PlugIn接口的Java源代碼示于Example 2-1. (為了清晰起見,去除了JavaDoc 文檔)

Example 2-1. Struts PlugIn 接口

 

package org.apache.struts.action;

import javax.servlet.ServletException;
import org.apache.struts.config.ModuleConfig;

public interface PlugIn {

    
public void destroy( );

    
public void init(ActionServlet servlet, ModuleConfig config)
        throws ServletException;
}

 

為了實現一個plug-in,只需要實現這個接口并且在struts-config.xml文件中聲明這個plug-in 實現。有兩個方法必須被實現:即init()和destroy( ), 它們在插件的生命周期中被調用。Struts 在啟動ActionServlet時實例化plug-in 之后調用init( )。Struts則在ActionServlet被銷毀時調用destroy()方法,通常是在一個用服務器停止時。首先,這個 plug-in 特征似乎是很單純和有限的。然而,通過使用Struts的另外一個特征,即set-property元素,你可以將特殊的信息傳遞到plug-in中。這種能力增強了這些類的靈活性。

set-property元素被幾乎所有定義Struts實體的元素所支持,比如form-bean, action-mapping, action, 以及plug-in。set-property元素有兩個屬性:namevalue。Struts調用name屬性的值指定的property的setter方法,將property設置為value屬性的字符串值。

對給定plug-in的所有set-property元素都將在調用plug-in的init( )方法之前進行處理。這允許plug-in 在init( )方法中使用屬性的值。

如果對一個plug-in使用多個set-property元素, Struts不能保證它們被調用的順序。每個setter方法都應該獨立于其他任何方法。

 

Struts 將對ActionServlet和plug-in的ModuleConfig的引用作為引數傳遞給init( )方法。ActionServlet允許訪問ServletContext來進行應用范圍的對象存儲。ActionServlet還可以允許你訪問更多高級的容器管理的J2EE 組件,比如數據源和消息隊列。ModuleConfig允許你訪問定義plug-in 的模塊的Struts配置。

每個Struts 應用至少有一個模塊:默認模塊。如果你不熟悉模塊,我們將在第2.5式中講解之。

為了更具體一些,請考慮一個簡單的,但仍然相關的例子。你需要定義一個plug-in,它可以使你決定應用何時啟動,以及它啟動和運行了多長時間。你可以使用下面所示的類跟蹤和報告你的應用的運行時間。

Example 2-2. Application uptime tracker 對象

 

package com.oreilly.strutsckbk;

import java.util.Date;

public class TimeTracker {

  
private long startUpTimeMillis;
  
private Date startedOn;

  
public TimeTracker( ) {
     startUpTimeMillis 
= System.currentTimeMillis( );
     startedOn 
= new Date( );
   }


  
public long getUptime( ) {
    
return System.currentTimeMillis( ) - startUpTimeMillis;
  }


  
public Date getStartedOn( ) {
    
return startedOn;
  }

}

 

創建一個PlugIn接口的實現,比如Example 2-3所示,它實例化了TimeTracker。plug-in 通過plug-in 屬性的值將TimeTracker實例保存在ServletContext中。你可以使用這個值來從Servlet上下文中獲取TimeTracker實例。雖然這個值是硬編碼的,使用屬性也提供了更大的靈活性。

Example 2-3. Time tracker plugin

 

package com.oreilly.strutsckbk;

import javax.servlet.ServletException;

import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;

public class TimeTrackerPlugin implements PlugIn {

    
private String contextKey;
   
   
public void setContextKey(String key) {
       
this.contextKey = key;
   }

   
   
public void init(ActionServlet servlet, ModuleConfig conf)
         throws ServletException 
{
      servlet.getServletContext( ).setAttribute(contextKey, 
new TimeTracker( ));
   }


   
public void destroy( ) {
    }

}

 

現在你已經有了為plug-in 創建的類,你可以通過在struts-config.xml中加入plug-in元素來將其集成到Struts 應用中。

 

<plug-in className="com.oreilly.strutsckbk.TimeTrackerPlugin">
    
<set-property property="contextKey" value="timeTracker"/>
</plug-in>

 

plug-in 在servlet 上下文中存儲了time tracker對象。可以訪問TimeTracker來顯示關于應用啟動運行時間的信息,下面是相關的JSP 片斷:

 

<h4>Continuously running since 
    
<bean:write name="timeTracker" 
            property
="startedOn" 
              format
="MM/dd/yyyy HH:mm"/> for
    
<bean:write name="timeTracker" 
            property
="uptime"/> milliseconds!
</h4>

 

你可以使用一個servlet 來載入像Struts plug-in之類的初始化數據。具有load-on-startup初始化參數的servlet,應將其設置為較低的數值,比如1, 一保證它們在應用啟動時載入。容器在實例化Servlet之后將調用servlet的init( )方法。但是Struts plug-in 方式由多個優點。首先,大多數Struts 應用在其初始化設置后不需要修改web.xml文件。必須在web.xml中聲明額外的Servlet意味著要維護額外的文件。其次,如果需要PlugIn接口提供對特定Struts信息的訪問。最后,因為plug-in 的生命周期緊隨ActionServlet的生命周期,所以可以保證在你的Struts應用所需時數據有效。

相關招式

第2.8式展示了set-property元素的另一種用法。Struts 文檔中關于plug-in 的信息可以訪問http://jakarta.apache.org/struts/userGuide/building_controller.html#plugin_classes.

你也可以使用一個Servlet 上下文listener 來載入初始化數據。



Eric.Zhou 2008-03-27 19:56 發表評論
]]>
struts2的struts.properties配置文件詳解http://m.tkk7.com/rain1102/archive/2008/02/28/182773.htmlEric.ZhouEric.ZhouThu, 28 Feb 2008 11:44:00 GMThttp://m.tkk7.com/rain1102/archive/2008/02/28/182773.htmlhttp://m.tkk7.com/rain1102/comments/182773.htmlhttp://m.tkk7.com/rain1102/archive/2008/02/28/182773.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/182773.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/182773.htmlstruts2的struts.properties配置文件詳解
struts.action.extension
          The URL extension to use to determine if the request is meant for a Struts action
           用URL擴展名來確定是否這個請求是被用作Struts action,其實也就是設置 action的后綴,例如login.do的'do'字。
struts.configuration
          The org.apache.struts2.config.Configuration implementation class
            org.apache.struts2.config.Configuration接口名
struts.configuration.files
          A list of configuration files automatically loaded by Struts
           struts自動加載的一個配置文件列表
struts.configuration.xml.reload
          Whether to reload the XML configuration or not
           是否加載xml配置(true,false)
struts.continuations.package
           The package containing actions that use Rife continuations
           含有actions的完整連續的package名稱
struts.custom.i18n.resources
          Location of additional localization properties files to load
           加載附加的國際化屬性文件(不包含.properties后綴)
struts.custom.properties
          Location of additional configuration properties files to load
           加載附加的配置文件的位置

struts.devMode
          Whether Struts is in development mode or not
           是否為struts開發模式
struts.dispatcher.parametersWorkaround
          Whether to use a Servlet request parameter workaround necessary for some versions of WebLogic
            (某些版本的weblogic專用)是否使用一個servlet請求參數工作區(PARAMETERSWORKAROUND)
struts.enable.DynamicMethodInvocation
          Allows one to disable dynamic method invocation from the URL
            允許動態方法調用
struts.freemarker.manager.classname
          The org.apache.struts2.views.freemarker.FreemarkerManager implementation class
           org.apache.struts2.views.freemarker.FreemarkerManager接口名
struts.i18n.encoding
          The encoding to use for localization messages
           國際化信息內碼
struts.i18n.reload
          Whether the localization messages should automatically be reloaded
           是否國際化信息自動加載
struts.locale
          The default locale for the Struts application
           默認的國際化地區信息
struts.mapper.class
          The org.apache.struts2.dispatcher.mapper.ActionMapper implementation class
            org.apache.struts2.dispatcher.mapper.ActionMapper接口
struts.multipart.maxSize
          The maximize size of a multipart request (file upload)
           multipart請求信息的最大尺寸(文件上傳用)
struts.multipart.parser
          The org.apache.struts2.dispatcher.multipart.MultiPartRequest parser implementation for a multipart request (file upload)
          專為multipart請求信息使用的org.apache.struts2.dispatcher.multipart.MultiPartRequest解析器接口(文件上傳用)

struts.multipart.saveDir
          The directory to use for storing uploaded files
           設置存儲上傳文件的目錄夾
struts.objectFactory
          The com.opensymphony.xwork2.ObjectFactory implementation class
           com.opensymphony.xwork2.ObjectFactory接口(spring)
struts.objectFactory.spring.autoWire
          Whether Spring should autoWire or not
           是否自動綁定Spring
struts.objectFactory.spring.useClassCache
          Whether Spring should use its class cache or not
           是否spring應該使用自身的cache
struts.objectTypeDeterminer
          The com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation class
            com.opensymphony.xwork2.util.ObjectTypeDeterminer接口
struts.serve.static.browserCache
          If static content served by the Struts filter should set browser caching header properties or not
           是否struts過濾器中提供的靜態內容應該被瀏覽器緩存在頭部屬性中
struts.serve.static
          Whether the Struts filter should serve static content or not
           是否struts過濾器應該提供靜態內容
struts.tag.altSyntax
          Whether to use the alterative syntax for the tags or not
           是否可以用替代的語法替代tags
struts.ui.templateDir
          The directory containing UI templates
           UI templates的目錄夾
struts.ui.theme
          The default UI template theme
           默認的UI template主題
struts.url.http.port
          The HTTP port used by Struts URLs
           設置http端口
struts.url.https.port
          The HTTPS port used by Struts URLs
           設置https端口
struts.url.includeParams
          The default includeParams method to generate Struts URLs
          在url中產生 默認的includeParams

struts.velocity.configfile
          The Velocity configuration file path
           velocity配置文件路徑
struts.velocity.contexts
          List of Velocity context names
           velocity的context列表

struts.velocity.manager.classname
          org.apache.struts2.views.velocity.VelocityManager implementation class
           org.apache.struts2.views.velocity.VelocityManager接口名
struts.velocity.toolboxlocation
          The location of the Velocity toolbox
           velocity工具盒的位置
struts.xslt.nocache
          Whether or not XSLT templates should not be cached
           是否XSLT模版應該被緩存 
本文轉自福州IT信息網(http://www.fzic.net),詳細出處參考:http://www.fzic.net/SrcShow.asp?Src_ID=990

 



Eric.Zhou 2008-02-28 19:44 發表評論
]]>
Struts2中對于radio list的預選(pre select),即:使一個值被默認選中 http://m.tkk7.com/rain1102/archive/2008/02/28/182759.htmlEric.ZhouEric.ZhouThu, 28 Feb 2008 09:23:00 GMThttp://m.tkk7.com/rain1102/archive/2008/02/28/182759.htmlhttp://m.tkk7.com/rain1102/comments/182759.htmlhttp://m.tkk7.com/rain1102/archive/2008/02/28/182759.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/182759.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/182759.html

在Struts2中,radio標簽可以使用一個list來輸出一組radio按鈕,
        <s:radio name="sex" list="#{'male','female'}" label="%{getText('app.label.sex')}" />
但是如何設置其中一個被默認選中。

查閱了struts2的文檔,發現radio標簽有一個value屬性是用于對radio的進行預選的: http://struts.apache.org/2.x/docs/radio.html
value: Preset the value of input element.
于是,進行了試驗,<s:radio name="sex" list="#{'male','female'}" label="%{getText('app.label.sex')}" value="male" />
結果失敗了。male的值并沒有被選中,經過反復研究,終于得到了正確的結果:
<s:radio name="sex" list="#{'male','female'}" label="%{getText('app.label.sex')}" value="'male'" />
看到其中的區別了嗎,就是多了兩個單引號。
我認為這是因為value屬性的特性引起的。如果male沒有加引號,那么struts2會去值的堆棧中尋找變量名為male的值,結果找不到。
加上單引號后,struts2(應該是ognl)把'male'認為是一個簡單的字符串。

這樣,radio就能夠正確地匹配到值,使指定的值默認被選中



Eric.Zhou 2008-02-28 17:23 發表評論
]]>
在使用struts2的datetimepicker標簽時候遇到JS錯誤:dojo未定義錯誤http://m.tkk7.com/rain1102/archive/2008/02/25/181907.htmlEric.ZhouEric.ZhouMon, 25 Feb 2008 02:18:00 GMThttp://m.tkk7.com/rain1102/archive/2008/02/25/181907.htmlhttp://m.tkk7.com/rain1102/comments/181907.htmlhttp://m.tkk7.com/rain1102/archive/2008/02/25/181907.html#Feedback6http://m.tkk7.com/rain1102/comments/commentRss/181907.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/181907.html <%@ page contentType="text/html;charset=UTF-8"%>
<%@ include file="../../commons/taglibs.jsp"%>
<s:datetimepicker label="releaseTime" name="releaseTime"/>

時間控件沒有顯示出來,而報JS錯誤:dojo未定義錯誤

解決辦法:
在頁面的<head>標簽中加入<s:head /> 就可以了
。。。
<head>
<title>Struts 2 Cool Tags - Others</title>
.....
<s:head /> 
</head>
。。。

Eric.Zhou 2008-02-25 10:18 發表評論
]]>
在Struts 2中使用JSON Ajax支持http://m.tkk7.com/rain1102/archive/2008/02/20/180907.htmlEric.ZhouEric.ZhouWed, 20 Feb 2008 09:02:00 GMThttp://m.tkk7.com/rain1102/archive/2008/02/20/180907.htmlhttp://m.tkk7.com/rain1102/comments/180907.htmlhttp://m.tkk7.com/rain1102/archive/2008/02/20/180907.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/180907.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/180907.html  簡單地說,JSON插件允許我們在JavaScript中異步調用Action,而且Action不再需要使用視圖資源來顯示該Action里的狀態信息,而是由JSON插件負責將Action里的狀態信息返回給調用頁面——通過這種方式,就可以完成Ajax交互。

  Struts2提供了一種可插拔方式來管理插件,安裝Struts2的JSON插件與安裝普通插件并沒有太大的區別,一樣只需要將Struts2插件的JAR文件復制到Web應用的WEB-INF/lib路徑下即可。

  安裝JSON插件按如下步驟進行:

  (1)登陸http://code.google.com/p/jsonplugin/downloads/list站點,下載Struts2的JSON插件的最新版本,當前最新版本是0.7,我們可以下載該版本的JSON插件。

  (2)將下載到的jsonplugin-0.7.jar文件復制到Web應用的WEB-INF路徑下,即可完成JSON插件的安裝。

  實現Actio邏輯

  假設wo,en輸入頁面中包含了三個表單域,這三個表單域對于三個請求參數,因此應該使用Action來封裝這三個請求參數。三個表單域的name分別為field1、field2和field3。

  處理該請求的Action類代碼如下:  
public class JSONExample
  {
  //封裝請求參數的三個屬性
  private String field1;
  private transient String field2;
  private String field3;
  //封裝處理結果的屬性
  private int[] ints = {10, 20};
  private Map map = new HashMap();
  private String customName = "custom";
  //三個請求參數對應的setter和getter方法
  public String getField1()
  {
  return field1;
  }
  public void setField1(String field1)
  {
  this.field1 = field1;
  }
  //此處省略了field1和field2兩個字段的setter和getter方法
  ...
  //封裝處理結果的屬性的setter和getter方法
  public int[] getInts()
  {
  return ints;
  }
  public void setInts(int[] ints)
  {
  this.ints = ints;
  }
  public Map getMap()
  {
  return map;
  }
  public void setMap(Map map)
  {
  this.map = map;
  }
  //使用注釋語法來改變該屬性序列化后的屬性名
  @JSON(name="newName")
  public String getCustomName()
  {
  return this.customName;
  }
  public String execute()
  {
  map.put("name", "yeeku");
  return Action.SUCCESS;
  }
  }
  在上面代碼中,使用了JSON注釋,注釋時指定了name域,name域指定Action屬性被序列化成JSON對象的屬性名。除此之外,JSON注釋還支持如下幾個域:

      serialize:設置是否序列化該屬性

  deserialize:設置是否反序列化該屬性。

  format:設置用于格式化輸出、解析日期表單域的格式。例如"yyyy-MM-dd'T'HH:mm:ss"。

  配置該Action與配置普通Action存在小小的區別,應該為該Action配置類型為json的Result。而這個Result無需配置任何視圖資源。

  配置該Action的struts.xml文件代碼如下: 
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.i18n.encoding" value="UTF-8"/>
<package name="example" extends="json-default">
<action name="JSONExample" class="lee.JSONExample">
<result type="json"/>
</action>
</package>
</struts>  
  在上面配置文件中有兩個值得注意的地方:

  第一個地方是配置struts.i18n.encoding常量時,不再是使用GBK編碼,而是UTF-8編碼,這是因為Ajax的POST請求都是以UTF-8的方式進行編碼的。

  第二個地方是配置包時,自己的包繼承了json-default包,而不再繼承默認的default包,這是因為只有在該包下才有json類型的Result。



Eric.Zhou 2008-02-20 17:02 發表評論
]]>
MyEclipse 開發 SSH 整合時 java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit 解決方案 http://m.tkk7.com/rain1102/archive/2007/12/23/169853.htmlEric.ZhouEric.ZhouSun, 23 Dec 2007 12:47:00 GMThttp://m.tkk7.com/rain1102/archive/2007/12/23/169853.htmlhttp://m.tkk7.com/rain1102/comments/169853.htmlhttp://m.tkk7.com/rain1102/archive/2007/12/23/169853.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/169853.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/169853.html Java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
 at net.sf.cglib.core.ClassEmitter.begin_class(ClassEmitter.java:77)
Spring Hibernate 共用的一些 jar 文件發生了版本沖突, 刪除 WEB-INF/lib/asm-2.2.3.jar 然后重啟 Tomcat.
asm-2.2.3.jar
       asm.jar
       asm-attrs.jar
      asm-commons-2.2.3.jar
      asm-util-2.2.3.jar


Eric.Zhou 2007-12-23 20:47 發表評論
]]>
Struts 2 Tagshttp://m.tkk7.com/rain1102/archive/2007/07/11/129667.htmlEric.ZhouEric.ZhouWed, 11 Jul 2007 10:20:00 GMThttp://m.tkk7.com/rain1102/archive/2007/07/11/129667.htmlhttp://m.tkk7.com/rain1102/comments/129667.htmlhttp://m.tkk7.com/rain1102/archive/2007/07/11/129667.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/129667.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/129667.htmlIn this section we will introduce you with the tags provided along with Struts 2 framework. It is necessary to understand all the tags provided along with Struts 2 framework. In this page we will have listed all the Struts 2 Tags and in subsequent sections we will provide you the examples of the these tags in detail.

The Struts 2 Tags can be divided into two types:

  • Struts Generic Tags
    The struts generic tags are used to control the execution flow when pages are rendered. Another use of struts generic tags are data extraction.
    Further Generic Tags are classified into Control Tags and Data Tags
    Control Tags: The Control Tags are used for flow control, such if, else and iterate.
    Here are the list of Control Tags:
    * if
    * elseIf
    * else
    * append
    * generator
    * iterator
    * merge
    * sort
    * subset
    Data Tags: The Data Tags are used for data manipulation or creation, such as bean, push, and i18n.
    Here are the list of Data Tags:
    * a
    * action
    * bean
    * date
    * debug
    * i18n
    * include
    * param
    * push
    * set
    * text
    * url
    * property
       
  • Struts UI tags
    Struts UI Tags are mainly designed to use the data from your action/value stack or from Data Tags. These tags are used to display the data on the HTML page. The UI tags are driven by templates and themes. 
    Struts UI Tags are of two types Form Tags and Non - Form tags.
    Form Tags are as follows:
    * autocompleter
    * checkbox
    * checkboxlist
    * combobox
    * datetimepicker
    * doubleselect
    * head
    * file
    * form
    * hidden
    * label
    * optiontransferselect
    * optgroup
    * password
    * radio
    * reset
    * select
    * submit
    * textarea
    * textfield
    * token
    * updownselect

    Non-Form UI Tags are:
    * actionerror
    * actionmessage
    * component
    * div
    * fielderror
    * table
    * tabbedPanel
    * tree
    * treenode

The main difference between Struts Generic Tags and Struts UI Tags are:

  • The generic tags simply output some content directly from the tag while the UI tags uses templates and often group the output together with theme


Eric.Zhou 2007-07-11 18:20 發表評論
]]>
struts2新特性預覽 http://m.tkk7.com/rain1102/archive/2007/07/11/129666.htmlEric.ZhouEric.ZhouWed, 11 Jul 2007 10:16:00 GMThttp://m.tkk7.com/rain1102/archive/2007/07/11/129666.htmlhttp://m.tkk7.com/rain1102/comments/129666.htmlhttp://m.tkk7.com/rain1102/archive/2007/07/11/129666.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/129666.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/129666.htmlStruts2與Struts1的對比

來源:struts2開發組 翻譯:tianxinet(胖猴)

Action 類:
• Struts1要求Action類繼承一個抽象基類。Struts1的一個普遍問題是使用抽象類編程而不是接口。
• Struts 2 Action類可以實現一個Action接口,也可實現其他接口,使可選和定制的服務成為可能。Struts2提供一個ActionSupport基類去實現 常用的接口。Action接口不是必須的,任何有execute標識的POJO對象都可以用作Struts2的Action對象。

線程模式:
• Struts1 Action是單例模式并且必須是線程安全的,因為僅有Action的一個實例來處理所有的請求。單例策略限制了Struts1 Action能作的事,并且要在開發時特別小心。Action資源必須是線程安全的或同步的。
• Struts2 Action對象為每一個請求產生一個實例,因此沒有線程安全問題。(實際上,servlet容器給每個請求產生許多可丟棄的對象,并且不會導致性能和垃圾回收問題)

Servlet 依賴:
• Struts1 Action 依賴于Servlet API ,因為當一個Action被調用時HttpServletRequest 和 HttpServletResponse 被傳遞給execute方法。
• Struts 2 Action不依賴于容器,允許Action脫離容器單獨被測試。如果需要,Struts2 Action仍然可以訪問初始的request和response。但是,其他的元素減少或者消除了直接訪問HttpServetRequest 和 HttpServletResponse的必要性。

可測性:
• 測試Struts1 Action的一個主要問題是execute方法暴露了servlet API(這使得測試要依賴于容器)。一個第三方擴展--Struts TestCase--提供了一套Struts1的模擬對象(來進行測試)。
• Struts 2 Action可以通過初始化、設置屬性、調用方法來測試,“依賴注入”支持也使測試更容易。

捕獲輸入:
• Struts1 使用ActionForm對象捕獲輸入。所有的ActionForm必須繼承一個基類。因為其他JavaBean不能用作ActionForm,開發者經常創建多余的類捕獲輸入。動態Bean(DynaBeans)可以作為創建傳統ActionForm的選擇,但是,開發者可能是在重新描述(創建)已經存在的JavaBean(仍然會導致有冗余的javabean)。
• Struts 2直接使用Action屬性作為輸入屬性,消除了對第二個輸入對象的需求。輸入屬性可能是有自己(子)屬性的rich對象類型。Action屬性能夠通過web頁面上的taglibs訪問。Struts2也支持ActionForm模式。rich對象類型,包括業務對象,能夠用作輸入/輸出對象。這種ModelDriven 特性簡化了taglib對POJO輸入對象的引用。

表達式語言:
• Struts1 整合了JSTL,因此使用JSTL EL。這種EL有基本對象圖遍歷,但是對集合和索引屬性的支持很弱。
• Struts2可以使用JSTL,但是也支持一個更強大和靈活的表達式語言--"Object Graph Notation Language" (OGNL).

綁定值到頁面(view):
• Struts 1使用標準JSP機制把對象綁定到頁面中來訪問。
• Struts 2 使用 "ValueStack"技術,使taglib能夠訪問值而不需要把你的頁面(view)和對象綁定起來。ValueStack策略允許通過一系列名稱相同但類型不同的屬性重用頁面(view)。
 
類型轉換:
• Struts 1 ActionForm 屬性通常都是String類型。Struts1使用Commons-Beanutils進行類型轉換。每個類一個轉換器,對每一個實例來說是不可配置的。
• Struts2 使用OGNL進行類型轉換。提供基本和常用對象的轉換器。

校驗:
• Struts 1支持在ActionForm的validate方法中手動校驗,或者通過Commons Validator的擴展來校驗。同一個類可以有不同的校驗內容,但不能校驗子對象。
• Struts2支持通過validate方法和XWork校驗框架來進行校驗。XWork校驗框架使用為屬性類類型定義的校驗和內容校驗,來支持chain校驗子屬性

Action執行的控制:
• Struts1支持每一個模塊有單獨的Request Processors(生命周期),但是模塊中的所有Action必須共享相同的生命周期。
• Struts2支持通過攔截器堆棧(Interceptor Stacks)為每一個Action創建不同的生命周期。堆棧能夠根據需要和不同的Action一起使用。




Eric.Zhou 2007-07-11 18:16 發表評論
]]>
Struts2.0請求過程http://m.tkk7.com/rain1102/archive/2007/07/10/129241.htmlEric.ZhouEric.ZhouTue, 10 Jul 2007 02:07:00 GMThttp://m.tkk7.com/rain1102/archive/2007/07/10/129241.htmlhttp://m.tkk7.com/rain1102/comments/129241.htmlhttp://m.tkk7.com/rain1102/archive/2007/07/10/129241.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/129241.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/129241.html整個請求過程可以分為六步驟:

  1. 一個請求產生并經由框架處理 - 框架根據請求匹配相應的配置,如使用哪些攔截器,action 類和結果。
  2. 請求通過一系列的攔截器 - 攔截器,和攔截器組經配置后,能處理不同等級的請求,它們為請求提供了各種預處理,切面處理。這和Struts的使用 Jakarta Commons Chain 構件的 RequestProcessor類很相似。
  3. 調用 Action - 產生一個新的action對象實例,并提供請求所調用的處理邏輯的方法。Struts2 可以在配置action時為請求分配其指定的方法。我們在第二部文章中將對這步驟進行進一步討論;
  4. 調用產生的結果 - 獲取通過action的方法處理后返回來的結果,匹配其result class并調用產生的實例。有種情況是在UI模板去生成HTML時才去處理這些結果。如果在這種情況下,在Struts2 模板中的tags能直接返回到 action 中,取結果來呈現界面?!?
  5. 請求再次經過一系列的攔截器處理后返回 - 請求反順序通過與原來進入時的攔截器鏈, 當然,你也可以配置在這個過程中減少或增加攔截器處理.
  6. 請求返回到用戶 - 最后一步是由 control 返回到servlet。通常是生成HTML返回到user, 但你也可以指定返回的HTTP頭或HTTP重定向。

最明顯的就是Struts2是pull-MVC 架構,就是可以直接從Action中獲取所需要的數據,而不是像Struts那樣必須把 beans 存到page, request,或者session中才能獲取。



Eric.Zhou 2007-07-10 10:07 發表評論
]]>
Struts實現資源上傳http://m.tkk7.com/rain1102/archive/2007/01/30/96690.htmlEric.ZhouEric.ZhouTue, 30 Jan 2007 03:40:00 GMThttp://m.tkk7.com/rain1102/archive/2007/01/30/96690.htmlhttp://m.tkk7.com/rain1102/comments/96690.htmlhttp://m.tkk7.com/rain1102/archive/2007/01/30/96690.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/96690.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/96690.html     <form-bean name="fileUploadForm" type="org.apache.struts.action.DynaActionForm">
       <form-property name="fileName" type="Java.lang.String"></form-property>
       <form-property name="docfile" type="org.apache.struts.upload.FormFile"/>
       <form-property name="fileDescription" type="Java.lang.String"></form-property>
    </form-bean>


<form name="form1" method="post" action="<%=request.getContextPath()%>/fileUpload.do?method=upload" enctype="multipart/form-data">
  <table width="43%" border="1" align="center">
    <tr>
      <td colspan="2"><div align="center">上傳周報</div></td>
    </tr>
    <tr>
      <td width="22%">文件名稱</td>
      <td width="78%"><input type="text" name="fileName"></td>
    </tr>
    <tr>
      <td width="22%">選擇文件</td>
      <td width="78%"><input type="file" name="docfile"/></td>
    </tr>
    <tr>
      <td width="22%">文件描述</td>
      <td><input type="textarea" name="fileDescription"/></td>
    </tr>
    <tr>
      <td colspan="2" align="center"><input type="submit" name="Submit" value="上傳"><input type="reset" name="Submit2" value="重置"></td>
    </tr>
  </table>


public ActionForward upload(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
  request.setCharacterEncoding("UTF-8");
  DynaActionForm dynaform = (DynaActionForm) form;
  FormFile docfile = (FormFile) dynaform.get("docfile");
  String fileName=dynaform.get("fileName").toString();
  String fileDescription=(String) dynaform.get("fileDescription");
  if (docfile == null) {
   return mapping.getInputForward();
  }
  if (docfile.getFileSize() == 0) {
   request.getSession().setAttribute("message", "未選中文件或文件大小為零!");
   return mapping.getInputForward();
  }
  String ctype = docfile.getContentType();
  if (ctype.indexOf("doc") != -1) {
   request.getSession().setAttribute("message", "文件類型錯誤!");
   return mapping.getInputForward();
  }
  // 寫文件
  BufferedInputStream bis = null;
  BufferedOutputStream bos = null;
  InputStream is = null;
  OutputStream fos = null;

  String filename = "";
  String filePath = "";
  try {
   is = (InputStream) docfile.getInputStream();// 把文件讀入
   bis = new BufferedInputStream(is);

   filePath ="E:/upload/";// 取當前系統路徑
   File rootfile = new File(filePath);
   if (!rootfile.exists()) {
    rootfile.mkdirs();
   }
   String name= new String(docfile.getFileName().getBytes("UTF-8"),"gb2312");
   filename = new Date().getTime()+request.getSession().getId()+fileName+".doc";
  fos = new FileOutputStream(filePath + filename);// 建立一個上傳文件的輸出流
   bos = new BufferedOutputStream(fos);
   int bytesRead = 0;
   byte[] buffer = new byte[2 * 1024];
   while ((bytesRead = bis.read(buffer)) != -1) {
    bos.write(buffer, 0, bytesRead);// 將文件寫入服務器
   }
   FileUpload fileUpload=new FileUpload();
   fileUpload.setFileName(fileName);
   fileUpload.setFilePath(filePath+filename);
   fileUpload.setFileDescription(fileDescription);
   this.getSiteBusiness().getFileLoadService().save(fileUpload);
   return mapping.findForward("uploadsucess");
  }catch (Exception e) {
   e.printStackTrace();
   return mapping.getInputForward();
  } finally {
   if (bos != null) {
    try {
     bos.close();
    } catch (IOException e) {
     System.err.print(e);
     return mapping.getInputForward();
    }
   }
   if (bis != null) {
    try {
     bis.close();
    } catch (IOException e) {
     System.err.print(e);
     return mapping.getInputForward();
    }
   }
  }

 }



Eric.Zhou 2007-01-30 11:40 發表評論
]]>
Struts tiles 中不能包含 .do 文件問題的解決http://m.tkk7.com/rain1102/archive/2007/01/26/96158.htmlEric.ZhouEric.ZhouFri, 26 Jan 2007 07:04:00 GMThttp://m.tkk7.com/rain1102/archive/2007/01/26/96158.htmlhttp://m.tkk7.com/rain1102/comments/96158.htmlhttp://m.tkk7.com/rain1102/archive/2007/01/26/96158.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/96158.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/96158.html 肖菁
軟件工程師

[文章摘要] Struts tiles中提供了基于模版的頁面組裝框架,然而模版中需要包含.do文件的內容時,我們遇到了麻煩,本文中作者給出了一種簡單的方式來解決這個問題。

[關鍵詞] Struts Tiles

1  問題描述

我們在Web應用中使用Struts Tiles時,如果被組裝的內容是.do的內容,比如下面的例子,將會出現錯誤信息。

實際例子:<insert:put attribute=" /companyView.do?action=before_new">

錯誤信息:ServletException in '/companyView.do?action=before_new': 應答已經提交。

2  問題原因分析

tiles 使用了 JSP 的 jsp:include 技術實現頁面組裝,只能適用于 jsp 頁面,無法用于 .do 這樣的情況。

找到出錯的地方:

TilesUtilImpl.java 的 doInclude(String uri, PageContext pageContext)

2.1  doInclude 方法源代碼

public void doInclude(String uri, PageContext pageContext)

throws IOException, ServletException {

pageContext.include(uri);

}

3  問題解決

3.1  修改 doInclude 方法

public void doInclude(String uri, PageContext pageContext)

throws IOException, ServletException {

if (uri.indexOf(".jsp") > 0)

pageContext.include(uri);

else if (uri.indexOf(".do") > 0)

pageContext.getOut().write(getPageContent(uri, pageContext));

}

3.2 給 TilesUtilImpl 增加一個新的方法getPageContent,獲取 .do 文件的內容用于顯示

private String getPageContent(String uri, PageContext pageContext) {

String result = "";

HttpServletRequest request = (HttpServletRequest) pageContext .getRequest();

String contextPath = request.getContextPath();

String serverIP = request.getServerName();

String serverPort = String.valueOf(request.getServerPort());

String uriTmp = "http://";

if (serverPort.equals("80"))

uriTmp = uriTmp + serverIP;

else

uriTmp = uriTmp + serverIP + ":" + serverPort;

uriTmp = uriTmp + contextPath;

if (uri.startsWith("/"))

uriTmp += uri;

else

uriTmp += "/" + uri;

try {

URL url = new URL(uriTmp);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

BufferedReader reader = new BufferedReader(new InputStreamReader(

conn.getInputStream()));

String line = null;

while ((line = reader.readLine()) != null) {

result += line;

}

conn.disconnect();

reader.close();

} catch (Exception e) {

e.printStackTrace();

}

return result;

}


Eric.Zhou 2007-01-26 15:04 發表評論
]]>
使用 Spring 更好地處理 Struts 動作http://m.tkk7.com/rain1102/archive/2006/09/19/70561.htmlEric.ZhouEric.ZhouTue, 19 Sep 2006 08:41:00 GMThttp://m.tkk7.com/rain1102/archive/2006/09/19/70561.htmlhttp://m.tkk7.com/rain1102/comments/70561.htmlhttp://m.tkk7.com/rain1102/archive/2006/09/19/70561.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/70561.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/70561.htmlStruts Recipes 的合著者 George Franciscus 將介紹另一個重大的 Struts 整合竅門 —— 這次是將 Struts 應用程序導入 Spring 框架。請跟隨 George,他將向您展示如何改變 Struts 動作,使得管理 Struts 動作就像管理 Spring beans 那樣。結果是一個增強的 web 框架,這個框架可以方便地利用 Spring AOP 的優勢。

您肯定已經聽說過控制反轉 (IOC) 設計模式,因為很長一段時間以來一直在流傳關于它的信息。如果您在任何功能中使用過 Spring 框架,那么您就知道其原理的作用。在本文中,我利用這一原理把一個 Struts 應用程序注入 Spring 框架,您將親身體會到 IOC 模式的強大。

將一個 Struts 應用程序整合進 Spring 框架具有多方面的優點。首先,Spring 是為解決一些關于 JEE 的真實世界問題而設計的,比如復雜性、低性能和可測試性,等等。第二,Spring 框架包含一個 AOP 實現,允許您將面向方面技術應用于面向對象的代碼。第三,一些人可能會說 Spring 框架只有處理 Struts 比 Struts 處理自己好。但是這是觀點問題,我演示三種將 Struts 應用程序整合到 Spring 框架的方法后,具體由您自己決定使用哪一種。

我所演示的方法都是執行起來相對簡單的,但是它們卻具有明顯不同的優點。我為每一種方法創建了一個獨立而可用的例子,這樣您就可以完全理解每種方法。

為什么 Spring 這么了不起?

Spring 的創立者 Rod Johnson 以一種批判的眼光看待 Java™ 企業軟件開發,并且提議很多企業難題都能夠通過戰略地使用 IOC 模式(也稱作依賴注入)來解決。當 Rod 和一個具有奉獻精神的開放源碼開發者團隊將這個理論應用于實踐時,結果就產生了 Spring 框架。簡言之,Spring 是一個輕型的容器,利用它可以使用一個外部 XML 配置文件方便地將對象連接在一起。每個對象都可以通過顯示一個 JavaBean 屬性收到一個到依賴對象的引用,留給您的簡單任務就只是在一個 XML 配置文件中把它們連接好。

IOC 和 Spring

IOC 是一種使應用程序邏輯外在化的設計模式,所以它是被注入而不是被寫入客戶機代碼中。將 IOC 與接口編程應用結合,就像 Spring 框架那樣,產生了一種架構,這種架構能夠減少客戶機對特定實現邏輯的依賴。請參閱 參考資料 了解更多關于 IOC 和 Spring 的信息。

依賴注入是一個強大的特性,但是 Spring 框架能夠提供更多特性。Spring 支持可插拔的事務管理器,可以給您的事務處理提供更廣泛的選擇范圍。它集成了領先的持久性框架,并且提供一個一致的異常層次結構。Spring 還提供了一種使用面向方面代碼代替正常的面向對象代碼的簡單機制。

Spring AOP 允許您使用攔截器 在一個或多個執行點上攔截應用程序邏輯。加強應用程序在攔截器中的日志記錄邏輯會產生一個更可讀的、實用的代碼基礎,所以攔截器廣泛用于日志記錄。您很快就會看到,為了處理橫切關注點,Spring AOP 發布了它自己的攔截器,您也可以編寫您自己的攔截器。

整合 Struts 和 Spring

與 Struts 相似,Spring 可以作為一個 MVC 實現。這兩種框架都具有自己的優點和缺點,盡管大部分人同意 Struts 在 MVC 方面仍然是最好的。很多開發團隊已經學會在時間緊迫的時候利用 Struts 作為構造高品質軟件的基礎。Struts 具有如此大的推動力,以至于開發團隊寧愿整合 Spring 框架的特性,而不愿意轉換成 Spring MVC。沒必要進行轉換對您來說是一個好消息。Spring 架構允許您將 Struts 作為 Web 框架連接到基于 Spring 的業務和持久層。最后的結果就是現在一切條件都具備了。

在接下來的小竅門中,您將會了解到三種將 Struts MVC 整合到 Spring 框架的方法。我將揭示每種方法的缺陷并且對比它們的優點。 一旦您了解到所有三種方法的作用,我將會向您展示一個令人興奮的應用程序,這個程序使用的是這三種方法中我最喜歡的一種。

三個小竅門

接下來的每種整合技術(或者竅門)都有自己的優點和特點。我偏愛其中的一種,但是我知道這三種都能夠加深您對 Struts 和 Spring 的理解。在處理各種不同情況的時候,這將給您提供一個廣闊的選擇范圍。方法如下:

  • 使用 Spring 的 ActionSupport 類整合 Structs
  • 使用 Spring 的 DelegatingRequestProcessor 覆蓋 Struts 的 RequestProcessor
  • 將 Struts Action 管理委托給 Spring 框架

裝載應用程序環境

無論您使用哪種技術,都需要使用 Spring 的 ContextLoaderPlugin 為 Struts 的 ActionServlet 裝載 Spring 應用程序環境。就像添加任何其他插件一樣,簡單地向您的 struts-config.xml 文件添加該插件,如下所示:

<plug-in className=
  "org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property=
      "contextConfigLocation" value="/WEB-INF/beans.xml"/>
 </plug-in>

竅門 1. 使用 Spring 的 ActionSupport

手動創建一個 Spring 環境是一種整合 Struts 和 Spring 的最直觀的方式。為了使它變得更簡單,Spring 提供了一些幫助。為了方便地獲得 Spring 環境,org.springframework.web.struts.ActionSupport 類提供了一個 getWebApplicationContext() 方法。您所做的只是從 Spring 的 ActionSupport 而不是 Struts Action 類擴展您的動作,如清單 1 所示:


清單 1. 使用 ActionSupport 整合 Struts
package ca.nexcel.books.actions;

import Java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import org.springframework.context.ApplicationContext;
import org.springframework.web.struts.ActionSupport;

import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;

public class SearchSubmit extends ActionSupport {   |(1)


  public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    DynaActionForm searchForm = (DynaActionForm) form;
    String isbn = (String) searchForm.get("isbn");
		
    //the old fashion way
    //BookService bookService = new BookServiceImpl();
		
    ApplicationContext ctx = 
      getWebApplicationContext();    |(2)
    BookService bookService = 
      (BookService) ctx.getBean("bookService");   |(3)
        
  Book book = bookService.read(isbn.trim());

    if (null == book) {
      ActionErrors errors = new ActionErrors();
      errors.add(ActionErrors.GLOBAL_ERROR,new ActionError
        ("message.notfound"));
      saveErrors(request, errors);
      return mapping.findForward("failure") ;
  }

    request.setAttribute("book", book);
    return mapping.findForward("success");
  }
}

讓我們快速思考一下這里到底發生了什么。在 (1) 處,我通過從 Spring 的 ActionSupport 類而不是 Struts 的 Action 類進行擴展,創建了一個新的 Action。在 (2) 處,我使用 getWebApplicationContext() 方法獲得一個 ApplicationContext。為了獲得業務服務,我使用在 (2) 處獲得的環境在 (3) 處查找一個 Spring bean。

這種技術很簡單并且易于理解。不幸的是,它將 Struts 動作與 Spring 框架耦合在一起。如果您想替換掉 Spring,那么您必須重寫代碼。并且,由于 Struts 動作不在 Spring 的控制之下,所以它不能獲得 Spring AOP 的優勢。當使用多重獨立的 Spring 環境時,這種技術可能有用,但是在大多數情況下,這種方法不如另外兩種方法合適。

竅門 2. 覆蓋 RequestProcessor

將 Spring 從 Struts 動作中分離是一個更巧妙的設計選擇。分離的一種方法是使用 org.springframework.web.struts.DelegatingRequestProcessor 類來覆蓋 Struts 的 RequestProcessor 處理程序,如清單 2 所示:


清單 2. 通過 Spring 的 DelegatingRequestProcessor 進行整合

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
 <form-beans>
    <form-bean name="searchForm" 
      type="org.apache.struts.validator.DynaValidatorForm">
               <form-property name="isbn"    type="Java.lang.String"/>
    </form-bean>
  
  </form-beans>

 <global-forwards type="org.apache.struts.action.ActionForward">
     <forward   name="welcome"                path="/welcome.do"/>
     <forward   name="searchEntry"            path="/searchEntry.do"/>
     <forward   name="searchSubmit"           path="/searchSubmit.do"/>
 </global-forwards>

 <action-mappings>
    <action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
    <action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
    <action    path="/searchSubmit" 
               type="ca.nexcel.books.actions.SearchSubmit"
               input="/searchEntry.do"
               validate="true"
               name="searchForm">
              <forward name="success" path="/WEB-INF/pages/detail.jsp"/>
              <forward name="failure" path="/WEB-INF/pages/search.jsp"/>
    </action>  

 </action-mappings>

 <message-resources parameter="ApplicationResources"/>

 <controller processorClass="org.springframework.web.struts.
   DelegatingRequestProcessor"/> |(1)

 <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames" 
      value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
 </plug-in>


 <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/>
 </plug-in>
 
</struts-config>

我利用了 <controller> 標記來用 DelegatingRequestProcessor 覆蓋默認的 Struts RequestProcessor。下一步是在我的 Spring 配置文件中注冊該動作,如清單 3 所示:


清單 3. 在 Spring 配置文件中注冊一個動作

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
  "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

  <bean name="/searchSubmit" 
    class="ca.nexcel.books.actions.SearchSubmit"> |(1)
     <property name="bookService">
        <ref bean="bookService"/>
     </property>
  </bean>
</beans>

注意:在 (1) 處,我使用名稱屬性注冊了一個 bean,以匹配 struts-config 動作映射名稱。SearchSubmit 動作揭示了一個 JavaBean 屬性,允許 Spring 在運行時填充屬性,如清單 4 所示:


清單 4. 具有 JavaBean 屬性的 Struts 動作

package ca.nexcel.books.actions;

import Java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;

import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;

public class SearchSubmit extends Action {
	
  private BookService bookService;
  public BookService getBookService() {
    return bookService;
  }

  public void setBookService(BookService bookService) { | (1)
    this.bookService = bookService; 
  } 

  public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    DynaActionForm searchForm = (DynaActionForm) form;
    String isbn = (String) searchForm.get("isbn");
		
  Book book = getBookService().read(isbn.trim());  |(2)

    if (null == book) {
      ActionErrors errors = new ActionErrors();
      errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));
      saveErrors(request, errors);
      return mapping.findForward("failure") ;
  }

      request.setAttribute("book", book);
      return mapping.findForward("success");
  }

}

在清單 4 中,您可以了解到如何創建 Struts 動作。在 (1) 處,我創建了一個 JavaBean 屬性。DelegatingRequestProcessor自動地配置這種屬性。這種設計使 Struts 動作并不知道它正被 Spring 管理,并且使您能夠利用 Sping 的動作管理框架的所有優點。由于您的 Struts 動作注意不到 Spring 的存在,所以您不需要重寫您的 Struts 代碼就可以使用其他控制反轉容器來替換掉 Spring。

DelegatingRequestProcessor 方法的確比第一種方法好,但是仍然存在一些問題。如果您使用一個不同的 RequestProcessor,則需要手動整合 Spring 的 DelegatingRequestProcessor。添加的代碼會造成維護的麻煩并且將來會降低您的應用程序的靈活性。此外,還有過一些使用一系列命令來代替 Struts RequestProcessor 的傳聞。 這種改變將會對這種解決方法的使用壽命造成負面的影響。

竅門 3. 將動作管理委托給 Spring

一個更好的解決方法是將 Strut 動作管理委托給 Spring。您可以通過在 struts-config 動作映射中注冊一個代理來實現。代理負責在 Spring 環境中查找 Struts 動作。由于動作在 Spring 的控制之下,所以它可以填充動作的 JavaBean 屬性,并為應用諸如 Spring 的 AOP 攔截器之類的特性帶來了可能。

清單 5 中的 Action 類與清單 4 中的相同。但是 struts-config 有一些不同:


清單 5. Spring 整合的委托方法

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
 <form-beans>
    <form-bean name="searchForm" 
      type="org.apache.struts.validator.DynaValidatorForm">
               <form-property name="isbn"    type="Java.lang.String"/>
    </form-bean>
  
  </form-beans>

 <global-forwards type="org.apache.struts.action.ActionForward">
     <forward   name="welcome"                path="/welcome.do"/>
     <forward   name="searchEntry"            path="/searchEntry.do"/>
     <forward   name="searchSubmit"           path="/searchSubmit.do"/>
 </global-forwards>

 <action-mappings>
    <action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
    <action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
    <action    path="/searchSubmit" 
             type="org.springframework.web.struts.DelegatingActionProxy" |(1)
             input="/searchEntry.do"
             validate="true"
             name="searchForm">
             <forward name="success" path="/WEB-INF/pages/detail.jsp"/>
             <forward name="failure" path="/WEB-INF/pages/search.jsp"/>
    </action>  

 </action-mappings>

 <message-resources parameter="ApplicationResources"/>


 <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property 
    property="pathnames" 
    value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
 </plug-in>


 <plug-in 
    className="org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
 </plug-in>

 
</struts-config>

清單 5 是一個典型的 struts-config.xml 文件,只有一個小小的差別。它注冊 Spring 代理類的名稱,而不是聲明動作的類名,如(1)處所示。DelegatingActionProxy 類使用動作映射名稱查找 Spring 環境中的動作。這就是我們使用 ContextLoaderPlugIn 聲明的環境。

將一個 Struts 動作注冊為一個 Spring bean 是非常直觀的,如清單 6 所示。我利用動作映射使用 <bean> 標記的名稱屬性(在這個例子中是 "/searchSubmit")簡單地創建了一個 bean。這個動作的 JavaBean 屬性像任何 Spring bean 一樣被填充:


清單 6. 在 Spring 環境中注冊一個 Struts 動作

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

  <bean name="/searchSubmit"   
        class="ca.nexcel.books.actions.SearchSubmit">
     <property name="bookService">
        <ref bean="bookService"/>
     </property>
  </bean>

</beans>

動作委托的優點

動作委托解決方法是這三種方法中最好的。Struts 動作不了解 Spring,不對代碼作任何改變就可用于非 Spring 應用程序中。RequestProcessor 的改變不會影響它,并且它可以利用 Spring AOP 特性的優點。

動作委托的優點不止如此。一旦讓 Spring 控制您的 Struts 動作,您就可以使用 Spring 給動作補充更強的活力。例如,沒有 Spring 的話,所有的 Struts 動作都必須是線程安全的。如果您設置 <bean> 標記的 singleton 屬性為“false”,那么不管用何種方法,您的應用程序都將在每一個請求上有一個新生成的動作對象。您可能不需要這種特性,但是把它放在您的工具箱中也很好。您也可以利用 Spring 的生命周期方法。例如,當實例化 Struts 動作時,<bean> 標記的 init-method 屬性被用于運行一個方法。類似地,在從容器中刪除 bean 之前,destroy-method 屬性執行一個方法。這些方法是管理昂貴對象的好辦法,它們以一種與 Servlet 生命周期相同的方式進行管理。

攔截 Struts

前面提到過,通過將 Struts 動作委托給 Spring 框架而整合 Struts 和 Spring 的一個主要的優點是:您可以將 Spring 的 AOP 攔截器應用于您的 Struts 動作。通過將 Spring 攔截器應用于 Struts 動作,您可以用最小的代價處理橫切關注點。

雖然 Spring 提供很多內置攔截器,但是我將向您展示如何創建自己的攔截器并把它應用于一個 Struts 動作。為了使用攔截器,您需要做三件事:

  1. 創建攔截器。
  2. 注冊攔截器。
  3. 聲明在何處攔截代碼。

這看起來非常簡單的幾句話卻非常強大。例如,在清單 7 中,我為 Struts 動作創建了一個日志記錄攔截器。 這個攔截器在每個方法調用之前打印一句話:


清單 7. 一個簡單的日志記錄攔截器

package ca.nexcel.books.interceptors;

import org.springframework.aop.MethodBeforeAdvice;

import Java.lang.reflect.Method;

public class LoggingInterceptor implements MethodBeforeAdvice {

   public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("logging before!");
    }
}

這個攔截器非常簡單。before() 方法在攔截點中每個方法之前運行。在本例中,它打印出一句話,其實它可以做您想做的任何事。下一步就是在 Spring 配置文件中注冊這個攔截器,如清單 8 所示:


清單 8. 在 Spring 配置文件中注冊攔截器

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
  "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

  <bean name="/searchSubmit" 
        class="ca.nexcel.books.actions.SearchSubmit">
     <property name="bookService">
        <ref bean="bookService"/>
     </property>
  </bean>

  <!--  Interceptors --> 
  <bean name="logger"    
    class="ca.nexcel.books.interceptors.LoggingInterceptor"/> |(1)

  <!-- AutoProxies -->
  <bean name="loggingAutoProxy" 
        class="org.springframework.aop.framework.autoproxy.
          BeanNameAutoProxyCreator"> |(2)
    <property name="beanNames">
          <value>/searchSubmit</valuesgt; |(3)
    </property>
    <property name="interceptorNames">
        <list>
          <value>logger</value> |(4)
        </list>
    </property>
   </bean>

</beans>

您可能已經注意到了,清單 8 擴展了 清單6 中所示的應用程序以包含一個攔截器。具體細節如下:

  • 在 (1) 處,我注冊了這個攔截器。
  • 在 (2) 處,我創建了一個 bean 名稱自動代理,它描述如何應用攔截器。還有其他的方法定義攔截點,但是這種方法常見而簡便。
  • 在 (3) 處,我將 Struts 動作注冊為將被攔截的 bean。如果您想要攔截其他的 Struts 動作,則只需要在 "beanNames" 下面創建附加的 <value> 標記。
  • 在 (4) 處,當攔截發生時,我執行了在 (1) 處創建的攔截器 bean 的名稱。這里列出的所有攔截器都應用于“beanNames”。

就是這樣。就像這個例子所展示的,將您的 Struts 動作置于 Spring 框架的控制之下,為處理您的 Struts 應用程序提供了一系列全新的選擇。在本例中,使用動作委托可以輕松地利用 Spring 攔截器提高 Struts 應用程序中的日志記錄能力。

結束語

在本文中,您已經學習了將 Struts 動作整合到 Spring 框架中的三種竅門。使用 Spring 的 ActionSupport 來整合 Struts(第一種竅門中就是這樣做的)簡單而快捷,但是會將 Struts 動作與 Spring 框架耦合在一起。如果您需要將應用程序移植到一個不同的框架,則需要重寫代碼。第二種解決方法通過委托 RequestProcessor 巧妙地解開代碼的耦合,但是它的可擴展性不強,并且當 Struts 的 RequestProcessor 變成一系列命令時,這種方法就持續不了很長時間。第三種方法是這三種方法中最好的:將 Struts 動作委托給 Spring 框架可以使代碼解耦,從而使您可以在您的 Struts 應用程序中利用 Spring 的特性(比如日志記錄攔截器)。

三種 Struts-Spring 整合竅門中的每一種都被實現成一個完整可用的應用程序。



Eric.Zhou 2006-09-19 16:41 發表評論
]]>
Ajax+Struts+Hibernate實現級聯下拉單http://m.tkk7.com/rain1102/archive/2006/09/13/69348.htmlEric.ZhouEric.ZhouWed, 13 Sep 2006 04:45:00 GMThttp://m.tkk7.com/rain1102/archive/2006/09/13/69348.htmlhttp://m.tkk7.com/rain1102/comments/69348.htmlhttp://m.tkk7.com/rain1102/archive/2006/09/13/69348.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/69348.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/69348.html<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>kind.html</title>
  <script type="text/javascript" src="js/common.js"></script>
  <script type="text/javascript">
    function refreshModelList(){ 
      var oneName=document.getElementById("kindone").value;
      if(oneName==""){
        clearlist();
        return;
      }
      var url="kind.do?method=search&&kindid="+oneName;
    
      createXMLHttpRequest();
     
      xmlHttp.onreadystatechange=handleStateChange;
      xmlHttp.open("GET",url,true);
      xmlHttp.send(null);
     
    }
    function handleStateChange(){
      if(xmlHttp.readyState==4){ 
        if(xmlHttp.status==200){
          setNames(); 
        }
      }
    }
    function clearlist(){
      var models=document.getElementById("kindtwo");
      while(models.childNodes.length>0){
        models.removeChild(models.childNodes[0]);
      }
    }
    function setNames(){
      clearlist();
      var models=document.getElementById("kindtwo");
      var xmlDoc=xmlHttp.responseXML;
      var results=xmlDoc.getElementsByTagName("kind");
      var option=null;
      for(var i=0;i<results.length;i++){
        option=document.createElement("option");
        option.appendChild(document.createTextNode(results[i].firstChild.nodeValue));
        models.appendChild(option);
      }
    }
  </script>
  </head>
 
  <body>
    <h2>dynamicLists</h2>
    <select id="kindone" onchange="refreshModelList();">
      <option value="1">a</option>
      <option value="2">b</option>
      <option value="3">c</option>
      <option value="4">d</option>
    </select>
    <select id="kindtwo">
    </select>
  </body>
</html>


/*
 * Generated by MyEclipse Struts
 * Template path: templates/java/JavaClass.vtl
 */
package com.rain.struts.action;

import Java.io.IOException;
import Java.io.PrintWriter;
import Java.util.Iterator;
import Java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import org.apache.struts.validator.DynaValidatorForm;

import com.rain.bean.KindDao;

/**
 * MyEclipse Struts
 * Creation date: 09-13-2006
 *
 * XDoclet definition:
 * @struts.action parameter="method"
 */
public class KindAction extends DispatchAction {
 /*
  * Generated Methods
  */

 /**
  * Method execute
  * @param mapping
  * @param form
  * @param request
  * @param response
  * @return ActionForward
  */
 public ActionForward search(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {
  DynaValidatorForm kindForm = (DynaValidatorForm)form;
  KindDao dao=new KindDao();
  int kindid=Integer.parseInt(kindForm.getString("kindid"));
  List list=dao.findAllKind(kindid);
  Iterator it=list.iterator();
  if(it.hasNext()){
   PrintWriter out;
   try {
    response.setContentType("text/xml;charset=UTF-8");
    response.setHeader("Cache-Control", "no-cache");
    out = response.getWriter();

    out.println("<response>");
    while(it.hasNext()){
     String name=it.next().toString();
     out.println("<kind>"+name+"</kind>");
    }
    out.println("</response>");
    it=null;
    out.close();
   } catch (IOException e) {
    // TODO 自動生成 catch 塊
    e.printStackTrace();
   }
   
  }else{
   response.setStatus(HttpServletResponse.SC_NO_CONTENT);
  }
  // TODO Auto-generated method stub
  return null;
 }
}



Eric.Zhou 2006-09-13 12:45 發表評論
]]>
Ajax+Struts+Hibernate注冊http://m.tkk7.com/rain1102/archive/2006/09/13/69302.htmlEric.ZhouEric.ZhouWed, 13 Sep 2006 01:29:00 GMThttp://m.tkk7.com/rain1102/archive/2006/09/13/69302.htmlhttp://m.tkk7.com/rain1102/comments/69302.htmlhttp://m.tkk7.com/rain1102/archive/2006/09/13/69302.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/69302.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/69302.htmlHTML代碼
<html>
<head>
<title>用戶注冊</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style type="text/css">
td {
 font-size:12px;
 color:#000033;
}
span {
 font-size:12px;
 color:#FF0000;
 text-align:center;
 height:20px;
 vertical-align:bottom;
}
input {
 border:0px;
 border-bottom:1px #666666 dotted;
 color:#3399FF;
}
</style>
<script language="JavaScript">
  var xmlHttp;
  function createXMLHttpRequest(){
  if(window.ActiveXObject){
     try {
    xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
  try {
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
   } catch (e) {}
  }
   }else if(window.XMLHttpRequest){
     xmlHttp = new XMLHttpRequest();
  if (xmlHttp.overrideMimeType) {
    xmlHttp.overrideMimeType('text/xml');
   }
   }
   if (!xmlHttp) {
   window.alert("Could not create XMLHttpRequest.");
   return false;
   }
  }
  function checkUsername(obj){
    createXMLHttpRequest();
    document.getElementById("usernameview").innerHTML="";
    var url="login.do?method=checkUserName&&UserName="+obj;
    xmlHttp.onreadystatechange=handleStateChange;
    xmlHttp.open("GET",url,true);
    xmlHttp.send(null);
  }
  function handleStateChange(){
    if(xmlHttp.readyState==4){
        if(xmlHttp.status==200){
          document.getElementById("usernameview").innerHTML=xmlHttp.responseText;
        }
      }
  }
  function checkPassword(obj){
    document.getElementById("pwdview").innerHTML="";
    if(obj.length<6){
      document.getElementById("pwdview").innerHTML="密碼長度不能小于六位!";
    }
    else{
      document.getElementById("pwdview").innerHTML="√";
    }
  }
  function checkPassword2(obj){
    var pwd1=document.getElementById("password1").value;
    document.getElementById("usernameview").innerHTML="";
    if(obj!=pwd1||obj==null)
    {
      document.getElementById("pwd2view").innerHTML="兩次輸入的密碼不一致!";
    }else{
      document.getElementById("pwd2view").innerHTML="√";
    }
  }
  function checkRealName(obj){
    if(obj==null){
       document.getElementById("realnameview").innerHTML="真實姓名不能為空!";
    }else{
        document.getElementById("realnameview").innerHTML="√";
    }
  }
</script>

</head>
<body>
 <form name="RegistForm">
 <table height="328" align="center" cellpadding="0" cellspacing="0" style="border:2px #666666 solid; ">
 
 <tr>
  <td colspan="2" height="30" bgcolor="#666666" align="center" style="border-bottom:1px #666666 solid;"><font color="#FFFFFF"><b>用&nbsp;戶&nbsp;注&nbsp;冊</b></font></td>
 </tr>
 <tr>
  <td width="147" height="35" align="right">用&nbsp;戶&nbsp;名:</td>
  <td width="368"><input type="text" name="UserName" id="username" maxlength="15" size="13" onblur="checkUsername(this.value);">&nbsp;&nbsp;<font color="#ff0000">*</font>&nbsp;&nbsp;<span id="usernameview"></span></td>
 </tr>
 <tr>
  <td height="35" align="right">密&nbsp;&nbsp;&nbsp;&nbsp;碼:</td>
  <td><input type="password" name="Password" id="password1" maxlength="15" size="15" onblur="checkPassword(this.value);">&nbsp;&nbsp;<font color="#ff0000">*</font><span id="pwdview"></span></td>
 </tr>
 <tr>
  <td height="35" align="right">密碼校驗:</td>
  <td><input type="password" name="Password2" id="password2" maxlength="15" size="15" onblur="checkPassword2(this.value);">&nbsp;&nbsp;<font color="#ff0000">*</font>&nbsp;&nbsp;<span id="pwd2view"></span></td>
 </tr>
 <tr>
  <td height="35" align="right">真實姓名:</td>
  <td><input type="text" name="realname" id="realname" size="10" maxlength="10" onblur="checkRealName(this.value);">&nbsp;&nbsp;<font color="#ff0000">*</font><span id="realnameview"></span></td>
 </tr>
 <tr>
  <td height="35" align="right">性&nbsp;&nbsp;&nbsp;&nbsp;別:</td>
  <td><select name="sex" id="sex">
  <option value="m">男</option>
  <option value="w">女</option></select>&nbsp;&nbsp;<font color="#ff0000">*</font></td>
 </tr>
 <tr>
  <td height="35" align="right">聯系電話:</td>
  <td><input type="text" name="tel" id="tel" maxlength="12" size="13" >&nbsp;&nbsp;<font color="#ff0000">*</font></td>
 </tr>
 <tr>
  <td height="35" align="right">手&nbsp;&nbsp;&nbsp;&nbsp;機:</td>
  <td><input type="text" name="mobile" id="mobile" maxlength="12" size="13">&nbsp;&nbsp;<font color="#ff0000">*</font></td>
 </tr>
 <tr>
  <td height="35" align="right">E - mail:</td>
  <td><input type="text" name="email" id="email" size="25" onChange="checkEmail();">&nbsp;&nbsp;<font color="#ff0000">*</font></td>
 </tr>
 <tr>
  <td height="86" align="right">個人簡介:</td>
  <td><textarea cols="30" rows="4" class="text" name="memo" style="overflow:auto; border:1px #666666 solid; color:#3399FF;"></textarea>&nbsp;&nbsp;<font color="#ff0000">*</font></td>
 </tr>
 <tr>
  <td height="10" colspan="2"></td>
 </tr>
 <tr>
  <td height="30" colspan="2" align="center" style="border-top:1px #666666 solid; "><input onClick="javascript:addUser();" style="background-color:#666666; color:#FFFFFF; border:0; text-align:center; width:60px;" type="button" name="add" value="A D D">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input style="background-color:#666666; color:#FFFFFF; border:0; width:60px;" type="reset" name="reset" value="R E T"></td>
 </tr>
 
 </table>
 </form>
</body>
</html>


/*
 * Generated by MyEclipse Struts
 * Template path: templates/java/JavaClass.vtl
 */
package com.rain.struts.action;

import Java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import org.apache.struts.validator.DynaValidatorForm;

import com.rain.bean.Regist;

/**
 * MyEclipse Struts
 * Creation date: 09-12-2006
 *
 * XDoclet definition:
 * @struts.action parameter="method" validate="true"
 */
public class LoginAction extends DispatchAction {
 

 /**
  * Method execute
  * @param mapping
  * @param form
  * @param request
  * @param response
  * @return ActionForward
  */
 public ActionForward checkUserName(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {
  Regist regist=new Regist();
  DynaValidatorForm loginForm = (DynaValidatorForm)form;
  String username=loginForm.getString("UserName");
  System.out.println(username);
  boolean flag=regist.findByName(username);
  System.out.println("test");
  if(flag)
  {
   try {
    response.getWriter().write("sorry!");
   } catch (IOException e) {
    // TODO 自動生成 catch 塊
    e.printStackTrace();
   }
  }else
  {
   try {
    response.getWriter().write("luck!");
   } catch (IOException e) {
    // TODO 自動生成 catch 塊
    e.printStackTrace();
   }
  }
    
  return null;
 }
}




Eric.Zhou 2006-09-13 09:29 發表評論
]]>
Ajax+Struts+Hibernate實現動態搜索http://m.tkk7.com/rain1102/archive/2006/09/13/69294.htmlEric.ZhouEric.ZhouWed, 13 Sep 2006 01:19:00 GMThttp://m.tkk7.com/rain1102/archive/2006/09/13/69294.htmlhttp://m.tkk7.com/rain1102/comments/69294.htmlhttp://m.tkk7.com/rain1102/archive/2006/09/13/69294.html#Feedback6http://m.tkk7.com/rain1102/comments/commentRss/69294.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/69294.htmlHTML源代碼
<%@ page language="Java" contentType="text/html; charset=UTF-8"%>
<html>
  <head>
    <title>article.html</title>
  <script type="text/javascript" src="js/common.js"></script>
  <script type="text/javascript">
  var completeDiv;
  var inputField;
  var nameTable;
  var nameTableBody;
  function initVars() {
     inputField = document.getElementById("title");           
     nameTable = document.getElementById("name_table");
     completeDiv = document.getElementById("popup");
     nameTableBody = document.getElementById("name_table_body");
    
  }
 
  function findNames(){
   initVars();
   if (inputField.value.length > 0) {
       createXMLHttpRequest(); 
       var url = "article.do?method=search&title="+encodeURI(inputField.value);  
       xmlHttp.open("GET", url, true);
       xmlHttp.onreadystatechange = callback;
       xmlHttp.send(null);
    } else {
       clearNames();
    }
  }
  function callback() {
            if (xmlHttp.readyState == 4) {
                if (xmlHttp.status == 200) {
               
                    var name = xmlHttp.responseXML.getElementsByTagName("title")[0].firstChild.data;
                    setNames(xmlHttp.responseXML.getElementsByTagName("title"));
                } else if (xmlHttp.status == 204){
                    clearNames();
                  
                }
            }
        }
       
        function setNames(the_names) {           
            clearNames();
            var size = the_names.length;
            setOffsets();

            var row, cell, txtNode;
            for (var i = 0; i < size; i++) {
                var nextNode = the_names[i].firstChild.data;
                row = document.createElement("tr");
                cell = document.createElement("td");
               
                cell.onmouseout = function() {this.className='mouseOver';};
                cell.onmouseover = function() {this.className='mouseOut';};
                cell.setAttribute("bgcolor", "#FFFAFA");
                cell.setAttribute("border", "0");
                cell.onclick = function() { populateName(this); } ;                            

                txtNode = document.createTextNode(nextNode);
                cell.appendChild(txtNode);
                row.appendChild(cell);
                nameTableBody.appendChild(row);
               
            }
        }

        function setOffsets() {
            var end = inputField.offsetWidth;
            var left = calculateOffsetLeft(inputField);
            var top = calculateOffsetTop(inputField) + inputField.offsetHeight;

            completeDiv.style.border = "black 1px solid";
            completeDiv.style.left = left + "px";
            completeDiv.style.top = top + "px";
            nameTable.style.width = end + "px";
        }
       
        function calculateOffsetLeft(field) {
          return calculateOffset(field, "offsetLeft");
        }

        function calculateOffsetTop(field) {
          return calculateOffset(field, "offsetTop");
        }

        function calculateOffset(field, attr) {
          var offset = 0;
          while(field) {
            offset += field[attr];
            field = field.offsetParent;
          }
          return offset;
        }

        function populateName(cell) {
            inputField.value = cell.firstChild.nodeValue;
            clearNames();
        }
  function clearNames() {
     var ind = nameTableBody.childNodes.length;
     for (var i = ind - 1; i >= 0 ; i--) {
       nameTableBody.removeChild(nameTableBody.childNodes[i]);
     }
    completeDiv.style.border = "none";
  }
  </script>
  </head>
 
  <body>
    <h3>Ajax Auto Complete Example</h3>
    請輸入名稱:<input type="text" name="title" id="title" size="30" width="100" height="20" onkeyup="findNames();">
    <div style="position:absolute;" id="popup">
        <table id="name_table" bgcolor="#FFFAFA" border="0" cellspacing="0" cellpadding="0"/>           
            <tbody id="name_table_body"></tbody>
        </table>
    </div>
  </body>
</html>


Action源代碼
/*
 * Generated by MyEclipse Struts
 * Template path: templates/java/JavaClass.vtl
 */
package com.rain.struts.action;

import Java.io.IOException;
import Java.io.PrintWriter;
import Java.io.UnsupportedEncodingException;
import Java.util.Iterator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import org.apache.struts.validator.DynaValidatorForm;

import com.rain.bean.ArticleDao;

/**
 * MyEclipse Struts
 * Creation date: 09-12-2006
 *
 * XDoclet definition:
 * @struts.action parameter="method"
 */
public class ArticleAction extends DispatchAction {
 /*
  * Generated Methods
  */

 /**
  * Method execute
  * @param mapping
  * @param form
  * @param request
  * @param response
  * @return ActionForward
  */
 public ActionForward search(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {
  DynaValidatorForm articleForm = (DynaValidatorForm)form;
  String title;
  try {
   title = new String(request.getParameter("title").getBytes("ISO8859_1"),"UTF-8");
   System.out.println(title);
   ArticleDao dao=new ArticleDao();
   
   Iterator it=dao.findAllName(title).iterator();
   
   if(it.hasNext()){
    PrintWriter out;
    try {
     
     response.setContentType("text/xml;charset=UTF-8");
     response.setHeader("Cache-Control", "no-cache");
     out = response.getWriter();
     out.println("<response>");
     while(it.hasNext()){
      String name=it.next().toString();
      out.println("<title>"+name+"</title>");
     }
     out.println("</response>");
     it=null;
     out.close();
    } catch (IOException e) {
     // TODO 自動生成 catch 塊
     e.printStackTrace();
    }
    
   }else{
    response.setStatus(HttpServletResponse.SC_NO_CONTENT);
   }
  } catch (UnsupportedEncodingException e1) {
   // TODO 自動生成 catch 塊
   e1.printStackTrace();
  }
  
  
  return null;
 }
}



Dao源代碼
/**
 *@type_name: ArticleDao
 *@date: 2006-9-13
 *@author scott_zhou
 */
package com.rain.bean;

import Java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.rain.HibernateSessionFactory;

/**
 *
 */
public class ArticleDao {

 public List findAllName(String title){
  System.out.println("11");
  String hql="select art.title from Article art where art.title like '"+title+"%'";
     List list=null;
     try{
     
      Session session=HibernateSessionFactory.getCurrentSession();

         Transaction tx=session.beginTransaction();
          Query query=session.createQuery(hql);
           
            list=query.list();
            tx.commit();
            session.close();
     }catch(Exception e){
      System.out.println(e.getMessage());
      e.printStackTrace();
     }
       
        return list;
 }
}



Eric.Zhou 2006-09-13 09:19 發表評論
]]>
Struts標記庫http://m.tkk7.com/rain1102/archive/2006/09/06/68065.htmlEric.ZhouEric.ZhouWed, 06 Sep 2006 08:51:00 GMThttp://m.tkk7.com/rain1102/archive/2006/09/06/68065.htmlhttp://m.tkk7.com/rain1102/comments/68065.htmlhttp://m.tkk7.com/rain1102/archive/2006/09/06/68065.html#Feedback0http://m.tkk7.com/rain1102/comments/commentRss/68065.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/68065.html閱讀全文

Eric.Zhou 2006-09-06 16:51 發表評論
]]>
Struts 配置骨架http://m.tkk7.com/rain1102/archive/2006/09/04/67610.htmlEric.ZhouEric.ZhouMon, 04 Sep 2006 08:28:00 GMThttp://m.tkk7.com/rain1102/archive/2006/09/04/67610.htmlhttp://m.tkk7.com/rain1102/comments/67610.htmlhttp://m.tkk7.com/rain1102/archive/2006/09/04/67610.html#Feedback1http://m.tkk7.com/rain1102/comments/commentRss/67610.htmlhttp://m.tkk7.com/rain1102/services/trackbacks/67610.html閱讀全文

Eric.Zhou 2006-09-04 16:28 發表評論
]]>
主站蜘蛛池模板: WWW亚洲色大成网络.COM| 精品亚洲AV无码一区二区三区| 色噜噜狠狠色综合免费视频| 影音先锋在线免费观看| 色在线亚洲视频www| 成人黄动漫画免费网站视频 | 一本色道久久综合亚洲精品| 农村寡妇一级毛片免费看视频| 亚洲高清成人一区二区三区 | 久章草在线精品视频免费观看| 亚洲第一AAAAA片| 最近的中文字幕大全免费8| 亚洲天堂一区二区三区| 美女视频黄免费亚洲| 亚洲另类无码专区丝袜| 国产老女人精品免费视频| 国产亚洲精品仙踪林在线播放| 亚洲精品和日本精品| a毛看片免费观看视频| 久久亚洲AV成人无码软件| AV大片在线无码永久免费| 丰满亚洲大尺度无码无码专线 | 免费在线观看毛片| 在线观看免费视频一区| 亚洲国产精品专区| 一本色道久久88综合亚洲精品高清| 三级片免费观看久久| 亚洲精品在线观看视频| 毛片免费观看的视频在线| 一级毛片a女人刺激视频免费| 亚洲人成电影在在线观看网色| 久久久久久国产精品免费免费| 免费无码国产V片在线观看| 久久精品亚洲综合| 在线jyzzjyzz免费视频| 国产午夜无码片免费| 亚洲乱码一二三四区乱码| 亚洲色一色噜一噜噜噜| 亚洲电影免费观看| jyzzjyzz国产免费观看| 亚洲人成网站在线观看播放动漫 |