strust2相關知識

本菜鳥開始寫博客啦......


一、Struts2的主要組建

  1. FilterDispatcher:中央控制作用的過濾器

  2. Action:處於Model層的Action,調用JavaBean實現業務邏輯

  3. struts.xml:核心配置文件,配置有Action、Result等

  4. result:與forward類似,轉發的目的地,支持多種視圖技術。


二、Struts2的Action訪問web對象

Action是一個普通的POJO對象,與web的四大內置對象未耦合在一起,便於單獨測試Action

訪問這些web內部對象有2種方式:

1. 直接訪問Web對象

Struts2框架提供org.apache.struts2.ServletActionContext輔助類來獲得web對象。

HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
HttpSession session = request.getSession();
ServletContext application = ServletActionContext.getServletContext();

2. Action訪問ActionContext

com.opensymphony.xwork2.ActionContext是一個Action執行的上下文,Action執行期間所用到的對象都保存在ActionContext中,例如session、參數等,並且ActionContext是一個局部線程變量,不用擔心Action的線程安全。

ActionContext context = ActionContext.getContext();
ActionContext中的常用方法
Object get(Object key):    使用key來查找當前ActionContext中的值
Map getApplication():    返回一個Application範圍的Map
static ActionContext getContext()    :獲得當前線程的ActionContext實例
Map getParameters():    Map類型的所有HttpServletRequest的參數
Map getSession():    Map類型的HttpSession值
ValueStack getValueStack():    返回一個ValueStack類型OGNL值棧
void put(Object key,Object value):    向當前ActionContext存入值,等於在HttpServletRequest中加入值
void setApplication(Map application):    設置application上下文
void setSession(Map session):    設置session值,參數爲Map實例
這種方法使用的所有對象和Web對象沒有直接聯繫,所以在測試的時候也是很方便的。


三、Action的分類


1. 繼承ActionSupport實現Action

通過繼承ActionSupport來實現Action是我們的推薦做法,因爲ActionSupport中提供了輸入驗證、國際化、execute等常用方法,使得編寫Action時代碼很簡單。


2. 模型驅動(ModelDriven)的Action

Struts2的Action屬於model層,Action中的方法代表業務邏輯,Action中的屬性代表請求中的參數,當頁面請求參數較多的時候,把過多的參數對象的屬性定義在Action中不太符合Struts所倡導的鬆耦合原則,所以我們推薦單獨用JavaBean來封裝參數,在Action中爲JavaBean賦值,這就是ModelDriven的Action。模型驅動的Action要求Action實現ModelDriven接口,假如登錄頁面需要傳輸參數username和userpass,我們把這2個參數封裝在一個數據的JavaBean中,然後在Action中定義該JavaBean爲Model即可,代碼如下:

UserInfo.java

package po;
//用戶名和密碼封裝對象
public class UserInfo {
    private String username;
    private String userpass;
    get...;
    set...;
}

UserAction.java

import com.opensymphony.xwork2.ActionSupport; 
import com.opensymphony.xwork2.ModelDriven;

public class UserAction extends ActionSupport implements ModelDriven<Userinfo> {
    private Userinfo model = new Userinfo();
    @Override public String execute() throws Exception { 
        // TODO Auto-generated method stub return SUCCESS; 
    } 
    //返回模型對象的實例
    public Userinfo getModel() { 
        // TODO Auto-generated method stub 
        return model; 
    } 
}

當請求該Action的時候,請求中的參數會自動填充到模型Userinfo的屬性中,當然需要參數名和屬性名一樣,到跳轉的頁面上利用Struts2標籤<s:property value="username" />可以取出模型Userinfo中的屬性username。在ModelDriven接口中的方法getModel()必須實現,通過它告訴系統模型的具體對象是什麼。


3. 多方法的Action

Action中的方法代表業務邏輯,那麼一個模塊中的多個業務邏輯如何用Action來處理呢?我們有2種辦法來處理這個問題:

1. 一個Action對應一個業務邏輯,實現方便,但是Action數量多,struts.xml中需要配置的內容也多,這種方法不推薦;

2. 一個Action對應多個業務邏輯,例如表的CRUD操作,含有多個業務邏輯,我們只寫一個Action來實現,Action的數量沒有增加,struts.xml的配置也簡單,所以這種方法是我們推薦的做法。

Action中自定義方法的聲明和execute方法一樣,方法的調用路徑爲“Action名稱!方法名稱.action”。

以用戶表Userinfo的CRUD操作爲例,看一下多方法Action的代碼:

import po.Userinfo;
import service.UserService;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class CrudUserAction extends ActionSupport implements ModelDriven<Userinfo> { 
    // crud業務方法
    private UserService userservice = new UserService();
    private Userinfo userinfo = new Userinfo();
    // 模型對象userinfo
    public Userinfo getModel() {
        // TODO Auto-generated method stub return userinfo;
    }
    // 增加
    public String create() throws Exception { 
        userservice.createUser(userinfo); return SUCCESS;
    }
    // 查詢
    public String retrive() throws Exception {
        // 查詢結果放在request中
        ActionContext.getContext().put("userlist", userservice.selectUsers());
        return "list"; 
    }
    // 修改
    public String update() throws Exception { 
        userservice.updateUser(userinfo); 
        return SUCCESS;
    }
    // 刪除
    public String delete() throws Exception { 
        userservice.deleteUser(userinfo.getUsername()); 
        return SUCCESS; 
    }
    // 默認的execute
    public String execute() throws Exception {
        return SUCCESS; 
    } 
}

在struts.xml中配置如下:

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE struts PUBLIC 
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 
    "http://struts.apache.org/dtds/struts-2.0.dtd"> 
<struts> 
    <package name="actions" extends="struts-default">
        <action name="CrudUser" class="action.CrudUserAction">
            <result>/Success.jsp</result> 
            <result name="list">/UserList.jsp</result>
        </action>
    </package>
</struts>

除了以上方式,還可以在<action>標籤中配置method屬性,使用通配符。


四、Result類型

    Action中表示跳轉的目的地使用了在struts.xml配置的字符串,格式爲:<result name=”” type=””></result>,type可以有多種選擇,Struts2支持各種視圖技術,例如JSP、JSF、XML等,默認的是JSP。常見的type類型配置如下:

dispatcher—轉發到JSP頁面,默認

redirect—重定向到JSP頁面

redirect-action—重定向到action,目的地爲Action,配置時可以指定如下兩個參數:actionName-重定向的Action名;namespace-重定向的Action所在的命名空間

chain—轉發到action,形成action-chain,可以指定兩個參數:actionName-重定向的Action名;namespace-重定向的Action所在的命名空間。

stream—用於向頁面返回一個InputStream,原始數據直接傳遞給HttpServletResponse,這種結果類型在用戶下載文件(例如PDF文件等)等情況下非常有意義.

plantext—用於輸出目的地JSP/HTML的源代碼內容,可以指定兩個參數:location-目的地JSP/HTML,charSet-輸出內容時使用的字符集。

除了上述類型以外,還支持如下的類型:

chart:用於整合JFreeChart的result類型;

freemarker:用於整合FreeMarker的result類型;

httpheader:用於處理特殊http行爲的result類型;

jasper:用於整合JasperReport的result類型;

jsf:用於整合JSF的result類型;

titles:用於整合Titles的result類型;

velocity:用於整合Velocity的result類型;

xslt:用於整合XML/XSLT的result類型。

這些視圖技術的支持,有些還需要導入相應的插件包,即Struts2提供的含有plugin字樣的jar包。


、Strut2的國際化

在struts.xml中配置struts.custom.i18n.resources常量

<constant name="struts.custom.i18n.resources" value="globalMessages"/>

在src目錄下建立中文和英文的資源文件


六、Struts2攔截器

    攔截器(interceptor)是Struts2框架核心組成部分。很多功能都是構建在攔截器基礎之上的,例如文件的上傳和下載、國際化、數據類型轉換和數據有效性驗證等,Struts2利用內建的攔截器,完成了框架內的大部分操作。

    攔截器就是動態攔截Action調用的對象。它提供了一種機制,使開發者可以定義一個特定的功能模塊,這個模塊可以在Action執行之前或之後運行,也可以在一個Action執行之前阻止Action執行。同時也提供了一種可以提取Action中可重用部分的方式。

    Struts2框架的Action被一個或者多個攔截器(攔截器棧)所包圍,所有的用戶請求都會被攔截器所攔截,然後交給Action處理,處理結果以邏輯視圖的方式返回給用戶。而這個調用的執行流程,是由Strut2的配置文件(struts.xml)來實現的。

    在前面幾節中,沒有明確說明攔截器,爲什麼可以直接調用Action呢?那是因爲在Struts2框架中如果沒有顯式的攔截器配置,則系統會調用默認的攔截器來調用Action,在用戶看來,好像沒有配置攔截器一樣。演示一個簡單攔截器的開發:HelloWorld攔截器。假設我們需要實現這麼一個功能,在調用每個Action之前都能在控制檯打印出“HelloWorld”。這樣的一個功能使用Struts2攔截器來實現最簡單。下面介紹一個具體的實現步驟。

    HelloWorldInterceptor.java

package interceptor; 
import action.MyAction; 
import com.opensymphony.xwork2.ActionInvocation; 
import com.opensymphony.xwork2.interceptor.AbstractInterceptor; 
public class HelloWorldInterceptor extends AbstractInterceptor { 
    //攔截方法
    @Override 
    public String intercept(ActionInvocation arg0) throws Exception { 
        // 獲得被調用的Action類
        Object action = arg0.getAction(); 
        // 打印HelloWorld 
        System.out.println("攔截器信息:HelloWorld!"); 
        // 執行Action或調用下一個攔截器
        String result = arg0.invoke(); 
        // 執行完action後提示
        System.out.println("Action執行完畢!");
        return result;
    }
}

在struts.xml中加入攔截器的配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC 
     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 
     "http://struts.apache.org/dtds/struts-2.0.dtd"> 
<struts>
     <package name="action" extends="struts-default">
          <!-- 定義攔截器 -->
          <interceptors>
               <interceptor name="helloworld" class="interceptor.HelloWorldInterceptor"/>
          </interceptors>
          <action name="test" class="action.MyAction">
              <result>Success.jsp</result> 
              <!-- action中引用默認攔截器-->
              <interceptor-ref name="defaultStack" />
              <!-- action中引用攔截器--> 
              <interceptor-ref name="helloworld"/>
          </action>
      </package>
</struts>

七、攔截器應用實例-文件上傳和下載

上傳單個文件

<body> 
<s:form action="fileupload" method="post" enctype="multipart/form-data"> 上傳文件:<s:file name="doc"/><br> 
<s:submit value="上傳"/> </s:form>
</body>

form表單的enctype屬性設置爲multipart/form-data。enctype用來指定表單數據的編碼方式,有如下3個值。

1. application/x-www-form-urlencoded:指定該值,則表單中的數據被編碼爲Key-Value對,這是默認的編碼方式。

2. multipart/form-data:使用mime編碼,會以二進制流的方式來處理表單數據,文件上傳需要使用該編碼方式。

3. text/plain:表單數據以純文本形式進行編碼,其中不含任何控件和格式字符。

    file類型表單域doc用於選擇上傳文件,它和Action中的java.io.File類型的屬性doc對應,同時上傳文件的文件名對應於Action中的屬性docFileName,上傳文件的文件類型對應於Action中的屬性docContentType。一般說來,爲了上傳文件,如果表單域名稱爲xxx,那麼在Action中應建立如下3個屬性來接收上傳文件的信息。

private java.io.File xxx;//封裝上傳文件的二進制內容
private String xxxContentType;//封裝上傳文件的文件類型
private String xxxFileName;//封裝上傳文件的文件名


上傳文件的過濾

上傳文件的時候可以限制上傳文件的類型和大小,使用攔截器來實現。文件上傳的攔截器是系統攔截器,我們只要配置參數就可以了。

<struts> 
    <!-- 上傳文件的臨時保存目錄-->
    <constant name="struts.multipart.saveDir" value="/tmp" />
       <package name="action" extends="struts-default">
            <action name="fileupload" class="action.FileUploadAction">
                <result>/Success.jsp</result> 
                <result name="input">/index.jsp</result> 
                <interceptor-ref name="fileUpload"> 
                    <!-- 允許上傳的文件類型 -->
                    <param name="allowedTypes">image/bmp,image/png,image/gif,image/jpeg
                    </param>
                    <!--上傳文件的最大容量單位字節-->
                    <param name="maximumSize">20000</param>
                </interceptor-ref>
                <interceptor-ref name="defaultStack" />
            </action>
        </package>
</struts>

在struts.xml中配置<constant name="struts.multipart.saveDir" value="/tmp" />用於指定上傳文件保存的臨時目錄,上傳完成後系統會自動刪除臨時目錄中的內容。


文件下載

public class FileDownloadAction extends ActionSupport {
    private String inputpath; //下載文件路徑
    private String contenttype; //文件類型
    private String filename;//文件名
    //返回一個InputStream類型
    public java.io.InputStream getInputStream() { 
        return ServletActionContext.getServletContext().getResourceAsStream(inputpath);     }
    @Override
    public String execute() throws Exception { 
        //調用相關業務邏輯方法動態設置下載信息
        inputpath = "/updfile/Bliss.jpg"; 
        contenttype = "image/jpeg"; 
        //解決下載的中文文件名問題
        filename = java.net.URLEncoder.encode("文件.jpg","utf-8");
        return SUCCESS;
    }

struts.xml中配置下載Action的result類型爲stream,內容如下:

<action name="filedownload" class="action.FileDownloadAction"> 
    <result name="success" type="stream"> 
        <!-- 定義相關參數 -->
        <param name="contentType">${contenttype}</param>
        <param name="inputName">inputStream</param>
        <param name="bufferSize">4096</param>
        <param name="contentDisposition">attachment;filename=${filename}</param>
    </result>
</action>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章