调用非execute方法

1)如果你的Action类是继承自ActionSupport的话,确切的说是重写了execute方法,ActionSupport里的默认实现就是返回"success"视图。因此,你可以不实现execute方法,只要你的struts.xml里有"success"对应的result即可。

2)如果你的Action类没有继承ActionSupport,而你又没有在struts.xml中对应<action>标签中用method属性指定你自己的方法的话,默认就要找execute方法,这时是必须要实现execute方法的,否则Struts2会找不到对应的方法而报错。

不过,大部分情况下都是继承ActionSupport的(比如输入验证、文件上传等功能就要求必须继承)。还有,不管你写没写execute方法,还是可以用<action>标签的method属性指定其他方法的。

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

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

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

(1)使用method属性

  1. package action;
  2. import bean.User;
  3. import com.opensymphony.xwork2.ActionSupport;
  4. public class UserAction extends ActionSupport{
  5. private String userName;
  6. private String password;
  7. public String getUserName() {
  8. return userName;
  9. }
  10. public void setUserName(String userName) {
  11. this.userName = userName;
  12. }
  13. public String getPassword() {
  14. return password;
  15. }
  16. public void setPassword(String password) {
  17. this.password = password;
  18. }
  19. @Override
  20. public String execute() throws Exception {
  21. //仅用于显示信息输入页面
  22. return INPUT;
  23. }
  24. //保存User
  25. public String save(){
  26. User user = new User();
  27. user.setUserName(userName);
  28. user.setPassword(password);
  29. //将user的信息保存到数据库
  30. //UserDao.save(user)
  31. return SUCCESS;
  32. }
  33. }

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

  1. package bean;
  2. public class User {
  3. private String userName;
  4. private String password;
  5. public String getUserName() {
  6. return userName;
  7. }
  8. public void setUserName(String userName) {
  9. this.userName = userName;
  10. }
  11. public String getPassword() {
  12. return password;
  13. }
  14. public void setPassword(String password) {
  15. this.password = password;
  16. }
  17. }

然后在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页面中多做一些工作:

  1. public class UserAction extends ActionSupport{
  2. private User user;
  3. public User getUser() {
  4. return user;
  5. }
  6. public void setUser(User user) {
  7. this.user = user;
  8. }
  9. public String add() throws Exception {
  10. //仅用于显示信息输入页面
  11. return INPUT;
  12. }
  13. //保存User
  14. public String save(){
  15. //将user的信息保存到数据库
  16. //UserDao.save(user)
  17. return SUCCESS;
  18. }
  19. }

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类中实现这个方法,并在其中将我们的域对象返回。该接口支持泛型。需要注意的就是我们在返回域对象时要确保这个域对象已经实例化了。

  1. public class UserAction extends ActionSupport implements ModelDriven<User> {
  2. private User user = new User();
  3. public String add() throws Exception {
  4. // 仅用于显示信息输入页面
  5. return INPUT;
  6. }
  7. public User getModel() {
  8. return user;
  9. }
  10. // 保存User
  11. public String save() {
  12. // 将user的信息保存到数据库
  13. // UserDao.save(user)
  14. return SUCCESS;
  15. }
  16. }

要做的改变就是这些,结果视图里面和最初使用纯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属性接收数据的方式比较多,这种方式操作简单,也比较容易控制。

Struts2 调用非execute方法的更多相关文章

  1. Java-main方法中调用非static方法

    java的calss中,在public static void main(String[] args) { }方法中调用非static的方法:在main方法中创建该calss的对象,用对象调用非sta ...

  2. 是否可以从一个static方法内部调用非static方法?

    不可以.静态成员不能调用非静态成员. 非static方法属于对象,必须创建一个对象后,才可以在通过该对象来调用static方法.而static方法调用时不需要创建对象,通过类就可以调用该方法.也就是说 ...

  3. 为什么static方法中不可以调用非static方法

    Java是面向对象的语言,所有的变量,方法都是针对对象而言的.一般来说,要调用一个方法,你需要new 这个方法的对象. 什么时候用static? 如果你想要: 对于一个类的所有对象共享一个变量或者是方 ...

  4. static方法与非static方法是否可以互相调用

    情况一.static方法调用非static方法 非静态方法只有实例对象才可调用,而静态方法随着类的加载而加载,类的加载在实例对象产生之前,所以静态方法不能调用非静态方法 情况二.非atic方法调用st ...

  5. struts2:多业务方法的处理(动态调用,DMI)

    struts2支持调用指定Action类中某一个业务方法.如果没有指定,则调用execute方法. 1. 第一种实现方式,通过URL叹号参数 1.1 创建Action类,带多个方法 package c ...

  6. 【SSH】——Struts2中的动态方法调用(二)

    当action中的方法有很多时,那应该怎么调用呢?上次我们提到的UserAction类中只有一个execute方法,如果我们需要增加用户的增删改查方法,如下: public class UserAct ...

  7. 【SSH】——Struts2中的动态方法调用(一)

    首先我们来看一个简单的调用: 1.在web.xml中配置拦截器StrutsPrepareAndExecuteFilter.StrutsPrepareAndExecuteFilter实现了filter接 ...

  8. Struts2学习四----------动态方法调用

    © 版权声明:本文为博主原创文章,转载请注明出处 Struts2动态方法调用 - 默认:默认执行方法中的execute方法,若指定类中没有该方法,默认返回success <package nam ...

  9. Struts2 表单提交与execute()方法的结合使用

    1.创建web项目,添加struts2支持的类库,在web.xml中配置struts2过滤器. 2.创建名为UserAction的Action对象,并在其中编写execute()方法,代码如下所示: ...

随机推荐

  1. 加载驱动三种execute

    executeQuery executeUpdate executeQueryBatch

  2. window与Linux之间的文件传输

    使用工具:WinSCP WinSCP可以直接通过SSH链接你的linux服务器:然后进行文件的复制操作:并且可以直接编辑文件. 1.下载WinSCP 2.登录WinSCP,输入你的Linux 的IP地 ...

  3. 将替代ListView的RecyclerView 的使用(一)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/by317966834/article/details/36205923 RecyclerView 是 ...

  4. 微信支付的notify.php中如何获取订单号(php版)

    不要直接使用demo中的notify.php,重写notify.php,继承WxPayNotify(可参考微信api),具体如下: require_once "WxPay.Api.php&q ...

  5. Cobalt Strike深入使用

    System Profiler使用 System Profiler 模块,搜集目标的各类机器信息(操作系统版本,浏览器版本等) Attacks->web drive-by->System ...

  6. easyui 如何引入

    一:引入easyui 1:参考官网:http://www.jeasyui.net/ 2:引入 整个文件夹:themes,包括:icon.css.image 等等 3:引入easyui.css      ...

  7. P2384 最短路

    题目背景 狗哥做烂了最短路,突然机智的考了Bosh一道,没想到把Bosh考住了...你能帮Bosh解决吗? 他会给你100000000000000000000000000000000000%10金币w ...

  8. P2157 [SDOI2009]学校食堂Dining

    题目描述 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以用一个非负整数 ...

  9. 2PC AND 3PC

    一.分布式数据一致性 在分布式系统中,为了保证数据的高可用,通常会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上. (1)什么是数据一致性 在数据有多份副本的情况下,如果网络 ...

  10. 2017-2018-2 20155203《网络对抗技术》Exp2 后门原理与实践

    基础问题回答 (1)例举你能想到的一个后门进入到你系统中的可能方式? 通过下载带后门的程序或者点开带有后门的软件,或者后门本身就在我的系统里: (2)例举你知道的后门如何启动起来(win及linux) ...