溫故知新:struts2_03參數的傳遞

          struts2的參數傳遞和OGNL息息相關,先從幾個OGNL的案例來感受一下

          OGNL的概念和作用,不贅述,直接百科傳送門:http://baike.baidu.com/view/1347280.htm。使用OGNL可以極為靈活的在頁面上對目標對象進行存取操作,而不僅僅是只是數據的展示。下面使用OGNL給出幾個常用的例子。
          測試用實體類User和Department
           1 package demo.ognlDemo;
           2 
           3 public class User {
           4 
           5     private String name;
           6     private int age;
           7     private Department department;
           8 
           9     public void hello(String name) {
          10         System.out.println("hello " + name);
          11     }
          12 
          13     public static void sayHi() {
          14         System.out.println("HI");
          15     }
          16 
          17     public User() {
          18         super();
          19     }
          20 
          21     public User(String name, int age, Department department) {
          22         super();
          23         this.name = name;
          24         this.age = age;
          25         this.department = department;
          26     }
          27    //get/set方法略
          28}

           1 package demo.ognlDemo;
           2 
           3 public class Department {
           4 
           5     private String name;
           6     private int no;
           7    
           8     //get/set方法略
           9
          } 

          下面給出測試類
           1 package demo.ognlDemo;
           2 
           3 import java.util.ArrayList;
           4 import java.util.HashMap;
           5 import java.util.List;
           6 import java.util.Map;
           7 
           8 import ognl.Ognl;
           9 import ognl.OgnlException;
          10 
          11 import org.junit.Test;
          12 
          13 
          14 public class OgnlDemo {
          15 
          16     @Test
          17     public void test01() {
          18         
          19         //定義兩個演示用的對象
          20         User u = new User();
          21         u.setAge(20);
          22         u.setName("Tom");
          23         
          24         Department dep = new Department();
          25         dep.setName("Security");
          26         dep.setNo(10);
          27         
          28         u.setDepartment(dep);
          29         
          30         //一個根map
          31         Map<String , Object> ctx = new HashMap<String, Object>();
          32         ctx.put("user", u);
          33         ctx.put("department", dep);
          34         
          35         try {
          36             //下列表達式都是在以指定對象為根進行屬性查找
          37             //以u為根
          38             System.out.println(Ognl.getValue("name", u));
          39             System.out.println(Ognl.getValue("age", u));
          40             System.out.println(Ognl.getValue("department.name", u));
          41             System.out.println("====================================");
          42             //以dep為根
          43             System.out.println(Ognl.getValue("name", dep));
          44             System.out.println(Ognl.getValue("no", dep));
          45             System.out.println("====================================");
          46             
          47             //以集合為根
          48             System.out.println(Ognl.getValue("department.name", ctx,ctx));
          49             //從根的集合中取值需要添加#來區分
          50             System.out.println(Ognl.getValue("#department.name", ctx,u));
          51             //訪問對象的方法
          52             System.out.println(Ognl.getValue("hello('Jerry')",ctx,u));
          53             //訪問靜態的方法,格式為@XXX.XXX.XXX(包名...類名)@XXX(靜態方法名)
          54             System.out.println(Ognl.getValue("@demo.ognlDemo.User@sayHi()",u));
          55             //root是根元素的鍵值,通過#root可以直接取得根元素
          56             System.out.println(Ognl.getValue("#root.name", ctx,u));
          57             System.out.println("====================================");
          58             
          59             //以一個集合為根,取得其中的某個元素
          60             List<User> users = new ArrayList<User>();
          61             User u1 = new User();
          62             u1.setName("zhangsan");
          63             User u2 = new User();
          64             u2.setName("lisi");
          65             users.add(u1);
          66             users.add(u2);
          67             System.out.println(Ognl.getValue("#root[0].name",users));
          68             
          69             //或者
          70             System.out.println(Ognl.getValue("get(0).name",users));
          71             
          72         } catch (OgnlException e) {
          73             e.printStackTrace();
          74         }
          75     }
          76 }

          下面回到struts2,struts2中的所有參數都保存在ValueStack中,而ValueStack就是一個OGNL結構。ValueStack由兩部分組成,一個是ActionContext,類似于OGNL的Map集合,另一個是compoundRoot,類似于OGNL的根對象,使用ArrayList維護了一個棧結構。而參數則可以通過三種方式進行傳遞。
          方法一:
          在action中添加屬性,并為屬性添加get/set方法
          這個方法實際上就是在ValueStack的根中創建一個action對象,取值的時候如果沒有特別指定,則默認取得棧頂的對象。在取值的時候從棧頂開始依次向下獲取,根據Key值返回第一個取得的值,同時,我們也可以對ValueStack進行操作,使用ActionContext.getContext().getValueStack()獲得ValueStack,進行push,peek或者remove等操作
          方法二:
          使用ActionContext存放值
          方法三:
          使用ServletActionContext存放值

          Action:
           1 package demo.ognlDemo;
           2 
           3 import org.apache.struts2.ServletActionContext;
           4 
           5 import com.opensymphony.xwork2.ActionContext;
           6 
           7 public class DemoAction {
           8     //1:通過action屬性傳值
           9     private String name;
          10     private String age;
          11     
          12     public String execute(){
          13         
          14         name = "Tom";
          15         age = "99";
          16         
          17         //2:通過actioncontext傳值
          18         ActionContext.getContext().put("demokey"99999999);
          19         
          20         //3:通過servletActionContext進行傳值
          21         ServletActionContext.getRequest().setAttribute("servletkey"00000000);
          22         
          23         return "success";
          24     }
          25     //get/set方法略
          26
          27 }
          JSP:
           1 <%@ page language="java" contentType="text/html; charset=UTF-8" isELIgnored="false"
           2     pageEncoding="UTF-8"%>
           3 <%@taglib prefix="s" uri="/struts-tags" %>
           4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
           5 <html>
           6 <head>
           7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
           8 <title>struts2 Demo</title>
           9 </head>
          10 <body>
          11 
          12 對于EL表達式而言,不論值存放在什么地方,都可以取得,但是使用struts2的標簽,需要注意key值的寫法
          13 
          14 <hr>
          15 通過屬性進行傳值:<br>
          16 EL表達式 -->${name}:${age}<br>
          17 s:property標簽 --<s:property value="name"/> : <s:property value="age"/>
          18 <hr>
          19 
          20 通過actionContext進行傳值<br>
          21 EL表達式--> ${demokey}<br>
          22 s:property標簽(訪問actionContext中的數據,需要在鍵值之前添加“#”) --<s:property value="#demokey"/>
          23 <hr>
          24 
          25 通過servletActionContext進行傳值<br>
          26 EL表達式 -->${servletkey}<br>
          27 s:property標簽 (訪問servletActionContext中的數據,需要在鍵值之前添加“#”,并且需要注明范圍:request/session/application)--<s:property value="#request.servletkey"/>
          28 <hr>
          29 </body>
          30 </html>
          為了能查看更詳細的信息,開發過程中可以在頁面中加入調試標簽
          1 <s:debug/>
          標簽展開之后Value Stack Contents就是根的內容,Stack Context就是集合的內容

          上述內容是從action到jsp的參數傳遞,下面是從jsp到action的參數傳遞
          方法一:
          通過地址欄參數進行參數傳遞,/XXX?param=YYY,在Action里可以直接通過對應的屬性來獲取,或者直接通過servletActionContext取得request,獲取參數值。
          這種方法對于少量的參數傳遞來說沒有問題,但是碰到大量的參數或者中文,其他特殊參數的傳遞就顯得力不從心,可能需要經過轉碼進行傳遞,不方便。
          方法二:
          表單傳遞參數,較直接使用地址欄傳參安全一些,但是參數一多,仍然很頭疼。可以使用以下方法將需要獲取的值注入到指定的對象中。
          1:比如,在通常情況下,為了傳遞多個值到一個user對象中,我們可以將表單域的名字寫為
          1 <input name="user.id" id="uid"/>
          這樣一來,user的id屬性就會接收到相應的值,以此類推,user的其他屬性值都可以參照此寫法。表單提交之后,在action中就可以使用user進行操作。
          2:或者我們可以使action實現ModelDriven<T>接口,這樣一來在傳遞表單的時候,表單域的name屬性就無需指定要傳遞到的對象,直接寫作
          1 <input name="id" id="uid"/>
          ModelDriven實際上就是在ValueStack中,root里的action之上又添加了一個指定的對象,該對象就是實現接口時指定的T,提交表單的時候,參數的值會根據root中的對象,從上到下依次填充,表單域中的屬性首先填充到ModelDrive的對象。

          上面提到的這兩種值填充,在某些情況下可能會有問題,要填充的屬性若是非String類型,比如Date類型,這樣就無法直接轉換,但是一般來說前端會使用控件來限制日期格式的輸入,然后通過String來接收日期字符串,自行轉換。struts2提供了這種問題的解決方案,雖然用的不多,但是見仁見智,轉換器有時也有它的用武之地。
          要使用struts2的轉換器,需要新建類,然后繼承StrutsTypeConverter
           1 package demo.ognlDemo;
           2 
           3 import java.text.ParseException;
           4 import java.text.SimpleDateFormat;
           5 import java.util.Date;
           6 import java.util.Map;
           7 
           8 import org.apache.struts2.util.StrutsTypeConverter;
           9 /**
          10  * 自定義的局部轉換器,將時間和字符串進行轉換
          11  * @author Administrator
          12  *
          13  */
          14 public class DateConverter extends StrutsTypeConverter{
          15 
          16     SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
          17     
          18     /**
          19      * 字符串到對象
          20      */
          21     @SuppressWarnings("rawtypes")
          22     @Override
          23     public Object convertFromString(Map context, String[] values, Class toClass) {
          24         
          25         try {
          26             if (values.length > 0 && values.length <= 1) {
          27                 String str = values[0];
          28                 return sdf.parse(str);
          29             }
          30             return null;
          31         } catch (ParseException e) {
          32             e.printStackTrace();
          33             return null;
          34         }
          35         
          36         
          37     }
          38 
          39     /**
          40      * 對象到字符串
          41      */
          42     @SuppressWarnings("rawtypes")
          43     @Override
          44     public String convertToString(Map context, Object o) {
          45         Date d = (Date)o;
          46         return d.toString();
          47     }
          48 
          49 }
          50 
          給出一個字符串和日期相互轉換的例子,重寫父類的convertFromStringconvertToString方法,convertFromString意味著吧頁面上傳遞過來的String參數經過加工變成自己想要的參數類型,values是參數數組,一般只有一個。convertToString意味著將參數從action傳出到頁面的時候需要進行的轉換。寫好轉換器之后,就需要配置自定義轉換器的使用,轉換器有局部和全局之分,兩種都需要定義對應的properties文件。

          局部轉換器,也就是針對某個action用的轉換器,需要定義名為“action名稱-conversion.properties”的配置文件,并且該文件需要和對應的action置于同一目錄,里面配置哪些屬性需要用哪個轉換器轉換。這段配置就意味著對應action中的creDate(Date類型)的屬性,使用DateConverter轉換
          1 creDate = demo.ognlDemo.DateConverter

          全局轉換器不限于哪個action使用,對整個項目都生效,需要配置名為“xwork-conversion.properties”的配置文件,置于src目錄下,里面需要配置具體action的具體哪個屬性用哪個轉換器轉換
          1 demo.ognlDemo.XXXAction.creDate = demo.ognlDemo.DateConverter

          posted on 2014-10-30 16:38 都較瘦 閱讀(175) 評論(0)  編輯  收藏 所屬分類: MVCFramework

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導航

          統計

          公告

          博客定位:囿于目前的水平,博客定位在記錄自己的學習心得和隨手的練習

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 大洼县| 东宁县| 腾冲县| 绵竹市| 黄平县| 双鸭山市| 永康市| 鹿泉市| 正蓝旗| 大悟县| 汉川市| 平原县| 攀枝花市| 定西市| 介休市| 四子王旗| 马鞍山市| 德兴市| 如东县| 鄂托克旗| 若羌县| 马龙县| 安阳市| 灌云县| 和政县| 乐至县| 南京市| 于田县| 南召县| 河北区| 双桥区| 固原市| 寿宁县| 澄城县| 柳州市| 和硕县| 台东县| 邯郸县| 铜陵市| 开化县| 呼伦贝尔市|