action在处理请求的时候,默认是execute方法处理请求并且返回对应的视图资源的字符串名称。当action太多的时候,整个工程会变得臃肿,为了不产生过多的action,可以是的逻辑上的共享一个action,具体做法就是:action不仅提供execute方法,并且提供其他的方法来处理不同的请求,也就是动态的调用action中的方法,而不是仅仅使用execute方法。
达到动态调用的目的方法共有三种:
1. actionName!methodName的方式。
2. 指定method属性。
3. 使用通配符
actionName!methodName实现动态调用。
这种方式就是指定action为action=“actionName!methodName”,其中actionName指定提交到哪一个action,methodName指定指定目标action的哪个方法。
使用!的方式需要开启
<constantname="struts.enable.DynamicMethodInvocation"value="true" />
,同时这好像也不是官方推荐的方式。
例如,在登录表单中添加一个注册按钮,在点击注册按钮的时候,使用JS将action修改为login!regist,然后将注册逻辑写在登录的action中,这样一来,就会提交登录的表单,但是执行的是登录action中的regist方法。
loginForm.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<script type="text/javascript">
function RegistButton() {
//使用Javascript在点击注册的时候动态修改action
targetForm = document.forms[0];
targetForm.action = "login!regist";
alert("修改成功");
}
</script>
<body>
<s:form action="login">
<s:textfield name="username" key="UserName" />
<s:textfield name="password" key="Password" />
<s:submit key="Login" />
<s:submit key="Regist" onclick="RegistButton()" />
</s:form>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
LoginAction.java:
package com.tuxianchao;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
// 封装请求参数
private String username;
private String password;
public LoginAction() {
super();
}
public LoginAction(String username, String password) {
super();
this.username = username;
this.password = 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;
}
// 添加一个regist方法,处理注册请求
public String regist() throws Exception {
//注册逻辑....
return "regist";
}
@Override
public String execute() throws Exception {
// 简单模拟登录逻辑
if (getUsername().equals("admin") && getPassword().equals("admin")) {
ActionContext.getContext().getSession().put("user", getUsername());
return SUCCESS;
}
return ERROR;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
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>
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<action name="index">
<result name="success">/jsp1/loginForm.jsp</result>
</action>
<action name="login" class="com.tuxianchao.LoginAction">
<result name="success">/jsp1/welcome.jsp</result>
<result name="error">/jsp1/error.jsp</result>
<result name="regist">/jsp1/regist.jsp</result>
</action>
</package>
</struts>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
其他还包含error.jsp,welcome.jsp,regist.jsp都是输出了一些提示信息。
点击Login:
点击Regist:
指定method属性实现动态调用。
还可以指定method方式来达到动态调用的目的,在配置action的时候,可以执行method属性来指定调用Action的哪个方法来处理请求,这样也能达到动态调用的目的。
将上面的struts.xml配置为:
<action name="login" class="com.tuxianchao.LoginAction">
<result name="success">/jsp/welcome.jsp</result>
<result name="error">/jsp/error.jsp</result>
</action>
<!-- 指定处理的method-->
<action name="regist" class="com.tuxianchao.LoginAction"
method="regist">
<result name="success">/jsp/regist.jsp</result>
</action>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
使用通配符实现动态调用。
通配符
struts.xml在配置action指定name的时候,可以使用模式字符串,就是用一个*
号来代替一个或者多个字符,接下来,就可以在class,method,以及result子元素中使用{N}(N表示地N个*匹配的字串)来代表子串。
例如:
1.使用通配符动态设置method
<action name="*Action" class="com.tuxianchao.LoginAction" method="{1}"></action>
表示当请求为loginAction的时候,method为login,调用LoginAction中的login方法处理请求;
当请求为registAction的时候,method为regist,调用LoginAction中的regist方法处理请求。
- 1
- 2
- 3
2.使用通配符来指定设置class
<action name="*Action" class="com.tuxianchao.{1}Action"></action>
表示当请求为loginAction的时候,,调用LoginAction中的execute方法处理请求;
当请求为registAction的时候,调用registAction中的execute方法处理请求。
- 1
- 2
- 3
3.使用通配符设置result
<action name="*">
<result>/{1}.jsp</result>
</action>
这是一个通用的action,表示对于任何请求,都会返回对应请求字符串的JSP页面
- 1
- 2
- 3
- 4
多个*的应用:
1.在任何情况下,优先对应完全和action的name相同的
对于两个通配符的情况,如果两个action都匹配,那么机会按照配置的顺序来匹配,对于任何带*的来说,不存在优先级的问题,都是同级的。
实现动态调用
对于上面的例子,可修改配置文件为:
<action name="*Action" class="com.tuxianchao.LoginAction"
method="{1}">
<result name="success">/jsp/welcome.jsp</result>
<result name="error">/jsp/error.jsp</result>
<result name="regist">/jsp/regist.jsp</result>
</action>
- 1
- 2
- 3
- 4
- 5
- 6
修改对应的action就可以了。添加一个login方法。
总结
其实动态调用就是通过各种方式决定调用action中哪一个方法来处理请求,或者说调用哪一个action来处理请求。