Struts原理與應用(三)

來源:互聯網
上載者:User
Chapter 5: Struts Work Flow

Struts principle and practice 

 

是Struts的工作流程,前邊我們提到,所有的請求都提交給ActionServlet來處理。

ActionServlet是一個FrontController,它是一個標準的Servlet,它將request轉寄給RequestProcessor來處理,

ActionMapping是ActionConfig的子類,實質上是對struts-config.xml的一個映射,從中可以取得所有的配置資訊

RequestProcessor根據提交過來的url,如*.do,從ActionMapping 中得到相應的ActionForn和Action。然後將request的參數對應到ActionForm中,進行form驗證。如果驗證通過則調用Action的execute()方法來執行Action,最終返回ActionFoward。

ActionFoward是對mapping中一個foward的封裝,對應於一個url

ActionForm使用了ViewHelper模式,是對HTML中form的一個封裝。其中包含有validate方法,用於驗證form資料的有效性。ActionForm是一個符合JavaBean規範的類,所有的屬性都應滿足get和set對應。對於一些複雜的系統,還可以採用DynaActionForm來構造動態Form,即通過預製參數來產生Form。這樣可以更靈活的擴充程式。

ActionErrors是對錯誤資訊的封裝,一旦在執行action或者form.validate中出現異常,即可產生一個ActionError並最終加入到ActionErrors。在Form驗證的過程中,如果有Error發生,則會將頁面重新導向至輸入頁,並提示錯誤。

Action是用於執行商務邏輯的RequsestHandler。每個Action都只建立一個instance。Action不是安全執行緒的,所以不應該在Action中訪問特定資源。一般來說,應改使用 Business Delegate 模式來對Business tier進行訪問以解除耦合。

Struts提供了多種Action供選擇使用。普通的Action只能通過調用execute執行一項任務,而DispatchAction可以根據配置參數執行,而不是僅進入execute()函數,這樣可以執行多種任務。如insert,update等。LookupDispatchAction可以根據提交表單按鈕的名稱來執行函數。

我們可以先回到剛才的例子,理解一下Struts的流程。

下面我們看Struts內建的example執行個體:

Chapter 6: Example 2: Login Application

Struts principle and practice

說明:執行個體二是Struts內建的example程式, 實現了登入,註冊,修改功能

代碼中大量應用了struts taglib,並且採用validator外掛程式進行form的驗證

但是代碼樹立了一個不好的榜樣,即把大量的商務邏輯寫在了action中。

部分代碼如下:

登入:logon.jsp

 

<%@ page contentType="text/html;charset=UTF-8" language="java" %> </p><p>// 聲明Taglib<br /><%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %><br /><%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> </p><p><html:html locale="true"><br /><head><br />// bean是用來從ApplicationResource中讀取i18n資訊<br /><title><bean:message key="logon.title"/></title><br /><html:base/><br /></head><br /><body bgcolor="white"></p><p>// 錯誤資訊部分<br /><html:errors/></p><p>// 登入form,action為logion.do<br /><html:form action="/logon" focus="username"<br />onsubmit="return validateLogonForm(this);"><br /><table border="0" width="100%"></p><p><tr><br /><th align="right"><br /><bean:message key="prompt.username"/>:<br /></th><br /><td align="left"><br /><html:text property="username" size="16" maxlength="18"/><br /></td><br /></tr></p><p><tr><br /><th align="right"><br /><bean:message key="prompt.password" bundle="alternate"/>:<br /></th><br /><td align="left"><br /><html:password property="password" size="16" maxlength="18"<br />redisplay="false"/><br /></td><br /></tr></p><p><tr><br /><td align="right"><br /><html:submit value="Submit"/><br /></td><br /><td align="left"><br /><html:reset/><br /></td><br /></tr></p><p></table></p><p></html:form></p><p>// Validator外掛程式,用於form驗證<br /><html:javascript formName="logonForm"<br />dynamicJavascript="true"<br />staticJavascript="false"/><br /><script language="Javascript1.1" src="staticJavascript.jsp"></script></p><p></body><br /></html:html></p><p>

struts-config.xml配置

<form-beans></p><p> <!-- Logon form bean --><br /> <form-bean name="logonForm"<br /> type="org.apache.struts.validator.DynaValidatorForm"><br /> <form-property name="username" type="java.lang.String"/><br /> <form-property name="password" type="java.lang.String"/><br /> </form-bean></p><p> <!-- Subscription form bean --><br /> <form-bean name="subscriptionForm"<br /> type="org.apache.struts.webapp.example.SubscriptionForm"/></p><p> </form-beans><br /> <action-mappings></p><p> <!-- Edit mail subscription --><br /> <action path="/editSubscription"<br /> type="org.apache.struts.webapp.example.EditSubscriptionAction"<br /> attribute="subscriptionForm"<br /> scope="request"<br /> validate="false"><br /> <forward name="failure" path="/mainMenu.jsp"/><br /> <forward name="success" path="/subscription.jsp"/><br /> </action><br />...<br />

subscriptionForm 是一個標準的ActionForm,其中reset方法用於清除form的值,validate方法用於驗證

public final class SubscriptionForm extends ActionForm {<br /> // The maintenance action we are performing (Create or Edit).<br /> private String action = "Create";<br /> // Should we auto-connect at startup time?<br /> private boolean autoConnect = false;<br /> // The host name.<br /> private String host = null;<br /> private String password = null;<br />private String type = null;<br /> private String username = null;</p><p> public String getAction() {return (this.action); }<br /> public void setAction(String action) { this.action = action; }</p><p> public boolean getAutoConnect() { return (this.autoConnect); }<br /> public void setAutoConnect(boolean autoConnect) { this.autoConnect = autoConnect; }</p><p> public String getHost() {return (this.host); }<br /> public void setHost(String host) { this.host = host; }</p><p> public String getPassword() {return (this.password); }<br /> public void setPassword(String password) { this.password = password; }</p><p> public String getType() {return (this.type); }<br /> public void setType(String type) { this.type = type; }</p><p> public String getUsername() {return (this.username); }<br /> public void setUsername(String username) { this.username = username; }</p><p> /**<br /> * Reset all properties to their default values.<br /> *<br /> * @param mapping The mapping used to select this instance<br /> * @param request The servlet request we are processing<br /> */<br /> public void reset(ActionMapping mapping, HttpServletRequest request) {</p><p> this.action = "Create";<br /> this.autoConnect = false;<br /> this.host = null;<br /> this.password = null;<br /> this.type = null;<br /> this.username = null;</p><p> }</p><p> /**<br /> * Validate the properties that have been set from this HTTP request,<br /> * and return an <code>ActionErrors</code> object that encapsulates any<br /> * validation errors that have been found. If no errors are found, return<br /> * <code>null</code> or an <code>ActionErrors</code> object with no<br /> * recorded error messages.<br /> *<br /> * @param mapping The mapping used to select this instance<br /> * @param request The servlet request we are processing<br /> */<br /> public ActionErrors validate(ActionMapping mapping,<br /> HttpServletRequest request) {</p><p> ActionErrors errors = new ActionErrors();</p><p>if ((host == null) || (host.length() < 1))<br /> errors.add("host",<br /> new ActionError("error.host.required"));<br />if ((username == null) || (username.length() < 1))<br /> errors.add("username",<br /> new ActionError("error.username.required"));<br />if ((password == null) || (password.length() < 1))<br /> errors.add("password",<br /> new ActionError("error.password.required"));<br />if ((type == null) || (type.length() < 1))<br /> errors.add("type",<br /> new ActionError("error.type.required"));<br />else if (!"imap".equals(type) && !"pop3".equals(type))<br /> errors.add("type",<br /> new ActionError("error.type.invalid", type));</p><p>return (errors);</p><p> }</p><p>}</p><p>

logonAction

public final class LogonAction extends Action {<br /> /**<br /> * Process the specified HTTP request, and create the corresponding HTTP<br /> * response (or forward to another web component that will create it).<br /> * Return an <code>ActionForward</code> instance describing where and how<br /> * control should be forwarded, or <code>null</code> if the response has<br /> * already been completed.<br /> *<br /> * @param mapping The ActionMapping used to select this instance<br /> * @param form The optional ActionForm bean for this request (if any)<br /> * @param request The HTTP request we are processing<br /> * @param response The HTTP response we are creating<br /> *<br /> * @exception Exception if business logic throws an exception<br /> */<br /> public ActionForward execute(ActionMapping mapping,<br /> ActionForm form,<br /> HttpServletRequest request,<br /> HttpServletResponse response)<br />throws Exception {</p><p>// Extract attributes we will need<br />Locale locale = getLocale(request);<br />MessageResources messages = getResources(request);<br />User user = null;</p><p>// Validate the request parameters specified by the user<br />ActionErrors errors = new ActionErrors();<br />String username = (String)<br /> PropertyUtils.getSimpleProperty(form, "username");<br /> String password = (String)<br /> PropertyUtils.getSimpleProperty(form, "password");<br />UserDatabase database = (UserDatabase)<br /> servlet.getServletContext().getAttribute(Constants.DATABASE_KEY);<br />if (database == null)<br /> errors.add(ActionErrors.GLOBAL_ERROR,<br /> new ActionError("error.database.missing"));<br />else {<br /> user = getUser(database, username);<br /> if ((user != null) && !user.getPassword().equals(password))<br />user = null;<br /> if (user == null)<br /> errors.add(ActionErrors.GLOBAL_ERROR,<br /> new ActionError("error.password.mismatch"));<br />}</p><p>// Report any errors we have discovered back to the original form<br />if (!errors.isEmpty()) {<br /> saveErrors(request, errors);<br /> return (mapping.getInputForward());<br />}</p><p>// Save our logged-in user in the session<br />HttpSession session = request.getSession();<br />session.setAttribute(Constants.USER_KEY, user);<br /> if (log.isDebugEnabled()) {<br /> log.debug("LogonAction: User '" + user.getUsername() +<br /> "' logged on in session " + session.getId());<br /> }</p><p> // Remove the obsolete form bean<br />if (mapping.getAttribute() != null) {<br /> if ("request".equals(mapping.getScope()))<br /> request.removeAttribute(mapping.getAttribute());<br /> else<br /> session.removeAttribute(mapping.getAttribute());<br /> }</p><p>// Forward control to the specified success URI<br />return (mapping.findForward("success"));</p><p> }</p><p> /**<br /> * Look up the user, throwing an exception to simulate business logic<br /> * rule exceptions.<br /> *<br /> * @param database Database in which to look up the user<br /> * @param username Username specified on the logon form<br /> *<br /> * @exception ModuleException if a business logic rule is violated<br /> */<br /> public User getUser(UserDatabase database, String username)<br /> throws ModuleException {</p><p> // Force an ArithmeticException which can be handled explicitly<br /> if ("arithmetic".equals(username)) {<br /> throw new ArithmeticException();<br /> }</p><p> // Force an application-specific exception which can be handled<br /> if ("expired".equals(username)) {<br /> throw new ExpiredPasswordException(username);<br /> }</p><p> // Look up and return the specified user<br /> return ((User) database.findUser(username));</p><p> }<br />}<br />

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.