调用非execute方法

在前面有关Action的学习中,我们的Action中真正实现业务逻辑的只有execute方法,如果我们每个Action中都只有这么一个方法的话,那么当我们程序中需要的功能很多时,我们就不得不手动编写很多的Action类了,这显然是不合理的。前面我也说道了我们的Action类并不一定非得继承某个类或者实现某个接口,我们可以使用POJO来作为我们的Action,并且我们的Action中也并不一定非得要有execute方法,如果我们使用的不是execute方法,那么我们就需要在配置Action的是时候在action标签上使用method属性来指出我们需要使用的动作方法。

那么我们也可以在一个Action中编写多个用于实现业务逻辑的方法,他们分别执行不同的功能,但是做的工作又是有相似的地方。比如我们可以将所有与用户相关的处理操作都写在UserAction当中,那么这样我们就能够更好的组织我们的代码。同样,我们只需要在struts.xml中为我们的action标签指定我们要使用的method即可。

要实现在一个Action类中调用非execute方法有三种实现方式:

(1)使用method属性

package action; import bean.User; import com.opensymphony.xwork2.ActionSupport; public class UserAction 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 { //仅用于显示信息输入页面 return INPUT; } //保存User public String save(){ User user = new User(); user.setUserName(userName); user.setPassword(password); //将user的信息保存到数据库 //UserDao.save(user) return SUCCESS; } }

这里我们还需要一个User实体类,其实就是一个简单的JavaBean即可。

package bean; public class User { 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; } }

然后在struts.xml中对我们的Action进行配置

<package name="default" namespace="/" extends="struts-default">

<action name="userAdd" class="action.UserAction">

<resultname="input">/input.jsp</result>

</action>

<action name="userSave" class="action.UserAction" method="save">

<result name="success">/success.jsp</result>

</action>

</package>

Input.jsp

<form action="userSave.action" method="post">

username : <input type="text" name="userName"/><br/>

password :<input type="password" name="password"><br/>

<input type="submit" value="submit"/>

</form>

success.jsp

<body>

hello ${userName }<br/>

your password is ${password }

</body>

我们在浏览器中测试一下:

我们直接在浏览器中访问userAdd.action,可以看到显示了信息输入页面

提交之后正确的显示除了success结果页面,说明我们的配置没有问题。

(2)使用通配符

除了使用上面说到的方法外,我们也可以不用在struts.xml中对Action中的每一个动作方法都进行配置,我们可以之配置一个,在这个actin中使用通配符来指定将要执行哪个方法。

<package name="default" namespace="/" extends="struts-default">

<action name="*User" class="action.UserAction" method="{1}">

<result name="input">/input.jsp</result>

<result name="success">success.jsp</result>

</action>

</package>

在UserAction中增加一个add方法,直接返回”input”,将input.jsp中form的action属性修改为”saveUser.action”。我们在浏览器中测试一下:

直接访问addUser.action,浏览器将会显示信息输入页面,说明调用了UserAction中的add方法:

页面提交到saveUser.action,调用了UserAction的save方法并呈现success结果页面.

注:通配符的方式也可以应用在result标签上。

(3)动态方法调用

除了上面介绍的方法,struts2中还有一种实现方法——动态方法调用。使用动态方法调用的格式为 action!method即使用”!”来连接我们配置的action和要执行的方法,使用这种方式我们不需要为acttion标签指定method属性。

<package name="default" namespace="/" extends="struts-default">

<action name="user" class="action.UserAction">

<result name="input">/input.jsp</result>

<result name="success">success.jsp</result>

</action>

</package>

然后我们要对input.jsp做一些修改,将form的action属性修改为”user!save”:

<form action="user!save" method="post">

username : <input ype="text" name="userName"/><br/>

password :<input type="password" name="password"><br/>

<input type="submit" value="submit"/>

</form>

修改完成之后我们在浏览器中直接访问http://localhost/action/user!add

Input.jsp页面被呈现,说明UserAction的add方法被调用。

提交到user!save后success.jsp被呈现,说明UserAction的save方法被调用。

注意:对于使用通配符的方法来说,Struts2会认为我们将这些匹配到的方法就像是硬编码在struts.xml中一样,因此我们可以为这些进行匹配的action做一些其他处理,比如数据验证、本地消息和类型转换等。但是使用动态方法调用的方式,struts2知道我们调用了同一个action,只是执行了非execute方法,因此使用这种方式,这些动作方法都会共享一个Action的配置。所以从这个角度上来说,通配符的方式优于动态方法调用的方式。我们可以在struts.xml中通过配置来决定是否启用动态方法调用。

<constant name="struts.enable.DynamicMethodInvocation"value="false"/>

向对象传递数据

上面我们接触到的Action类都有一个共同的特性,那就是在action中使用属性来接收请求中的参数。我们定义了一个User类,专门由于表示User实体,但是在我们的Action类中我们都是手动的new一个User实体对象,然后使用set方法将接收到的值设置到User实体对象上,那么能不能直接使用User对象类接收请求中的参数,我们在动作方法中就可以直接操作User实体对象呢,答案是肯定的。实现的方式有两种。

(1)    对象支持的javabean属性

我们已经知道Strtus2中的params拦截器会自动将请求中的数据转移到动作对象属性上。那么我们也可以直接使用实体对象作为动作对象的属性,这样Struts2就能自动将请求中的数据填充到我们的实体对象上。为了实现这个功能,我们需要在jsp页面中多做一些工作:

public class UserAction extends ActionSupport{ private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String add() throws Exception { //仅用于显示信息输入页面 return INPUT; } //保存User public String save(){ //将user的信息保存到数据库 //UserDao.save(user) return SUCCESS; } }

input.jsp

<form action="user!save" method="post">

username : <input type="text" name="user.userName"/><br/>

password :<input type="password" name="user.password"><br/>

<input type="submit" value="submit"/>

</form>

Success.jsp

<body>

hello ${user.userName }<br/>

your password is ${user.userName }

</body>

运行浏览器进行测试,其结果和前面的测试相同,页面均能正常执行。

需要注意的是,我们的User对象并不需要我们手动实例化,Strtus2会自动实例化user,并且装配上面的属性。要实现这个功能,我们需要在结果视图中明确指出Action类中的实体(域)对象。下面学习的第二种方法我们的jsp页面可以不做任何改变,就和全部使用javabean一样。

(1)    ModelDriven动作

要使用ModelDriven动作需要我们的动作实现com.opensymphony.xwork2.ModelDriven接口,在该接口中定义了一个getModel方法,我们要在Action类中实现这个方法,并在其中将我们的域对象返回。该接口支持泛型。需要注意的就是我们在返回域对象时要确保这个域对象已经实例化了。

public class UserAction extends ActionSupport implements ModelDriven<User> { private User user = new User(); public String add() throws Exception { // 仅用于显示信息输入页面 return INPUT; } public User getModel() { return user; } // 保存User public String save() { // 将user的信息保存到数据库 // UserDao.save(user) return SUCCESS; } }

要做的改变就是这些,结果视图里面和最初使用纯JavaBean实现时相同。

运行浏览器进行测试,可以看到得出的结果和前面相同。其实现原理是通过拦截器来调用,查看defaultStack拦截器栈,会看到其中有一个ModelDriven拦截器:

<interceptor-stack ame="defaultStack">

<interceptor-ref name="exception"/>

<interceptor-ref name="alias"/>

<interceptor-ref name="servletConfig"/>

<interceptor-ref name="i18n"/>

<interceptor-ref name="prepare"/>

<interceptor-ref name="chain"/>

<interceptor-ref name="scopedModelDriven"/>

<interceptor-ref name="modelDriven"/>

<interceptor-ref name="fileUpload"/>

<interceptor-ref name="checkbox"/>

<interceptor-ref name="multiselect"/>

<interceptor-ref name="staticParams"/>

<interceptor-ref name="actionMappingParams"/>

<interceptor-ref name="params">

<param name="excludeParams">dojo\..*,^struts\..*</param>

</interceptor-ref>

<interceptor-ref name="conversionError"/>

<interceptor-ref name="validation">

<param name="excludeMethods">input,back,cancel,browse</param>

</interceptor-ref>

<interceptor-ref name="workflow">

<param name="excludeMethods">input,back,cancel,browse</param>

</interceptor-ref>

<interceptor-ref name="debugging"/>

</interceptor-stack>

这个拦截器在params拦截器之前,那么会在参数传递到到Action对象上之前将通过getModel获取到的域对象压入valueStack中,以供params拦截器将参数设置上去。查看文档可以知道modeldriven拦截器的实现类是com.opensymphony.xwork2.interceptor. ModelDrivenInterceptor

查看该拦截器的interceptor方法源码:

public Stringintercept(ActionInvocation invocation)throws Exception {

Object action = invocation.getAction();

if (actioninstanceof ModelDriven) {

ModelDriven modelDriven =(ModelDriven) action;

ValueStack stack =invocation.getStack();

Object model =modelDriven.getModel();

if (model != null) {

stack.push(model);

}

if (refreshModelBeforeResult) {

invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven,model));

}

}

return invocation.invoke();

}

可以清晰看出这个拦截器对域对象所做的处理。从这里也可以看出,我们的域对象必须先实例化,才能产生效果。

总结:虽然使用实体对象保存请求数据看起来比较不错,不过在实际使用中还是直接使用javabean属性接收数据的方式比较多,这种方式操作简单,也比较容易控制。

转载于:https://www.cnblogs.com/JPAORM/archive/2012/05/18/2509743.html

Struts2学习笔记(五) Action(下)相关推荐

  1. Struts2学习笔记(五)之异常处理机制

    我们在知道在软件开发中的异常处理是很重要的,作为成熟的MVC框架的Struts2也提供了异常处理处理机制,对于一场处理:用户发送请求-->Action控制器-->发现相应的异常--> ...

  2. python函数是一段具有特定功能的语句组_Python学习笔记(五)函数和代码复用

    本文将为您描述Python学习笔记(五)函数和代码复用,具体完成步骤: 函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Pyth ...

  3. Ethernet/IP 学习笔记五

    Ethernet/IP 学习笔记五 Accessing data within a device using a non-time critical message (an explicit mess ...

  4. StackExchange.Redis学习笔记(五) 发布和订阅

    StackExchange.Redis学习笔记(五) 发布和订阅 原文:StackExchange.Redis学习笔记(五) 发布和订阅 Redis命令中的Pub/Sub Redis在 2.0之后的版 ...

  5. ROS学习笔记五:理解ROS topics

    ROS学习笔记五:理解ROS topics 本节主要介绍ROS topics并且使用rostopic和rqt_plot命令行工具. 例子展示 roscore 首先运行roscore系列服务,这是使用R ...

  6. Python学习笔记五:控制语句

    Python学习笔记五:控制语句 Pycharm 开发环境的下载安装配置_项目管理 控制语句 Pycharm 开发环境的使用 Pycharm 下载和安装 激活和选择不同UI 风格 创建项目和初始化配置 ...

  7. motan学习笔记 五 opentracing学习入门

    motan学习笔记 一 微博轻量级RPC框架Motan motan学习笔记 二 motan架构分析 motan学习笔记 三 motan Demo 分析 motan学习笔记 四 motan Demo 之 ...

  8. 哈工大操作系统学习笔记五——内核级线程实现

    哈工大os学习笔记五(内核级线程实现) 文章目录 哈工大os学习笔记五(内核级线程实现) 一. 中断入口.中断出口(前后两段) 1. 从int中断进入内核(中断入口第一段) 2.中断出口(最后一段) ...

  9. 华清远见fs4412开发板学习笔记(五)

    fs4412开发板学习笔记(五) 作业1: 输入10个整数,按从小到大的顺序输出(选择排序) 每轮排序在未排序的集合中找到(最小/最大),将找到的数与未排序的 第一个数交换位置. 5 4 3 2 1 ...

  10. 【K210】K210学习笔记五——串口通信

    [K210]K210学习笔记五--串口通信 前言 K210如何进行串口通信 K210串口配置 K210串口发送相关定义 K210串口接收相关定义 K210串口发送接收测试 完整源码 前言 本人大四学生 ...

最新文章

  1. UI设计要学哪些软件
  2. centos6.5 架设Telnet服务
  3. 【转】gif文件格式详解
  4. idea自动为行尾加分号
  5. python中可用于布尔测试的,如何在Python中使用布尔值?
  6. 【渝粤教育】广东开放大学 商务英语听说 形成性考核 (37)
  7. webflux databuffer输出
  8. Python | 如何强制除法运算为浮点数? 除数一直舍入为0?
  9. 线程切换是如何给 CPU 洗脑的?
  10. 投资基金融资理财服务企业网站源码 织梦dedecms模板
  11. Docker Compose配置springboot微服务项目
  12. Category类别、继承
  13. iptables_ftp
  14. modern php笔记---2.1、特性(命名空间、特性、性状)
  15. Horizon client连接windows桌面显示:USB设备已禁用/USB重定向功能已禁用
  16. sharepoint FAST serach 设置
  17. 常见分布的数学期望和方差
  18. 树梅派-人脸识别菜鸡起步
  19. steam for linux 安装目录,我该如何安装Steam?
  20. kafka不消费:9092 (id: 0 rack: null)

热门文章

  1. jquery元素插入、删除、清空
  2. Unieap3.5-Grid编辑列中数字与下拉改变
  3. JAVA线程池的创建
  4. 【Java从0到架构师】SpringMVC - 特殊的请求参数
  5. 《Algorithms》Comparable 实现希尔排序
  6. Java自动跳转到debug模式的解决方法
  7. 加载mySQL数据到内存_【测试验证】数据库加载到内存占用大小
  8. 10张架构图包含Python所有方向的学习路线,你们要的体系全在这
  9. 真正能挣钱的分析模型有哪些?这三个你绝对要学会
  10. 案例学习BlazeDS+Spring之三InSync01查找联系人