Struts 2 实现Action的几种方式
action用于处理用户的请求,因此也被称为业务控制器。每个action类就是一个工作单元,struts 2框架负责将用户的请求与相应的action匹配,如果匹配成功,则调用该action类对用户请求进行处理,而匹配规则需要在struts 2的配置文件中声明。
struts 2框架下实现action类有以下三种方式:
- 普通的pojo类,该类通常包含一个无参数的execute()方法,返回值为字符串类型。
- 实现action接口
- 继承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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。