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實例裏的 相關對象,爲該對象屬性賦值。
- 方式一(通過ActionContext):