`
zddava
  • 浏览: 243679 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Struts2的Action调用(二)

阅读更多
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 2 action 动态调用

    ### Struts 2 Action 动态方法调用详解 #### 一、引言 在Struts 2框架中,Action动态方法调用是一项非常实用的功能。它允许开发者在一个Action类中定义多个处理方法,而不仅仅局限于传统的`execute()`方法。这种...

    Struts2 动态方法调用(十三)

    在Struts2中,动态方法调用(Dynamic Method Invocation,DMI)是一种特性,允许我们通过URL直接调用Action类的方法,而无需在配置文件中显式指定。这在某些情况下提供了更大的灵活性。 在Struts2的动态方法调用中...

    struts2利用通配符调用同一个Action里面不同的方法

    在Struts2中,Action是业务逻辑处理的核心,而通配符的使用则是Struts2框架中一种灵活的配置方式,允许我们以更简洁的方式调用同一个Action中的不同方法。下面我们将深入探讨如何利用Struts2的通配符来实现这一功能...

    Struts2动态方法调用

    Struts2的配置文件(struts.xml)可以通过通配符来定义Action,使得一个Action能够处理多个方法调用。例如,我们可以定义一个Action,然后使用不同的参数值来调用不同的Action方法。这样可以减少Action的数量,简化...

    Struts2 Action参数详细说明

    默认情况下,Struts2会调用Action类中的execute方法来处理请求。但是,通过`method`属性,我们可以指定不同的方法对应不同的Action,这样可以实现一个类中多个方法的映射,提高代码复用性。例如: ```xml &lt;action ...

    struts2一个action处理多个请求 struts2实例

    在Struts2的配置文件(通常为struts.xml或struts.properties)中,我们定义Action的映射规则,包括请求路径、方法调用以及结果视图等。默认情况下,一个Action类对应一个请求URL,但通过特定配置,可以让一个Action...

    一个Action多方法调用的Struts 2的应用程序

    利用Struts 2框架创建一个web项目chap2_e22,实现用户登录过程。具体要求是在loginAction类中分别用login()和registered()处理用户登录和注册的过程,分别创建login.jsp和register.jsp两个页面实现登录和注册的...

    Struts2之异步调用机制详解案例struts014

    这个案例“struts014”很可能展示了如何在Struts2中实现异步调用来处理耗时操作,如数据库查询或复杂计算。 异步调用的基本概念是,客户端(通常是Web浏览器)发起一个请求,服务器不立即返回结果,而是启动一个...

    struts2 Action 包 命名空间 servlet API

    Struts2通过FilterDispatcher这个Servlet过滤器来拦截所有到达服务器的请求,判断是否需要由Struts2框架处理,如果是,则根据配置的Action映射调用相应的execute()方法。 Struts2的包结构清晰,每个包都有其特定的...

    Struts2 in action(struts2实战)

    - **Interceptor**(拦截器):拦截器是Struts2的核心组件,它们按照预定义的顺序对Action的调用进行拦截,实现如日志记录、权限验证、事务管理等功能。 2. **配置方式**: - **XML配置**:传统的Struts2配置通常...

    Struts 2实战 Struts 2 in action 的中文版

    根据提供的信息,我们可以推断出这是一本关于Struts 2框架的书籍——《Struts 2实战 Struts 2 in action 的中文版》。本书主要介绍了Struts 2框架的相关概念、工作原理以及实际应用案例等内容。接下来,我们将根据...

    struts2笔记之动态调用Action指定方法及默认Action

    Struts2 动态调用 Action 指定方法及默认 Action 配置 Struts2 框架中,一个 Action 可以包含多个处理逻辑,而不是只有一个 execute() 方法。在实际开发中,我们经常需要在一个 Action 中实现多个处理逻辑,这样...

    JS调用Struts中的Action

    ### JS调用Struts中的Action #### 背景与概念 在Web开发中,JavaScript(简称JS)作为客户端脚本语言,常被用来增强用户体验、处理表单验证等前端任务。而Struts框架则是Java Web开发中常用的一个MVC(Model-View-...

    struts2动态调用之通配符

    Struts2会根据URL中的部分替换通配符,并尝试调用Action类中的方法。如果找不到与之匹配的方法,Struts2将会回退到默认的执行方法(通常是`execute`)。 为了更高效地利用这一特性,我们需要遵循以下几点: 1. 方法...

    Struts2 in action中文版+配套源代码

    2. **拦截器(Interceptors)**:Struts2的拦截器机制允许开发者定义一系列处理请求的规则,如日志记录、权限检查、事务管理等,这些规则可以在Action执行前后被调用,提高了代码的复用性和模块化。 3. **结果类型...

    ajaxt json 调用struts2 action的实例(myeclipse 直接导入运行)

    ajaxt json 调用struts2 action的实例(myeclipse 直接导入运行) 学习点: 1;怎样在页面用ajax调用struts2的action 2;怎样对struts进行配置 3;ajax的运行历程 最简单明了的实例,清晰的帮你弄清上述概念,运行...

    Struts2 in action 中文版

    3. **FilterDispatcher**:Struts2的核心控制器,负责拦截所有请求,解析并调用相应的Action,然后根据Action的结果进行响应。 4. **配置文件**:Struts2的配置通常存储在XML文件中,包括对Action、拦截器、结果...

    struts2 action的三种访问方式

    在Struts2中,Action是处理用户请求的核心组件。它负责业务逻辑的执行,并将结果返回给视图进行展示。本篇文章将详细介绍Struts2 Action的三种访问方式:传统方式、通配符方式和动态方式。 1. **传统方式(Static ...

    Struts2 in action 中文版.pdf

    《Struts2 in Action》是一本深入探讨Struts2框架的权威著作,中文版的发布使得国内开发者能够更方便地理解和应用这一强大的Java Web开发框架。Struts2是Apache软件基金会旗下的一个开源项目,它是MVC(Model-View-...

    struts2的API耦合与动态方法调用

    login.action`表示两部分,第一部分`login`匹配struts.xml中的action名,第二部分`login`则指定了要调用的具体方法。这种方式提供了更高的灵活性,允许在不修改配置文件的情况下改变Action的执行逻辑。 总的来说,...

Global site tag (gtag.js) - Google Analytics