Struts2的傳值方式及原理

1.普通的傳值方式html

UserActionForCommonParam類
java

Action類接收三個參數,分別是id,username,content.apache

  1. package com.struts.action;  
  2.   
  3. public class UserActionForCommonParam {  
  4.     private int id;  
  5.     private String username;  
  6.     private String content;  
  7.   
  8.     public int getId() {  
  9.         return id;  
  10.     }  
  11.   
  12.     public void setId(int id) {  
  13.         this.id = id;  
  14.     }  
  15.   
  16.     public String getUsername() {  
  17.         return username;  
  18.     }  
  19.   
  20.     public void setUsername(String username) {  
  21.         this.username = username;  
  22.     }  
  23.   
  24.     public String getContent() {  
  25.         return content;  
  26.     }  
  27.   
  28.     public void setContent(String content) {  
  29.         this.content = content;  
  30.     }  
  31.       
  32.     // 從前臺頁面接收到參數後會在這個方法裏打印  
  33.     public String addUser() {  
  34.         System.out.println("ID: " + this.getId());  
  35.         System.out.println("Username: " + this.getUsername());  
  36.         System.out.println("Content: " + this.getContent());  
  37.         return "success";  
  38.     }  
  39. }  


對應的struts.xmlsession

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <!DOCTYPE struts PUBLIC  
  4.         "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"  
  5.         "http://struts.apache.org/dtds/struts-2.3.dtd">  
  6.   
  7. <struts>  
  8.     <constant name="struts.enable.DynamicMethodInvocation" value="true"/>  
  9.     <constant name="struts.devMode" value="true"/>  
  10.     <package name="default" namespace="/" extends="struts-default">  
  11.         <action name="UserActionForCommonParam" class="com.struts.action.UserActionForCommonParam" method="addUser">  
  12.             <result name="success">/UserPage.jsp</result>  
  13.         </action>  
  14.     </package>  
  15. </struts>  


前臺頁面UserPage.jsp數據結構

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>  
  2. <%@ taglib prefix="s" uri="/struts-tags" %>  
  3. <html>  
  4. <head>  
  5.     <title>UserPage</title>  
  6. </head>  
  7. <body>  
  8.     <%--下面的Table用於提交參數(id,username,content)--%>  
  9.     <form action="UserActionForCommonParam" method="POST">  
  10.         <table border="1">  
  11.             <tr>  
  12.                 <td>ID:</td>  
  13.                 <td><input type="text" name="id"/></td>  
  14.             </tr>  
  15.             <tr>  
  16.                 <td>Username:</td>  
  17.                 <td><input type="text" name="username"/></td>  
  18.             </tr>  
  19.             <tr>  
  20.                 <td>Content:</td>  
  21.                 <td><input type="text" name="content"/></td>  
  22.             </tr>  
  23.             <tr>  
  24.                 <td colspan="2" align="center">  
  25.                     <input type="submit" value="提交"/>  
  26.                 </td>  
  27.             </tr>  
  28.         </table>  
  29.     </form>  
  30.     <br/>  
  31.     <%--下面的Table用於顯示傳遞回來id,username,content--%>  
  32.     <table border="1">  
  33.         <tr>  
  34.             <td>ID: </td>  
  35.             <td><input type="text" value="${id}"/></td>  
  36.         </tr>  
  37.         <tr>  
  38.             <td>Username: </td>  
  39.             <td><input type="text" value="${username}"/></td>  
  40.         </tr>  
  41.         <tr>  
  42.             <td>Content: </td>  
  43.             <td><input type="text" value="${content}"/></td>  
  44.         </tr>  
  45.     </table>  
  46.     <%--用於查看ValueStack中的傳遞的值--%>  
  47.     <s:debug/>  
  48. </body>  
  49. </html>  

在實踐後會發現,若是遇到參數很是多的狀況,那麼就須要在Action類中寫很是多的屬性以及對應的get/set方法.因此這種方式不太可取.解決問題的方法必然是封裝一個JavaBean.這就用到了Strut2的第二種傳值方式--DomainModelapp

2.DomainModel傳值框架

首先要建立一個存儲的JavaBeanjsp

User類ide

把id,username,content封裝的到一個User類當中.
函數

  1. package com.struts.model;  
  2.   
  3. public class User {  
  4.     private int id;  
  5.     private String username;  
  6.     private String content;  
  7.   
  8.     public int getId() {  
  9.         return id;  
  10.     }  
  11.   
  12.     public void setId(int id) {  
  13.         this.id = id;  
  14.     }  
  15.   
  16.     public String getUsername() {  
  17.         return username;  
  18.     }  
  19.   
  20.     public void setUsername(String username) {  
  21.         this.username = username;  
  22.     }  
  23.   
  24.     public String getContent() {  
  25.         return content;  
  26.     }  
  27.   
  28.     public void setContent(String content) {  
  29.         this.content = content;  
  30.     }  
  31. }  

UserActionForDomainModel類

  1. package com.struts.action;  
  2.   
  3. import com.opensymphony.xwork2.ActionSupport;  
  4. import com.struts.model.User;  
  5.   
  6. public class UserActionForDomainModel extends ActionSupport{  
  7.     private User user;  
  8.   
  9.     public User getUser() {  
  10.         return user;  
  11.     }  
  12.   
  13.     public void setUser(User user) {  
  14.         this.user = user;  
  15.     }  
  16.   
  17.     public String addUser() {  
  18.         System.out.println("ID: " + user.getId());  
  19.         System.out.println("Username: " + user.getUsername());  
  20.         System.out.println("Content: " + user.getContent());  
  21.         return "success";  
  22.     }  
  23. }  


對應的struts.xml

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <!DOCTYPE struts PUBLIC  
  4.         "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"  
  5.         "http://struts.apache.org/dtds/struts-2.3.dtd">  
  6.   
  7. <struts>  
  8.     <constant name="struts.enable.DynamicMethodInvocation" value="true"/>  
  9.     <constant name="struts.devMode" value="true"/>  
  10.     <package name="default" namespace="/" extends="struts-default">  
  11.         <action name="userForDomainModel" class="com.struts.action.UserActionForDomainModel" method="addUser">  
  12.             <result name="success">/UserPage.jsp</result>  
  13.         </action>  
  14.     </package>  
  15. </struts>  


前臺頁面UserPage.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>  
  2. <%@ taglib prefix="s" uri="/struts-tags" %>  
  3. <html>  
  4. <head>  
  5.     <title>UserPage</title>  
  6. </head>  
  7. <body>  
  8.     <%--要特別注意的是DomainModel的傳值方式必需要使用對象.參數方式進行賦值以及取值--%>  
  9.     <form action="userForDomainModel" method="POST">  
  10.         <table border="1">  
  11.             <tr>  
  12.                 <td>ID:</td>  
  13.                 <td><input type="text" name="user.id"/></td>  
  14.             </tr>  
  15.             <tr>  
  16.                 <td>Username:</td>  
  17.                 <td><input type="text" name="user.username"/></td>  
  18.             </tr>  
  19.             <tr>  
  20.                 <td>Content:</td>  
  21.                 <td><input type="text" name="user.content"/></td>  
  22.             </tr>  
  23.             <tr>  
  24.                 <td colspan="2" align="center">  
  25.                     <input type="submit" value="提交"/>  
  26.                 </td>  
  27.             </tr>  
  28.         </table>  
  29.     </form>  
  30.     <br/>  
  31.     <%--下面的Table用於顯示傳遞回來id,username,content--%>  
  32.     <table border="1">  
  33.         <tr>  
  34.             <td>ID: </td>  
  35.             <td><input type="text" value="${user.id}"/></td>  
  36.         </tr>  
  37.         <tr>  
  38.             <td>Username: </td>  
  39.             <td><input type="text" value="${user.username}"/></td>  
  40.         </tr>  
  41.         <tr>  
  42.             <td>Content: </td>  
  43.             <td><input type="text" value="${user.content}"/></td>  
  44.         </tr>  
  45.     </table>  
  46.     <%--用於查看ValueStack中的傳遞的值--%>  
  47.     <s:debug/>  
  48. </body>  
  49. </html>  

實際上User類不須要顯式的實例化,struts會自動幫你實例化,但前提條件是,傳值時須要使用對象.參數名的方式進行傳遞.

除了這種傳值方式外,struts2還提供另一種傳值方式.

3.ModelDriven傳值

依然要建立User的JavaBean

User類

  1. package com.struts.model;  
  2.   
  3. public class User {  
  4.     private int id;  
  5.     private String username;  
  6.     private String content;  
  7.   
  8.     public int getId() {  
  9.         return id;  
  10.     }  
  11.   
  12.     public void setId(int id) {  
  13.         this.id = id;  
  14.     }  
  15.   
  16.     public String getUsername() {  
  17.         return username;  
  18.     }  
  19.   
  20.     public void setUsername(String username) {  
  21.         this.username = username;  
  22.     }  
  23.   
  24.     public String getContent() {  
  25.         return content;  
  26.     }  
  27.   
  28.     public void setContent(String content) {  
  29.         this.content = content;  
  30.     }  
  31. }  


UserActionForModelDriven類

  1. package com.struts.action;  
  2.   
  3. import com.opensymphony.xwork2.ModelDriven;  
  4. import com.struts.model.User;  
  5.   
  6. public class UserActionForModelDriven implements ModelDriven<User>{  
  7.     private User user;  
  8.   
  9.     public String addUser() {  
  10.         System.out.println("ID: " + user.getId());  
  11.         System.out.println("Username: " + user.getUsername());  
  12.         System.out.println("Content: " + user.getContent());  
  13.         return "success";  
  14.     }  
  15.   
  16.     @Override  
  17.     public User getModel() {  
  18.         if (user == null) {  
  19.             user = new User();  
  20.         }  
  21.         return user;  
  22.     }  
  23. }  

這種方式能夠不用在Action類中編寫對應的get/set方法,可是須要實例化User類.

前臺UserPage.jsp

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>  
  2. <%@ taglib prefix="s" uri="/struts-tags" %>  
  3. <html>  
  4. <head>  
  5.     <title>UserPage</title>  
  6. </head>  
  7. <body>  
  8.     <form action="userForModelDriven" method="POST">  
  9.         <table border="1">  
  10.             <tr>  
  11.                 <td>ID:</td>  
  12.                 <td><input type="text" name="id"/></td>  
  13.             </tr>  
  14.             <tr>  
  15.                 <td>Username:</td>  
  16.                 <td><input type="text" name="username"/></td>  
  17.             </tr>  
  18.             <tr>  
  19.                 <td>Content:</td>  
  20.                 <td><input type="text" name="content"/></td>  
  21.             </tr>  
  22.             <tr>  
  23.                 <td colspan="2" align="center">  
  24.                     <input type="submit" value="提交"/>  
  25.                 </td>  
  26.             </tr>  
  27.         </table>  
  28.     </form>  
  29.     <br/>  
  30.     <%--下面的Table用於顯示傳遞回來id,username,content--%>  
  31.     <table border="1">  
  32.         <tr><span id="transmark"></span>  
  33.             <td>ID: </td>  
  34.             <td><input type="text" value="${id}"/></td>  
  35.         </tr>  
  36.         <tr>  
  37.             <td>Username: </td>  
  38.             <td><input type="text" value="${username}"/></td>  
  39.         </tr>  
  40.         <tr>  
  41.             <td>Content: </td>  
  42.             <td><input type="text" value="${content}"/></td>  
  43.         </tr>  
  44.     </table>  
  45.     <%--用於查看ValueStack中的傳遞的值--%>  
  46.     <s:debug/>  
  47. </body>  
  48. </html>  

頁面仍是和普通傳值同樣.

能夠去ValueStack當中觀察參數的存儲,更透徹的理解Struts2的參數傳遞. : <s:debug/>

1.什麼是ValueStack

對於每個action的調用,Struts在執行相應的動做方法以前會先建立一個名爲ValueStack的對象。Value Stack用來保存該動做對象或者對象。因爲最終在執行Action類相應的action方法以前,攔截器須要先訪問ValueStack。視圖也須要訪問ValueStack。Struts框架將其保存在一個名爲struts.valueStack的請求屬性中。

2.獲取valueStack的三種方法:

ValueStack v1 = ActionContext.getContext().getValueStack(); ValueStack v2 = ServletActionContext.getValueStack(ServletActionContext.getRequest()); ValueStack v3 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack"); 

打印其HashCode碼如出一轍。
說明:
一、 值是同樣的,說明只有一個對象
二、 由於有一種是從request域中獲取的,因此是一次請求

3.ValueStack的內容

valueStack分爲對象棧(Object Stack)和Map棧(Context Map).

Struts將把動做和相關對象壓入Object Stack,而把各類各樣的映射關係壓入Context Map。

一般說的ValueStack就是指Object Stack,它是一個真正數據結構意義的棧。Object Stack也經常被稱爲root(實際上是一個ArrayList)。Context Map咱們通常稱其爲context(是一個HashMap)它是整個OGNL其中包括了root

4.OGNL中的兩種對象

OGNL中包含兩種對象,即_root和_value.
_value即:request, session, application, parameters, attr等命名對象,但這些命名對象都不是根。
_root即:當前請求的Action實例等
「根」對象和普通命令對象的區別在於:
「根」對象(root) 對象棧: 其實是 CompoundRoot 類型, 是一個使用 ArrayList 定義的棧. 裏邊保存各類和當前 Action 實例相關的對象(若是這個Action實例包括域對象的話域對象會進root).是一個數據結構意義的棧.

1)訪問Context Map裏的對象須要在對象名以前添加 #
2)訪問Object Stack對象的屬性時,能夠省略#而直接經過屬性名來搜索

這裏寫圖片描述

說明:
從上圖中也能夠看出valueStack總共分爲兩個部分:

對象棧:root (CompoundRoot類)
      Map棧:_values和_root (OgnlContext 類)

5.Struts會把當前訪問的Action實例壓入值棧棧定

壓入時間點爲:
因爲Struts2最後終將調用Action類中的action方法。但在調用此方法以前:

*先建立一個StrutsActionProxy (ActionProxy默認實現的子類)
*在建立StrutsActionProxy以後,對其進行初始化,把Action對象壓入值棧

在調用該方法前該Action被壓入棧頂,若是在初始化的過程當中,在Action的構造函數中又初始化了其餘類,這這個類也會被壓入值棧。因此最後棧頂的元素會是這個新初始化的類。

6.ValueStack中對象的存取

Object Stack 的存放: push 或者 add:

將一個對象放入Object Stack的棧頂:

  • 1 ActionContext.getContext().getValueStack().push(object);
  • 2 ActionContext.getContext().getValueStack().getRoot().add(0,object);

Object Stack的提取: peek() 或 pop()

peek()取得的是棧頂元素:

  • 1 Object object = ActionContext.getContext().getValueStack().peek();

Object Stack的元素的彈出:pop:

  • 1 Object object = ActionContext.getContext().getValueStack().pop();

7.動態修改ValueStack中對象的屬性

這裏寫圖片描述

說明:
能夠利用valueStack.setParameter方法改變對象棧中對象的屬性的值。至於匹配哪一個。則依次從對象棧的棧頂向下搜索,找到匹配的就修改

相關文章
相關標籤/搜索