一、爲什麼Action要訪問web元素?
在使用struts2框架進行開發的時候, 頁面與Action類進行交互, 由於Action中無法取得前端request、session、application、HttpServletRequest、HttpSession、ServletApplication,但是當有用戶登錄的時候, 需要在程序中爲該用戶創建session以標識該用戶的登錄狀態及其他信息, 如何才能使得Action能夠訪問web元素,並把相應數據放到session、application…中呢?
注意:response對象不需要在Action中訪問, 因爲在struts框架中, 結果的返回是通過result方式返回。
二、Action訪問Web元素的四種方式
- session、application、request(依賴於容器)
- session、application、request(IoC)(非常重要, 實際開發基本上全用這種方式)
- HttpServletRequest、HttpSession、ServletApplication(依賴於容器)
- HttpServletRequest、HttpSession、ServletApplication(IoC)
<!-- login.jsp 登錄頁面部分代碼 --> <form name="login" action="" method="post"> 用戶名:<input type="text" name="name"/> 密碼:<input type="text" name="password"/> <input type="button" value="submit1" onclick="javascript:document.login.action='login/login.action';document.login.submit(); " /> </form> <!-- struts.xml配置文件代碼 --> <struts> <constant name="struts.devMode" value="true" /> <package name="login" extends="struts-default" namespace="/login"> <action name="login" class="com.keyman.user.action.LoginAction " method="login"> <result>/login_success.jsp</result> <result name="error">/login_error.jsp</result> </action> </package> </struts>
session、application、request(依賴於容器)
/*LoginAction.java代碼*/ public class LoginAction extends ActionSupport{ private Map<String, Object> request; private Map<String, Object> session; private Map<String, Object> application; public LoginAction() { request = (Map) ActionContext.getContext().get("request"); session = ActionContext.getContext().getSession(); application = ActionContext.getContext().getApplication(); } public String login() { request.put("username", "keyman"); session.put("username", "keyman"); session.put("state", "admin"); application.put("username", "keyman"); System.out.println(this.getPassword() + " " + this.getUsername()); return SUCCESS; } } /*login_success.jsp代碼*/ <s:property value="#request.username"/> | <%=request.getAttribute("username") %> <br> <s:property value="#session.username"/> | <%=session.getAttribute("username") %> <br> <s:property value="#session.state"/> |<%=session.getAttribute("state") %> <br> <s:property value="#application.username"/> | <%=application.getAttribute("username") %> <br> <s:property value="#attr.username"/> <br> <s:property value="#attr.state"/> <br> <s:debug></s:debug> <br>
ActionContext爲運行時action的上下文環境,Action運行的時候,首先接受請求,獲取request,response等對象,初始化好環境之後,纔會執行後續的業務處理流程。在Action執行過程中,很多相關的上下文中的參數都要通過ActionContext來獲取。
之所以在後臺將相應的數據存到request、session、application中, 前臺就可以獲取對應的值, 是因爲struts2框架內部建立了這些對象與前端HttpRequest等之前的映射橋樑,現象上來看,就是在Action中設置的session等對象會被複制到前端的Http對象中。
前端取值的方式有兩種:
- 第一種- :<%=request.getAttribute("username") %>
- 第二種-:<s:property value="#request.username"/>
第二種爲使用struts標籤的形式, 在debug模式中可以看到詳細信息!
在實際開發中, request很少需要單獨獲取, 因爲Action的成員變量默認會起到request的作用
/*LoginAction.java代碼*/ public class LoginAction extends ActionSupport implements RequestAware,SessionAware, ApplicationAware{ private Map<String, Object> request; private Map<String, Object> session; private Map<String, Object> application; public String login() { request.put("username", "keyman"); session.put("username", "keyman"); session.put("state", "admin"); application.put("username", "keyman"); return SUCCESS; } @Override public void setApplication(Map<String, Object> application) { this.application = application; } @Override public void setSession(Map<String, Object> session) { this.session = session; } @Override public void setRequest(Map<String, Object> request) { this.request = request; } } 說明:login.jsp、login_success.jsp及login_error.jsp均同上, 此處不再列出
此方式需要實現三個接口, 並且要必須實現對應的抽象方法,
第二種方式實現了三個接口,這三個接口分別要求你一定要實現三個對應的方法。此處並沒有顯示的獲取request、session及application對象, 因爲struts2框架的三個接口已經預先做好這部分工作, 所以可以直接使用,這種思想就體現了IOC依賴注入的設計模式。
執行過程:當客戶端發出請求, struts接受到請求會首先創建Action對象,對象創建之後會進而檢查Action是否實現了RequestAware、SessionAware、ApplicationAware接口,如果實現了對應的接口, 就可以使用對應接口的set方法.
Struts2處理請求是從filter開始的,部署在servlet容器裏的filter也可以取到HttpRequest對象,然後會把裏面的內容拿出來放到一個Map裏,並且命名爲request。也就是把原始類型HttpRequest轉成Map類型的request.
至此, session、application、request均由struts容器來管理, IoC的完美體現。
3. HttpServletRequest、HttpSession、ServletApplication(依賴於容器)
此方式使用ServletActionContext得到request再得到sesion和application
public class LoginAction extends ActionSupport { private HttpServletRequest request; private HttpSession session; private ServletContext application; public LoginAction() { this.request = ServletActionContext.getRequest(); this.session = this.request.getSession(); this.application = this.session.getServletContext(); } public String login() { this.request.setAttribute("username", "keyman"); session.setAttribute("username", "keyman"); session.setAttribute("state", "admin"); application.setAttribute("username", "keyman"); return SUCCESS; } } 說明:login.jsp、login_success.jsp及login_error.jsp均同上, 此處不再列出
4. HttpServletRequest、HttpSession、ServletApplication(IoC)
此方式需要首先獲取request, 再根據request獲取session和application。
需要實現ServletRequestAware接口,以獲取request對象
public class LoginAction extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; private HttpSession session; private ServletContext application; @Override public void setServletRequest(HttpServletRequest request) { this.request = request; this.session = this.request.getSession(); this.application = this.session.getServletContext(); } public String login() { this.request.setAttribute("username", "keyman"); session.setAttribute("username", "keyman"); session.setAttribute("state", "admin"); application.setAttribute("username", "keyman"); return SUCCESS; } } 說明:login.jsp、login_success.jsp及login_error.jsp均同上, 此處不再列出
*************************************************************************************
以上即爲在Struts中訪問web元素的方式, 實際開發中基本上都用第二種方式, 第一種方式偶爾會用, 第三種和第四種方式基本上不會用!
*************************************************************************************
如有疑問, 歡迎吐槽!