action中如何接受頁面傳過來的參數
第一種情況:(同名參數)
例如:
通過頁面要把id=****1 name=tom age=20這三個參數傳給action
action裏面定義三個成員變量id name age,這個三個變量的名字一定要和所傳變量的名字一致.
提供get/set方法
將來頁面把這三個參數傳過來的時候,struts2框架會自動的幫我們把這個三個參數值放action中的三個屬性裏面.(同時還做了類型的轉換)
注意:這個工作其實是由defaultStack這個攔截器棧裏面的攔截器來完成了.
傳值完成之後,我們只要在execute方法中去直接使用就可以了,不需要做其他事情.
第二種情況:(域模型)
在接收到頁面傳值的時候,還可以讓struts2框架直接幫我們把這些接收到的值封裝到一個javabean對象裏面.
action中定義一個User類型的變量user,User類中有三屬性值,id name age,同時User類中還有get/set方法
action中給這個user屬性提供get/set方法
頁面向action傳值的時候,參數的名字要寫成user.id=1 user.name=tom user.age=20
將來接收到這個參數值以後,struts2框架會幫我們去創建一個User對象,並且把所傳參數的三個值封裝到對象的三個屬性裏面,最後把這個封裝好的對象放到action的user屬性中
第三種情況:(模型驅動)
class TestAction implements ModelDriven<User>{
@Override
public User getModel() {
if(user == null){
user= new User();
}
return user;
}
}
從action向頁面傳值
在action中依然可以像以前在servlet裏面一樣,
使用request、session、application向頁面傳送,除此之外,
action裏面還有倆個獨有的傳值方式:ValueStack ActionContext
ValueStack是一個接口:com.opensymphony.xwork2.util.ValueStack
ActionContext是一個類:com.opensymphony.xwork2.ActionContext
我們可以使用這個倆個類型的對象,從action裏面把值帶到頁面.
ActionContext context = ActionContext.getContext();
ValueStack vs = context.getValueStack();
我們在頁面中,可以通過一個struts2的標籤來看到action傳到頁面中的值(這裏我們使用標籤庫需要導入兩個jar包):
`<s:debug/>`
頁面引入標籤庫:`<%@taglib uri="/struts-tags" prefix="s" %>`
當前action進行跳轉的時候,struts2框架會自動的把當這個action對象本身分別放到ValueStack和ActionContext這個倆個對象,
<s:property value="customer.username"/>
然後struts2框架再把這個倆個對象傳給頁面,所以我們在頁面中只要通過這個倆個對象,就可以拿到之前放進去的值.(在頁面的debug標籤中,可以看到struts框架放到這倆個對象裏面的action)
除了struts框架自動的像ValueStack和ActionContext裏面放值以外,
我們還可以手動的向這倆個對象裏面放值.
(在execute方法中拿到這個倆個對象就可以向裏面放值了)
如何拿到ValueStack和ActionContext對象
獲得ActionContext對象:
`ActionContext ac = ActionContext.getContext();`
獲得ValueStack對象:
`ValueStack vs = ac.getValueStack();`
自己向ac和vs中主動放值
向ActionContext對象中放值:
ac.put(String,Object);
ac.put("hello","world");
向ValueStack對象中放值:
User user = new User();
vs.push(user);
ValueStack的特點(值棧)
把一個對象放到vs裏面之後,我們從這個vs中是拿不到這個對象的,但是我們可以直接拿到這個對象裏面的屬性以及屬性值.
從vs中拿值的時候,是從vs中的property name這一個列來拿的,拿到的是property value這一列的值.(在debug中的vs視圖可以看這些列)
所以如果我們通過vs把一個值傳到頁面,我們不能直接把這個值放到vs裏,因爲這樣拿不到,我們應該把這個值放到一個對象的屬性裏面,然後再把這個對象放vs中,這個時候就可以通過vs拿到這個對象的屬性了,也就是我們要傳的值.
每次瀏覽器發送一個新的請求,都會生成一個新的ValueStack對象,上一次的ValueStack對象就沒了,找不到了.(類似之前學習的request對象的特點)
每次創建一個新的ValueStack對象後,會把這個對象放到ActionContext裏面.
ActionContext的特點
- 向ac裏面放值的時候是通過key-value的形式存放的,key是String類型,value是Object類型,取值的是同樣通過key拿到value.
- struts框架默認向這個對象裏面存放的對象(數據)很多,包括request、session、application、ValueStack、parameters等
每次請求都會創建一個新的ActionContext對象(每次請求打印出ac的地址值可以看出來)
注意:使用vs和ac傳值的時候,要使用服務器內部跳轉的方式.
客戶端發送一個請求到action,struts2框架會創建倆個對象:
ValueStack對象和ActionContext對象,action執行完進行跳轉的的同時,struts2框架會這個當前執行的a**ction對象分別放到ValueStack對象和ActionContext對象裏面**,在頁面中通過debug標籤可以到放到這倆個對象裏面的action對象.所以最終我們在頁面就可以通過ValueStack對象或者ActionContext對象拿到action裏面的屬性值(get/set方法)
在action中訪問web元素(request session application)
在struts2框架中,這三個對象分別都有倆個類型:原類型 Map類型(這個對象都在ActionContext裏面)
原類型: (指的就是之前在servlet中使用的對象類型)
HttpServletRequest request
HttpSession session
ServletContext application
- Map類型:
Map<String,Object> request
Map<String,Object> session
Map<String,Object> application
- 在使用的時候,我們可以選擇使用原類型的request或者選擇使用Map類型的request.(session和application也是這樣的情況)
- 不管是原類型的還是Map類型的對象,都是被struts2框架默認存放到了ActionContext對象裏面.(使用debug標籤可以看到)
- 原類型的和Map類型的關係.
Map<String,Object> session1 = ActionContext.getContext().getSession();
HttpSession session2 = ServletActionContext.getRequest().getSession();
- 使用Map類型的對象,可以降低代碼中對 servlet的API的依賴(降耦)
- 我們使用原類型大多時候也是存值和取值,而且原類型裏面本身也是封裝了Map對象。所以我們使用Map類型的對象也可以完成存值和取值.
- Map類型的request對象裏面的值(k-v),其實就是複製的原類型的request對象裏面的值(k-v),當然原類型的request對象裏面除了k-v類型的鍵值對以外,還有其他的屬性和方法,因爲它畢竟是HttpServletRequest類型的對象.
- 所以原類型的request和Map類型的request對象,我們可以理解爲他們裏面的值(k-v)是相通的,相通的意思是:這個對象裏面有什麼值,那個對象裏就也會什麼值.所以我們在action裏面向Map類型的對象中存放一個值(k-v),將來在頁面中同樣是可以使用原類型的request對象那這個值(k-v)取出來的.
注:session和application的情況也是一樣的道理.
原類型和Map類型相當於下面這個例子:
張三手裏有一個錢包,我們平時都是把錢給張三,張三再把錢放到錢包裏面, 我們拿錢的時候也是通過張三,張三從錢包裏拿出錢,然後再把錢給我們.現在我們不想這麼做,覺得很麻煩,我們直接從張三手裏搶過來這個錢包,我們存錢和拿錢都直接操作這個錢包原類型的request就相當於這裏的張三,Map類型對象就相當於這個錢包
在action中如果拿到Map類型和原類型的對象
獲取Map類型對象
第一種方式:自己在方法中主動獲得
ActionContext ac = ActionContext.getContext();
//獲得Map類型request
`Map<String,Object> request = (Map<String, Object>) ac.get("request");`
//獲得Map類型session
`Map<String, Object> session = ac.getSession();`
//獲得Map類型application
Map<String, Object> application = ac.getApplication();
第二種方式:讓struts2框架把Map類型的對象自動的放到action裏(依賴注入)
第一種方式是自己主動拿到這個對象,第二種方式是自己被動接受這個對象.
實現三個接口,分別可以讓struts2框架把Map類型的request、session、application對象通過調用實現的接口中方法傳給我們的action,在action裏面我們只要接收這三個對象就可以了,那到後可以直接使用.三個接口依次爲:
RequestAware,SessionAware,ApplicationAware
例如:
public class WebActionTest extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{
private Map<String, Object> request;
private Map<String, Object> session;
private Map<String, Object> application;
@Override
public String execute() throws Exception {
//頁面中用原類型的對象去正常值就可以了
request.put("MyName", "tom");
session.put("YourName", "zhansan");
application.put("HerName", "lily");
return SUCCESS;
}
public void setRequest(Map<String, Object> request) {
this.request = request;
}
public void setSession(Map<String, Object> session) {
this.session = session;
}
public void setApplication(Map<String, Object> application) {
this.application = application;
}
}
獲取原類型對象
第一種方式:自己主動獲得
獲得原類型request對象
HttpServletRequest req = ServletActionContext.getRequest();
獲得原類型response對象
HttpServletResponse res = ServletActionContext.getResponse();
獲得原類型session對象
HttpSession sess = req.getSession();
獲得原類型application對象
ServletContext app1 = sess.getServletContext();
或者
ServletContext app2 = ServletActionContext.getServletContext();
第二種方式:自己被動接收
struts2框架中提供了一個接口,可以用來獲得原類型的request對象,
因爲通過原類型的request對象就可以獲得原類型的session對象和原
類型的application對象
實現接口:ServletRequestAware,然後struts2框架會通過action所實現的抽 象方法,把原類型的request對象自動放到action裏面.
類似的還有一接口:ServletResponseAware,和上面的效果、用法是一樣的。
頁面中獲得action傳過來的值
在struts2框架所提供的頁面取值方式中,需要使用到倆個東西:struts2框架的標籤、OGNL表達式
注意:同時我們也可以使用jsp內置對象取值已經使用jstl標籤+EL表達式取值.
struts2中可以使用的取值方式:
- jsp內置對象取值
- jstl標籤+EL表達式取值
- struts2標籤+OGNL表達式
注意:OGNL表達式只能寫在struts2的標籤屬性中,在這裏面我們先使用一下struts2的這樣一個標籤:,這個標籤的作用就是向頁面輸出值.
例如:<s:property value=" OGNL表達式寫在這 "/>
從ValueStack和ActionContext中取值
從ValueStack中取值.
//注意這個value屬性中的值name,其實就是ongl表達式
//這個表示從valueStack中取一個名字叫做name的property值
<s:property value="name"/>
<s:property value="user"/>
<s:property value="user.id"/>
<s:property value="user.name"/>
注意:從ValueStack中取值的時候,如果Valuestack裏面有倆個名字相同的值,我們只能取到最上面的值(從debug標籤中看vs中最上面的值)(其實取值的方式特殊處理一下還是可以取到下面的屬性值的)
從ActionContext中取值.
要使用ognl表達式通過AC中的key來拿相對於的value值。取值的時候需要加上一個符號:#
<s:property value="#action.name"/><br>
<s:property value="#msg"/><br>
<s:property value="#user"/><br>
<s:property value="#user.id"/><br>
<s:property value="#user.name"/><br>
<s:property value="#user.age"/><br>
ActionContext中的parameters、attr、request、session、application等key值.(這些都是AC中的key)
parameters對應的值中存放的是客戶端所傳過來的參數.
//接收客戶端傳來的名字爲name的參數值
<s:property value="#parameters.name"/><br>
//獲得request中的值
<s:property value="#request.MyName"/><br>
//獲得session中的值
<s:property value="#session.MyName"/><br>
//獲得application中的值
<s:property value="#application.MyName"/><br>
//默認依次從request、session、appliction中取值,取到了就直接輸出,取不到就算了.
<s:property value="#attr.MyName"/><br>
還可以使用以前的方式從request、session、application中取值.
注意:如果我們用request通過key去取值的時候,會先在request裏面找,request裏面找不到會到ValueStack裏面找。因爲**ValueStack默認也被放在request裏面.但是**session和application沒有像request的這樣的特點.
使用jsp腳本代碼取值
<%=request.getAttribute("name") %><br>
<%=session.getAttribute("name") %><br>
<%=application.getAttribute("name") %><br>
使用EL表達式取值:
${requestScope.MyName }<br>
${requestScope.name } <br>
${sessionScope.MyName } <br>
${applicationScope.MyName } <br>
${MyName } <br>
${name } <br>