使用Struts2.5.2 学习Action通配符时,出现错误:HTTP Status 404 - There is no Action mapped for namespace [/] and action name [regist_Action] associated with context path [/wildcard1].
在确保代码无误的情况下,用Struts2.3 JAR包代替后可正常使用,而Struts2.5不行,最后确定是Struts2.5.2 JAR本身的问题。
查看文档struts-2.5.2\docs\docs\action-configuration.html后找到问题所在。
首先,2.3版本中多了一个Strict DMI,当设置包属性strict-method-invocation="true"
时,Struts会拒绝一切不明确的方法属性包括通配符。(有点难翻译,具体看原文)
而2.5版本中的 Method Invocation(SMI)继承了2.3中的Strict DMI,属性strict-method-invocation被默认设置为true,所以才会出现这个错误。
解决方法:修改struts.xml,在<allowed-methods>准确添加method
<struts>
<package name="lee" extends="struts-default">
<action name="*_Action" class="org.crazyit.app.action.LoginRegistAction"
method="{1}">
<!-- 定义逻辑视图和物理视图之间的映射关系 -->
<result name="error">/WEB-INF/content/error.jsp</result>
<result>/WEB-INF/content/welcome.jsp</result>
<allowed-methods>login,regist</allowed-methods>
</action>
<action name="*">
<result>/WEB-INF/content/{1}.jsp</result>
</action>
</package>
</struts>
附docs部分原文:
Strict DMI
In Struts 2.3, an option was added to restrict the methods that DMI can invoke. First, set the attribute strict-method-invocation="true"
on your <package>
element. This tells Struts to reject any method that is not explicitly allowed via either the method
attribute (including wildcards) or the <allowed-methods>
tag. Then specify <allowed-methods>
as a comma-separated list of method names in your <action>
. (If you specify a method
attribute for your action, you do not need to list it in <allowed-methods>
.)
Note that you can specify <allowed-methods>
even without strict-method-invocation
. This restricts access only for the specific actions that have <allowed-methods>
.
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
<
struts
>
<
constant
name
=
"struts.enable.DynamicMethodInvocation"
value
=
"true"
/>
<
package
name
=
"default"
extends
=
"struts-default"
strict-method-invocation
=
"true"
>
<
action
name
=
"index"
class
=
"org.apache.struts2.examples.actions.Index"
>
<
result
name
=
"success"
type
=
"redirectAction"
>hello</
result
>
</
action
>
<
action
name
=
"hello"
class
=
"org.apache.struts2.examples.actions.HelloAction"
>
<
result
name
=
"success"
>/WEB-INF/content/hello.jsp</
result
>
<
result
name
=
"redisplay"
type
=
"redirectAction"
>hello</
result
>
<
allowed-methods
>add</
allowed-methods
>
</
action
>
</
package
>
</
struts
>
|
Strict Method Invocation
In Struts 2.5 the Strict DMI was extended and it's called Strict Method Invocation aka SMI. You can imagine that the DMI is a "border police", where SMI is a "tax police" and keeps eye on internals. With this version, SMI is enabled by default (strict-method-invocation
attribute is set to true
by default in struts-default
package), you have option to disable it per package - there is no global switch to disable SMI for the whole application. To gain advantage of new configuration option please use the latest DTD definition:
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
<
struts
>
...
</
struts
>
|
SMI works in the following way:
<allowed-methods>
/@AllowedMethods
is defined per action - SMI works without switching it on but just for those actions (plus adding<global-allowed-methods/>
)- SMI is enabled but no
<allowed-methods>
/@AllowedMethods
are defined - SMI works but only with<global-allowed-methods/>
- SMI is disabled - call to any action method is allowed that matches the default RegEx -
([A-Za-z0-9_$]*)
You can redefine the default RegEx by using a constant as follow <constant name="struts.strictMethodInvocation.methodRegex" value="([a-zA-Z]*)"/>
When using wildcard mapping in actions' definitions SMI works in two ways:
- SMI is disabled - any wildcard will be substituted with the default RegEx, ie.:
<action name="Person*" method="perform*">
will be translated intoallowedMethod = "regex:perform([A-Za-z0-9_$]*)".
- SMI is enabled - no wildcard substitution will happen, you must strictly define which methods can be accessed by annotations or
<allowed-method/>
tag.
You can configure SMI per <action/>
using <allowed-methods/>
tag or via @AllowedMethod
annotation plus using per <package/>
<global-allowed-methods/>
, see the examples below:
<
package
...>
...
<
global-allowed-methods
>execute,input,back,cancel,browse</
global-allowed-methods
>
...
<
action
name
=
"Bar"
>
<
allowed-methods
>foo,bar</
allowed-methods
>
</
action
>
...
</
package
>
|
@AllowedMethods
(
"end"
)
public
class
ClassLevelAllowedMethodsAction {
public
String execute() {
return
...
}
}
|
@org
.apache.struts2.convention.annotation.AllowedMethods({
"home"
,
"start"
})
package
org.apache.struts2.convention.actions.allowedmethods;
|
Allowed methods can be defined as:
-
literals ie. in xml:
execute,cancel
or in annotation:{"
execute
", "cancel
"}
- patterns when using with wildcard mapping, i.e
<action ... method="do{2}"/>
- RegExs using
regex:
prefix, ie:<global-allowed-methods>execute,input,cancel,regex:user([A-Z]*)</global-allowed-methods>
Please be aware when using your own Configurationprovider
that the logic to set allowed methods is defined in built-in providers - XmlConfigurationProvider
and PackageBasedActionConfigBuilder
- and you must replicate such logic in your code as by default only execute
method is allowed, even when SMI is disabled.