2. 获得Action Mapping:mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
下面来看一下默认使用的ActionMapper实现DefaultActionMapper的#getMapping():
public ActionMapping getMapping(HttpServletRequest request,
ConfigurationManager configManager) {
ActionMapping mapping = new ActionMapping();// (1)
String uri = getUri(request);// (2)
uri = dropExtension(uri);// (3)
if (uri == null) {
return null;
}
parseNameAndNamespace(uri, mapping, configManager);// (4)
handleSpecialParameters(request, mapping);// (5)
if (mapping.getName() == null) {
return null;
}
if (allowDynamicMethodCalls) {// (6)
String name = mapping.getName();
int exclamation = name.lastIndexOf("!");
if (exclamation != -1) {
mapping.setName(name.substring(0, exclamation));
mapping.setMethod(name.substring(exclamation + 1));
}
}
return mapping;
}
主要有6处需要重点说明:
(1) 关于ActionMapping类,它内部封装了如下5个字段:
private String name;// Action名
private String namespace;// Action名称空间
private String method;// 执行方法
private Map params;// 可以通过set方法设置的参数
private Result result;// 返回的结果
这些在配置文件中都是可设置的,确定了ActionMapping类的各个字段的值,就可以对请求的Action进行调用了。
(2) String uri = getUri(request);
这个步骤用于获取请求的URI,源代码如下:
String getUri(HttpServletRequest request) {
// handle http dispatcher includes.
String uri = (String) request.getAttribute("javax.servlet.include.servlet_path");
if (uri != null) {
return uri;
}
uri = RequestUtils.getServletPath(request);
if (uri != null && !"".equals(uri)) {
return uri;
}
uri = request.getRequestURI();
return uri.substring(request.getContextPath().length());
}
这个方法首先判断请求是否来自于一个jsp的include,如果是,那么请求的"javax.servlet.include.servlet_path"属性可以获得include的页面uri,否则通过一般的方法获得请求的uri,最后返回去掉ContextPath的请求路径,比如http://127.0.0.1:8087/test/jsp/index.jsp?param=1,返回的为/jsp/index.jsp。去掉了ContextPath和查询字符串等。
(3) uri = dropExtension(uri);
负责去掉Action的"扩展名"(默认为"action"),源代码如下:
String dropExtension(String name) {
if (extensions == null) {
return name;
}
Iterator it = extensions.iterator();
while (it.hasNext()) {
String extension = "." + (String) it.next();
if (name.endsWith(extension)) {
name = name.substring(0, name.length() - extension.length());
return name;
}
}
return null;
}
注意,这个步骤对于不是以特地扩展名结尾的请求会返回一个null的uri,进而#getMapping()也会返回null,FilterDispatcher的#doFilter()就会把这次请求当作一个普通请求对待了。
(4) parseNameAndNamespace(uri, mapping, configManager);
此方法用于解析Action的名称和命名空间,并赋给ActionMapping对象。源代码如下:
void parseNameAndNamespace(String uri, ActionMapping mapping, ConfigurationManager configManager) {
String namespace, name;
/* 例如 http://127.0.0.1:8087/teststruts/namespace/name.action?param=1 */
/* dropExtension()后,获得uri为/namespace/name */
int lastSlash = uri.lastIndexOf("/");
if (lastSlash == -1) {
namespace = "";
name = uri;
} else if (lastSlash == 0) {
namespace = "/";
name = uri.substring(lastSlash + 1);
} else if (alwaysSelectFullNamespace) {// alwaysSelectFullNamespace默认为false,代表是否将最后一个"/"前的字符全作为名称空间。
namespace = uri.substring(0, lastSlash);// 获得字符串 namespace
name = uri.substring(lastSlash + 1);// 获得字符串 name
} else {
/* 例如 http://127.0.0.1:8087/teststruts/namespace1/namespace2/actionname.action?param=1 */
/* dropExtension()后,获得uri为/namespace1/namespace2/actionname */
Configuration config = configManager.getConfiguration();
String prefix = uri.substring(0, lastSlash);// 获得 /namespace1/namespace2
namespace = "";
// 如果配置文件中有一个包的namespace是 /namespace1/namespace2,那么namespace为/namespace1/namespace2,name为actionname
// 如果配置文件中有一个包的namespace是 /namespace1,那么namespace为/namespace1,name为/namespace2/actionname
for (Iterator i = config.getPackageConfigs().values().iterator(); i
.hasNext();) {
String ns = ((PackageConfig) i.next()).getNamespace();
if (ns != null && prefix.startsWith(ns) && (prefix.length() == ns.length() || prefix.charAt(ns.length()) == '/')) {
if (ns.length() > namespace.length()) {
namespace = ns;
}
}
}
name = uri.substring(namespace.length() + 1);
}
if (!allowSlashesInActionNames && name != null) {// allowSlashesInActionNames代表是否允许"/"出现在Action的名称中,默认为false
int pos = name.lastIndexOf('/');
if (pos > -1 && pos < name.length() - 1) {
name = name.substring(pos + 1);
}
}// 以 name = /namespace2/actionname 为例,经过这个if块后,name = actionname
mapping.setNamespace(namespace);
mapping.setName(name);
}
(5) handleSpecialParameters(request, mapping);
此方法用于处理Struts框架定义的四种特殊的prefix:
下边是struts2的javadoc里提供的例子:
Method prefix:调用baz的另外一个方法"anotherMethod"而不是"execute"
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="method:anotherMethod" value="Cancel"/>
</a:form>
Action prefix:调用anotherAction的"execute"
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="action:anotherAction" value="Cancel"/>
</a:form>
Redirect prefix:将请求重定向,下例中为定向到google
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="redirect:www.google.com" value="Cancel"/>
</a:form>
Redirect-action prefix:重定向action,下例中为定向到dashboard.action
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="redirect-action:dashboard" value="Cancel"/>
</a:form>
handleSpecialParameters的源代码如下:
public void handleSpecialParameters(HttpServletRequest request, ActionMapping mapping) {
Set<String> uniqueParameters = new HashSet<String>();
Map parameterMap = request.getParameterMap();
for (Iterator iterator = parameterMap.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
if (key.endsWith(".x") || key.endsWith(".y")) {// 去掉图片按钮的位置信息,具体情况我也不是很了解
key = key.substring(0, key.length() - 2);
}
// 处理四种特殊的prefix:Method prefix,Action prefix,Redirect prefix,Redirect-action prefix
if (!uniqueParameters.contains(key)) {
ParameterAction parameterAction = (ParameterAction) prefixTrie.get(key);
if (parameterAction != null) {// 当发现某种特殊的predix时
parameterAction.execute(key, mapping);// 调用它的execute方法,在DefaultActionMapper的构造函数中定义
uniqueParameters.add(key);// 下边已经break了为什么还要把key加入到排重的Set里呢??
break;
}
}
}
}
(6) 处理调用的不是execute方法的情况:
Struts框架也可以处理"name!method"形式的action调用,碰到这种情况,在此处将name和method分别解析出来然后赋给ActionMapping对象。
分享到:
相关推荐
struts 1框架的动态调用也许你会,但是struts2 的动态调用更经典,这个文档让你玩转struts 2 动态调用.......
struts2利用通配符调用同一个Action里面不同的方法,在struts.xml配置文件中将请求方法的不相同部分抽象成“*".
利用Struts 2框架创建一个web项目chap2_e22,实现用户登录过程。具体要求是在loginAction类中分别用login()和registered()处理用户登录和注册的过程,分别创建login.jsp和register.jsp两个页面实现登录和注册的...
ajaxt json 调用struts2 action的实例(myeclipse 直接导入运行) 学习点: 1;怎样在页面用ajax调用struts2的action 2;怎样对struts进行配置 3;ajax的运行历程 最简单明了的实例,清晰的帮你弄清上述概念,运行...
JS调用Struts中的ActionJS调用Struts中的ActionJS调用Struts中的Action
struts2动态调用之通配符,相当于是改进的method动态调用方法,减少对同一action不同method的多次配置
第1章 Struts 2:现代Web框架 2 1.1 Web应用程序:快速学习 2 1.1.1 构建Web应用程序 2 1.1.2 基础技术简介 3 1.1.3 深入研究 6 1.2 Web应用程序框架 7 1.2.1 什么是框架 7 1.2.2 为什么使用框架 8 1.3 Struts 2框架...
1 在Action实现类方面的对比:Struts 1要求Action类继承一个抽象基类;Struts 1的一个具体问题是使用抽象类编程而不是接口。Struts 2 Action类可以实现一...Struts 2 Action可以通过初始化、设置属性、调用方法来测试。
很经典的struts2开发实例,其中的action类的写法可以教你很清楚的了解具体的调用过程回给你开发带来很大的帮助
struts动态访问调用之一,采用method属性,同一个Action内的不同方法来响应用户请求
首先,Struts的ActionServlet接收到一个请求,然后根据struts-config.xml的配置定位到相应的mapping (映射);接下来如果form的范围是request或者在定义的范围中找不到这个form,创建一个新的form实例;取得form...
详细讲解struts2中单个action中多个处理逻辑的配置方法, 以及默认Action的配置.
另外,按照惯例,在Struts1.x中只有“execute”方法能调用Action, 但在Struts2中并非必要,任何声明为public String methodName() 方法,都能通过配置来调用Action。 最后,和Struts1.x最大的革命性的不同是,...
Namespace、自定义Action、路径问题、通配符、包含模块配置文件、默认Action、接受用户输入、服务器跳转、Action中访问web元素、简单数据校验、调用Action的自定义方法 5struts2国际化 ......... 6 struts2输入校验...
目的:主要为了在一个Action成功后跳转调用另一个程序。 Struts2.xml [html] 代码如下: <?xml version=”1.0″ encoding=”UTF-8″?> <!DOCTYPE struts PUBLIC “-//Apache Software Foundation//DTD ...
最近修了几个struts2.1升级到2.3后动态方法调用失效的bug,深有感悟, 但是我那种原始方法有一个局限,就是在submit那里写下的action不起作用,就算启动了动态方法调用也不行(我想应该是struts2.3的一个bug),所以...
ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类。例如,用户注册示例将找到UserReg类。 ActionProxy创建一个ActionInvocation实例,同时ActionInvocation通过...
2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 3 接着FilterDispatcher被调用,...
十二、总结 本教程对struts2的基本知识进行了一些说明,关于struts2的更多详细内容应参看struts2的官方文档及提供的app实例。 下面对struts2的基本执行流程作一简要说明,此流程说明可以结合官方提供的struts2结构图...
Struts2简介以及Struts2的环境配置和Struts2框架实现功能的原理