Struts2的簡單使用(四)action向頁面傳值
在action中依然可以像以前在servlet裡面一樣,使用request、session、application向頁面傳送值,除此之外,action裡面還有倆個獨有的傳值方式:ValueStack ActionContext
一,先來說說這倆個獨有的傳值方式~
1.ValueStack的特點(值棧):
1.把一個物件放到vs裡面之後,我們從這個vs中是拿不到這個物件的,但是我們可以直接拿到這個物件裡面的屬性以及屬性值.
2.從vs中拿值的時候,是從vs中的property name這一個列來拿的,拿到的是property value這一列的值.(在debug中的vs檢視可以看這些列)
所以如果我們通過vs把一個值傳到頁面,我們不能直接把這個值放到vs裡,因為這樣拿不到,我們應該把這個值放到一個物件的屬性裡面,然後再把這個物件放vs中,這個時候就可以通過vs拿到這個物件的屬性了,也就是我們要傳的值.
3.每次瀏覽器傳送一個新的請求,都會生成一個新的ValueStack物件,上一次的ValueStack物件就沒了,找不到了.(類似之前學習的request物件的特點)
4.每次建立一個新的ValueStack物件後,會把這個物件放到ActionContext裡面.
2.ActionContext的特點
1.向ac裡面放值的時候是通過key-value的形式存放的,key是String型別,value是Object型別,取值的是同樣通過key拿到value.
2.struts框架預設向這個物件裡面存放的物件(資料)很多,包括request、session、application、ValueStack、parameters等
3.每次請求都會建立一個新的ActionContext物件(每次請求打印出ac的地址值可以看出來)
接下來就程式碼編寫~
第一步:
ValueStack是一個介面:com.opensymphony.xwork2.util.ValueStack
ActionContext是一個類:com.opensymphony.xwork2.ActionContext
我們可以使用這個倆個型別的物件,從action裡面把值帶到頁面.
程式碼編寫如下:ValueStackAction類
public class ValueStackAction extends ActionSupport{ private static final long serialVersionUID = 1L; public String execute(){ //測試action,ValueStack, ActionContext context=ActionContext.getContext(); ValueStack stack=context.getValueStack(); System.out.println("action:"+this); System.out.println("context:"+context); System.out.println("stack:"+stack); return SUCCESS; } }
第二步:
我們在頁面中,可以通過一個struts2的標籤來看到action傳到頁面中的值:
<s:debug/>
頁面引入標籤庫:<%@taglib uri="/struts-tags" prefix="s" %>
程式碼如下:在頁面index.jsp中寫標籤~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<span style="color:#ff0000;"><%@taglib uri="/struts-tags" prefix="s"%></span>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index.jsp</title>
</head>
<body>
<h4>index.jsp</h4>
<span style="color:#ff0000;"><s:debug></s:debug> </span>
</body>
第三步:
當前action進行跳轉的時候,struts2框架會自動的把當這個action物件本身分別放到ValueStack和ActionContext這個倆個物件,然後struts2框架再把這個倆個物件傳給頁面,所以我們在頁面中只要通過這個倆個物件,就可以拿到之前放進去的值.(在頁面的debug標籤中,可以看到struts框架放到這倆個物件裡面的action)
配置檔案struts.xml配置這個Action:
<action name="vs"
class="com.xu.struts2.web.action.ValueStackAction">
<result name="success" >/WEB-INF/jsp/index.jsp</result>
</action>
在瀏覽器中輸入localhost:9999/Struts2/vs.action,效果圖如下:
第四步:
除了struts框架自動的像ValueStack和ActionContext裡面放值以外,我們還可以手動的向這倆個物件裡面放值.
(在execute方法中拿到這個倆個物件就可以向裡面放值了)
程式碼如下:
ValueStackAction類--get和set方法一定要寫
public class ValueStackAction extends ActionSupport{
private String name;
private int age;
private Boolean gender;
private static final long serialVersionUID = 1L;
public String execute(){
//測試action,ValueStack,
name="tee";
age=12;
gender=true;
ActionContext context=ActionContext.getContext();
ValueStack stack=context.getValueStack();
System.out.println("action:"+this);
System.out.println("context:"+context);
System.out.println("stack:"+stack);
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Boolean getGender() {
return gender;
}
public void setGender(Boolean gender) {
this.gender = gender;
}
}
頁面index.jsp也要新增幾行程式碼,用到了EL表示式~
<body>
<h4>index.jsp</h4>
<hr>
name:${name } <br>
age:${age } <br>
gender:${gender }<br>
<hr>
<s:debug></s:debug>
</body>
效果圖如下:
第五步:
向ac和vs中主動放值
向ActionContext物件中放值:
context.put(String,Object);
context.put("hello","world");
向ValueStack物件中放值:
User user = new User();
stack.push(user);
只是需要改寫ValueStack~,程式碼如下:
public class ValueStackAction extends ActionSupport{
private String name;
private int age;
private Boolean gender;
private static final long serialVersionUID = 1L;
private User user;
public String execute(){
//測試action,ValueStack,
name="tee";
age=12;
gender=true;
user=new User(1L, "larr", 12, false, "123");
ActionContext context=ActionContext.getContext();
ValueStack stack=context.getValueStack();
context.put("hello", "world");
stack.push(user);//手動把user物件放入值桟
System.out.println("action:"+this);
System.out.println("context:"+context);
System.out.println("stack:"+stack);
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Boolean getGender() {
return gender;
}
public void setGender(Boolean gender) {
this.gender = gender;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
效果圖如下:
注意:使用vs和ac傳值的時候,要使用伺服器內部跳轉的方式.
總結:
客戶端傳送一個請求到action,struts2框架會建立倆個物件:ValueStack物件和ActionContext物件,action執行完進行跳轉的的同時,struts2框架會這個當前執行的action物件分別放到ValueStack物件和ActionContext物件裡面,在頁面中通過debug標籤可以到放到這倆個物件裡面的action物件.所以最終我們在頁面就可以通過ValueStack物件或者ActionContext物件拿到action裡面的屬性值(get/set方法)
二,再來說說在action中訪問web元素(request session application)
1.在struts2框架中,這三個物件分別都有倆個型別:原型別和Map型別(這個物件都在ActionContext裡面)
2.原型別: (指的就是之前在servlet中使用的物件型別)
HttpServletRequest request
HttpSession session
ServletContext application
Map型別:
Map<String,Object> request
Map<String,Object> session
Map<String,Object> application
3.在使用的時候,我們可以選擇使用原型別的request或者選擇使用Map型別的request.(session和application也是這樣的情況)
4.不管是原型別的還是Map型別的物件,都是被struts2框架預設存放到了ActionContext物件裡面.(使用debug標籤可以看到)
5.原型別的和Map型別的關係.
Map<String,Object> session1 = ActionContext.getContext().getSession();
HttpSession session2 = ServletActionContext.getRequest().getSession();
a.使用Map型別的物件,可以降低程式碼中對 servlet的API的依賴(降耦)
b.我們使用原型別大多時候也是存值和取值,
而且原型別裡面本身也是封裝了Map物件。
所以我們使用Map型別的物件也可以完成存值和取值.
c.Map型別的request物件裡面的值(k-v),其實就是複製的原型別的
request物件裡面的值(k-v),當然原型別的request物件裡面除了k-v型別的鍵值對以外,
還有其他的屬性和方法,因為它畢竟是HttpServletRequest型別的物件.
d.所以原型別的request和Map型別的request物件,我們可以理解為他們裡面的值(k-v)是相通的,相通的意思就是:這個物件裡面有什麼值,那個物件裡就也
會什麼值.所以我們在action裡面向Map型別的物件中存放一個值(k-v),將來在頁面中同樣是可以使用原型別的request物件那這個值(k-v)取出來的.
注:session和application的情況也是一樣的道理.
原型別和Map型別相當於下面這個例子:
張三手裡有一個錢包,我們平時都是把錢給張三,張三再把錢放到錢包裡面, 我們拿錢的時候也是通過張三,張三從錢包裡拿出錢,然後再把錢給我們.現在我們不想這麼做,覺得很麻煩,我們直接從張三手裡搶過來這個錢包,我們存錢和拿錢都直接操作這個錢包原型別的request就相當於這裡的張三,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
第一種方式-主動方式~
程式碼如下:
WebAction:
public class WebAction extends ActionSupport {
private static final long serialVersionUID = 1L;
@Override
public String execute() throws Exception {
//主動
ActionContext context=ActionContext.getContext();
//ServletContext 實際存放值的地方
Map<String,Object>application=context.getApplication();
//HttpSession實際存放值的地方
Map<String, Object>session=context.getSession();
session.put("sessionKey", "sessionValue...");
application.put("applicationKey", "applicationValue...");
return SUCCESS;
}
}
在struts.xml要配置這個action,程式碼如下:
<action name="web" class="com.xu.struts2.web.action.WebAction">
<result name="success" >/WEB-INF/jsp/index.jsp</result>
</action>
在index.jsp這個頁面要接收值~
<body>
<h4>index.jsp</h4>
<hr>
session:${sessionScope.sessionKey }<br>
application:${applicationScope.applicationKey }<br>
<hr>
</body>
在瀏覽器中輸入localhost:9999/Struts/web.action,效果圖如下:
第二種方式-被動方式~
程式碼如下:
WebAction類:
public class WebAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{
private static final long serialVersionUID = 1L;
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;
}
}
在index.jsp要接收從action傳來的值,程式碼如下:
<body>
<h4>index.jsp</h4>
<hr>
request:${requestScope.MyName }<br>
session:${sessionScope.YourName }<br>
application:${applicationScope.HerName }<br>
<hr>
</body>
效果圖如下:
第二步:
獲取原型別物件
第一種方式:自己主動獲得
獲得原型別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,和上面的效果、用法是一樣的。
程式碼編寫如下:
第一種方式-主動獲得~
Web2Action類:
public class Web2Action extends ActionSupport {
public String execute(){
//主動獲取
ServletContext s_application=ServletActionContext.getServletContext();
HttpServletRequest s_request=ServletActionContext.getRequest();
HttpSession s_session=s_request.getSession();
s_application.setAttribute("application", "zhangsan");
s_request.setAttribute("request", "lili");
return SUCCESS;
}
}
在struts.xml配置這個action:
<action name="web2" class="com.xu.struts2.web.action.Web2Action">
<result name="success" >/WEB-INF/jsp/index.jsp</result>
</action>
在頁面index.jsp接收這個引數:
<body>
<h4>index.jsp</h4>
<hr>
request:${requestScope.request }<br>
session:${sessionScope.session }<br>
application:${applicationScope.application }<br>
<hr>
</body>
在瀏覽器中輸入localhost:9999/Struts2/web2.action
效果圖如下:
第二種方式-被動方式~
實現介面
程式碼如下:
Web2Action類:
public class Web2Action extends ActionSupport
implements ServletRequestAware,ServletContextAware{
private HttpServletRequest request;
private ServletContext application;
public String execute(){
//被動獲取
HttpSession session=request.getSession();
request.setAttribute("request", "00requsetKey00");
session.setAttribute("session","00sessionKey00");
application.setAttribute("application", "00applicationKey00");
return SUCCESS;
}
@Override
public void setServletRequest(HttpServletRequest request) {
// TODO Auto-generated method stub
this.request=request;
}
@Override
public void setServletContext(ServletContext application) {
// TODO Auto-generated method stub
this.application=application;
}
}
別的什麼都不變~
效果圖如下:
好了,到這裡action向頁面傳值就寫完了~
有什麼疑問的可以問我~