1. 程式人生 > >分享知識-快樂自己:Struts2(動態方法、動態結果、萬用字元、方法內部跳轉、action跳轉、OGNL 的使用及注意事項)

分享知識-快樂自己:Struts2(動態方法、動態結果、萬用字元、方法內部跳轉、action跳轉、OGNL 的使用及注意事項)

這裡主要以案例演示:涵蓋以下知識點

1、動態方法呼叫:使用關鍵 符號 ! 進行操作   例如:/名稱空間 ! 方法名

2、動態結果集:就是說,通過後臺返回的結果 ${} 獲取,重定向到符合預期的頁面。

3、萬能萬用字元:*_*  :第一個 * 為 類名、第二個 * 為方法名;{1}是第一個 *

4、內部方法的呼叫:就是說 Action 類中的 A()  呼叫 B()  A方法返回B()的結果集

5、跳轉Action:就是說訪問一個方法,根據返回的結果匹配 result中的 name 值 跳入下一個action (result type=chain)

 6、OGNL:(不過多講述相關概念,這裡以程式碼為核心)

值棧的內部結構分為兩部分:

  第一部分:root,結構是 list 集合一般操作的都是 root 裡面的資料

  第二部分:context,結構為 Map 集合

使用經歷:

root 單列集合下的 前臺獲取的時候不需要寫 #

context 雙列集合  前臺獲取的時候需要寫 #

1、往 單列集合中推送 集合型別的資料時,不能觸碰到集合的引用名稱。

將泛型集合推送到值棧中:

 

使用 <s:debug/> 標籤檢視 值棧的資訊:

2、值棧的訪問順序為 從上往下 定址。如有同名的屬性名,則定址離值棧頂端最近的

核心程式碼擷取:推送到root 也就是單列集合下

使用 <s:debug/> 標籤檢視 值棧的資訊:

3、在我們實現 Action 介面 或 繼承ActionSupport 的類中的成員屬性都是放在 root 單列集合下的

4、往值棧 context 推送 key那一列會有我們指定的引用名稱(需要獲取的時候需要 #)

 

 以上為可能會遇到的問題。

完整Demo展示:

 點我下載案例Demo:

 案例結構:

為演示萬用字元需要方法名與jsp名稱一致,add.jsp 與 list.jsp 建立在 CoordinAction檔案下 

POM:

 <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>

        <!--測試JAR-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>
        <!--javaee.jar包是支援javaweb程式設計的基礎jar包,跟javase程式設計需要jre一樣!-->
        <dependency>
            <groupId>javaee</groupId>
            <artifactId>javaee-api</artifactId>
            <version>5</version>
        </dependency>
        <!--Struts2-core核心-->
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>2.3.4.1</version>
        </dependency>
        <!--xwork 的核心包,最主要的功能是 支援了過濾器(interceptor)。-->
        <dependency>
            <groupId>org.apache.struts.xwork</groupId>
            <artifactId>xwork-core</artifactId>
            <version>2.3.4.1</version>
        </dependency>

    </dependencies>
View Code

CoordinAction:

package com.gdbd.action;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

import java.util.Map;

/**
 * @author asus
 */
public class CoordinAction extends ActionSupport {

    private String message;
    private String mess;
  ...省略 Get Set


    /***
     * 動態方法的呼叫
     * @return
     */
    public String list() {
        this.setMessage("通過呼叫 add 方法拿到返回的name定址,再次排程 Action 中的list");
        return "list";
    }

    public String add() {
        this.setMessage("動態方法排程!!!!");
        return "add";
    }

    public String get() {
        Map<String, Object> session = ActionContext.getContext().getSession();
        if (this.message != null) {
            session.put("message", "動態結果集呼叫成功!!!");
            this.setMess("demo2");
        } else {
            session.put("message", "動態結果集呼叫失敗!!!");
            this.setMess("error");
        }
        return "get";
    }

    /***
     * 內部方法的呼叫
     * @return
     */
    public String demo1() {
        Map request = (Map) ActionContext.getContext().get("request");
        request.put("message", "測試資料Action內部排程!!!");
        return "demo2";
    }

    public String demo2() {
        return demo1();
    }


}
View Code

OgnlAction:

package com.gdbd.action;

import com.gdbd.bean.UserInfo;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
import java.util.List;
import java.util.ArrayList;

/**
 * @author asus
 */
public class OgnlAction extends ActionSupport {

    private List<UserInfo> List;
  ...省略 Get Set


    /***
     * OGNL:儲存到單列集合
     */
    public String demo1() {
        ActionContext context = ActionContext.getContext();
        //獲取值棧
        ValueStack valueStack = context.getValueStack();
        //偽造資料
        UserInfo userInfo=new UserInfo();
        userInfo.setUserName("MLQ");
        userInfo.setUserPwd("MLQ");
        UserInfo userInfo1=new UserInfo();
        userInfo1.setUserName("FKX");
        userInfo1.setUserPwd("FKX");
        List<UserInfo> infoList=new ArrayList<UserInfo>();
        infoList.add(userInfo);
        infoList.add(userInfo1);
        /***
         * 將資料推送到單列集合中
         * 缺點:對集合型別進行操作的時候,沒有辦法觸碰到集合的引用名稱
         * 例如:新增一個 泛型List<UserInfo> 集合  沒有
         */
        valueStack.push(userInfo);
        valueStack.push(userInfo1);
        valueStack.push(infoList);
        return  "demo1";
    }
    /***
     * OGNL:儲存到雙列集合
     */
    public String demo2() {
        ActionContext context = ActionContext.getContext();
        //獲取值棧
        ValueStack valueStack = context.getValueStack();
        //偽造資料
        UserInfo userInfo=new UserInfo();
        userInfo.setUserName("MLQ");
        userInfo.setUserPwd("MLQ");
        UserInfo userInfo1=new UserInfo();
        userInfo1.setUserName("FKX");
        userInfo1.setUserPwd("FKX");
        List<UserInfo> infoList=new ArrayList<UserInfo>();
        infoList.add(userInfo);
        infoList.add(userInfo1);
        /***
         * 將資料推送到雙列集合中
         */
        //valueStack.push(infoList);將泛型集合推送到值棧中,沒有引用地址
        this.List=infoList;
        valueStack.getContext().put("infoList",infoList);

        return  "demo1";
    }


}
View Code

UserInfo:

package com.gdbd.bean;

import java.io.Serializable;

/**
 * user 實體類
 * @author asus
 */
public class UserInfo implements Serializable {

    private String userName;
    private String userPwd;

    ...省略 Get Set
}
View Code

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>

    <!-- 是否開啟動態方法呼叫 -->
    <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
    <!--更改 Struts.xml的 節點不需要重啟-->
    <constant name="struts.devMode" value="true"></constant>

    <!--動態-->
    <package name="default" namespace="/" extends="struts-default">

        <!--動態方法排程 使用( ! ) -->
        <action name="demo" class="com.gdbd.action.CoordinAction">
            <result name="add">/error.jsp</result>
        </action>
        <!--
            *_*:
            第一個 *  為 類名
            第二個 *  為  方法名
        -->
        <!--萬能萬用字元-->
        <action name="*_*" class="com.gdbd.action.{1}" method="{2}">
            <result name="{2}">{1}/{2}.jsp</result>
        </action>

    </package>

    <!--內部方法的呼叫-->
    <package name="demo" namespace="/demo1" extends="struts-default">

        <!--
            action 內部方法排程
         -->
        <action name="mo" class="com.gdbd.action.CoordinAction" method="demo1">
            <result name="demo2">/demo2.jsp</result>
        </action>
        <!--
            action 內部方法排程 重定向頁面
         -->
        <action name="mo1" class="com.gdbd.action.CoordinAction" method="demo1">
            <result name="demo2" type="redirect">/demo2.jsp</result>
        </action>

    </package>

    <!--排程 action 中的方法,在根據結果集再次跳轉到 action 方法 -->
    <package name="demo2" namespace="/demo2" extends="struts-default">

        <action name="listdemo" class="com.gdbd.action.CoordinAction" method="list">
            <result name="list">/demo2.jsp</result>
        </action>

        <action name="mo" class="com.gdbd.action.CoordinAction" method="add">
            <result name="add" type="chain">
                <!--預設是轉發-->
                <param name="actionName">listdemo</param>
                <param name="namespace">/demo2</param>
            </result>
        </action>

    </package>

    <!--動態結果:重定向頁面(轉發無效)-->
    <package name="demo3" namespace="/demo3" extends="struts-default">

        <action name="mo" class="com.gdbd.action.CoordinAction" method="get">
            <result name="get" type="redirect">${mess}</result>
        </action>
        <action name="demo2">
            <result>/demo2.jsp</result>
        </action>
        <action name="error">
            <result>/error.jsp</result>
        </action>

    </package>

    <!--OGNL 測試-->
    <package name="demo4" namespace="/demo4" extends="struts-default">

        <!--推送到單列集合中-->
        <action name="mo" class="com.gdbd.action.OgnlAction" method="demo1">
            <result name="demo1">/demo1.jsp</result>
        </action>
        <!--推送到雙列集合中-->
        <action name="mo1" class="com.gdbd.action.OgnlAction" method="demo2">
            <result name="demo1">/demo1.jsp</result>
        </action>
    </package>

</struts>
View Code

add.jsp:

<%--
  Created by IntelliJ IDEA.
  User: asus
  Date: 2018/11/17
  Time: 9:33
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>add==========</h1>
</body>
</html>
View Code

list.jsp:

<%--
  Created by IntelliJ IDEA.
  User: asus
  Date: 2018/11/17
  Time: 9:33
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>list==========</h1>
</body>
</html>
View Code

demo1.jsp:

<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
  Created by IntelliJ IDEA.
  User: asus
  Date: 2018/11/17
  Time: 9:33
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<fieldset>
    <legend>OGNL:獲取的結果(值棧單列集合)</legend>
    姓名為:<s:property value="userName"></s:property>
    <br/>
    密碼為:<s:property value="userPwd"></s:property>
</fieldset>
<br/><br/>
<fieldset>
    <legend>OGNL:獲取的結果(值棧Root 單列集合)</legend>
    姓名為:<s:property value="List[0].userName"></s:property>
    <br/>
    密碼為:<s:property value="List[1].userPwd"></s:property>
</fieldset>
<br/><br/>
<fieldset>
    <legend>OGNL:獲取的結果(值棧雙列集合)</legend>
    姓名為:<s:property value="#infoList[0].userName"></s:property>
    <br/>
    密碼為:<s:property value="#infoList[1].userPwd"></s:property>
</fieldset>
<br/><br/>
<fieldset>
    <legend>OGNL:獲取的結果(值棧雙列集合,便利讀取)</legend>
    <s:iterator value="infoList" id="info">
        <s:property value="#info.userName"/>
    </s:iterator>
</fieldset>
<br/><br/>
<s:debug/>
</body>
</html>
View Code

demo2.jsp:

<%--
  Created by IntelliJ IDEA.
  User: asus
  Date: 2018/11/17
  Time: 9:33
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>
View Code

error.jsp:

<%--
  Created by IntelliJ IDEA.
  User: asus
  Date: 2018/11/17
  Time: 9:33
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>
View Code

index.jsp:

<%--
  Created by IntelliJ IDEA.
  User: asus
  Date: 2018/11/17
  Time: 10:34
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<fieldset>
    <legend>動態方法排程</legend>
    <a href="/demo!add">動態方法排程</a>
</fieldset>
<br/><br/>
<fieldset>
    <legend>萬能萬用字元</legend>
    <a href="/CoordinAction_list">萬能萬用字元</a>
    &nbsp;&nbsp;&nbsp;
    <a href="/CoordinAction_add">萬能萬用字元</a>
</fieldset>
<br/><br/>
<fieldset>
    <legend>內部方法排程返回的資訊</legend>
    <a href="/demo1/mo">內部方法排程返回的資訊:預設是轉發</a>
    &nbsp;&nbsp;&nbsp;
    <a href="/demo1/mo1">內部方法排程返回的資訊:使用重定向</a>
</fieldset>
<br/><br/>
<fieldset>
    <legend>排程 action 中的方法,在根據結果集再次跳轉到 action 方法</legend>
    <a href="/demo2/mo">跳轉 add 方法 根據結果再次 指向list:轉發操作</a>
    &nbsp;&nbsp;&nbsp;
    <a href="#">###</a>
</fieldset>
<br/><br/>
<fieldset>
    <legend>動態結果排程</legend>
    <a href="/demo3/mo?message=123">動態結果排程:重定向</a>
    &nbsp;&nbsp;&nbsp;
    <a href="#">###</a>
</fieldset>
<br/><br/>
<fieldset>
    <legend>OGNL</legend>
    <a href="/demo4/mo">OGNL:儲存到值棧的單列集合</a>
    &nbsp;&nbsp;&nbsp;
    <a href="/demo4/mo1">OGNL:儲存到值棧的單列集合</a>
    &nbsp;&nbsp;&nbsp;
</fieldset>
<br/><br/>
</body>
</html>
View Code

web.xml:

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>

    <!--核心過濾器-->
    <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>

</web-app>
View Code