1.传统方式配置action
public class LoginAction {
public String a(){
System.out.println("A");
return Action.SUCCESS;
}
public String b(){
System.out.println("B");
return Action.SUCCESS;
}
public String c(){
System.out.println("C");
return Action.SUCCESS;
}
}
<action name="A" class="com.action.Login" method="a">
<result>B</result>
</action>
<action name="B" class="com.action.Login" method="b">
<result>C</result>
</action>
<action name="C" class="com.action.Login" method="c">
<result>/c.jsp</result>
</action>
ps1:你是否看出了这份配置存在错误,如果没看出,对比 2 中的配置文件,应该能得到答案。
传统配置方式即一个action对应一个处理方法。
上面的配置意图是 请求 localhost:port/web/A, 调用方法 a,返回 Action.SUCCESS,请求 B, 调用方法 b,返回 Action.SUCCESS,请求C, 调用方法 c,返回 Action.SUCCESS,请求 localhost:port/web/c.jsp。
如上所示,虽然处理方法不同,但都来自同一个处理类。显然这很容易造成配置文件过大,不利于开发。是否存在一种方式,使用同一个处理类的不同方法时,只写一个action,答案当然是肯定的,这就是动态方法。
2.通过动态方法(!)
需要在struts.xml配置文件中,添加常量指明可以动态调用方法,
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<action name="dynamic" class="com.action.LoginAction">
<result name="B" type="redirect">dynamic!b</result>
<result name="C" type="redirect">dynamic!c</result>
<result>/index.jsp</result>
</action>
此时想调用特定方法,可以通过 actionName!methodName 方式,如 dynamic!a, 可见此种方式是通过result的name属性来区别调用的方法,所以相应的 处理类方法返回值要做修改。
public class LoginAction {
public String a(){
System.out.println("A");
return "B";
}
public String b(){
System.out.println("B");
return "C";
}
public String c(){
System.out.println("C");
return Action.SUCCESS;
}
}
请求 localhost:port/web/dynamic!a, 会让a方法得到执行,返回“B”, 匹配result集后,请求dynamic!b,返回“C”, 匹配result集后,请求dynamic!c, 返回 Action.SUCCESS, 匹配result集后,请求 index.jsp,相比传统方式,简化了不少。
ps2:如果页面出现bug,可能你遇到了和我一样的问题,文末会给出我遇到的问题。
但是,这种方法会把方法暴露出去,增加了被不法攻击的可能性,官方不推荐使用。
3.通过通配符
<action name="*" class="com.action.LoginAction" method="{1}">
<result name="B" type="redirect">b</result>
<result name="C" type="redirect">c</result>
<result>/index.jsp</result>
</action>
处理类与 2 一致,不做修改。 “*”可以匹配任意多个字符, method=“{1}” 的含义是调用第一个*号匹配的方法处理,对于
<action name="*_*" class="com.action.LoginAction" method="{2}">
method=“{2}” 的含义是调用第二个*号匹配的方法处理。
请求 localhost:port/web/a, 会让a方法得到执行,返回“B”, 匹配result集后,请求b,返回“C”, 匹配result集后,请求c, 返回 Action.SUCCESS, 匹配result集后,请求 index.jsp。
4.通过注解
首先要导入 struts2-convention-plugin-2.5.18.jar 包,直接在action处理类使用注解
@ParentPackage("struts-default")
@Namespace("/")
public class LoginAction {
@org.apache.struts2.convention.annotation.Action(value = "A", results={
@Result(name="B",location = "/B", type="redirect"),
})
public String a(){
System.out.println("A");
return "B";
}
@org.apache.struts2.convention.annotation.Action(value = "B", results={
@Result(name="C", location = "/C", type="redirect"),
})
public String b(){
System.out.println("B");
return "C";
}
@org.apache.struts2.convention.annotation.Action(value = "C", results={
@Result(name="success", location = "/index.jsp"),
})
public String c(){
System.out.println("C");
return Action.SUCCESS;
}
}
其中 @org.apache.struts2.convention.annotation.Action(value = "A" 处的value相当于struts.xml里 action标签 的 name属性,这样就可以省去 struts.xml 相应的 package 部分了,其他就不再累赘。
5.文末
- 在使用 动态方法 时,你可能会遇到如下错误
我是遇到了,所以我在相应的 package 里,添加了
<global-allowed-methods>a,b,c</global-allowed-methods>
- 在使用 注解 时,你的idea可能会报下面错误
二话不说,导入 asm-5.2.jar 包
- 在使用中如果出现 unable to read class ,如下
可能是jdk版本问题,我把我环境由 jdk10 改为 jdk1.8 解决问题。