`
sswh
  • 浏览: 163945 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Struts2释疑之一

阅读更多
问题:
1、Struts2在web.xml中配置为“/*”和“*.action,*.jsp”的差别。
2、There is no Action mapped for namespace / and action name ...的问题。

分析(环境是Struts2.1.8.1):
Struts2过滤器的配置有2种方式:
<filter-mapping>
	<filter-name>struts2</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
	<filter-name>struts2</filter-name>
	<url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
	<filter-name>struts2</filter-name>
	<url-pattern>*.jsp</url-pattern>
</filter-mapping>

那么这两种方式的配置,究竟有什么差别呢?
首先,假如配置方式是*.action的话,一般应当同时配置*.jsp,因为如果不通过action而直接访问jsp页面的话,Struts2标签在解析的时候会获取当前线程ThreadLocal中的Dispatcher。而Dispatcher是在Struts过滤器中预设的。代码如下:
public static ValueStack getStack(PageContext pageContext) {
HttpServletRequest req = (HttpServletRequest) pageContext.getRequest();
ValueStack stack = (ValueStack) req.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
if (stack == null) {
	HttpServletResponse res = (HttpServletResponse) pageContext.getResponse();
	Dispatcher du = Dispatcher.getInstance();
	if (du == null) {
		throw new ConfigurationException("The Struts dispatcher cannot be found.  This is usually caused by "+
		"using Struts tags without the associated filter. Struts tags are only usable when the request "+
		"has passed through its servlet filter, which initializes the Struts dispatcher needed for this tag.");
	}
	//略...


除了为当前线程预设Dispatcher以外,Struts2对“/*”的请求,在完成普通的“*.action”过滤的基础上,另外提供2点功能:
第1点用于访问classpath中特定的静态资源;
第2点支持无后缀名的Action请求;
Struts2的标签有时候需要某些CSS、JS文件的支持,比如<s:head/>标签,可能就转换成:
<link rel="stylesheet" href="/demo/struts/xhtml/styles.css" type="text/css"/>
<script src="/demo/struts/utils.js" type="text/javascript"></script>

第1点功能带来的好处是可以把这些Struts2框架用到的CSS、JS文件打包在Struts2-core-***.jar文件中分发,使得Struts2的发布包对开发人员而言更加简洁。
下面看一下StrutsPrepareAndExecuteFilter是怎样实现的:
①将Dispatcher预设到线程的ThreadLocal变量上;
②对于Action请求,直接execute.executeAction(request,response,mapping);
③如果是/struts、或者/static开始的资源,则在classpath下查找特定的包下面的匹配资源;
④其他的所有资源(包括直接访问的JSP、以及其他静态资源)转交过滤器链的下一个环节处理:chain.doFilter(request, response);
上面所说的特定包,是指在
<filter>
	<filter-name>struts2</filter-name>
	<filter-class>
	org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
	</filter-class>
	<init-param>
		<param-name>packages</param-name>
		<param-value>eee</param-value>
	</init-param>
</filter>

中通过packages参数指定的包、以及 "org.apache.struts2.static template org.apache.struts2.interceptor.debugging static"这4个包。
由于packages可配置,从而,如果有自己的classpath上的资源需要访问,或者需要更改Struts本身的静态资源时,只要把Classpath下相应的package设置在过滤器的初始参数中即可(这一条看上去好像没什么用处)。

上面是使用/*时对静态资源的访问,那么使用*.action时如果需要的话,如何访问静态资源呢?
很简单,只要把需要用到的静态资源解压缩到WebContent/struts目录下即可。

第2点“支持无后缀名的Action请求”经常带来一些混乱,最典型的就是“/*”错误地拦截了其他的映射为无后缀名的Servlet请求。比如DWR、FCKEditor等都存在这种问题。
比如,当访问“/demo/dwr”时,正常情况应该显示当前系统中对外暴露的JS方法的列表,但在Struts2的默认配置下,却得到“There is no Action mapped for namespace / and action name dwr.”
又比如在默认配置下,访问http://localhost:8080/demo/hello.action
和访问http://localhost:8080/demo/hello这两者是等同的。
当然,也只有无后缀名的URL请求才会被Struts2当做是Action,这也是为什么/dwr无法访问,然而/dwr/interface.js可以访问的原因。

具体的,看一下下面的代码就明白了:
//Struts2默认将“*.action”或者无后缀的URL当做Action
protected List<String> extensions = new ArrayList<String>() {{ add("action"); add("");}};
protected String dropExtension(String name, ActionMapping mapping) {
if (extensions == null) {
	return name;
}
for (String ext : extensions) {
	if ("".equals(ext)) {
// This should also handle cases such as /foo/bar-1.0/description. It is tricky to distinquish /foo/bar-1.0 but perhaps adding a numeric check in the future could work
// request uri如果不包含扩展名的话,则匹配此情况
		int index = name.lastIndexOf('.');
		if (index == -1 || name.indexOf('/', index) >= 0) {
			return name;
		}
	} else {
		String extension = "." + ext;
		if (name.endsWith(extension)) {
			name = name.substring(0, name.length() - extension.length());
			mapping.setExtension(ext);
			return name;
		}
	}
}
return null;
}

那么,怎么解决此问题呢?
有2种办法。
第1种很简单,在Struts.properties中定义:
struts.action.extension = action即可解决此问题。
Struts2缺省配置对应于:
struts.action.extension = action,(注意后面有个逗号)
第2种是在Struts.properties中设置:
struts.action.excludePattern = /dwr.*,/webEditor.*(注意,这儿是正则表达式,不是URL匹配模式,所以要写/dwr.*而不是/dwr/*)
这种写法应配置StrutsPrepareAndExecuteFilter,配置FilterDispatcher是无效的。
分享到:
评论
13 楼 kinghema 2013-04-16  
看一下struts2源码就ok了
12 楼 chengpan 2011-05-23  
写的不错,我也遇到这过这种问题,今天看到你的分析没事又回过头看了一下所有的配置信息了解一下
11 楼 tianhandigeng 2011-01-15  
说真的,楼主到底为了说明什么问题,我还没怎么弄清楚,不过在我的项目中却出现了这样的问题,我jar包用得是2.1.8,不带后缀访问action,默认的extension也没有修改也就是说不带后后缀是可以访问的,但是我页面中这样写url:href="manage",在struts.xml也这样配置了:
<package name="default" extends="struts-default">
<action name="manage"
    class="com.zuwoba.presentation.action.manage.ManageAction">
<result name="login">/manage/login.jsp</result>
<result name="success">/manage/misc/index</result>
</action>
</package>
也就是我url应该是http://localhost:8080/myproject/manage这样子的,但是奇怪的是当我点击链接访问时,url却变成:
http://localhost:8080/myproject/manage/这样子了,突然多加了一个“/”,结果就报错说找不到"manage/"这个action,这事真的很奇怪,弄了好久都没弄清楚,到底是哪里出了问题,不知道哪位大侠知道
10 楼 xskowscut 2010-09-25  
struts.action.excludePattern  这个正则貌似还不够准? /dwr/.*才对吧
9 楼 dwangel 2010-09-08  
sswh 写道

这一点我想很多人都没有意识到struts.action.extension是支持空缺后缀的(而且要命的是,这是缺省情况)。
Struts2缺省的配置可以看作是(或者等价于)struts.action.extension=action,(最后有一个逗号)
就是这个逗号导致There is no Action mapped for namespace / and action name ...的问题。
这也是我非常郁闷的,不知道Struts2为何要这样做。
这个问题网上随便一搜大把,但很少有说清楚产生问题的真正原因的。

上面的问题不看源码我估计自己是弄不清楚的了。

/ 是web.xml的welcome-file-list部分设定的默认页面。struts确实没必要做mapping。做了反而会跟Web容器冲突。

当然welcome-file也可以设定action的url
<welcome-file-list>
<welcome-file>login.action</welcome-file>
</welcome-file-list>
8 楼 rainsilence 2010-09-07  
lewisw 写道
说明问题是不错的,不过实际上是不需要看什么源码的,servlet规范中关于url-pattern的规定清楚,及struts.action.extension属性理解清楚就行了。
还有为什么要配置*.jsp? 如果jsp是作为mvc的view,就应该放在WEB-INF目录下保护起来,如果是独立的页面,也不需要struts管(只要你不去配struts.action.extension=xxx,jsp, 自找麻烦)的。

严重同意
7 楼 lihuan5120 2010-09-07  
其实lz总结的不错,思考定位也很准确,确实解决了新手使用struts2时候遇到的一些问题,我觉得很不错。希望大家多给予鼓励,如果lz说的有偏颇之处或者不全,大家尽可指出,但是如果片面的就去评论,难免会有偏颇之处,只是个人的一点看法。
总之,希望楼主再接再厉,呵呵
6 楼 sswh 2010-09-07  
lewisw 写道
servlet规范中关于url-pattern的规定清楚


第1个问题想说明的不是servlet规范中url-pattern的用法(这一点我想只要不是弱智,应该都明白),而是说为什么*.action映射还不能满足Struts2的要求,还需要使用/*作为filter-mapping?

这个问题困扰我比较长时间了,我现在的所能得到的结论就是
使用/*最主要的用处就是处理Struts2-core-***.jar包中的静态资源。
主要是为了减少配置。不然的话,需要同时配置*.action、/struts(或者/static)、(*.jsp特殊情况下需要)为filter-mapping。

lewisw 写道
及struts.action.extension属性理解清楚

这一点我想很多人都没有意识到struts.action.extension是支持空缺后缀的(而且要命的是,这是缺省情况)。
Struts2缺省的配置可以看作是(或者等价于)struts.action.extension=action,(最后有一个逗号)
就是这个逗号导致There is no Action mapped for namespace / and action name ...的问题。
这也是我非常郁闷的,不知道Struts2为何要这样做。
这个问题网上随便一搜大把,但很少有说清楚产生问题的真正原因的。

上面的问题不看源码我估计自己是弄不清楚的了。

lewisw 写道
还有为什么要配置*.jsp?

我个人不赞成从浏览器直接访问JSP页面。但是假如某人想要这么做的话,不配置/*就必须配置*.jsp,
这也是配置/*和配置*.action时应该要知道的差别。
5 楼 xiaoxiaoniao 2010-09-07  
两个问题很清楚怎么解决的,但第一次看这些底层的东西,受益匪浅,谢谢

Good Luck!
4 楼 lewisw 2010-09-07  
说明问题是不错的,不过实际上是不需要看什么源码的,servlet规范中关于url-pattern的规定清楚,及struts.action.extension属性理解清楚就行了。
还有为什么要配置*.jsp? 如果jsp是作为mvc的view,就应该放在WEB-INF目录下保护起来,如果是独立的页面,也不需要struts管(只要你不去配struts.action.extension=xxx,jsp, 自找麻烦)的。
3 楼 francis.xjl 2010-09-07  
lz的总结还是不错的,我以前总是为这个错误头疼半天。
最烦人的是
访问根目录,比如说http://localhost:8080/struts2_project/,也会弹出2、There is no Action mapped for namespace / and action name ...的问题。

我想lz的总结会给我一点启示。
2 楼 crazy24k 2010-09-07  
只是一个web.xml配置的问题。
   着重点在于web容器解析web.xml
1 楼 yangguo 2010-09-07  
折腾,两个问题都不是要看什么源代码的问题。

相关推荐

    struts2帮助文档

    struts2介绍之使用连接标签 struts2入门 struts2进阶学习一 struts2进阶学习二 struts2进阶学习三 struts2进阶学习四 struts2进阶学习一 struts2进阶学习一 struts2进阶学习一 struts2进阶学习一

    struts2jar包

    Struts2是一个强大的Java EE应用程序框架,主要用于构建企业级的Web应用。它的核心是MVC(Model-View-Controller)设计模式,可以帮助开发者组织代码,提高开发效率,并且提供了丰富的特性来支持表单验证、国际化、...

    Struts2漏洞检查工具Struts2.2019.V2.3

    Struts2是一款非常流行的Java Web框架,用于构建企业级应用。然而,随着时间的推移,Struts2在安全方面暴露出了一些重要的漏洞,这给使用该框架的系统带来了潜在的安全风险。"Struts2漏洞检查工具Struts2.2019.V2.3...

    struts2-scan_struts2-scan_struts2scan_scan_struts2漏洞_

    Struts2是一个非常流行的Java MVC框架,用于构建企业级Web应用程序。然而,它在历史上曾出现过多个安全漏洞,其中最著名的就是“Struts2漏洞”。这个标题和描述提到的"struts2-scan"是一种工具,专门用来检测Struts2...

    留言板留言板struts2留言板struts2

    3. **拦截器(Interceptor)**:Struts2的核心组件之一,可以理解为对请求和响应进行预处理和后处理的中间层。拦截器链是Struts2的一大特色,允许开发者自定义拦截器,实现如权限验证、日志记录、事务管理等功能。 4....

    Struts2漏洞测试

    Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试Struts2漏洞测试...

    struts2小程序 struts2代码

    Struts2是一个强大的Java web应用程序框架,用于构建和管理MVC(模型-视图-控制器)架构的应用。这个“struts2小程序”很可能是开发者利用Struts2框架开发的一个小型项目,可能包含了基本的CRUD操作或其他特定功能。...

    struts2项目开发

    Struts2 是一个基于 Java Web 的框架,广泛应用于 Web 应用程序的开发。下面将从 Struts2 项目开发的角度,详细介绍 Struts2 框架的应用、开发流程、技术架构、实践经验等方面的知识点。 项目需求分析 在 Struts2 ...

    Struts2视频教程

    - **Action类详解**:Action类是Struts2的核心组件之一,负责处理用户的请求并返回相应的结果。了解如何编写Action类、设置其属性以及处理请求参数至关重要。 - **Result配置**:Result用于指定Action执行后的结果...

    struts2-core.jar

    struts2-core-2.0.1.jar, struts2-core-2.0.11.1.jar, struts2-core-2.0.11.2.jar, struts2-core-2.0.11.jar, struts2-core-2.0.12.jar, struts2-core-2.0.14.jar, struts2-core-2.0.5.jar, struts2-core-2.0.6.jar,...

    struts2 总结工程大全

    struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全...

    struts1和struts2的区别

    - **Struts2**: 每个Action实例都只服务于一次请求,之后会被销毁。这样可以确保每个Action实例都是干净的状态,不会出现意外的数据污染。同时,这种方式也降低了内存消耗。 #### Servlet依赖 - **Struts1**: ...

    Struts2接口文档

    Struts2是一个强大的Java web应用程序开发框架,它基于Model-View-Controller(MVC)设计模式,旨在简化创建用户交互式、数据驱动的web应用的过程。这个“Struts2接口文档”是开发者的重要参考资料,提供了关于...

    struts2jar.zip

    Struts2是一个强大的Java web应用程序框架,它基于Model-View-Controller(MVC)设计模式,为开发者提供了构建可维护性、可扩展性良好的企业级应用的工具。这个"struts2jar.zip"压缩包包含了Struts2学习和研究的基础...

    struts2中文学习文档

    在Struts2之前,WebWork是另一个流行的轻量级框架,Struts2在设计上借鉴了很多WebWork的理念和特性,因此可以说WebWork是Struts2的基础之一。 ### Struts2与WebWork的关系 Struts2和WebWork都属于MVC(Model-View-...

    struts2 最新漏洞 S2-016、S2-017修补方案 .docx

    Struts2 是一个基于 Java 的 Web 应用程序框架,由 Apache 软件基金会维护。最近,Struts2 发生了两个严重的漏洞,分别是 S2-016 和 S2-017,这两个漏洞可能会导致攻击者执行恶意代码,从而危害到网站的安全。 S2-...

    Struts2教学视频

    Struts2是一个强大的Java web开发框架,用于构建可维护、可扩展且结构良好的应用程序。它在MVC(Model-View-Controller)设计模式的基础上提供了一种实现方式,使得开发者能够更方便地处理用户请求,控制业务逻辑,...

    struts2-showcase.rar

    2. **拦截器(Interceptors)**:Struts2的核心功能之一,拦截器可以插在Action调用之前和之后,实现如日志、事务管理、验证等通用功能,增强了代码的可复用性。 3. **动态方法调用(Dynamic Method Invocation,DMI...

    Struts2 Struts2 超好的Struts2 pdf 文档

    Struts2是一个基于MVC(Model-View-Controller)设计模式的Java web应用程序框架,它在Web开发领域中被广泛使用。这个“超好的Struts2 pdf 文档”很可能包含了关于Struts2的全面介绍、核心概念、配置、拦截器、结果...

    struts2 ,struts2 demo

    这个“struts2,struts2 demo”很显然是一个包含Struts2框架示例代码的压缩包,旨在帮助开发者理解和学习如何在实际项目中运用Struts2。 **1. Struts2简介** Struts2是Apache软件基金会下的一个开源项目,它继承了...

Global site tag (gtag.js) - Google Analytics