(三)struts2進階之實現Action
Action是Struts2應用的核心,用於處理使用者的請求,因此Action也被稱為業務控制器。每個Action都是一個工作單元,而Struts2框架則負責將使用者的請求與相應的Action匹配。匹配成功則使用相應的Action處理使用者的請求,匹配的規則在struts.xml中進行設定。
實現Action有三種方式:
1.普通的POJO類,該類包含一個無引數的execute()方法,返回值為String。
2.實現Action介面。
3.繼承ActionSupport類。
1.POJO實現方式
在(一)Struts2實現第一個案例這篇文章裡,寫的那個UserAction就是POJO的實現方式,這裡就不再說了,以後文章儘量精簡一點,不然看著疲憊,寫的也累。
執行tomcat,開啟網頁輸入賬戶名密碼地址後,點選提交,結果如下
2.實現Action介面方式
Action介面的定義如下
public interface Action {
public static final String SUCCESS = "success";
public static final String NONE = "none";
public static final String ERROR = "error";
public static final String INPUT = "input";
public static final String LOGIN = "login";
public String execute() throws Exception;
}
通過實現Action介面,我們就可以使用裡面的常量值作為execute()方法的返回值。
package com.codeliu.action;
import com.opensymphony.xwork2.Action;
/**
* 通過實現Action介面來建立一個action
* @author liu
*/
public class LoginAction2 implements Action {
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;
}
@Override
public String execute() throws Exception {
if("admin".equals(username) && "admin".equals(password)) {
// Action介面中的靜態常量,返回成功介面
return SUCCESS;
} else {
// 返回失敗介面
return ERROR;
}
}
}
在struts.xml中增加一個Action,同時修改表單的action
<!-- 通過實現Action介面來實現一個action -->
<action name="login2" class="com.codeliu.action.LoginAction2">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
執行結果和上面一樣。
3.繼承ActionSupport類方式
ActionSupport是Struts2預設的Action處理類,如果在struts.xml中配置Action時,省略了class屬性,則預設呼叫ActionSupport類對作為Action的處理類,對使用者的請求進行處理。編寫Action時繼承ActionSupport類能簡化Action的開發,提高效率。
/**
* 通過繼承ActionSupport來實現一個action
* @author liu
*/
@SuppressWarnings("serial")
public class LoginAction3 extends ActionSupport {
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;
}
@Override
public String execute() throws Exception {
System.out.println("使用者名稱:" + username);
System.out.println("密碼:" + password);
if("admin".equals(username) && "admin".equals(password)) {
return SUCCESS;
} else {
return ERROR;
}
}
@Override
/**
* 重寫validate方法,可以在execute方法執行之前執行,對使用者輸入的資料進行驗證
*/
public void validate() {
if(username == null || "".equals(username)) {
// 將錯誤資訊寫到ActionSupport類的FieldErrors中,此時Struts2框架自動返回input頁面
this.addFieldError(username, "使用者名稱不能為空");
System.out.println("使用者名稱為空");
}
if(password == null || password.length() < 6) {
this.addFieldError(password, "密碼不能為空且長度要大於6");
System.out.println("密碼為空或長度小於6");
}
}
}
在上面的程式碼中,我們重寫了ActionSupport類中的validate方法,該方法是在execute方法之前執行的,可以對使用者輸入的資料進行一些合法性的判斷,如果不符合要求,則會自動跳轉到輸入頁面。
其實Struts2有完整的驗證框架,可以通過配置檔案的方式對需要驗證的內容進行配置,更加靈活,便於維護,這會在後面系列文章中講到。
同樣在struts.xml中增加一條一個Action,同時修改表單的action
<!-- 通過繼承ActionSupport類來實現一個action -->
<action name="login3" class="com.codeliu.action.LoginAction3">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
<result name="input">/index.jsp</result>
</action>
我們新增了一條result,對應的是validate方法,如果不符合要求,則跳轉到index.jsp。
執行後如果輸入符合要求,則結果和上面的一樣,如果不符合要求,比如密碼為空,則會在控制檯列印輸出密碼為空或長度小於6,同時介面跳轉到index.jsp。
4.通過ActionContext類間接獲取Servlet API
Struts2相比於Struts1一個很大的不同是Action進行了解耦,提高了程式碼的複用率,但如果我們要獲取Servlet API,還是得通過Struts2提供的一些類。比如ActionContext類。
ActionContext類提供了一些方法讀寫Servlet中HttpServletRequest、HttpSession和ServletContext中的資料,常用方法如下
方法 | 功能描述 |
---|---|
Object get(Object key) | 獲取屬性值,與HttpServletRequest的getAttribute(String name)方法類似 |
Map getApplication() | 返回一個物件,該物件模擬了web應用物件的ServletContext物件 |
static ActionContext getContext() | 靜態方法,用於獲取系統的ActionContext物件 |
Map getParameters() | 獲取所有的請求引數,類似於呼叫HttpServletRequest的getParameterMap()方法 |
Map getSession() | 返回一個Map物件,該物件模擬了HttpSession例項 |
void setApplication(Map application) | 直接傳入一個Map物件,將該Map物件中的鍵/值對轉換成application的屬性值和屬性名 |
void setSession(Map session) | 直接傳入一個Map物件,將該物件裡的鍵/值對轉成session的屬性名和屬性值 |
下面看看程式碼
@SuppressWarnings("serial")
public class ClickNumAction extends ActionSupport {
@Override
public String execute() throws Exception {
// 獲取一個ActionContext例項物件
ActionContext act = ActionContext.getContext();
// 獲取application中num的值
Integer num = (Integer)act.getApplication().get("num");
// 第一次獲取時為null
if(num == null) {
num = 1;
} else {
num++;
}
// 設定的num的值
act.getApplication().put("num", num);
return SUCCESS;
}
}
上面通過ActionContext的靜態方法getContext()獲取一個ActionContext例項,然後通過getApplication()方法獲取ServletContext對應的Map物件,呼叫put/get方法進行資料的讀寫操作。
再寫一個clickNum.jsp來看看效果
<body>
<form action="click.action" method="post">
<input type = "submit" value="click">
</form>
<!-- 通過EL表示式獲取applicationScope中的num值 -->
點選按鈕
${empty applicationScope.num ? 0:applicationScope.num}次
</body>
記得在struts.xml中增加一個Action的配置
<!-- 通過ActionContext類獲取Servlet API -->
<action name="click" class="com.codeliu.action.ClickNumAction">
<result name="success">/clickNum.jsp</result>
</action>
啟動tomcat執行後,效果如下
5.通過某些介面直接獲取Servlet API
雖然通過ActionContext類能獲取,但畢竟不是直接獲取,好多方法我們還是不能用,侷限性太大,Struts2還提供了其他一系列的介面來直接獲取Servlet API
介面名 | 描述 |
---|---|
ServletContextAware | 實現該介面的Action可以直接訪問Web應用的ServletContext例項 |
ServletRequestAware | 實現該介面的Action可以直接訪問Web應用的HttpServletRequest例項 |
ServletResponseAware | 實現該介面的Action可以直接訪問Web應用的HttpServletResponse例項 |
以ServletRequestAware為例,原始碼如下
public interface ServletRequestAware {
public void setServletRequest(HttpServletRequest request);
}
裡面只有一個方法,實現該介面的同時實現這個方法就能獲取HttpServletRequest 例項。程式碼如下
public class LoginAction4 extends ActionSupport implements ServletRequestAware {
private HttpServletRequest request;
@Override
/**
* 重寫ServletRequestAware介面中的方法,獲取HttpServletRequest例項
*/
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public String execute() throws Exception {
if("admin".equals(username) && "admin".equals(password)) {
// 獲取session物件
HttpSession session = request.getSession();
session.setAttribute("username", username);
return SUCCESS;
} else {
return ERROR;
}
}
}
上面都是些重複的程式碼,我就刪了,只留了些主要的,可以通過直接建立一個HttpServletRequest 的變數,然後傳給setServletRequest方法就可以獲取到HttpServletRequest的例項,之後就可以使用它的所有功能。
可以去struts.xml新增一條Action的配置,試一試,我就不試了。
ServletContextAware、ServletResponseAware和ServletRequestAware的使用方法基本一致。
除此之外,Struts2還提供了一個ServletActionContext工具類,裡面有一些靜態方法。
方法 | 描述 |
---|---|
static PageContext getPageContext() | 獲取web應用的pageContext物件 |
static HttpServletRequest getRequest() | 獲取web應用的HttpServletRequest 物件 |
static HttpServletResponse getResponse() | 獲取web應用的HttpServletResponse 物件 |
static ServletContext getServletContext() | 獲取web應用的ServletContext 物件 |
總結:因為Struts2的特點就是Action不與任何Servlet API耦合,所以我們推薦使用ActionContext來間接獲取Servlet API,也可以使用ServletActionContext工具類,以更簡單的方式獲取Servlet API。
相關文章
- Struts2教程之三Action訪問方式
- Vue 進階系列(三)之Render函式原理及實現Vue函式
- 007--在Struts2的Action中訪問Servlet API三種形式ServletAPI
- JAVAEE框架學習——Struts2——Action API 使用Java框架API
- 【Flutter】開發之進階Widget(三)Flutter
- Struts2中Action動態呼叫DMI出現的一個問題
- Struts2教程之二Action建立方式
- Struts2 action前的資料預處理
- Redux 進階 — 優雅的處理 async actionRedux
- Redux 進階 -- 優雅的處理 async actionRedux
- 【Android進階】RecyclerView之繪製流程(三)AndroidView
- Python爬蟲進階之APP逆向(三)Python爬蟲APP
- 05. struts2中為Action屬性注入值
- Vue 進階系列(一)之響應式原理及實現Vue
- 高階前端進階(三)前端
- python實現三階魔方還原Python
- React 進階(三) 高階元件React元件
- Docker進階與實踐之七:LibcontainerDockerAI
- Docker進階與實踐之三:Docker映象Docker
- React 進階之路(三)React
- Android進階5:SurfaceView實現原理分析AndroidView
- 利用Github Action實現Tornadofx/JavaFx打包GithubJava
- Django 進階之 celeryDjango
- 前端進階之困前端
- javascript 進階之 - PromiseJavaScriptPromise
- 【狂神說】Docker(三) - 高階進階Docker
- Struts2在web.xml中配置為“/*”和“*.action,*.jsp”的差別WebXMLJS
- 【譯】JavaScript進階 從實現理解閉包JavaScript
- Python 實現郵件傳送功能(進階)Python
- Promise進階——如何實現一個Promise庫Promise
- Python進階:自定義物件實現切片功能Python物件
- javascript實現放大鏡外掛【含進階】JavaScript
- Docker進階與實踐之六:容器卷管理Docker
- struts2總結(三)--官網下載struts2的jar包JAR
- 【進階4-3期】面試題之如何實現一個深拷貝面試題
- 高階前端的進階——CSS之flex前端CSSFlex
- Vue 進階系列(二)之外掛原理及實現Vue
- HR系統助力企業實現管理進階