欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Struts 2 实现Action的几种方式

程序员文章站 2024-04-01 18:51:04
action用于处理用户的请求,因此也被称为业务控制器。每个action类就是一个工作单元,struts 2框架负责将用户的请求与相应的action匹配,如果匹配成功,则调...

action用于处理用户的请求,因此也被称为业务控制器。每个action类就是一个工作单元,struts 2框架负责将用户的请求与相应的action匹配,如果匹配成功,则调用该action类对用户请求进行处理,而匹配规则需要在struts 2的配置文件中声明。

struts 2框架下实现action类有以下三种方式:

  1. 普通的pojo类,该类通常包含一个无参数的execute()方法,返回值为字符串类型。
  2. 实现action接口
  3. 继承actionsupport类

pojo实现方式

以用户登录为例,创建loginaction类。

package com.qst.chapter03.action;

public class loginaction {
  /* 用户名 */
  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;
  }

  /**
   * 调用业务逻辑方法,控制业务流程
   */
  public string execute() {
    system.out.println("----登录的用户信息-----");
    system.out.println("用户名:" + username);
    system.out.println("密码:" + password);
    if (username.startswith("qst") && password.length() >= 6) {
      // 返回成功页面
      return "ok";
    } else {
      // 返回失败页面
      return "error";
    }
  }

}

登录页面:

<%@ page language="java" contenttype="text/html; charset=utf-8"
  pageencoding="utf-8"%>
<html>
<head>
<title>用户登录</title>
</head>
<body>
  <form action="login.action" method="post" name="logform">
    <table>
      <tr>
        <td>用户名</td>
        <td><input type="text" name="username" size="15" /></td>
      </tr>
      <tr>
        <td>密码</td>
        <td><input type="password" name="password" size="15" /></td>
      </tr>
      <tr>
        <td colspan="2"><input type="submit" value="登录"></td>
      </tr>
    </table>
  </form>
</body>
</html>

错误页面:

<%@ page language="java" contenttype="text/html; charset=utf-8"
  pageencoding="utf-8"%>
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd">
<html>
<head>

<title>错误页面</title>
</head>
<body>
     登录失败!
</body>
</html>

成功页面:

<%@ page language="java" contenttype="text/html; charset=utf-8"
  pageencoding="utf-8"%>
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd">
<html>
<head>

<title>显示用户信息</title>
</head>
<body>
登录成功!欢迎用户${param.username} !
</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>
  <!-- 指定struts2处于开发阶段,可以进行调试 -->
  <constant name="struts.devmode" value="true" />
  <constant name="struts.enable.dynamicmethodinvocation" value="true" />

  <!-- struts2的action都必须配置在package里,此处使用默认package -->
  <package name="default" namespace="/" extends="struts-default">
    <!-- 定义一个名为user的action,实现类为com.qst.chapter03.action.loginaction -->
    <action name="login" class="com.qst.chapter03.action.loginaction3">
      <!-- 配置execute()方法返回值与视图资源之间的映射关系 -->
      <result name="ok">/ok.jsp</result>
      <result name="error">/error.jsp</result>
    </action>
  </package>

</struts>

这样就以pojo方式实现了一个action,当单击“登录按钮时”,表单中的数据会提交给login.action,struts 2框架将自动调用loginaction的setter方法将请求参数值封装到对应的属性中,并执行execute()方法。

实现action接口方式

为了让action类更规范,使各个开发人员编写的execute()方法返回的字符串风格是一致的,struts 2提供一个action接口,该接口定义了acitoin处理类应该实现的通用规范:

public abstract interface action {
 
 public static final java.lang.string success = "success";
 public static final java.lang.string none = "none";
 public static final java.lang.string error = "error";
 public static final java.lang.string input = "input";
 public static final java.lang.string login = "login";

 public string execute() throws exception;
}

下面代码使用action接口来创建action类:

package com.qst.chapter03.action;

import com.opensymphony.xwork2.action;

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;
  }

  /**
   * 调用业务逻辑方法,控制业务流程
   */
  public string execute() {
    system.out.println("----登录的用户信息-----");
    system.out.println("用户名:" + username);
    system.out.println("密码:" + password);
    if (username.startswith("qst") && password.length() >= 6) {
      // 返回成功页面
      return success;
    } else {
      // 返回失败页面
      return error;
    }
  }

}

struts.xml:

<struts>
  <!-- 指定struts2处于开发阶段,可以进行调试 -->
  <constant name="struts.devmode" value="true" />
  <constant name="struts.enable.dynamicmethodinvocation" value="true" />

  <!-- struts2的action都必须配置在package里,此处使用默认package -->
  <package name="default" namespace="/" extends="struts-default">
    <!-- 定义一个名为user的action,实现类为com.qst.chapter03.action.loginaction -->
    <action name="login" class="com.qst.chapter03.action.loginaction3">
      <!-- 配置execute()方法返回值与视图资源之间的映射关系 -->
      <result name="success">/ok.jsp</result>
      <result name="error">/error.jsp</result>
    </action>
  </package>

</struts>

继承actionsupport类方式

struts 2框架为action接口提供了一个实现类actionsupport,该类提供了许多默认方法,写action类时继承actionsupport类会大大简化action的开发。actionsupport类是struts 2默认的action处理类,如果配置action类时没有指定class属性,系统自动默认使用actionsupport类作为action的处理类。

下面代码通过继承actionsupport类来创建action类,并重写validate()验证方法:

package com.qst.chapter03.action;

import com.opensymphony.xwork2.actionsupport;

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;
  }

  /**
   * 调用业务逻辑方法,控制业务流程
   */
  public string execute() {
    system.out.println("----登录的用户信息-----");
    system.out.println("用户名:" + username);
    system.out.println("密码:" + password);
    if (username.startswith("qst") && password.length() >= 6) {
      // 返回成功页面
      return success;
    } else {
      // 返回失败页面
      return error;
    }
  }

  // 重写validate()方法
  public void validate() {
    // 简单验证用户输入
    if (this.username == null || this.username.equals("")) {
      // 将错误信息写入到action类的fielderrors中
      // 此时struts 2框架自动返回input视图
      this.addfielderror("username", "用户名不能为空!");
      system.out.println("用户名为空!");
    }
    if (this.password == null || this.password.length() < 6) {
      this.addfielderror("password", "密码不能为空且密码长度不能小于6");
      system.out.println("密码不能为空且密码长度不能小于6!");
    }
  }

}

上述代码增加了一个对表单提交的数据进行验证的validate()方法,该方法会在执行execute()方法之前运行,如果发现表单提交数据不符合要求,则执行addfielderror()方法,将错误信息写入action类的字段错误列表fielderrors中,并且将自动返回到input输入视图,让用户重新输入表单并提交。

在struts.xml配置文件中增加input输入视图:

<?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>
  <!-- 指定struts2处于开发阶段,可以进行调试 -->
  <constant name="struts.devmode" value="true" />
  <constant name="struts.enable.dynamicmethodinvocation" value="true" />

  <!-- struts2的action都必须配置在package里,此处使用默认package -->
  <package name="default" namespace="/" extends="struts-default">
    <!-- 定义一个名为user的action,实现类为com.qst.chapter03.action.loginaction -->
    <action name="login" class="com.qst.chapter03.action.loginaction3">
      <!-- 配置execute()方法返回值与视图资源之间的映射关系 -->
      <result name="success">/ok.jsp</result>
      <result name="error">/error.jsp</result>
      <result name="input">/login.jsp</result>
    </action>
  </package>

</struts>

当表单提交的数据验证不通过时,则会返回到输入页面,程序会依然“停留”(看起来是这样,但其实是一个新的输入页面)在输入页面login.jsp。

访问actioncontext

相对于struts1,struts 2的一个重要改进是使action不再和任何servlet api耦合,但有些时候action类不访问servlet api是不能实现业务逻辑的(例如跟踪http session的状态)。此时action就需要访问servlet api中的httpsession。

struts 2提供了一种更加轻松的方式来访问servlet api。在struts 2框架中,action可以通过actioncontext类来访问servlet api,actioncontext提供了读写servlet api中的httpservletrequest、httpsession和servletcontext中数据的方法。

常用方法如下表所示:

方法 功能描述
object get(object key) 获取属性值,与httpsevletrequest的getattribute(string name)类似
map getapplication() 返回一个map对象,该对象模拟了web应用对应的servletcontext对象
static actioncontext getcontext() 静态方法,用于获取系统的actioncontext对象
map getparameters() 获取所有的请求参数,类似于调用httpsevletrequest对象的getparametermap()方法
map getsession() 返回一个map对象,该对象模拟了httpsession实例
void setapplication(map application) 直接传入一个map对象,并将该map对象中的键/值对转换成application的属性名和属性值
void setsession(map session) 直接传入一个map对象,并将该map对象中的键/值对转换成session的属性名和属性值

下面代码演示action访问actioncontext的使用

package com.qst.chapter03.action;

import com.opensymphony.xwork2.actioncontext;
import com.opensymphony.xwork2.actionsupport;

public class clicknumaction extends actionsupport {
  public string execute() {
    // 获取actioncontext对象,通过该对象访问servlet api
    actioncontext ctx = actioncontext.getcontext();
    // 获取servletcontext里的num属性
    integer num = (integer) ctx.getapplication().get("num");
    // 如果num属性为null,设置num属性为1
      if (num == null) {
        num = 1;
      } else {
        // 将num加1
        num++;
      }
    // 将加1后的num值保存在application中
    ctx.getapplication().put("num", num);
    return success;
  }
}

上面代码先使用actioncontext.getcontext()静态方法获取系统的actioncontext对象,再调用actioncontext对象的getapplication()方法获取servletcontext对应的map对象,然后调用get()/put()方法进行数据的读/写操作。最后将num值保存到servletcontext中。

编写clicknum.jsp 页面,对application进行访问:

<%@ page language="java" contenttype="text/html; charset=utf-8"
  pageencoding="utf-8"%>
<html>
<head>
<title>点击次数统计</title>
</head>
<body>
<form action="clicknum.action" method="post">
  <input type="submit" value="点击!" />
</form>
  <!--输出点击次数 -->
  点击按钮,已点击了
  <!-- 通过表达式访问servletcontext对象的属性 -->
  ${empty applicationscope.num?0:applicationscope.num} 次
</body>
</html>

上述代码创建了一个表单,表单的action属性值为clicknum,action,当单击“提交”按钮时会将表单提交给counteraction进行处理。

在struts.xml配置文件中增加counteraction的配置:

<?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>
  <!-- 指定struts2处于开发阶段,可以进行调试 -->
  <constant name="struts.devmode" value="true" />
  <constant name="struts.enable.dynamicmethodinvocation" value="true" />

  <!-- struts2的action都必须配置在package里,此处使用默认package -->
  <package name="default" namespace="/" extends="struts-default">
    <!-- 定义一个名为user的action,实现类为com.qst.chapter03.action.loginaction -->
    <action name="login" class="com.qst.chapter03.action.loginaction3">
      <!-- 配置execute()方法返回值与视图资源之间的映射关系 -->
      <result name="success">/ok.jsp</result>
      <result name="error">/error.jsp</result>
      <result name="input">/login.jsp</result>
    </action>
    <action name="clicknum" class="com.qst.chapter03.action.clicknumaction">
      <result name="success">/clicknum.jsp</result>
    </action>
  </package>

</struts>

访问servlet api

虽然struts 2提供了actioncontext来直接访问servlet api。但有时你需要直接访问sevlet api。为了在action中能够直接访问servlet api,struts 2还提供了一系列的其他接口,通过实现这些接口,action可以直接访问servlet api。

struts 2框架提供的访问servlet api的接口如下表所示:

方法 功能描述
servletcontextaware 实现该接口的action可以直接访问web应用的sevletcontext实例
servletrequestaware 实现该接口的action可以直接访问用户请求的httpservletrequest实例
servletresponseaware 实现该接口的action可以直接访问服务器响应的httpsevletresponse实例

下面代码以实现sevletrequestaware接口为例,通过获取httpsession,将登陆成功的用户名保存到session中:

package com.qst.chapter03.action;

import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpsession;

import org.apache.struts2.interceptor.servletrequestaware;

import com.opensymphony.xwork2.actionsupport;

public class loginaction4 extends actionsupport implements servletrequestaware {
  /* 用户名 */
  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;
  }

  //声明request对象
  private httpservletrequest request;
  //重写servletrequestaware中的方法
  public void setservletrequest(httpservletrequest request) {
    this.request = request;
  }

  /**
   * 调用业务逻辑方法,控制业务流程
   */
  public string execute() {
    system.out.println("----登录的用户信息-----");
    system.out.println("用户名:" + username);
    system.out.println("密码:" + password);
    if (username.startswith("qst") && password.length() >= 6) {
      // 获得session对象
      httpsession session = request.getsession();
      //将用户名存放到session中
      session.setattribute("curuser", username);
      // 返回成功页面
      return success;
    } else {
      // 返回失败页面
      return error;
    }
  }

  // 重写validate()方法
  public void validate() {
    // 简单验证用户输入
    if (this.username == null || this.username.equals("")) {
      // 将错误信息写入到action类的fielderrors中
      // 此时struts 2框架自动返回input视图
      this.addfielderror("username", "用户名不能为空!");
      system.out.println("用户名为空!");
    }
    if (this.password == null || this.password.length() < 6) {
      this.addfielderror("password", "密码不能为空且密码长度不能小于6");
      system.out.println("密码不能为空且密码长度不能小于6!");
    }
  }

}

上述代码定义的loginaction4 实现了sevletrequestaware接口,并且重写该接口中setservletrequest()方法,setservletrequest()方法的参数是httpservletrequest对象,运行web应用时,struts 2框架会自动将当前请求对象传入setservletrequest()方法,再将该请求对象赋给loginaction4的request属性,这样在loginaction4类的其他方法中就可以访问到request对象了。通过request对象可以获取httpsession对象,并将当前用户信息保存到session中。

将login.jsp页面中表单的action属性改成login4.action:

...
<form action="login.action" method="post" name="logform">
...

创建first.jsp显示用户信息:

<%@ page language="java" contenttype="text/html; charset=utf-8"
  pageencoding="utf-8"%>
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd">
<html>
<head>

<title>显示用户信息</title>
</head>
<body>
登录成功!欢迎用户${param.username} <br/>
当前用户${session.curuser } <br/>
<a href="second.jsp" rel="external nofollow" >下一页</a>
</body>
</html>

再创建一个second.jsp:

<%@ page language="java" contenttype="text/html; charset=utf-8"
  pageencoding="utf-8"%>
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd">
<html>
<head>

<title>显示用户信息</title>
</head>
<body>
请求中的用户信息:${param.username} <br/>
session中的用户信息:${session.curuser }
</body>
</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。