论坛首页 Java企业应用论坛

关于struts2原理的几点疑惑和大家讨论下

浏览 8050 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-04-17  
1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)
3 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action
4 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
5 ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
6 ActionProxy创建一个ActionInvocation的实例。
7 ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper

上述是大家熟知的struts2原理
在下有几点疑问:
疑问1:第三步中,ActionMapper如何判断请求是action请求
疑问2:第七步中,ActionInvocation实例使用命名模式来调用,何谓命名模式?
疑问3:第七步中,调用action的前后要调用一系列的拦截器,请问拦截器的作用是什么?
   发表时间:2013-04-17  
1、来自客户端的都是httprequest,ActionMapper只是负责将请求映射到具体的Action上处理
2、ActionInvocation使用的是命令模式
3、拦截器Intercepter可以完成额外的工作,比如TokenInterceptor可以在执行具体的业务前后增加对token的检验,又比如RolesInterceptor可以检验权限等,将这些功能与核心代码分离,AOP思想
0 请登录后投票
   发表时间:2013-04-17  
cectsky 写道
1、来自客户端的都是httprequest,ActionMapper只是负责将请求映射到具体的Action上处理
2、ActionInvocation使用的是命令模式
3、拦截器Intercepter可以完成额外的工作,比如TokenInterceptor可以在执行具体的业务前后增加对token的检验,又比如RolesInterceptor可以检验权限等,将这些功能与核心代码分离,AOP思想

第三点解答的不错,1,2您等于木有说啊,我想知道的,1是如何判断一个请求是action,2是命名模式是什么意思,您如果只说了第三点我会觉得你是个高手,明明不知道还凑了1,2点,我就觉得画蛇添足了,不过还是谢谢您
0 请登录后投票
   发表时间:2013-04-17  
mumuaimao2009 写道
cectsky 写道
1、来自客户端的都是httprequest,ActionMapper只是负责将请求映射到具体的Action上处理
2、ActionInvocation使用的是命令模式
3、拦截器Intercepter可以完成额外的工作,比如TokenInterceptor可以在执行具体的业务前后增加对token的检验,又比如RolesInterceptor可以检验权限等,将这些功能与核心代码分离,AOP思想

第三点解答的不错,1,2您等于木有说啊,我想知道的,1是如何判断一个请求是action,2是命名模式是什么意思,您如果只说了第三点我会觉得你是个高手,明明不知道还凑了1,2点,我就觉得画蛇添足了,不过还是谢谢您


1、如何判断一个请求是action??请求和action根本就不是一个概念,action是负责accept和redirect请求的,根本没有判断,只有映射。
2、都说了是命令模式,你还在那说命名模式,命毛的名
0 请登录后投票
   发表时间:2013-04-17  
cectsky 写道
mumuaimao2009 写道
cectsky 写道
1、来自客户端的都是httprequest,ActionMapper只是负责将请求映射到具体的Action上处理
2、ActionInvocation使用的是命令模式
3、拦截器Intercepter可以完成额外的工作,比如TokenInterceptor可以在执行具体的业务前后增加对token的检验,又比如RolesInterceptor可以检验权限等,将这些功能与核心代码分离,AOP思想

第三点解答的不错,1,2您等于木有说啊,我想知道的,1是如何判断一个请求是action,2是命名模式是什么意思,您如果只说了第三点我会觉得你是个高手,明明不知道还凑了1,2点,我就觉得画蛇添足了,不过还是谢谢您


1、如何判断一个请求是action??请求和action根本就不是一个概念,action是负责accept和redirect请求的,根本没有判断,只有映射。
2、都说了是命令模式,你还在那说命名模式,命毛的名

您还是不知道我问的是什么,我问的是actionMapper如何判断是否要调用一个action
您说是命令模式?什么叫命令模式呢?就这样给我们小白解释啊?我倒
0 请登录后投票
   发表时间:2013-04-17  
mumuaimao2009 写道
cectsky 写道
mumuaimao2009 写道
cectsky 写道
1、来自客户端的都是httprequest,ActionMapper只是负责将请求映射到具体的Action上处理
2、ActionInvocation使用的是命令模式
3、拦截器Intercepter可以完成额外的工作,比如TokenInterceptor可以在执行具体的业务前后增加对token的检验,又比如RolesInterceptor可以检验权限等,将这些功能与核心代码分离,AOP思想

第三点解答的不错,1,2您等于木有说啊,我想知道的,1是如何判断一个请求是action,2是命名模式是什么意思,您如果只说了第三点我会觉得你是个高手,明明不知道还凑了1,2点,我就觉得画蛇添足了,不过还是谢谢您


1、如何判断一个请求是action??请求和action根本就不是一个概念,action是负责accept和redirect请求的,根本没有判断,只有映射。
2、都说了是命令模式,你还在那说命名模式,命毛的名

您还是不知道我问的是什么,我问的是actionMapper如何判断是否要调用一个action
您说是命令模式?什么叫命令模式呢?就这样给我们小白解释啊?我倒


1、ActionMapper获取xml中action的配置信息,装配成ActionMapping对象,当dispatchAction收到request后,寻找是否有对于的ActionMapping对象,有就调用反射调用action的方法,没有就exception

2、命令模式,google之,设计模式不是简单能说明白的,看看例子
0 请登录后投票
   发表时间:2013-04-17   最后修改:2013-04-17
关于第三步的疑问:

1. 查看 org.apache.struts2.dispatcher.mapper.DefaultActionMapper.getMapping 这个方法,
   逻辑是会先把你的 requestURI取到, 然后去掉后缀 (你如果没有配置, 默认是.action, 由struts.action.extension 配置项指定, 多个可以用逗号隔开)
   看 org.apache.struts2.dispatcher.mapper.DefaultActionMapper.dropExtension
2. 去掉后缀后 解析这个路径, 得到 该路径对应的 namespance, action name
   看 org.apache.struts2.dispatcher.mapper.DefaultActionMapper.parseNameAndNamespace

3. 如果解析得到null, 那么就不会进入到对应的action里面
   如果解析得到action存在的话, 就看是不是需要用!method表达式指定的方法
   if (allowDynamicMethodCalls) {
            // handle "name!method" convention.
            String name = mapping.getName();
            int exclamation = name.lastIndexOf("!");
            if (exclamation != -1) {
                mapping.setName(name.substring(0, exclamation));
                mapping.setMethod(name.substring(exclamation + 1));
            }
        }
通过以上3步, 就得到一个完整的actionMapping了.

4. 得到actionMapping后, 就交给Dispacher 去处理执行了
  看 org.apache.struts2.dispatcher.Dispatcher.serviceAction, 通过actionMapping等信息可以得到一个ActionProxy, 接下来就是执行了(先执行iterceptor, 再action, 具体看:com.opensymphony.xwork2.DefaultActionInvocation.invoke()  可以得到答案)
0 请登录后投票
   发表时间:2013-04-17  
关于第三步的疑问:
0 请登录后投票
   发表时间:2013-04-18  
wujiazhao88 写道
关于第三步的疑问:

1. 查看 org.apache.struts2.dispatcher.mapper.DefaultActionMapper.getMapping 这个方法,
   逻辑是会先把你的 requestURI取到, 然后去掉后缀 (你如果没有配置, 默认是.action, 由struts.action.extension 配置项指定, 多个可以用逗号隔开)
   看 org.apache.struts2.dispatcher.mapper.DefaultActionMapper.dropExtension
2. 去掉后缀后 解析这个路径, 得到 该路径对应的 namespance, action name
   看 org.apache.struts2.dispatcher.mapper.DefaultActionMapper.parseNameAndNamespace

3. 如果解析得到null, 那么就不会进入到对应的action里面
   如果解析得到action存在的话, 就看是不是需要用!method表达式指定的方法
   if (allowDynamicMethodCalls) {
            // handle "name!method" convention.
            String name = mapping.getName();
            int exclamation = name.lastIndexOf("!");
            if (exclamation != -1) {
                mapping.setName(name.substring(0, exclamation));
                mapping.setMethod(name.substring(exclamation + 1));
            }
        }
通过以上3步, 就得到一个完整的actionMapping了.

4. 得到actionMapping后, 就交给Dispacher 去处理执行了
  看 org.apache.struts2.dispatcher.Dispatcher.serviceAction, 通过actionMapping等信息可以得到一个ActionProxy, 接下来就是执行了(先执行iterceptor, 再action, 具体看:com.opensymphony.xwork2.DefaultActionInvocation.invoke()  可以得到答案)

不错
0 请登录后投票
   发表时间:2013-04-22  
在web.xml中配置的Struts2的Filter相应的doFilter中会执行如下代码:
ActionMapping mapping = prepare.findActionMapping(request, response, true);
				if (mapping == null) {
					boolean handled = execute.executeStaticResourceRequest(request, response);
					if (!handled) {
						chain.doFilter(request, response);
					}
				} else {
					execute.executeAction(request, response, mapping);
				}

而findActionMapping会根据request的uri来获取,如果请求没有和配置的extension匹配,会返回null,代码:
    public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
        ActionMapping mapping = new ActionMapping();
        String uri = getUri(request);

        int indexOfSemicolon = uri.indexOf(";");
        uri = (indexOfSemicolon > -1) ? uri.substring(0, indexOfSemicolon) : uri;

        uri = dropExtension(uri, mapping);
        if (uri == null) {
            return null;
        }

        parseNameAndNamespace(uri, mapping, configManager);
        handleSpecialParameters(request, mapping);
        return parseActionName(mapping);
    }
    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
                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;
    }

见第一段代码,如果没有相应匹配的请求,则会执行后续的filter,都不存在,会返回404
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics