struts2小結(3)

OGNL概述

1 、之前web階段,學習過EL表達式,EL表達式在jsp中獲取域對象裏面的值

2、 OGNL是一種表達式,這個表達式功能更加強大,

(1)在struts2裏面操作值棧數據

(2)一般把ognl在struts2操作:和struts2標籤一起使用操作值棧

3 、OGNL不是struts2的一部分,是單獨的項目,經常和struts2一起使用

(1)使用ognl時候首先導入jar包,struts2提供jar包



OGNL入門案例

1 、使用ognl+struts2標籤實現計算字符串長度


(1)在java代碼中,調用字符串.length();

2 使用struts2標籤

(1)使用jstl時候,導入jar包之外,在jsp頁面中引入標籤庫

使用struts2標籤時候,在jsp中引入標籤庫


<%@ taglib uri="/struts-tags" prefix="s"%>

(2)使用struts2標籤實現操作

<body>
	<!-- 使用ognl與struts2標籤實現字符串長度的計算 
	value寫的是ognl表達式
	-->
	<s:property value="'haha'.length()"/>
</body>

什麼是值棧

1 、之前在web階段,在servlet裏面進行操作,把數據放到域對象裏面,在頁面中使用el表達式獲取到,域對象在一定範圍內,存值和取值(https://blog.csdn.net/m0_37307255/article/details/79862056   el表達式)

2 、在struts2裏面提供本身一種存儲機制,類似於域對象,是值棧,可以存值和取值

(1)在action裏面把數據放到值棧裏面,在頁面中獲取到值棧數據 

3、 servlet和action區別

(1)Servlet:默認在第一次訪問時候創建,創建一次,單實例對象

(2)Action:訪問時候創建,每次訪問action時候,都會創建action對象,創建多次,多實例對象

證明action是多實例對象:


4 值棧存儲位置

(1)每次訪問action時候,都會創建action對象,

(2)在每個action對象裏面都會有一個值棧對象(只有一個)

什麼是棧?一種數據結構,先進後出,彈棧壓棧


獲取值棧對象

1、 獲取值棧對象有多種方式

(1)常用方式:使用ActionContext類裏面的方法得到值棧對象

public String execute() {
		// 第一種方式 使用值棧裏的set方法將數據存入值棧(用的不多)
		// 1 獲取值棧對象
		ActionContext context = ActionContext.getContext();
		ValueStack valueStack1 = context.getValueStack();
		// 調用值棧的set方法
		valueStack1.set("wangzhi", "www.baidu.com");
}

2、每個action對象中只有一個值棧對象,以下實例返回True,說明是同一對象

public String execute() {
		// 獲取ActionContext的對象
		ActionContext context = ActionContext.getContext();
		// 調用方法得到值棧對象
		ValueStack valueStack1 = context.getValueStack();
		ValueStack valueStack2 = context.getValueStack();
		// 比較值棧內的值是否爲同一個值。驗證一個Action中是否只有一個值棧對象
		System.out.println(valueStack1 == valueStack2);
		return NONE;
	}

值棧內部結構

1 、值棧分爲兩部分:

第一部分 root,結構是list集合

(1)一般操作都是root裏面數據

第二部分 context,結構map集合

2 、struts2裏面標籤 s:debug,使用這個標籤可以查看值棧結構和存儲值

(1)訪問action,執行action的方法有返回值,配置返回值到jsp頁面中,

<package name="demo1" extends="struts-default" namespace="/">
		<action name="useraction" class="com.struct2_stu.action.UserAction"></action>
</package>

在jsp頁面中使用debug標籤

<!-- 使用struct2標籤查看值棧結構 -->
	<s:debug></s:debug>

效果:

點擊超鏈接看到結構:


(2)在action沒有做任何操作,棧頂元素是 action引用


- action對象裏面有值棧對象

- 值棧對象裏面有action引用

向值棧放數據

1 、向值棧放數據多種方式

第一種 獲取值棧對象,調用值棧對象裏面的 set 方法

	public String execute() {
		// 第一種方式 使用值棧裏的set方法將數據存入值棧(用的不多)
		// 1 獲取值棧對象
		ActionContext context = ActionContext.getContext();
		ValueStack valueStack1 = context.getValueStack();
		// 調用值棧的set方法
		valueStack1.set("wangzhi", "www.baidu.com");
                return "success";
	}

在值棧棧頂多了一個map集合

第二種 獲取值棧對象,調用值棧對象裏面的  push方法

	public String execute() {
		// 第一種方式 使用值棧裏的set方法將數據存入值棧(用的不多)
		// 1 獲取值棧對象
		ActionContext context = ActionContext.getContext();
		ValueStack valueStack1 = context.getValueStack();

		// 第二種 調用方法push
		valueStack1.push("abcd");
		return "success";
	}

棧頂多個一個String數據

第三種 在action定義變量,生成變量的get方法(最常用)

package com.struct2_stu.action;

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

public class ValueStackAction extends ActionSupport {

	// 第三中放值方式:在action成員變量位置定義變量
	String name;

	// 生成變量get方法
	public String getName() {
		return name;
	}

	public String execute() {
		//第三步:在執行的方法中設置值
		name="xyz";
		return "success";
	}
}

使用第三種方式數據直接放在action中,減少對數據的分配,增加執行效率

向值棧放對象

1、 實現步驟

第一步 定義對象變量

第二步 生成變量的get方法

第三步 在執行的方法裏面向對象中設置值

package com.struct2_stu.action;

import com.opensymphony.xwork2.ActionSupport;
import com.struct2_stu.entity.User;

public class ObjectDemoAction extends ActionSupport {
	// 定義對象變量
	private User user;
	// 生成get方法
	public User getUser() {
		return user;
	}
	public String execute() throws Exception {
		// 向user的值棧放數據
		user = new User();
		user.setUsername("root");
		user.setPassword("123");
		return "success";
	}
}

user放入值棧的action中:


向值棧放list集合(重要

第一步 定義list集合變量

第二步 生成變量的get方法

第三步 在執行的方法裏面向list集合設置值

package com.struct2_stu.action;

import java.util.ArrayList;
import java.util.List;

import com.struct2_stu.entity.User;

//向值棧中放入list集合
public class PutListAction {
	//定義list集合變量
	private List list=new ArrayList<User>();
	//生成list集合的get方法、

	public List<User> getList() {
		return list;
	}
	
	public String execute(){
		User user1 = new User();
		user1.setPassword("123");
		user1.setUsername("root");
		
		User user2 = new User();
		user2.setUsername("admin");
		user2.setPassword("123456");
		
		list.add(user1);
		list.add(user2);
		return "success";
	}
}

從值棧獲取數據

1、 使用struts2的標籤+ognl表達式獲取值棧數據

(1)<s:property value=”ognl表達式”/>

獲取字符串

1 、向值棧放字符串

private String name;
	public String getName() {
		return name;
	}
	public String execute() {
		name="lucy";
		return "success";
	}

2 在jsp使用struts2標籤+ognl表達式獲取

	<!-- 獲取值棧中的值 -->
	<!-- 獲取字符串的值 -->
	<s:property value="name" />

獲取對象

1 、向值棧放對象

// 定義對象變量
	private User user;
	// 生成get方法
	public User getUser() {
		return user;
	}
	public String execute() throws Exception {
		// 向user的值棧放數據
		user = new User();
		user.setUsername("root");
		user.setPassword("123");
		return "success";
	}

2、 在頁面中獲取值

	<!-- 獲取對象的值,ognl表達式 -->
	獲取對象的值:
	<br />
	<s:property value="user.username" />
	<s:property value="user.password" />

獲取list集合

第一種方式:

<!-- 獲取值棧中list集合的數據 -->
	<!-- 第一種方式實現,不靈活,將數據寫死了 -->
	獲取list值第一種方式:
 	<s:property value="list[0].username"/>
	<s:property value="list[0].password"/>
	
	<s:property value="list[1].username"/>
	<s:property value="list[1].password"/> 
	<br/><br/>

第二種方式:

<!--第二種方式實現 ,使用struts的iterator標籤遍歷list集合-->
	獲取list值第二種方式:
	<%-- el表達式的foreach遍歷方法
		<c:foreach items="user">
			${user.username}
		</foreach>
	 --%>
	<%-- 注意:使用<!--  -->註釋標籤無法註釋掉<>頁面中的這種標籤,使用它註釋會報錯 --%>
	<s:iterator value="list">
		<!-- 得到list中的每個user對象,直接輸出 -->
		<s:property value="username" />
		<s:property value="password" />
	</s:iterator>

第三種方式:

<!-- 獲取list值第三種方式:也是使用iterator標籤 -->
	獲取list值第三種方式:
	<s:iterator item="list" var="user">
		<!-- 遍歷list集合,得到每個user對象
	優化機制:把每次遍歷出來的user對象放到contexrt中去
	要獲取context裏面的數據,寫ognl表達式,需要使用特殊符號#才能取出context數據 -->
		<s:property value="#user.username" />
		<s:property value="#user.password" />
		<br />
	</s:iterator>

其他操作

1、 使用set方法向值棧放數據,獲取

// 1 獲取值棧對象
		ActionContext context = ActionContext.getContext();
		ValueStack valueStack1 = context.getValueStack();
		// 調用值棧的set方法
		valueStack1.set("wangzhi", "www.baidu.com");
	<!--獲取set方法設置的值valueStack1.set("wangzi", "www.baidu.com");  -->
	<s:property value="wangziohjj"/>

2、 使用push方法向值棧放數據,獲取

// 第二種 調用方法push
valueStack1.push("abcd");

(1)使用push方法設置值,沒有名稱,只有設置的值

(2)向值棧放數據,把向值棧放數據存到數組裏面,數組名稱 top,根據數組獲取值

	<!-- 獲取push方法設置的數據 valueStack1.push("abcd");,push沒有名字,取法稍微複雜
	-->
	<!-- 表示取到棧頂值 -->
	<<s:property valaue=[0].top/>

EL表達式獲取值棧數據(爲什麼)(重點

1 、EL表達式獲取域對象值

2 、向域對象裏面放值使用setAttribute方法,獲取值使用getAttribute方法

3 、底層增強request對象裏面的方法getAttribute方法

(1)首先從request域獲取值,如果獲取到,直接返回

(2)如果從request域獲取不到值,到值棧中把值獲取出來,把值放到域對象裏面

4、 查看源代碼



OGNL的#、%使用

# 使用

1、 使用#獲取context裏面數據,注意:使用<!--  -->註釋標籤無法註釋掉<>頁面中的這種標籤,使用它註釋會報錯,錯誤極爲難找,要注意

<!--第二種方式實現 ,使用struts的iterator標籤遍歷list集合-->
	獲取list值第二種方式:
	<%-- el表達式的foreach遍歷方法
		<c:foreach items="user">
			${user.username}
		</foreach>
	 --%>
	<%-- 注意:使用<!--  -->註釋標籤無法註釋掉<>頁面中的這種標籤,使用它註釋會報錯 --%>
	<s:iterator value="list">
		<!-- 得到list中的每個user對象,直接輸出 -->
		<s:property value="username" />
		<s:property value="password" />
	</s:iterator>

2 、演示# 操作

(1)向request域放值

(2)在頁面中使用ognl獲取

	<!-- 獲取context裏面的數據,寫ognl的時候首先要添加一個符號#
	#後就寫context的key的名稱.域對象名稱,context的key是固定的,如果要得到request中的值就寫request
	 -->
	<s:property value="#request.req"/>

% 使用

1、 在struts2標籤中表單標籤

(1)在struts2標籤裏面使用ognl表達式,如果直接在struts2表單標籤裏面使用ognl表達式不識別,只有%之後纔會識別。直接寫value="#request.req”沒有效果

	<!-- html普通輸入項 -->
	<!-- <input type="text" name="name" value="123"/> -->
	<!-- strut2普通輸入項 -->
	<s:textfield name="username" value="%{#request.req}"></s:textfield>
	

案例-列表功能改造(值棧)



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章