1. 程式人生 > >Struts2知識復習之三

Struts2知識復習之三

什麽 etc 中心 otn el表達式 引用 上下文環境 類型 一個棧

Struts2的MVC思想以及面向AOP切面編程

1 MVC簡單概述:
M Model(業務邏輯模型,service層,dao層)
V View(視圖,html,css,js頁面)
C Controller(前端控制器,servlet,jsp,action)
2 Struts2MVC的流程:
客戶端發送請求,struts2核心過濾器filter進行攔截處理後傳遞到Action --Controller
Action中調用service,dao層的業務方法 ---Model
Action返回結果,進行頁面跳轉 --View
3 Aop切面編程
精簡含義:縱向重復代碼,橫向抽取。

典型應用:

  • Servlet時代,使用過濾器filter統一處理多個Servlet類的亂碼問題
  • Action時代,使用Interceptor攔截器將相同的參數傳遞給多個不同的action中

    Struts2與OGNL語言(Struts的默認表達式語言)

    1 概述:OGNL(Object Graph Navigation Language )對象圖導航語言是一種開源表達式語言。
    它可通過表達式語法,存取java對象的屬性和調用java對象的方法,同時可自動實現類型轉換。
    2 功能:

    (1)支持對象方法調用的方式。如 objectName.method()
    (2)支持類靜態方法調用和值訪問,格式為:@全類名@方法名|值名,
             如:java.lang.Math@min(xx)
    (3)支持賦值操作和表達式串聯。
    (4)可訪問OGNL上下文對象OGNL Context和Action上下文對象ActionContext
    (5)可操作集合對象

    3 OGNL詳解
    (1)概述:OGNL表達式語言結構由三要素組成:表達式(Expression),根對象(Root Object),上下文環境(Context)。
    <1>OGNL的表達式(規定OGNL做什麽)
    & 它是OGNL的核心,所有OGNL操作都是針對表達式進行的。
    & 它是一個帶語法含義的字符串,該字符串規定了操作類型和操作內容。
    & 它不僅支持鏈式對象訪問路徑,還支持在表達式中進行簡單的計算。
    <2>OGNL的根對象(規定對誰操作)
    & 它是OGNL的操作對象,它能以任意對象為根,通過OGNL可以訪問該對象關聯的其他對象。
    & 設置了Root對象,OGNL可以對Root對象進行任何取寫操作。

    <3>Context對象(規定了在哪裏操作)
    & Root對象所在的環境就是OGNL的上下文對象Context。
    & 上下文對象Context是一個Map類型對象,使用表達式訪問Context中的對象時,
    需使用“#”號加上對象名稱。
    (2)OGNL的API
    <1>OgnlContext和Root對象的創建
    //創建一個User對象作為Root對象的數據
    User rootUser=new User("tom", 18);
    //創建一個Map集合作為OgnlContext對象的數據
    Map<String,User>map=new HashMap<String,User>();
    map.put("user1",new User("jack",18));
    map.put("user2",new User("rose",19));

          //創建OgnlContext對象
          OgnlContext oc=new OgnlContext();
          //把map數據封裝到OGNLContext中
          oc.setValues(map);
          //將rootUser數據封裝到Root
          oc.setRoot(rootUser);
    <2>獲取OgnlContext的root對象和其他對象數據。
            //獲取OgnlContext中整個Root對象
            User root = (User) Ognl.getRoot(oc);
            //獲取OgnlContext中Root對象的name和age的屬性值
            String name = (String) Ognl.getValue("name",oc,oc.getRoot());
            int age= (int) Ognl.getValue("age",oc,oc.getRoot());
            System.out.println("root:"+root+",rootName:"+name+",rootAge:"+age); 
    
            //獲取OgnlContext其他對象數據
            //獲取OgnlContext內整個user1對象
            User user1 = (User) Ognl.getValue("#user1",oc,oc.getRoot());
            //獲取OgnlContext內user1對象的name和age屬性
            String user1_name = (String) Ognl.getValue("#user1.name",oc,oc.getRoot());
            Integer user1_age = (Integer) Ognl.getValue("#user1.age",oc,oc.getRoot());
            System.out.println("user1:"+user1+",user1Name:"+user1_name+",user1Age:"+user1_age);
    <3>修改OgnlContext的root對象和其他對象數據。
              //修改OgnlContext中Root對象的name和age屬性數據
              Ognl.getValue("name=‘flower‘",oc,oc.getRoot());
              Ognl.getValue("age=100",oc,oc.getRoot());
              //獲取修改後的Root對象
              User root = (User) Ognl.getRoot(oc);
              System.out.println("root:"+root);
    
              //修改OgnlContext中其他對象user1的name和age屬性
              String user1_name = (String) Ognl.getValue("#user1.name=‘panda‘",oc,oc.getRoot());
              Integer user1_age = (Integer) Ognl.getValue("#user1.age=200",oc,oc.getRoot());
              //獲取修改後Context內的user1對象
              User user1 = (User) Ognl.getValue("#user1",oc,oc.getRoot());
              System.out.println("user1:"+user1);
    <4>OGNL的操作之調用對象方法
              //調用 OgnlContext中root對象和user1對象的setName方法
              Ognl.getValue("setName(‘root1111‘)",oc,oc.getRoot()); 
              Ognl.getValue("#user1.setName(‘u11111‘)",oc,oc.getRoot());
    
              //取掉用方法後的root對象和user1對象
              User root = (User) Ognl.getRoot(oc);
              User user1 = (User) Ognl.getValue("#user1",oc,oc.getRoot());
              System.out.println("root:"+root);
              System.out.println("user1:"+user1);
    <4>OGNL的操作之調用工具類的靜態方法
            //自定工具類MyUtils如下
            public class MyUtils {
                //回音方法
                public static Object echo(Object o) {
                    return o;
                }
            }
             //調用 自定義工具類靜態方法格式:@+完整類名+@靜態方法
              String value = (String) Ognl.getValue("@cn.xx.MyUtils@echo(‘hello flower‘)",oc,oc.getRoot());
              System.out.println(value);
              //調用 jdk內置工具類 Math的靜態屬性 PI
              Double pi=  (Double) Ognl.getValue("@java.lang.Math@PI",oc,oc.getRoot());
              Double pi2=  (Double) Ognl.getValue("@@PI",oc,oc.getRoot());//簡寫 
              System.out.println(pi2);
    <5>GONL的操作之 存儲List單列集合對象數據到OgnlContext內,註意這裏沒有  用到 #  號
              //在OgnlContext內創建List集合對象--註意裏面元素字母超過一個才可識別字符串,否則作為字符集合處理
              Ognl.getValue("{‘aa‘,‘bb‘,‘cc‘}",oc,oc.getRoot());
              //從OgnlContext裏重新獲取整個list集合對象以及集合的其他數據
              List<String> list = (List<String>) Ognl.getValue("{‘aa‘,‘bb‘,‘cc‘}",oc,oc.getRoot());
              Integer size = (Integer) Ognl.getValue("{‘aa‘,‘bb‘,‘cc‘}.size()",oc,oc.getRoot());
              String name1 = (String) Ognl.getValue("{‘aa‘,‘bc‘,‘cc‘}[0]",oc,oc.getRoot());
              String name2 = (String) Ognl.getValue("{‘aa‘,‘bc‘,‘cc‘}.get(0)",oc,oc.getRoot());
              System.out.println("list:"+list+";\n"+"listSize:"+size+
                                ";listName1:"+name1+";listName2:"+name2);
    <6>GONL的操作之 存儲Map雙列集合對象數據到OgnlContext內,註意這裏用到了 # 號
          //創建Map雙列集合--用#識別
          Ognl.getValue("#{‘name‘:‘zs‘,‘age‘:18}",oc,oc.getRoot());
          //獲取整個Map集合以及Map集合的數據
          HashMap<String,Object> map =
            (HashMap<String, Object>) Ognl.getValue("#{‘name‘:‘zs‘,‘age‘:18}",oc,oc.getRoot());
          Integer size2 = (Integer) Ognl.getValue("#{‘name‘:‘zs‘,‘age‘:18}.size()",oc,oc.getRoot());
          String name3 = (String) Ognl.getValue("#{‘name‘:‘zs‘,‘age‘:18}[‘name‘]",oc,oc.getRoot());
          String name4 = (String) Ognl.getValue("#{‘name‘:‘zs‘,‘age‘:18}.get(‘name‘)",oc,oc.getRoot());
          System.out.println(map+"\n"+size2+";"+name3+";"+name4);

    (3)Ognl總結
    Ognl表達式語言,其運行在一個上下文對象環境OgnlContext裏,
    該環境由Root對象和一個Map集合類型的Context組成。

    Struts2的值棧(ValueStack)

    1 概述
    (1)值棧ValueStack的產生:
    Ognl表達式要想運行必須有Ognl環境OgnlContext。
    struts2為結合Ognl技術,產生了一個OgnlContext,名為ValueStack。
    ValueStack由兩個部分組成,一部分為Root,是一個棧,
    另一部分為ActionContext數據中心,是一個map集合。
    (2)值棧特點:
    & 值棧ValueStack是Struts2的一個接口,OgnlValueStack是ValueStack的實現類。
    & 客戶端發送請求,struts2創建一個Action實例的同時創建一個OgnlValueStack值棧實例。
    & struts2通過OGNL在值棧中存取,讀寫Action參數數據。
    2 OgnlValueStack的內部結構
    (1) 概述:OgnlValue包括兩部分,值棧(CompoundRoot)和 Map<String,Object>Context(ognl的上下文對象 OgnlContext).
    (2) CompoundRoot細述
    <1>它作為OgnlContext的Root對象,存儲action實例數據。
    <2>它繼承了ArrayList實現壓棧和出棧功能,擁有先進後出的特點,我們稱其為對象棧。
    CompoundRoot中的Action實例位於棧頂,struts2會先從棧頂的Action實例查找相應的屬性,
    若找不到則從棧頂往下找其他對象。
    <3>CompoundRoot(自定義棧)是struts2對Ognl的Root使用的改進,
    調用OgnlValueStack的findValue()方法即可查找CompoundRoot棧中的對象及其屬性。
    (3)OgnlContext細述
    <1>它是一個Map<String,Object>結構,存儲一些引用,parameters,request,session,application,attr等.
    <2>Ognl的一些引用
    & parameters:該Map為當前請求的請求參數。
    & request:該Map為request域中的數據
    & session:該Map為session域中的數據
    & appliaction:該Map為application域中的數據。
    & attr:該Map按如下順序檢索以上對象,request,session,application
    3 ValueStack細述
    (1) ActionContext和ValueStack的關系

    • Struts2創建ActionContext的同時也創建ValueStack值棧對象。
    • ActionContext內有一個ValueStack的引用,ValueStack內也有一個ActionContext的引用。
    • ActionContext獲取ServletApI依賴ValueStack值棧。
      (2)ValueStack相應ApI操作
      <1>獲取值棧對象
      • 方式一(通過ActionContext):
        ValueStack valueStack = ActionContext.getContext().getValueStack();
      • 方式二(通過ServletActionContext):
        String vs=ServletActionContext.STRUTS_VALUESTACK_KEY;
        ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(vs);
        <2>操作值棧對象
      • 方式一:在Action中 提供get方法的方式
        因為Action本身在值棧中,所以可通過屬性的get()方法從值棧中獲取Action的屬性值。
      • 方式二:手動操作值棧
        調用值棧的push和set方法手動操作值棧中數據。
        <3>struts2的El表達式
      • #號的使用
        & 獲取值棧中的 上下文對象OgnlContext內的數據,如request的數據
        示例:<s:property value="#request.name"/>
        &遍歷集合的值
        <s:iterator value="#{‘aaa‘:‘111‘,‘bbb‘:‘222‘ }" var="entry"> ------------------------------
      • %號的使用
        & 強制解析Ognl的表達式
        <s:textfield name="name" value="%{#request.name}"></s:textfield>
        & 強制不解析Ognl的表達式
        <s:property value="%{‘#request.name‘}"/>
      • $號的使用
        在struts2配置文件中書寫ognl表達式時使用。

        Struts2結合ognl技術封裝數據的過程

        1 屬性驅動
        (1)客戶端發送請求參數,struts2的param攔截器進行攔截,ognl對參數進行處理。
        (2)ognl先從ValueStack值棧的Root棧裏獲取 Action實例裏的 相關屬性,為該屬性賦值。
        2 對象驅動
        (1)客戶端發送請求參數,struts2的param攔截器進行攔截,ognl對參數進行處理。
        (2)ognl先從ValueStack值棧的Root棧裏獲取 Action實例裏的 相關對象,為該對象屬性賦值。
        3 模型驅動
        (1)客戶端發送請求參數,struts2的param攔截器進行攔截,ognl對參數進行處理。
        ()ognl先從ValueStack值棧的Root棧裏獲取 Action實例裏的 相關對象,為該對象屬性賦值。

Struts2知識復習之三