1. 程式人生 > >Struts2學習之1(Struts2的工作流程,動作類的編寫,struts.xml配置檔案的編寫)

Struts2學習之1(Struts2的工作流程,動作類的編寫,struts.xml配置檔案的編寫)

Struts2的開始

Struts2的作用

現在專案一般都是按照三層架構來開發的,表現層,業務邏輯層,資料訪問層,Struts2就是用來代替servlet處理表現層的一種框架,用來處理頁面的請求跳轉與資料顯示等,Struts2裡面還是用servlet來實現的,只不過被高度封裝了。

搭建Struts2開發環境

下載jar包

拷貝jar包到專案中去

開啟Struts2發行包\apps\struts2-blank\WEB-INF\lib,把其中jar都拷貝過來即可。

編寫配置檔案

在構建路徑的頂端,建立一個配置檔案struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> </struts>

宣告部分可以拷貝struts-core-xxx.jar中的struts-default.xml裡的頭部宣告。

配置控制對映

在專案的web.xml中配置如下資訊

 <!-- 配置Struts2框架的核心控制器 -->
  <filter
>
<filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern
>
</filter-mapping>

開始一個小例子

頁面編寫

<body>
    <a href="${pageContext.request.contextPath}/uuu/helloWorld.action">點選</a>
  </body>

配置檔案編寫

<struts>
    <!-- name為包名,唯一的; namespace為名稱空間,先找到namespace,找到了就在當前namespace下找action,找不到action則在預設的namespace下找action,extends是繼承某個包,預設寫struts-default,該包可以在struts-default.xml中找到 -->
    <package name="p1" extends="struts-default" namespace="/uuu">
        <!-- name為請求連結名(動作名稱),class為請求的類全名,預設為com.opensymphony.xwork2.ActionSupport
        method為請求類裡的處理方法,預設為execute() -->
        <action name="helloWorld" class="com.jyh.action.HelloWorldAction" method="sayHello">
            <!-- result為返回的頁面 -->
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
    </package>
</struts>

動作類編寫

package com.jyh.action;

public class HelloWorldAction {

    public String sayHello(){
        return "success";
    }
}

結果檢視編寫

建立success.jsp和error.jsp

案例執行過程簡析

頁面點擊發送請求,由web.xml配置檔案中配置的struts攔截器攔截,讀取struts中的配置,先找到namespace,然後在對應的namespace下找到action,然後到action中class指向的類中找到method指向的方法,返回的字串與result中的name屬性匹配,然後跳轉到結果頁面。頁面中的連結就是:當前專案路徑/namespace/action.name。
struts的執行過程圖

動作類

動作類的三種編寫方式

方式一

如上圖所示,直接編寫一個普通的類

方式二

實現com.opensymphony.xwork2.Action介面

package com.jyh.action;

import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class Demo1 extends ActionSupport {

    public String execute() throws Exception {
        return SUCCESS;
    }


}

Action介面中的常量:
String SUCCESS:success。一切正常。
String NONE:none。動作方法執行後,不轉向任何的結果檢視。或者在動作方法中返回null。
String ERROR:error。動作方法執行時遇到異常,轉向錯誤提示頁面。
String INPUT:input。驗證、轉換失敗,轉向輸入頁面。
String LOGIN:login。檢測使用者是否登入,沒有登入轉向此檢視。

方式三

繼承com.opensymphony.xwork2.ActionSupport(推薦)
意義:提供了一些基本的功能。比如驗證和國際化訊息提示等。

動作類中動作方法的編寫

public String xxx(){};

動作類的萬用字元對映

<!-- name中的*號代表定義一個萬用字元,頁面的連結與name屬性匹配代表給萬用字元*賦值,如頁面中連結為addCustomerUI
        則表示第一個*為add,第二個*為UI,後面的{1}代表引用第一個統配符號,以*在name屬性出現的順序為序號來引用,
        所以可以看成method="add",result轉向頁面為/customer/UICustomer.jsp -->
        <action name="*Customer*" class="com.jyh.action.CustomerAction" method="{1}">
            <result name="success">/customer/{2}Customer.jsp</result>
        </action>

動態方法呼叫:DMI(Dynamic Method Invocation)

在訪問時指定執行的動作方法:
http://localhost:8080/XXX/demo4!m1 執行demo4動作對應動作類的m1動作方法
預設情況下:會報錯,說找不到demo4!m1這個動作方法。因為struts2框架預設是禁止動態方法呼叫的。
<constant name="struts.enable.DynamicMethodInvocation" value="true">
注意:不建議使用。容易暴露動作類中的動作方法,害怕非法執行。

動作類獲取ServletAPI

方式一(推薦)

package com.jyh.action;

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

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class ServletAction extends ActionSupport {

    @Override
    public String execute() throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        ServletContext context = ServletActionContext.getServletContext();
        System.out.println(request);
        System.out.println(response);
        System.out.println(context);
        return null;
    }
}

方式二

package com.jyh.action;

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

import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;

public class ServletAction2 implements ServletRequestAware,ServletResponseAware,ServletContextAware {

    /**
     * 攔截器注入的這些東西(servletConfig攔截器)
     */
    private HttpServletRequest request;
    private HttpServletResponse response;
    private ServletContext context;

    public String execute() throws Exception {

        System.out.println(request);
        System.out.println(response);
        System.out.println(context);
        return null;
    }

    public void setServletResponse(HttpServletResponse response) {
        this.response = response;
    }

    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
    }

    public void setServletContext(ServletContext context) {
        this.context = context;
    }

}

Struts2配置檔案struts.xml

Struts2的其它一些配置檔案和寫法

自帶的一些配置檔案

  1. default.properties:struts2-core**.jar org.apache.struts包中(只讀)
  2. struts-default.xml:struts2-core**.jar中(只讀)
  3. struts-plugin.xml:在外掛的jar包中(只讀)
  4. struts.xml:在應用的構建路徑頂端。自己定義的Struts配置檔案(推薦)
  5. struts.properties:在應用的構建路徑頂端。自己編寫(不推薦)
  6. web.xml:配置過濾器時,指定引數。自己編寫(不推薦)
    特別注意:順序是固定的。後面的配置會覆蓋前面的同名配置資訊。

一些常用的預設引數的修改與設定

包含其他配置檔案
<include file="user.xml"></include>

<!-- 修改連結預設字尾,多個字尾可以用逗號隔開 -->
    <constant name="struts.action.extension" value="do"></constant>
    <!-- 設定瀏覽器是否快取靜態內容,預設值為true -->
    <constant name="struts.serve.static.browserCache" value="false"></constant>
    <!-- 當struts的配置檔案修改後系統是否自動重新載入該檔案,預設值為false,推薦開啟 -->
    <constant name="struts.configuration.xml.reload" value="true"></constant>
    <!-- 開發模式,會非常詳細的打印出一些錯誤資訊,開啟它則預設開啟了i18n.reload、configuration.xml.reload。  -->
    <constant name="struts.devMode" value="true"></constant>
    <!-- 檢視主題(simple,xhtml,css_xhtml),預設為xhtml,也就是struts2自帶的檢視主題,simple為不普通的標籤不帶任何主題 -->
    <constant name="struts.ui.theme" value="simple"></constant>
    <!-- 與spring整合時,指定由spring負責action物件的建立 -->
    <constant name="struts.objectFactory" value="spring"></constant>
    <!-- 該屬性設定struts是否支援動態方法呼叫,預設為false-->
    <constant name="struts.enable.DynamicMethodInvocation" value="false"></constant>
    <!-- 上傳檔案大小限制 -->
    <constant name="struts.multipart.maxSize" value="100000000"></constant>

package元素

意義:分模組開發。
屬性:
- name:必須的。配置檔案中要唯一。就是一個名字。
- extends:指定父包。會把父包中的配置內容繼承下來。一般需要直接或間接的繼承一個叫做“struts-default”的包(在struts-default.xml配置檔案中)。如果不繼承該包,那麼Struts2中的核心功能將無法使用。
- abstract:是否是抽象包。沒有任何action子元素的package可以宣告為抽象包。
- namespace:指定名稱空間。一般以”/”開頭。該包中的動作訪問路徑:namesapce+動作名稱。如果namespace=””,這是預設名稱空間,和不寫該屬性是一樣的。

action元素

作用:定義一個動作。
屬性:
- name:必須的。動作名稱。使用者用於發起請求。在包中要唯一。
- class:指定動作類的全名。框架會通過反射機制例項化。預設是:com.opensymphony.xwork2.ActionSupport。
- method:指定動作類中的動作方法。框架會執行該方法。預設是execute()。
預設類在struts-default.xml中聲明瞭,也可以用
<default-class-ref class="完整類名"></default-class-ref>覆蓋

結果檢視result元素

  • name:邏輯檢視名稱。它對應的是動作方法的返回值。預設值:success。
  • type:結果型別,到達目標的形式。預設值:dispatcher-轉發。

  • 全域性檢視:<global-results></global-results>,直接寫在包下

  • 區域性檢視:<results></global>,寫在action下
    在什麼下範圍就多大,先找action下的區域性檢視(範圍精確),再找報下的全域性檢視

預設擁有的結果型別(result的type元素)

struts-default.xml中定義的結果檢視

<result-types>
            <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
            <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
            <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
            <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
            <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
            <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
            <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
            <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
            <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
            <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
        </result-types>
  1. freemarker:用於轉發到另外一個freemarker模板。(頁面靜態化)
  2. velocity:用於轉發到另外一個velocity模板。
  3. httpheader:用於輸出http協議的訊息頭。
  4. xslt:XML有關的樣式
  5. redirect:用於重定向到另外一個JSP頁面。
  6. redirectAction:用於重定向到另外一個動作。
  7. stream:用於檔案下載(日後再講。檔案上傳和下載)
  8. plainText:以純文字的形式展現頁面。輸出原始碼。
  9. chain:使用者轉發到另外一個動作。
  10. dispatcher:用於轉發到另外一個JSP頁面。
<!-- 同一個包下一個動作轉發到另一個動作 -->
    <package name="d1" extends="struts-default" namespace="/n1">
        <action name="demo1" class="com.jyh.action.Demo1" method="execute">
            <result name="success" type="chain">demo2</result>
        </action>
        <action name="demo2" class="com.jyh.action.Demo1" method="execute">
            <!-- <result name="success" type="dispatcher">/demo1.jsp</result> -->
            <!-- 同上,dispatcher表示轉發到頁面 -->
            <result name="success" type="dispatcher">
                <param name="location">/demo1.jsp</param>
            </result>
        </action>
    </package>
    <!-- 轉發到另一個包中的動作 -->
    <package name="d2" extends="struts-default" namespace="/n2">
        <action name="demo3" class="com.jyh.action.Demo1" method="execute">
            <result name="success" type="chain"><!-- 配置type="chain"意思是從這個動作跳到另一個動作 -->
                <param name="namespace">/n1</param><!-- 配置轉發目標動作所在的名稱空間 -->
                <param name="actionName">demo2</param><!-- 配置轉發目標動作的名稱 -->
            </result>
        </action>
    </package>

自定義結果型別(result的type元素)

1.編寫一個類,直接或間接實現com.opensymphony.xwork2.Result介面。一般繼承org.apache.struts2.dispatcher.StrutsResultSupport類

package com.jyh.action;

/**
 * 自定義結果型別,生成驗證碼
 */
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.StrutsResultSupport;

import cn.dsna.util.images.ValidateCode;

import com.opensymphony.xwork2.ActionInvocation;

@SuppressWarnings("serial")
public class CaptchaResult extends StrutsResultSupport {

    private int width = 200;//長度
    private int height = 80;//寬度
    private int codeCount = 4;//驗證碼個數
    private int lineCount = 100;//干擾線條數

    public void setWidth(int width) {
        this.width = width;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setCodeCount(int codeCount) {
        this.codeCount = codeCount;
    }

    public void setLineCount(int lineCount) {
        this.lineCount = lineCount;
    }

    protected void doExecute(String finalLocation, ActionInvocation invocation)
            throws Exception {
        ValidateCode vCode = new ValidateCode(width, height, codeCount, lineCount);
        BufferedImage image = vCode.getBuffImg();
        HttpServletResponse response = ServletActionContext.getResponse();
        ImageIO.write(image, "jpeg", response.getOutputStream());
    }

}

2.宣告定義結果型別

<!-- 自定義結果型別 -->
<package name="d3" extends="struts-default">
    <!-- 宣告定義結果型別 -->
    <result-types>
        <!-- name為結果型別名稱,class為具體實現的類 -->
        <result-type name="captcha" class="com.jyh.action.CaptchaResult"/>
    </result-types>
</package>

3.使用自定義的結果型別

<action name="captcha">
    <!-- 使用定義的結果型別 -->
    <result name="success" type="captcha">
        <!-- 設定結果型別對應的實現類中的屬性 -->
        <param name="width">200</param>
        <param name="height">80</param>
        <param name="codeCount">4</param>
        <param name="lineCount">100</param>
    </result>
</action>