一、为什么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>


  1. 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运行的时候,首先接受请求,获取requestresponse等对象,初始化好环境之后,才会执行后续的业务处理流程。在Action执行过程中,很多相关的上下文中的参数都要通过ActionContext来获取。


        之所以在后台将相应的数据存到request、session、application中, 前台就可以获取对应的值, 是因为struts2框架内部建立了这些对象与前端HttpRequest等之前的映射桥梁,现象上来看,就是在Action中设置的session等对象会被复制到前端的Http对象中。


        前端取值的方式有两种:

            - 第一种- :<%=request.getAttribute("username") %>

            - 第二种-:<s:property value="#request.username"/>

              第二种为使用struts标签的形式, 在debug模式中可以看到详细信息!


2. session、application、request(IoC)

        在实际开发中, 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元素的方式, 实际开发中基本上都用第二种方式, 第一种方式偶尔会用, 第三种和第四种方式基本上不会用!

*************************************************************************************


如有疑问, 欢迎吐槽!