1. 程式人生 > >Struts2的簡單使用(四)action向頁面傳值

Struts2的簡單使用(四)action向頁面傳值

在這裡我要說一下在action中怎麼向頁面傳值~

在action中依然可以像以前在servlet裡面一樣,使用requestsessionapplication向頁面傳送值,除此之外,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向頁面傳值就寫完了~

有什麼疑問的可以問我~