Struts2第四篇【請求資料自動封裝、Action得到域物件】
前言
前三篇的Struts博文基本把Struts的配置資訊講解完了…..本博文主要講解Struts對資料的處理
一般地,我們使用Servlet的時候都是分為幾個步驟的:
- 得到web層的資料、封裝資料
- 呼叫service層的邏輯業務程式碼
- 將資料儲存在域物件中,跳轉到對應的JSP頁面
現在問題來了,我們自己編寫的Action類是沒有request、response、Session、application之類的物件的….我們是怎麼得到web層的資料、再將資料存到域物件中的呢??
請求資料封裝
前面已經說過了,Struts預先幫我們完成了對資料封裝的功能,它是通過params攔截器來實現資料封裝的
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
register.jsp
首先,我們填寫表單頁面的資料,請求Action處理資料
<form action="${pageContext.request.contextPath}/date01" method="post">
使用者名稱:<input type="text" name="username"><br>
密碼:<input type="text" name="psd"><br>
年齡:<input type="text" name="age"><br>
生日:<input type="text" name="birthday"><br>
<input type="submit" value="註冊"><br>
</form>
Action封裝基本資訊
在Action設定與JSP頁面相同的屬性,併為它們編寫setter方法
private String username;
private String psd;
private int age;
private Date birthday;
public void setUsername(String username) {
this.username = username;
}
public void setPsd(String psd) {
this.psd = psd;
}
public void setAge(int age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
我們直接在業務方法中訪問這些變數,看是否能得到表單的值。
Action封裝物件
一般地,我們註冊的時候,都是在Servlet上把基本資訊封裝到物件上…那麼在Struts怎麼做呢?
- 建立一個User類,基本的資訊和JSP頁面是相同的。
package qwer;
import java.util.Date;
/**
* Created by ozc on 2017/4/27.
*/
public class User {
private String username;
private String psd;
private int age;
private Date birthday;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPsd() {
return psd;
}
public void setPsd(String psd) {
this.psd = psd;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
- 在Action中定義User物件出來,並給出setter和getter方法….值得注意的是:基本資訊只要setter就夠了,封裝到物件的話,需要setter和getter
public class ccAction extends ActionSupport {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String register() {
System.out.println(user.getUsername());
System.out.println(user.getPsd());
System.out.println(user.getAge());
System.out.println(user.getBirthday());
return "success";
}
}
- 在JSP頁面,提交的name要寫成
user.username
之類的
<form action="${pageContext.request.contextPath}/register" method="post">
使用者名稱:<input type="text" name="user.username"><br>
密碼:<input type="text" name="user.psd"><br>
年齡:<input type="text" name="user.age"><br>
生日:<input type="text" name="user.birthday"><br>
<input type="submit" value="註冊"><br>
</form>
得到域物件
Struts怎麼把資料儲存在域物件中呢???Struts提供了三種方式
一、得到Servlet API
我們可以通過ServletActionContext得到Servlet API
由於每個使用者擁有一個Action物件,那麼底層為了維護使用者拿到的是當前執行緒的request等物件,使用ThreadLocal來維護當前執行緒下的request、response等物件…
//通過ServletActionContext得到Servlet API
javax.servlet.ServletContext context = ServletActionContext.getServletContext();
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
HttpServletResponse response = ServletActionContext.getResponse();
二、ActionContext類
我們還可以通過ActionContext類來得到request、response、session、application被Struts封裝的Map集合
//得到ActionContext 物件
ActionContext context = ActionContext.getContext();
Map<String, Object> session = context.getSession();
Map<String, Object> application = context.getApplication();
//這是request的Map
Map<String, Object> request = context.getContextMap();
三、實現介面
當web容器發現該Action實現了Aware介面,會把相對應的資源通過Aware介面注射進去,實際上就是一種IOC。
Aware實際就是一種攔截器,攔截程式碼在執行Action之前執行、將資源注射到Action中
實現SessionAware, RequestAware, ApplicationAware介面,它就要在程式中實現三個方法:
private Map<String, Object> request;
private Map<String, Object> session;
private Map<String, Object> application;
@Override
public void setApplication(Map<String, Object> map) {
this.application = map;
}
@Override
public void setRequest(Map<String, Object> map) {
this.request = map;
}
@Override
public void setSession(Map<String, Object> map) {
this.session = map;
}
通過這些方法,我們就可以得到對應的Map物件…..
小總結
那麼,我們有三種方法可以得到Servlet對應的物件,那麼該使用哪一種呢???
分析:
- 第一種方法:需要匯入Servlet的包,與Struts耦合了
- 第二種方法:只能在業務方法中使用ActionContext類得到對應的Map物件,如果有多個方法,那麼每個方法都需要寫類似的程式碼
- 第三種方法:可以在類上定義成員變數,以至於整個類都能使用。但是需要實現類、實現對應的方法
如果我們需要使用到物件的其他方法,類似getContextPath()之類的,那麼只能使用第一種
如果我們就按照平常的開發,我們就使用第二種【獲取簡單,沒有耦合】
至於第三種,當我們將來可能開發BaseAction的時候,就使用它!