Struts2-4 action与Action类


一、比较 action与Action类

 1. action:代表一个Struts2的请求(应用程序可以完成的每一个操作,如显示表单、保存信息等)
 2. Action类:能够处理Struts2请求的类(普通Java类), 必须遵守以下规则:

  • 属性: 属性名必须遵守与JavaBeans属性名相同的命名规则;属性类型可以是任意类型,从字符串到非字符串(基本数据库类型)之间的数据转换可以自动发生;
  • 构造器: 必须有一个不带参的构造器,action通过反射创建Action类的实例;
  • 方法: 同一个Action类可以包含多个(至少一个)可供action调用的方法;
  • 非单例: Struts2会为每一个HTTP请求创建一个新的Action实例,即Action不是单例的,是线程安全的。

二、如何在Action类中访问WEB资源?

1. 什么是WEB资源?

  HttpServletRequest、HttpSession、ServletContext等原生的Servlet API。

2. 为什么要访问WEB资源?

  在B\S应用的控制器中必然需要访问WEB资源,如向域对象中读写属性、读写Cookie、获取realPath等……

3. 如何访问WEB资源?
  • 与Servlet API解耦的方式:只能访问到有限的Servlet API对象,且只能访问其有限的方法(读取请求参数、读写域对象的属性、Session失效等);
  • 与Servlet API耦合的方式:可以访问更多的Servlet API对象,且可以调用其原生的方法。

三、采用与Servlet API解耦的方式来访问WEB资源

  为了避免与Servlet API耦合,方便Action进行单元测试,Struts2封装了HttpServletRequest、HttpSession与ServletContext,并构造了3个Map对象来替代,故在Action中可以直接使用HttpServletRequest、HttpSession与ServletContext所对应的Map对象来保存和读取数据

1. 通过ActionContext访问WEB资源

  ActionContext是Action执行的上下文对象,可以从中获取当前Action所需要的任何信息,包括parameters、request、session和application等……

2. 通过实现XxxAware接口访问WEB资源

  Action类可以通过实现XxxAware接口,使Struts2框架在运行时向Action实例**注入**parameters、request、session和application对应的Map对象。
  
代码整体结构为:
这里写图片描述
  
 TextActionContextAction.java:

package com.qiaobc.struts2.action;

import java.util.Date;
import java.util.Map;
import org.apache.struts2.dispatcher.SessionMap;
import com.opensymphony.xwork2.ActionContext;

/**
* 通过ActionContext的方式来实现对WEB资源的访问
 * 具体步骤:
 *  1). 调用ActionContext对象的getContext()方法获取ActionContext对象
 *  2). 调用ActionContext对象的getXxx()方法获取对应Map对象
 *  3). 操作Map对象即可
 * 具体对比:若Action类中有多个action方法,多个方法中均需使用域对象对应的Map对象时,不建议使用该方式
 * 注意:session对应的Map实际上是SessionMap类型的,强转后调用其invalidate()方法可使其失效!
 * @author qiaobc
 */
public class TextActionContextAction {

    public String execute() {
        // 0. 获取ActionContext对象,即Action的上下文对象,可以从中获取到当前Action需要的一切信息
        ActionContext actionContext = ActionContext.getContext();

        // 1. 获取application对应的Map对象,并操作
        // 通过调用ActionContext对象的getApplication()方法来获取application所对应的Map对象进行操作
        Map<String, Object> applicationMap = actionContext.getApplication();
        // 设置属性
        applicationMap.put("applicationKey", "applicationValue");
        // 获取属性
        Date date = (Date) applicationMap.get("date");
        System.out.println("Date: " + date);

        // 2. 获取session对应的Map对象,并操作
        Map<String, Object> sessionMap = actionContext.getSession();
        sessionMap.put("sessionKey", "sessionValue");
        if(sessionMap instanceof SessionMap) {
            SessionMap sm = (SessionMap) sessionMap;
            sm.invalidate(); // 使Session失效
        }

        // 3. 获取request对应的Map对象,并操作
        // ActionContext中并未提供getRequest()方法来获取request对应的Map对象,而需要调用其get("request")来获取
        Map<String, Object> requestMap = (Map<String, Object>) actionContext.get("request");
        requestMap.put("requestKey", "requestValue");

        // 4. 获取请求参数对应的Map对象,并操作
        // 注意:1. getParameters()返回值为Map<String, Object>,而不是Map<String, Object[]>
        //      2. parametersMap只能读而不能写入数据,如果写入不会出错且不起作用
        Map<String, Object> parametersMap = actionContext.getParameters();
        parametersMap.put("parametersKey", "parametersValue");
        System.out.println(((String[])parametersMap.get("name"))[0]);

        return "success";
    }
}

 TextAwareAction.java:

package com.qiaobc.struts2.action;

import java.util.Map;
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.ParameterAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;

/**
 * 通过实现XxxAware接口的方式来实现对WEB资源的访问
 * 具体步骤:
 *  1). 实现对应的XxxAware接口,并实现其中的抽象方法
 *  2). 依赖注入:定义成员变量,接收Struts2已封装好的对应Map对象
 *  3). 操作Map对象即可
 * 具体对比:若Action类中有多个action方法,多个方法中均需使用域对象对应的Map对象时,建议使用该方式
 * 注意:session对应的Map实际上是SessionMap类型的,强转后调用其invalidate()方法可使其失效!
 * @author qiaobc
 */
public class TextAwareAction implements ApplicationAware, SessionAware,
        RequestAware, ParameterAware {

    private Map<String, Object> application;
    private Map<String, Object> session;
    private Map<String, Object> request;
    private Map<String, String[]> parameters;

    public String execute() {
        // 1. 向application中加入属性:applicationKey2-->applicationValue2
        application.put("applicationKey2", "applicationValue2");
        session.put("sessionKey2", "sessionValue2");
        request.put("requestKey2", "requestValue2");

        // 2. 从application中读取属性:data,并打印输出
        System.out.println(application.get("date"));
        System.out.println(parameters.get("name")[0]);

        return "success";
    }

    @Override
    public void setApplication(Map<String, Object> application) {
        this.application = application;
    }

    @Override
    public void setParameters(Map<String, String[]> parameters) {
        this.parameters = parameters;
    }

    @Override
    public void setRequest(Map<String, Object> request) {
        this.request = request;
    }

    @Override
    public void setSession(Map<String, Object> session) {
        this.session = session;
    }
}

 index.jsp:

<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

    <a href="TextActionContext.action?name=qiaobc">Text ActionContext...</a>
    <br><br>

    <a href="TextAwareAction.action?name=qiaobc">Text AwareAction...</a>
    <br><br>

    <%
        if(application.getAttribute("date") == null) {
            application.setAttribute("date", new Date());
        }
    %>

</body>
</html>

 test-ActionContext.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
    <h4>Test ActionContext Page...</h4>
    <br><br>

    ApplicationValue: ${applicationScope.applicationKey }  <br><br>
    SessionValue: ${sessionScope.sessionKey }              <br><br>
    RequestValue: ${requestScope.requestKey }              <br><br>
    ParametersValue: ${parameters.name }                   <br><br>
</body>
</html>

 test-AwareAction.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
    <h4>Test AwareAction Page...</h4>
    <br><br>

    ApplicationValue: ${applicationScope.applicationKey2 } <br><br>
    SessionValue: ${sessionScope.sessionKey2 }             <br><br>
    RequestValue: ${requestScope.requestKey2 }             <br><br>
    ParametersValue: ${parameters.name }                   <br><br>
</body>
</html>

 struts.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <package name="struts2-text-ActionContext" extends="struts-default">
        <action name="TextActionContext"
            class="com.qiaobc.struts2.action.TextActionContextAction" method="execute">
            <result name="success">/test-ActionContext.jsp</result>
        </action>
        <action name="TextAwareAction"
            class="com.qiaobc.struts2.action.TextAwareAction" method="execute">
            <result name="success">/test-AwareAction.jsp</result>
        </action>
    </package>

</struts>

 再次说明:若Action类中有多个action方法,多个方法中均需使用域对象对应的Map对象时,建议使用实现Aware接口的方式来访问WEB资源。


四、采用与Servlet API耦合的方式来访问WEB资源

  直接访问Servlet的原生API将使Action类与Servlet环境耦合在一起,测试时需要有Servlet容器,不便于对Action进行单元测试。

1. 通过ServletActionContext访问WEB资源
/**
 * 通过ServletActionContext对象的方式来实现对WEB资源的充分访问
 * 常用方法:
 *  1). 获取HttpServletRequest对象:ServletActionContext.getRequest()
 *  2). 获取HttpSession对象:ServletActionContext.getRequest().getSession()
 *  3). 获取ServletContext对象:ServletActionContext.getServletContex()
 * @author qiaobc
 */
2. 通过实现ServletXxxAware接口访问WEB资源
/**
 * 通过实现ServletXxxAware接口的方式可以由Struts2注入需要使用的Servlet相关的对象
 * 常用接口:
 *  1). ServletRequestAware接口:注入HttpServletRequest对象
 *  2). ServletContextAware接口:注入ServletContext对象
 *  3). ServletResponseAware接口:注入HttpServletResponse对象
 * @author qiaobc
 */

五、关于ActionSupport类

  • ActionSupport类是默认的Action类,若action节点未配置class属性,则其默认值为com.opensymphony.xwork2.ActionSupport,默认执行的方法为execute()方法;
  • 在手工完成字段验证、显示错误消息、国际化等情况下,推荐继承于ActionSupport,进行相应扩展即可。

六、练习实例

1. 关于Struts2可受理的请求的扩展名问题
  • org.apache.struts2包下的default.properties中配置了Struts2应用的一些常量;
  • 常量struts.action.extension定义了当前Struts2应用可应答的请求的扩展名;
  • 可以再struts.xml文件中以常量配置的方式修改default.properties中所配置的常量。
<!-- 配置当前Struts应用可受理的请求的扩展名 -->
<constant name="struts.action.extension" value="action,do,"></constant>
2. 关于Struts2访问WEB资源的练习

具体实现要求:
 这里写图片描述
 
整体代码结构:
这里写图片描述

UserAction.java:

package com.qiaobc.struts2.action;

import java.util.Map;

import org.apache.struts2.dispatcher.SessionMap;
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.SessionAware;

public class UserAction implements SessionAware, ApplicationAware{

    private String userName;

    public void setUsername(String userName) {
        this.userName = userName;
    }

    private Map<String, Object> sessionMap;
    private Map<String, Object> applicationMap;

    public String executeLogin() {
        // 将用户信息保存在Session域中
        //  1). 采用实现XxxAware接口的方式,获取session对应的map对象
        //  2). 获取登录信息:通过在Action中添加对应的setter方法来获取
        //  3). 把用户信息保存在Session域中
        sessionMap.put("userName", userName);

        // 使在线人数加1
        // 1). 从application中获取当前的在线人数
        Integer count = (Integer) applicationMap.get("count");
        if(count == null) {
            count = 0;
        }

        // 2). 使当前的在线人数加1
        count++;
        applicationMap.put("count", count);

        return "LoginSuccess";
    }

    public String executeLogout() {
        // 当前在线人数减1
        Integer count = (Integer) applicationMap.get("count");
        if(count != null && count > 0){
            count--;
            applicationMap.put("count", count);
        }

        // 使session失效
        ((SessionMap) sessionMap).invalidate();

        return "LogoutSuccess";
    }

    @Override
    public void setSession(Map<String, Object> sessionMap) {
        this.sessionMap = sessionMap;
    }

    @Override
    public void setApplication(Map<String, Object> applicationMap) {
        this.applicationMap = applicationMap;

    }

}

index.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

    <h4>The Begin Page...</h4>
    <a href="Login_Ui">>>> Login...</a>

</body>
</html>

login.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

    <h4>Login</h4>

    <form action="User_login.action" method="post">
        <table>
            <tr>
                <td>User Name: </td>
                <td><input type="text" name="username"/>
            </tr>
            <tr>
                <td>Password: </td>
                <td><input type="text" name="password"/>
            </tr>
        </table>
        <input type="submit" value="Submit"/>
    </form>

</body>
</html>

details.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

    Welcome: ${sessionScope.userName } <br><br>
    Welcome. The number of users online is ${applicationScope.count }.     <br><br>
    <a href="User_logout.action">>>>Logout...</a>

</body>
</html>

struts.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <!-- 配置当前Struts应用可受理的请求的扩展名 -->
    <constant name="struts.action.extension" value="action,do,"></constant>

    <package name="struts2-accessWebRes" extends="struts-default">
        <action name="Login_Ui">
            <result>/WEB-INF/pages/login.jsp</result>
        </action>
        <action name="User_login" class="com.qiaobc.struts2.action.User" method="executeLogin">
            <result name="LoginSuccess">/WEB-INF/pages/details.jsp</result>
        </action>
        <action name="User_logout" class="com.qiaobc.struts2.action.User" method="executeLogout">
            <result name="LogoutSuccess">/WEB-INF/pages/login.jsp</result>
        </action>
    </package>

</struts>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值