本文簡要的介紹類Struts2的Result結果配置、Servlet的API的訪問,以及模型驅動、屬性驅動基本使用示例。 ...
一.Result結果配置
1.全局和局部結果
平常我們設置跳轉頁面,是在action標簽裡面加上 result標簽來控制,這種設置的頁面跳轉,稱之為局部結果頁面但是我們有時候在很多個action裡面,針對不同的結果進行跳轉時,也有可能跳轉同一個頁面,那麼這個時候就可以配置全局結果頁面。
-
在action裡面寫上的result跳轉的頁面,稱之為局部結果頁面配置
<action name="demo01_*" class="com.pri.web.action.ActionDemo01" method="{1}"> <result name="error">/error.jsp</result> </action>
1.2全局結果
-
如果有多個action的結果跳轉的頁面是一樣的,那麼我們可以提取出來,做成全局結果頁面的配置. 全局頁面通過
package
標簽中配置global-results
標簽來定義<package name="test" extends="struts-default" namespace="/"> <global-results> <result name="error">/error.jsp</result> </global-results> .... </package>
優先順序: 局部>全局
1.3不同包裡面的全局結果的配置
<!--把全局的結果抽取到父包裡面 --> <package name="base" extends="struts-default" abstract="true"> <global-results> <!--全局的結果: 配置在package裡面的 特點:可以被當前包裡面所有的Action共用; 使用場景:不同的Action需要跳轉到相同的結果的時候eg: 錯誤頁面, msg頁面等 --> <result name="error">/msg.jsp</result> </global-results> </package> <package name="test" extends="base" namespace="/"> <action name="demo01_fun01" class="com.pri.web.ActionDemo01" method="fun01"> </action> <action name="demo02_fun02" class="com.pri.web.ActionDemo02" method="fun02"> </action> </package>
2.結果的類型【常用】
根據前面學的servlet知識,我們知道伺服器響應給瀏覽器的時候,有三種類型:response響應JSON數據&請求轉發 & 重定向。 對於Struts2而言,無非就是Action跳轉(轉發重定向)到頁面,Action跳轉到Action....
文檔位置 docs/docs/result-types.html
2.1Action跳轉頁面
-
轉發(預設)
<result name="success" type="dispatcher">/index.jsp</result>
- 重定向
<result name="success" type="redirect">/index.jsp</result>
2.2Action跳轉Action
-
轉發
<action name="demo01_*" class="com.pri.web.action.ActionDemo01" method="{1}"> <result name="success" type="chain">demo02_fun02</result> </action> <action name="demo02_*" class="com.pri.web.action.ActionDemo02" method="{1}"> </action>
-
重定向
<action name="demo01_*" class="com.pri.web.action.ActionDemo01" method="{1}"> <result name="success" type="redirectAction">demo02_fun02</result> </action> <action name="demo02_*" class="com.pri.web.action.ActionDemo02" method="{1}"> </action>
2.3其它的結果
一般來說,我們平常的請求到來,我們要不就是跳轉到 頁面上 ,要不就是跳轉到下一個action 去。 但是除了這兩種結果之外,我們仍然還有一些其他結果類型可以控制.
比如: 我們可以返回一個文件數據給客戶端 (比如文件下載).再比如: 我們可以返回一個json字元串給來請求的頁面,而不是重新打開新的頁面 (有點像之前的Ajax請求,返回json數據)
2.3.1響應JSON數據【瞭解】
-
導入struts-json-plugin-xxx.jar
-
Java代碼
-
1 public class ActionDemo01 extends ActionSupport { 2 private User json; 3 4 public User getJson() { 5 return json; 6 } 7 8 public String fun01(){ 9 json = new User(); 10 json.setName("張三"); 11 json.setAge(18); 12 json.setPassword("123456"); 13 14 return "success"; 15 } 16 }
-
-
配置文件
-
<struts> <package name="test" extends="json-default" namespace="/"> <action name="demo01" class="com.pri.web.action.ActionDemo01" method="fun01"> <result name="success" type="json"> <param name="root">json</param> <!--這裡的name必須是root 至於這個json 是我們在action裡面的成員 變數 json(屬性) --> </result> </action> </package> </struts>
-
註意:
-
- root:配置對象。action類中必須提供一個和root值相同的屬性名稱,且需要提供getter方法。
- package需要繼承json-default
- result的type值是json
2.3.2響應流(文件下載)【瞭解】
-
Action裡面的代碼
-
1 public class ActionDemo01 extends ActionSupport { 2 private InputStream stream; 3 4 public void setStream(InputStream stream) { 5 this.stream = stream; 6 } 7 public InputStream getStream() { 8 return stream; 9 } 10 public String fun01() throws Exception{ 11 System.out.println("demo01 執行了..."); 12 stream = new FileInputStream("E:/data/Desktop/a.jpg"); 13 14 return "success"; 15 } 16 }
-
配置文件
<struts> <package name="test" extends="struts-default" namespace="/"> <action name="demo01" class="com.pri.web.action.ActionDemo01" method="fun01"> <result name="success" type="stream"> <param name="contentType">image/jpeg</param> <param name="inputName">stream</param> <param name="contentDisposition">attachment;filename="b.jpg"</param> <param name="bufferSize">1024</param> </result> </action> </package> </struts>
註意:
- contentType:下載文件類型
- contentDisposition:下載到客戶端時,客戶端文件名稱
- bufferSize:讀文件的緩存大小
- inputName:對應要輸出到客戶端流聲明的名稱,也就是說需要和Action裡面聲明的變數名要一致
二、Struts2中的Servlet的API的訪問
客戶端與服務端交互時,通常會帶參數過來,伺服器也會回寫數據給客戶端。在此過程中,參與著請求,和響應,以及會話。servlet在此過程中提供了HttpServletRequest作為獲取請求數據的方案,HttpServletResponse作為響應的方案,HttpSession負責了會話方案。Struts其實是基於servlet實現的web框架,他需要遵循規則提供請求,響應和會話的API供開發人員使用,因此Struts針對這一問題提供了自己的一套API封裝,提供了多種方式的訪問。
1.ActionContext
1.1概述
ActionContext是Action的上下文,Struts2自動在其中保存了一些在Action執行過程中所需的對象,比如session, parameters等。Struts2會根據每個執行HTTP請求的線程來創建對應的ActionContext,即一個線程有一個唯一的ActionContext。
1.2使用
-
獲得(創建)ActionContext
ActionContext context = ActionContext.getContext();
-
獲得請求參數
Map<String, Object> parameters = context.getParamters();
相當於Servlet中的request.getParamters()方法,只能獲得所有的請求參數
2.ServletActionContext
2.1概述
ServletActionContext繼承ActionContext,因此比ActionContext功能要強大。ServletActionContext提供了多個靜態方法。
2.2使用
-
獲得Request對象
HttpServletRequest request = ServletActionContext.getRequest();
-
獲得Response對象
HttpServletResponse response = ServletActionContext.getResponse();
-
獲得ServletContext
ServletContext servletContext = ServletActionContext.getServletContext();
3.實現介面的方式
- 編寫Action,讓Action使用實現特定的介面的方式訪問Servlet的API,有如下介面可以實現
- ServletContextAware
- ServletRequestAware
- ServletResponseAware
- SessionAware
- ApplicationAware
-
Eg:
-
1 public class ActionDemo03 extends ActionSupport implements ServletRequestAware { 2 private HttpServletRequest request; 3 public String fun03() throws IOException{ 4 HttpServletRequest request = ServletActionContext.getRequest(); 5 String username = request.getParameter("username"); 6 String password = request.getParameter("password"); 7 System.out.println(username+":"+password); 8 return NONE; 9 } 10 11 @Override 12 public void setServletRequest(HttpServletRequest request) { 13 this.request = request; 14 } 15 }
三、獲得請求參數
1.獲得零散數據
1.1使用上面介紹的Struts2中的Servlet的API獲取
-
ActionContext
//1.創建ActionContext對象 ActionContext context = ActionContext.getContext(); //2.獲得所有的請求參數 Map<String, Object> parameters = context.getParamters();
-
ServletActionContext
//1.獲得request對象 HttpServletRequest request = ServletActionContext.getRequest(); requet.getParameter(String key); requet.getParameterValues(String key); requet.getParameterMap();
1.2屬性驅動【常用】
-
頁面
<h1>01使用屬性驅動</h1> <form method="post" action="${pageContext.request.contextPath }/demo01"> 用戶名:<input type="text" name="username"/><br/> 密 碼:<input type="password" name="password"/><br/> <input type="submit"/> </form>
-
Action.java
public class ActionDemo01 extends ActionSupport { private String username;//和表單裡面的name屬性值要一致,並且提供set方法 private String password;//和表單裡面的name屬性值要一致,並且提供set方法 public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public String fun01(){ System.out.println(username+":"+password); return NONE; } }
2.獲得封裝後的數據(對象)
2.1屬性驅動
-
頁面
<h1>01使用屬性驅動方式</h1> <form method="post" action="${pageContext.request.contextPath }/demo01"> 用戶名:<input type="text" name="user.username"/><br/> 密 碼:<input type="password" name="user.password"/><br/> <input type="submit"/> </form>
-
Action.java
-
1 public class ActionDemo01 extends ActionSupport { 2 //1. User類裡面的欄位屬性需要和表單裡面的name屬性一致, 且提供無參構造 3 //2. user需要set和get方法 4 private User user; 5 public User getUser() { 6 return user; 7 } 8 public void setUser(User user) { 9 this.user = user; 10 } 11 12 public String fun01(){ 13 System.out.println(user.toString()); 14 return NONE; 15 } 16 }
2.2模型驅動【常用】
-
頁面
<h1>02使用模型驅動方式</h1> <form method="post" action="${pageContext.request.contextPath }/demo02"> 用戶名:<input type="text" name="username"/><br/> 密 碼:<input type="password" name="password"/><br/> <input type="submit"/> </form>
Action.java
1 public class ActionDemo02 extends ActionSupport implements ModelDriven<User> { 2 3 private User user; 4 5 public String fun02(){ 6 System.out.println(user.toString()); 7 return NONE; 8 } 9 @Override 10 public User getModel() { 11 if(user == null){ 12 user = new User(); 13 } 14 return user; 15 } 16 }
結論:我們在實際開發裡面,
- 如果要獲得單個(零散)的數據,我們通常用屬性驅動
- 如果要獲得封裝後的數據, 我們通常用模型驅動
2.3封裝到集合
封裝到集合,一般我們會在批量添加 、批量更新場景下見到。也就是說頁面上同一個請求,這時候提交過來多份數據,如果我們是批量添加用戶的話,可能會提交過來多個用戶,那麼這個時候,我們就需要把他們封裝到List集合或者Map集合中去。 刨去批量操作、我們比較少用這種封裝到集合的知識點。
2.3.1封裝到list
-
頁面
<h1>01封裝到list</h1> <form method="post" action="${pageContext.request.contextPath }/demo01"> 用戶名:<input type="text" name="list[0].username"/><br/> 密 碼:<input type="password" name="list[0].password"/><br/> 用戶名:<input type="text" name="list[1].username"/><br/> 密 碼:<input type="password" name="list[1].password"/><br/> <input type="submit"/> </form>
-
Action.java
public class ActionDemo01 extends ActionSupport { private List<User> list; public List<User> getList() { return list; } public void setList(List<User> list) { this.list = list; } public String fun01(){ System.out.println(list.toString()); return NONE; } }
2.3.2封裝到Map
-
頁面
<h1>02封裝到map</h1> <form method="post" action="${pageContext.request.contextPath }/demo02"> 用戶名:<input type="text" name="map['user1'].username"/><br/> 密 碼:<input type="password" name="map['user1'].password"/><br/> 用戶名:<input type="text" name="map['user2'].username"/><br/> 密 碼:<input type="password" name="map['user2'].password"/><br/> <input type="submit"/> </form>
-
Action.java
-
public class ActionDemo02 extends ActionSupport { private Map<String, User> map; public Map<String, User> getMap() { return map; } public void setMap(Map<String, User> map) { this.map = map; } public String fun02(){ Set<Entry<String, User>> entrySet = map.entrySet(); for (Entry<String, User> entry : entrySet) { System.out.println(entry.getKey()+":"+entry.getValue().toString()); } return NONE; }