jsp和struts action的交互

一、jsp向action傳值,jsp發送的方法

1、form表單提交的方法

<form action="login" method="post"name="form1">
 

用戶名:<s:textfieldname="username"/><br/>
   密 碼:<s:passwordname="password"/><br/>
              <s:submit value="提交"/>
  </form>
2、href方法

<a href = "messageDelete.action?id=<%=msg.getId()%>">刪除</a>


二、jsp向action傳值,action接受的方法


1.在Action類中定義表單屬性,兩者屬性名稱必須一致。提供setter,getter方法。即可接收到表單傳過來的參數.

        private String username;
private String password;


public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}

2.把表單傳遞過來的參數封裝成一個類,然後調用其中的屬性.

如,把login.jsp頁面要傳來的參數進行封裝(例如:封裝於Users 類)

private String username;
private String password;

public String getUsername() {
  return username;
}
public void setUsername(String username) {
  this.username = username;
}
public String getPassword() {
  return password;
}
public void setPassword(String password) {
  this.password = password;
}

然後再Action方法中,定義該類的對象就可以了,如

public class loginAction extends ActionSupport{
private Users users;
public Users getUsers(){
return users;
}
public void setUsers(Users users){
this.users=users;
}
}

通過這種方法傳值,還必須在jsp頁面做一下處理,login.jsp中from1的屬性名應該改成這樣:

登陸表單login.jsp:

<form action="login" method="post"name="form1">
  用戶名:<s:textfieldname="users.username"/><br/>
   密 碼:<s:passwordname="users.password"/><br/>
              <s:submit value="提交"/>
  </form>

這種方法,在struts開發中是很常用的一種方法!

3.通過實現ModelDriven接口接收表單數據


首先Action類必須實現ModelDriven接口,同樣把表單傳來的數據封裝起來,Action類中必須實例化該對象,並且要重寫getModel()方法
public class loginAction extends ActionSupport implementsModelDriven<Users>{
private Users users =new Users();
public Users getModel(){
return users;
}
}
三、action傳回jsp,jsp接受方法
1、在Action中通過調用session或者request對象的setAttirbute方法就可以了,然後jsp裏去取。
           在action的java源文件中這麼寫
                ActionContext ac = ActionContext.getContext();
Map session = ac.getSession();
session.put("currentUser", user);
           在jsp頁面中就可以通過session訪問到user
                User user = (User)session.getAttribute("currentUser");
2、OGNL(轉自http://struts2.group.iteye.com/group/wiki/1356-how-to-use-ognl-in-struts2)
OGNL是XWork引入的一個非常有效的數據處理的工具。我們已經瞭解了OGNL的基本操作和OGNL的內部結構,接下來,我們來看看XWork對OGNL做了什麼樣的加強,以及OGNL的體系在Struts2中如何運轉。

從例子開始 Top

我們先從一個例子開始,看看數據在Struts2中是如何運轉的。 

Java代碼  收藏代碼
  1. /** 
  2.  * @author Downpour 
  3.  */  
  4. public class User {  
  5.       
  6.     private Integer id;  
  7.       
  8.     private String name;  
  9.       
  10.     private Department department = new Department();  
  11.       
  12.         // setter and getters  
  13. }  
  14.   
  15. //=========================================================================  
  16.   
  17. /** 
  18.  * @author Downpour 
  19.  */  
  20. public class Department {  
  21.       
  22.     private Integer id;  
  23.       
  24.     private String name;  
  25.           
  26.         // setter and getters  
  27. }  
  28.   
  29. //=========================================================================  
  30.   
  31. <form method="post" action="/struts-example/ognl.action">  
  32.     user name: <input type="text" name="user.name" value="downpour" />  
  33.     department name: <input type="text" name="department.name" value="dev" />  
  34.     <input type="submit" value="submit" />  
  35. </form>  
  36.   
  37. //=========================================================================  
  38.   
  39. /** 
  40.  * @author Downpour 
  41.  */  
  42. public class OgnlAction extends ActionSupport {  
  43.   
  44.     private static final Log logger = LogFactory.getLog(OgnlAction.class);  
  45.   
  46.     private User user;  
  47.       
  48.     private Department department;  
  49.       
  50.     /* (non-Javadoc) 
  51.      * @see com.opensymphony.xwork2.ActionSupport#execute() 
  52.      */  
  53.     @Override  
  54.     public String execute() throws Exception {  
  55.         logger.info("user name:" + user.getName());   // -> downpour  
  56.         logger.info("department name:" + department.getName());   // -> dev  
  57.         return super.execute();  
  58.     }  
  59.   
  60.     // setter and getters  
  61. }  
  62.   
  63. //=========================================================================  
  64.   
  65. user name: <s:property value="user.name" />  
  66. department name: <s:property value="department.name" />  
  67.   
  68. //=========================================================================  


我們可以看到在JSP中,form中的元素input等,都使用OGNL的表達式作爲name的值。而在form提交時,這些值都會被設置到Action中的Java對象中。而當Action轉向到JSP時,Struts2的Tag又可以從Action的Java對象中,通過OGNL進行取值。 

在這裏,你看不到任何的OGNL的代碼級別操作,因爲這些都在Struts2內部進行了封裝。而這些封裝,都是建立在OGNL的基本概念,也就是根對象和上下文環境之上。下面就分別就這兩個方面分別進行講解。

Struts2中使用OGNL進行計算 Top

取值計算 

有了上面的這些知識,我們就能非常容易的理解在Struts2中如何使用OGNL進行取值計算。 

提問:在Struts2中,如何使用自身的Tag讀取Action中的變量? 

Struts2自身的Tag會根據value中的OGNL表達式,在ValueStack中尋找相應的對象。因爲action在ValueStack的頂部,所以默認情況下,Struts2的Tag中的OGNL表達式將查找action中的變量。請注意,value中的內容直接是OGNL表達式,無需任何el的標籤包裝。 

例如:<s:property value="user.name" /> 

提問:在Struts2中,如何使用自身的Tag讀取HttpServletRequest,HttpSession中的變量? 

在上面的知識中,我們知道,Struts2中OGNL的上下文環境中,包含request,session,application等servlet對象的Map封裝。既然這些對象都在OGNL的上下文中,那麼根據OGNL的基本知識,我們可以通過在表達式前面加上#符號來對這些變量的值進行訪問。 

例如:<s:property value="%{#application.myApplicationAttribute}" /> 
<s:property value="%{#session.mySessionAttribute}" /> 
<s:property value="%{#request.myRequestAttribute}" /> 
<s:property value="%{#parameters.myParameter}" /> 

在這裏囉嗦一句,在Tag的value中包括%{開頭和}結尾的字符串,不知道Struts2爲什麼要做出這樣的設置,從源碼上看,它似乎沒有什麼特別額外的作用: 
Java代碼  收藏代碼
  1. if (value == null) {  
  2.             value = "top";  
  3.         }  
  4.         else if (altSyntax()) {  
  5.             // the same logic as with findValue(String)  
  6.             // if value start with %{ and end with }, just cut it off!  
  7.             if (value.startsWith("%{") && value.endsWith("}")) {  
  8.                 value = value.substring(2, value.length() - 1);  
  9.             }  
  10.         }  
  11.   
  12.         // exception: don't call findString(), since we don't want the  
  13.         //            expression parsed in this one case. it really  
  14.         //            doesn't make sense, in fact.  
  15.         actualValue = (String) getStack().findValue(value, String.class);  
  16.           
  17.         ......  
  18.   
  19. }  


有興趣的朋友可以研究一下,這一對符號的原理究竟是什麼。 

提問:在Struts2中,如何使用JSTL來讀取Action中的變量? 

這是一個歷史悠久的問題。因爲事實上,很多朋友(包括我在內)是不使用Struts2自身的標籤庫,而是使用JSTL的,可能因爲JSTL標籤庫比較少,簡單易用的原因吧。 

我們知道,JSTL默認是從page,request,session,application這四個Scope逐次查找相應的EL表達式所對應的對象的值。那麼如果要使用JSTL來讀取Action中的變量,就需要把Action中的變量,放到request域中才行。所以,早在Webwork2.1.X的年代,我們會編寫一個攔截器來做這個事情的。大致的原理是:在Action執行完返回之前,依次讀取Action中的所有的變量,並依次調用request.setAttribute()來進行設置。具體的整合方式,請參考以下這篇文檔:http://wiki.opensymphony.com/display/WW/Using+WebWork+and+XWork+with+JSP+2.0+and+JSTL+1.1 

不過隨着時代的發展,上面的這種方式,已經不再被推薦使用了。(雖然如此,我們依然可以學習它的一個解決問題的思路)目前來說,自從Webwork2.2以後,包括Struts2,都使用另外一種整合方式:對HttpServletRequest進行裝飾。讓我們來看一下源碼: 

Java代碼  收藏代碼
  1. public class StrutsRequestWrapper extends HttpServletRequestWrapper {  
  2.   
  3.     /** 
  4.      * The constructor 
  5.      * @param req The request 
  6.      */  
  7.     public StrutsRequestWrapper(HttpServletRequest req) {  
  8.         super(req);  
  9.     }  
  10.   
  11.     /** 
  12.      * Gets the object, looking in the value stack if not found 
  13.      * 
  14.      * @param s The attribute key 
  15.      */  
  16.     public Object getAttribute(String s) {  
  17.         if (s != null && s.startsWith("javax.servlet")) {  
  18.             // don't bother with the standard javax.servlet attributes, we can short-circuit this  
  19.             // see WW-953 and the forums post linked in that issue for more info  
  20.             return super.getAttribute(s);  
  21.         }  
  22.   
  23.         ActionContext ctx = ActionContext.getContext();  
  24.         Object attribute = super.getAttribute(s);  
  25.   
  26.         boolean alreadyIn = false;  
  27.         Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");  
  28.         if (b != null) {  
  29.             alreadyIn = b.booleanValue();  
  30.         }  
  31.   
  32.         // note: we don't let # come through or else a request for  
  33.         // #attr.foo or #request.foo could cause an endless loop  
  34.         if (!alreadyIn && attribute == null && s.indexOf("#") == -1) {  
  35.             try {  
  36.                 // If not found, then try the ValueStack  
  37.                 ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);  
  38.                 ValueStack stack = ctx.getValueStack();  
  39.                 if (stack != null) {  
  40.                     attribute = stack.findValue(s);  
  41.                 }  
  42.             } finally {  
  43.                 ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);  
  44.             }  
  45.         }  
  46.         return attribute;  
  47.     }  
  48. }  


看到了嘛?這個類會在Struts2初始化的時候,替換HttpServletRequest,運行於整個Struts2的運行過程中,當我們試圖調用request.getAttribute()的時候,就會執行上面的這個方法。(這是一個典型的裝飾器模式)在執行上面的方法時,會首先調用HttpServletRequest中原本的request.getAttribute(),如果沒有找到,它會繼續到ValueStack中去查找,而action在ValueStack中,所以action中的變量通過OGNL表達式,就能找到對應的值了。 

在這裏,在el表達式廣泛使用的今天,JSTL1.1以後,也支持直接使用el表達式。注意與直接使用struts2的tag的區別,這裏需要使用el的表示符號:${} 

例如:${user.name}, <c:out value="${department.name}" /> 

提問:在Struts2中,如何使用Freemarker等模板來讀取Action中的變量以及HttpServletRequest和HttpSession中的變量? 

Freemarker等模板在Struts2中有對應的Result,而在這些Result中,Freemarker等模板會根據ValueStack和ActionContext中的內容,構造這些模板可識別的Model,從而使得模板可以以他們各自的語法對ValueStack和ActionContext中的內容進行讀取。 

有關Freemarker對於變量的讀取,可以參考Struts2的官方文檔,非常詳細:http://struts.apache.org/2.0.14/docs/freemarker.html 

設值計算 

Struts2中使用OGNL進行設值計算,就是指View層傳遞數據到Control層,並且能夠設置到相應的Java對象中。這個過程從邏輯上說需要分成兩步來完成: 

1. 對於每個請求,都建立一個與相應Action對應的ActionContext作爲OGNL的上下文環境和ValueStack,並且把Action壓入ValueStack 

2. 在請求進入Action代碼前,通過某種通用的機制,蒐集頁面上傳遞過來的參數,並調用OGNL相關的代碼,對Action進行設值。 

上面的第一個步驟,在處理URL請求時完成,而第二個步驟,則涉及到另外一個XWork的核心知識:攔截器。所以有關Struts2使用OGNL進行設值計算的詳細分析,將會在攔截器章節具體給出。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章