Posted on 2007-06-01 11:16
筱筱 閱讀(289)
評論(0) 編輯 收藏 所屬分類:
Struts學習日記
1.分析helloapp應用的需求
·接受用戶輸入的姓名<userName>,然后返回字符串"Hello<userName>!"。
·如果用戶沒有輸入姓名就提交表單,將返回出錯信息,提示用戶首先輸入姓名。
·如果用戶輸入姓名為"Monster",將返回出錯信息,拒絕向"Monster"打招呼。
2. 運用Struts框架
·模型包括一個JavaBean組件PersonBean,它有一個userName屬性,代表用戶輸入的名字。它提供了get/set方法,分別用于讀取和設置userName屬性,它還提供一個save()方法,負責把userName屬性保存到持久化存儲系統中,如數據庫或文件系統。對于更為復雜的Web應用,JavaBean組件可以作為EJB或Web服務的前端組件。
·視圖包括一個JSP文件hello.jsp,它提供用戶界面,接受用戶輸入的姓名。視圖還包括一個ActionForm Bean,它用來存放表單數據,并進行表單驗證,如果用戶沒有輸入姓名就提交表單,將返回出錯信息。
·控制器包括一個Action類HelloAction,它完成三項任務:1.進行業務邏輯驗證,如果用戶輸入的姓名為"Monster", 將返回錯誤消息;2.調用模型組件PersonBean的save()方法,保存用戶輸入的名字;3.決定將合適的視圖組件返回給用戶。
·除了創建模型、視圖和控制器組件,還需要創建Struts的配置文件struts-config.xml,它可以把這些組件組裝起來,使它們協調工作。此外,還需要創建整個Web應用的配置文件web.xml。
3.創建視圖組件
本例中,視圖包括兩個組件:
·一個JSP文件:hello.jsp
·一個ActionForm Bean: HelloForm Bean (HelloForm.java)。
其中,jsp中有代碼<html:bean action="/HelloWorld" focus="userName">
當用戶提交了HTML表單后,Struts框架將自動把表單數據組裝到ActionForm Bean中。ActionForm Bean中的屬性和HTML表單中的字段一一對應。ActionForm Bean還提供了數據驗證方法,以及把屬性重新設置為默認值的方法。Struts框架中定義的ActionForm類是抽象的,必須在應用中創建它的子類,來存放具體的HTML表單數據。
HelloForm.java中有兩個特殊的方法:
·validate():用于表單驗證。
·reset():把屬性重新設置為默認值。
本例中的資源文件是application.properties,用來存放數據信息。
4.創建控制器組件:HelloAction.java
控制器組件包括ActionServlet類和Action類。ActionServlet類是Struts框架自帶的,它是整個Struts框架的控制樞紐,通常不需要擴展。Struts框架提供了可供擴展的Action類,它用來處理特定的HTTP請求。
所有的Action類都是org.apache.struts.action.Action的子類,Action子類應該覆蓋父類的execute()方法。
HelloAction.java的代碼如下:
package hello;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;
import com.yourcompany.struts.PersonBean;
import com.yourcompany.struts.form.HelloForm;
/**
* @struts.action path="/hello" name="helloForm" input="/form/hello.jsp" scope="request" validate="true"
*/
public final class HelloAction extends Action {
/**
* Method execute
* @param mapping:ActionMapping包含了這個Action的配置信息和Struts-config.xml文件中的<action>元素對應。
* @param form:ActionForm包含了用戶的表單數據,當Struts框架調用execute()方法時,ActionForm中的數據
*已經通過了表單驗證。
* @param request:HttpServletRequest當前的HTTP請求對象
* @param response:HttpServletResponse當前的HTTP響應對象
* @return ActionForward
*/
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{
/* These "massage come from the ApplicationResources.properties file"
* getResources(HttpServletRequest request)方法返回當前默認的MessageResource對象,它封裝了Resource
*Bundle 中的文本內容。
* 接下來Action類就可以通過MessageResource對象來訪問文本內容。例如:如果要讀取消息key
*為"hello.jsp.title"對應的文本內容,可以調用MessageResources類的getMessage(String key)方法:
*String title=messages.getMessage("hello.jsp.title");
* MessageResources messages=getResources(request);
*/
/*
* Validate the request parameters specified by the user
* Note: Basic field validation done in HelloForm.java
* Business logic validation done in HelloAction.java
* 如果用戶輸入的姓名為"Monster",將創建包含錯誤信息的AcrionMessage對象,ActionMessage對象被保存
*到ActionMessages對象中。接下來調用在Action基類中定義的saveErrors()方法,它負責把ActionMessages
*對象保存到request范圍內。最后返回ActionForward對象,Struts框架會根據ActionForward對象包含的轉發
*信息把請求轉發到恰當的視圖組件,視圖組件通過<html:errors>標簽把request范圍內的ActionMessages對象
*中包含的錯誤消息顯示出來,提示用戶修改錯誤。
* */
ActionMessages errors=new ActionMessages();
String userName=(String)((HelloForm) form).getUserName();
String badUserName="Monster";
if(userName.equalsIgnoreCase(badUserName))
{
//equalsIgnoreCase方法同vequals,只不過equalsIgnoreCase 是忽略大小寫。
errors.add("username",new ActionMessage("hello.dont.talk.to.monster",badUserName));
saveErrors(request,errors);
return (new ActionForward(mapping.getInput()));
}
/*
* HelloAction類創建了一個模型組件PersonBean對象,并調用它的saveToPersistentStore()方法來保存userName
*屬性。
* from the View,we now update the model
*
* */
PersonBean pb=new PersonBean();
pb.setUserName(userName);
pb.saveToPersistentStore();
/*
* 把PersonBean對象保存在request范圍內內
* 從request范圍內刪除ActionForm Bean。由于后續的請求轉發目標組件不再需要HelloForm Bean,所以
*可將它刪除。當HelloAction類調用HttpServletRequest的setAttribute()方法,向hello.jsp傳遞PersonBean對象時,
*需要提供一個名為“persinbean”的屬性key:request..setAttribute("personbean",pb);
* hello.jsp通過這個名為"personbean"的屬性來讀取PersonBean對象:
* <login:present name="personbean" scope="request">
* <h2>Hello <bean:write name="personbean" property="userName"/>!</h2>
* </logic:persent>
* 對于Struts應用,提倡將這些屬性key常量定義在一個Java文件Constant.java中,例如本例。
* */
request.setAttribute(com.yourcompany.struts.Constants.PERSON_KEY,pb);
request.removeAttribute(mapping.getAttribute());
return (mapping.findForward("SayHello"));
}
}
5.創建模型組件
本例的模型組件是PersonBean.java,PersonBean是一個非常簡單的JavaBean,它包括一個userName屬性,以及相關的get/set方法。此外,它還有一個業務方法saveToPersistentStore()。
6. 創建存放常量的Java文件:Constant.java
7.創建配置文件web.xml和struts-config.xml
本例的運行流程為:
1.Servlet容器在web.xml文件中尋找<url-pattern>屬性為"*.do"的<servlet-mapping>元素:
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
2.Servlet容器依據以上<servlet-mapping>元素的<servlet-name>屬性"action",在web.xml文件中尋找匹配的<servlet>元素:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
3.Servlet容器把請求轉發給以上<servlet>元素指定的ActionServlet,ActionServlet依據用戶請求路徑"/HelloWorld",在Struts配置文件中檢索path屬性為"/HelloWorld"的Action元素:
<action
path="/HelloWorld"
type="hello.HelloAction"
name="HelloForm"
attribute="inputForm"
scope="request"
validate="true"
input="/hello.jsp"
>
<forward name="SayHello" path="/hello.jsp" />
</action>
4.ActionServlet根據<action>元素的name屬性,創建一個HelloForm對象,把客戶提交的表單數據傳給HelloForm對象,再把HelloForm對象保存在<action>元素的scope屬性指定的request范圍內。
5.由于<action>元素的validate屬性為true,ActionServlet調用HelloForm對象的validate()方法執行表單驗證。
·當文本框中不輸入姓名的時候,vallidate()方法返回一個ActionErrors對象。
ActionServlet把HelloForm的validate()方法返回的ActionErrors對象保存在request范圍內,然后根據<action>元素的input屬性,把客戶請求轉發給hello.jsp。
·當文本框中輸入姓名"Monster"的時候,vallidate()方法返回ActionErrors對象中不包含任何ActionMessage對象,表示表單驗證成功。
ActionServlet查找HelloAction實例是否存在,如果不存在就創建一個實例,然后調用HelloAction的execute()方法。
HelloAction的execute()方法先進行邏輯驗證,由于沒有通過邏輯驗證,就創建一個ActionMessage對象,這個ActionMessage對象封裝了錯誤消息,execute()方法把ActionMessage對象保存在ActionMessages對象中,再把ActionMessages對象存放在request范圍內。最后返回一個ActionForward對象,該對象包含的請求轉發路徑為<action>元素的input屬性指定的hello.jsp。
·當文本框中輸入其他姓名的時候,vallidate()方法返回ActionErrors對象中不包含任何ActionMessage對象,表示表單驗證成功。
HelloAction的execute()方法進行邏輯驗證,這次通過了驗證,然后執行相關的業務邏輯,最后調用ActionMapping.findForward()方法,參數為“SayHello”:return (mapping.findForward("SayHello"));
ActionMapping.findForward()方法從<action>元素中尋找name屬性為“SayHello”的<forward>子元素,然后返回與之對應的ActionForward對象,它代表的請求轉發路徑為“/hello.jsp”。
HelloAction的execute()方法把ActionForward對象返回給ActionServlet,ActionServlet再把客戶請求轉發給hello.jsp。
hello.jsp的<bean:message>標簽從Resource Bundle中讀取文本,把它們輸出到網頁上,最后生成動態網頁。