一、为什么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元素的方式, 实际开发中基本上都用第二种方式, 第一种方式偶尔会用, 第三种和第四种方式基本上不会用!
*************************************************************************************
如有疑问, 欢迎吐槽!