(三)struts2进阶之实现Action

Action是Struts2应用的核心,用于处理用户的请求,因此Action也被称为业务控制器。每个Action都是一个工作单元,而Struts2框架则负责将用户的请求与相应的Action匹配。匹配成功则使用相应的Action处理用户的请求,匹配的规则在struts.xml中进行设置。

实现Action有三种方式:
1.普通的POJO类,该类包含一个无参数的execute()方法,返回值为String。
2.实现Action接口。
3.继承ActionSupport类。


1.POJO实现方式

(一)Struts2实现第一个案例这篇文章里,写的那个UserAction就是POJO的实现方式,这里就不再说了,以后文章尽量精简一点,不然看着疲惫,写的也累。

运行tomcat,打开网页输入账户名密码地址后,点击提交,结果如下
运行结果


2.实现Action接口方式

Action接口的定义如下

public interface Action {
    public static final String SUCCESS = "success";
    public static final String NONE = "none";
    public static final String ERROR = "error";
    public static final String INPUT = "input";
    public static final String LOGIN = "login";
    public String execute() throws Exception;

}

通过实现Action接口,我们就可以使用里面的常量值作为execute()方法的返回值。

package com.codeliu.action;

import com.opensymphony.xwork2.Action;

/**
 * 通过实现Action接口来创建一个action
 * @author liu
 */
public class LoginAction2 implements Action {

    private String username;
    private String password;


    public String getUsername() {
        return username;
    }



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



    public String getPassword() {
        return password;
    }



    public void setPassword(String password) {
        this.password = password;
    }



    @Override
    public String execute() throws Exception {
        if("admin".equals(username) && "admin".equals(password)) {
            // Action接口中的静态常量,返回成功界面
            return SUCCESS;
        } else {
            // 返回失败界面
            return ERROR;
        }
    }
}

在struts.xml中增加一个Action,同时修改表单的action

<!-- 通过实现Action接口来实现一个action -->
<action name="login2" class="com.codeliu.action.LoginAction2">
    <result name="success">/success.jsp</result>
    <result name="error">/error.jsp</result>
</action>

运行结果和上面一样。


3.继承ActionSupport类方式

ActionSupport是Struts2默认的Action处理类,如果在struts.xml中配置Action时,省略了class属性,则默认调用ActionSupport类对作为Action的处理类,对用户的请求进行处理。编写Action时继承ActionSupport类能简化Action的开发,提高效率。

/**
 * 通过继承ActionSupport来实现一个action
 * @author liu
 */
@SuppressWarnings("serial")
public class LoginAction3 extends ActionSupport {
    private String username;
    private String password;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String execute() throws Exception {
        System.out.println("用户名:" + username);
        System.out.println("密码:" + password);
        if("admin".equals(username) && "admin".equals(password)) {
            return SUCCESS;
        } else {
            return ERROR;
        }
    }

    @Override
    /**
     * 重写validate方法,可以在execute方法执行之前执行,对用户输入的数据进行验证
     */
    public void validate() {
        if(username == null || "".equals(username)) {
            // 将错误信息写到ActionSupport类的FieldErrors中,此时Struts2框架自动返回input页面
            this.addFieldError(username, "用户名不能为空");
            System.out.println("用户名为空");
        }
        if(password == null || password.length() < 6) {
            this.addFieldError(password, "密码不能为空且长度要大于6");
            System.out.println("密码为空或长度小于6");
        }
    }
}

在上面的代码中,我们重写了ActionSupport类中的validate方法,该方法是在execute方法之前执行的,可以对用户输入的数据进行一些合法性的判断,如果不符合要求,则会自动跳转到输入页面

其实Struts2有完整的验证框架,可以通过配置文件的方式对需要验证的内容进行配置,更加灵活,便于维护,这会在后面系列文章中讲到。

同样在struts.xml中增加一条一个Action,同时修改表单的action

<!-- 通过继承ActionSupport类来实现一个action -->
<action name="login3" class="com.codeliu.action.LoginAction3">
    <result name="success">/success.jsp</result>
    <result name="error">/error.jsp</result>
    <result name="input">/index.jsp</result>
</action>

我们新增了一条result,对应的是validate方法,如果不符合要求,则跳转到index.jsp。

运行后如果输入符合要求,则结果和上面的一样,如果不符合要求,比如密码为空,则会在控制台打印输出密码为空或长度小于6,同时界面跳转到index.jsp。
12.png


4.通过ActionContext类间接获取Servlet API

Struts2相比于Struts1一个很大的不同是Action进行了解耦,提高了代码的复用率,但如果我们要获取Servlet API,还是得通过Struts2提供的一些类。比如ActionContext类。

ActionContext类提供了一些方法读写Servlet中HttpServletRequest、HttpSession和ServletContext中的数据,常用方法如下

方法功能描述
Object get(Object key)获取属性值,与HttpServletRequest的getAttribute(String name)方法类似
Map getApplication()返回一个对象,该对象模拟了web应用对象的ServletContext对象
static ActionContext getContext()静态方法,用于获取系统的ActionContext对象
Map getParameters()获取所有的请求参数,类似于调用HttpServletRequest的getParameterMap()方法
Map getSession()返回一个Map对象,该对象模拟了HttpSession实例
void setApplication(Map application)直接传入一个Map对象,将该Map对象中的键/值对转换成application的属性值和属性名
void setSession(Map session)直接传入一个Map对象,将该对象里的键/值对转成session的属性名和属性值

下面看看代码

@SuppressWarnings("serial")
public class ClickNumAction extends ActionSupport {
    @Override
    public String execute() throws Exception {
        // 获取一个ActionContext实例对象
        ActionContext act = ActionContext.getContext();
        // 获取application中num的值
        Integer num = (Integer)act.getApplication().get("num");
        // 第一次获取时为null
        if(num == null) {
            num = 1;
        } else {
            num++;
        }
        // 设置的num的值
        act.getApplication().put("num", num);
        return SUCCESS;
    }
}

上面通过ActionContext的静态方法getContext()获取一个ActionContext实例,然后通过getApplication()方法获取ServletContext对应的Map对象,调用put/get方法进行数据的读写操作。

再写一个clickNum.jsp来看看效果

<body>
    <form action="click.action" method="post">
        <input type = "submit" value="click">
    </form>
    <!-- 通过EL表达式获取applicationScope中的num值 -->
    点击按钮
    ${empty applicationScope.num ? 0:applicationScope.num}次
</body>

记得在struts.xml中增加一个Action的配置

<!-- 通过ActionContext类获取Servlet API -->
<action name="click" class="com.codeliu.action.ClickNumAction">
    <result name="success">/clickNum.jsp</result>
</action>

启动tomcat运行后,效果如下
13.png


5.通过某些接口直接获取Servlet API

虽然通过ActionContext类能获取,但毕竟不是直接获取,好多方法我们还是不能用,局限性太大,Struts2还提供了其他一系列的接口来直接获取Servlet API

接口名描述
ServletContextAware实现该接口的Action可以直接访问Web应用的ServletContext实例
ServletRequestAware实现该接口的Action可以直接访问Web应用的HttpServletRequest实例
ServletResponseAware实现该接口的Action可以直接访问Web应用的HttpServletResponse实例

以ServletRequestAware为例,源代码如下

public interface ServletRequestAware {
    public void setServletRequest(HttpServletRequest request);
}

里面只有一个方法,实现该接口的同时实现这个方法就能获取HttpServletRequest 实例。代码如下

public class LoginAction4 extends ActionSupport implements ServletRequestAware {
    private HttpServletRequest request;
    @Override
    /**
     * 重写ServletRequestAware接口中的方法,获取HttpServletRequest实例
     */
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
    }
    @Override
    public String execute() throws Exception {
        if("admin".equals(username) && "admin".equals(password)) {
            // 获取session对象
            HttpSession session = request.getSession();
            session.setAttribute("username", username);
            return SUCCESS;
        } else {
            return ERROR;
        }
    }
}

上面都是些重复的代码,我就删了,只留了些主要的,可以通过直接创建一个HttpServletRequest 的变量,然后传给setServletRequest方法就可以获取到HttpServletRequest的实例,之后就可以使用它的所有功能。

可以去struts.xml新增一条Action的配置,试一试,我就不试了。

ServletContextAware、ServletResponseAware和ServletRequestAware的使用方法基本一致。

除此之外,Struts2还提供了一个ServletActionContext工具类,里面有一些静态方法。

方法描述
static PageContext getPageContext()获取web应用的pageContext对象
static HttpServletRequest getRequest()获取web应用的HttpServletRequest 对象
static HttpServletResponse getResponse()获取web应用的HttpServletResponse 对象
static ServletContext getServletContext()获取web应用的ServletContext 对象

总结:因为Struts2的特点就是Action不与任何Servlet API耦合,所以我们推荐使用ActionContext来间接获取Servlet API,也可以使用ServletActionContext工具类,以更简单的方式获取Servlet API。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值