- 浏览: 64266 次
- 性别:
- 来自: 北京
最新评论
-
wucaifang819787:
你好!麻烦问下不知道哪个图片行不行的:http://dl.it ...
struts2源码浅析(四) -
ChenXzh:
高手,佩服得五体投地
关于struts2报There is no Action mapped for namespace / and action name xxx_xxx
接上篇http://mazhiyuan.iteye.com/blog/1202086,本文着重dispatcher和filter的探讨。
Dispatcher已经在之前讲过,FilterDispatcher是Struts2的核心控制器,首先看一下init()方法。
public void init(FilterConfig filterConfig) throws ServletException { try { this.filterConfig = filterConfig; initLogging(); //创建dispatcher,前面都已经讲过啰 dispatcher = createDispatcher(filterConfig); dispatcher.init(); //注入将FilterDispatcher中的变量通过container注入,如下面的staticResourceLoader dispatcher.getContainer().inject(this); //StaticContentLoader在BeanSelectionProvider中已经被注入了依赖关系:DefaultStaticContentLoader //可以在struts-default.xml中的<bean>可以找到 staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig)); } finally { ActionContext.setContext(null); } } //下面来看DefaultStaticContentLoader的setHostConfig public void setHostConfig(HostConfig filterConfig) { //读取初始参数pakages,调用parse(),解析成类似/org/apache/struts2/static,/template的数组 String param = filterConfig.getInitParameter("packages"); //"org.apache.struts2.static template org.apache.struts2.interceptor.debugging static" String packages = getAdditionalPackages(); if (param != null) { packages = param + " " + packages; } this.pathPrefixes = parse(packages); initLogging(filterConfig); }
doFilter方法,struts2中最富盛名的方法了,每当有一个Request,都会调用这些Filters的doFilter方法
先来张图
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; ServletContext servletContext = getServletContext(); String timerKey = "FilterDispatcher_doFilter: "; try { // FIXME: this should be refactored better to not duplicate work with the action invocation //先看看ValueStackFactory所注入的实现类OgnlValueStackFactory //new OgnlValueStack ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack(); ActionContext ctx = new ActionContext(stack.getContext()); ActionContext.setContext(ctx); UtilTimerStack.push(timerKey); //如果是multipart/form-data就用MultiPartRequestWrapper进行包装 //MultiPartRequestWrapper是StrutsRequestWrapper的子类,两者都是HttpServletRequest实现 //此时在MultiPartRequestWrapper中就会把Files给解析出来,用于文件上传 //所有request都会StrutsRequestWrapper进行包装,StrutsRequestWrapper是可以访问ValueStack //下面是参见Dispatcher的wrapRequest // String content_type = request.getContentType(); //if(content_type!= null&&content_type.indexOf("multipart/form-data")!=-1){ //MultiPartRequest multi =getContainer().getInstance(MultiPartRequest.class); //request =new MultiPartRequestWrapper(multi,request,getSaveDir(servletContext)); //} else { // request = new StrutsRequestWrapper(request); // } request = prepareDispatcherAndWrapRequest(request, response); ActionMapping mapping; try { //根据url取得对应的Action的配置信息 //看一下注入的DefaultActionMapper的getMapping()方法.Action的配置信息存储在 ActionMapping对象中 mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager()); } catch (Exception ex) { log.error("error getting ActionMapping", ex); dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex); return; } //如果找不到对应的action配置,则直接返回。比如你输入***.jsp等等 //这儿有个例外,就是如果path是以“/struts”开头,则到初始参数packages配置的包路径去查找对应的静态资源并输出到页面流中,当然.class文件除外。如果再没有则跳转到404 if (mapping == null) { // there is no action in this request, should we look for a static resource? String resourcePath = RequestUtils.getServletPath(request); if ("".equals(resourcePath) && null != request.getPathInfo()) { resourcePath = request.getPathInfo(); } if (staticResourceLoader.canHandle(resourcePath)) { // 在DefaultStaticContentLoader中:return serveStatic && (resourcePath.startsWith("/struts") || resourcePath.startsWith("/static")); staticResourceLoader.findStaticResource(resourcePath, request, response); } else { // this is a normal request, let it pass through chain.doFilter(request, response); } // The framework did its job here return; } //正式开始Action的方法 dispatcher.serviceAction(request, response, servletContext, mapping); } finally { try { ActionContextCleanUp.cleanUp(req); } finally { UtilTimerStack.pop(timerKey); } } }
//下面是ActionMapper接口的实现类 DefaultActionMapper的getMapping()方法的源代码: public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) { ActionMapping mapping = new ActionMapping(); String uri = getUri(request);//得到请求路径的URI,如:testAtcion.action或testAction.do int indexOfSemicolon = uri.indexOf(";");//修正url的带;jsessionid 时找不到而且的bug uri = (indexOfSemicolon > -1) ? uri.substring(0, indexOfSemicolon) : uri; uri = dropExtension(uri, mapping);//删除扩展名,默认扩展名为action if (uri == null) { return null; } parseNameAndNamespace(uri, mapping, configManager);//匹配Action的name和namespace handleSpecialParameters(request, mapping);//去掉重复参数 //如果Action的name没有解析出来,直接返回 if (mapping.getName() == null) { returnnull; } //下面处理形如testAction!method格式的请求路径 if (allowDynamicMethodCalls) { // handle "name!method" convention. String name = mapping.getName(); int exclamation = name.lastIndexOf("!");//!是Action名称和方法名的分隔符 if (exclamation != -1) { mapping.setName(name.substring(0, exclamation));//提取左边为name mapping.setMethod(name.substring(exclamation + 1));//提取右边的method } } return mapping; }
从代码中看出,getMapping()方法返回ActionMapping类型的对象,该对象包含三个参数:Action的name、namespace和要调用的方法method。
如果getMapping()方法返回ActionMapping对象为null,则FilterDispatcher认为用户请求不是Action,自然另当别论.
FilterDispatcher会做一件非常有意思的事:如果请求以/struts开头,会自动查找在web.xml文件中配置的 packages初始化参数
<filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class> <init-param> <param-name>packages</param-name> <param-value>com.mazhiyuan.action</param-value> </init-param> </filter>
FilterDispatcher会将com.lizanhong.action包下的文件当作静态资源处理,即直接在页面上显示文件内容,不过会忽略扩展名为class的文件。
比如在com.mazhiyuan.action包下有一个mazhiyuan.txt的文本文件,其内容为“mazhiyuan”,访问 http://localhost:8081/Struts2Demo/struts/mazhiyuan.txt时会输出txt中的内容
FilterDispatcher.findStaticResource()方法
protectedvoid findStaticResource(String name, HttpServletRequest request, HttpServletResponse response) throws IOException { if (!name.endsWith(".class")) {//忽略class文件 //遍历packages参数 for (String pathPrefix : pathPrefixes) { InputStream is = findInputStream(name, pathPrefix);//读取请求文件流 if (is != null) { ... // set the content-type header String contentType = getContentType(name);//读取内容类型 if (contentType != null) { response.setContentType(contentType);//重新设置内容类型 } ... try { //将读取到的文件流以每次复制4096个字节的方式循环输出 copy(is, response.getOutputStream()); } finally { is.close(); } return; } } } }
如果用户请求的资源不是以/struts开头——可能是.jsp文件,也可能是.html文件,则通过过滤器链继续往下传送,直到到达请求的资源为止。
如果getMapping()方法返回有效的ActionMapping对象,则被认为正在请求某个Action,将调用Dispatcher.serviceAction(request, response, servletContext, mapping)方法,该方法是处理Action的关键所在。
本文到此结束,下一篇讲讲serviceAction,并以此结束struts2的源码之旅。
下一篇:http://mazhiyuan.iteye.com/blog/1202128
发表评论
-
JAVA多线程-厕所问题
2012-11-22 11:55 1984在http://my.oschina.net/xpbug/bl ... -
第八章 最大自序列和
2012-11-01 20:29 899第八章的问题是常见的---最大自序列和 的问题 书中提 ... -
第二章 旋转字符串的思考
2012-10-26 16:09 893编程珠玑第二章旋转字符串,abcdefg向左旋转3位,变为de ... -
Mongdb的upsert出现E11000 duplicate key errors的错误分析
2012-10-25 17:36 9213昨日上线的系统,今天查日志时发现有不少E11000 dupli ... -
开源的Mongodb java client -- mango发布
2012-07-20 21:53 1885Mango ---- 一个非常简单的操作mongodb的 ... -
SOAP消息
2012-03-05 20:37 1288本文转自:http://blog.csdn.net/chang ... -
wsdl文档结构
2012-03-05 20:32 1553本文转自:http://blog.csdn.net/chang ... -
浅出Apache Cxf
2012-03-05 20:14 0由于业务需要,开放了系统的 Web Se ... -
struts2源码浅析(四)
2011-10-19 17:15 1594接上一篇讲了filter后,现在request到了action ... -
struts2源码浅析(二)
2011-10-19 16:34 2279接上一篇http://mazhiyuan.iteye.com/ ... -
struts2源码浅析(一)
2011-10-19 16:18 17861. Struts2架构图 请求首先通过Filter ... -
struts2.1权威指南-笔记
2010-12-19 22:36 11311.struts 1.x 和 struts 2.x的 ... -
Hibernate学习总结4---对象状态
2010-12-10 16:14 993session 的几个主要方法: 1,save方法和persi ... -
Hibernate学习总结3 --配置文件
2010-12-10 16:10 995如果不希望使用默认的hibernate.cfg.xml 文件作 ... -
Hibernate 学习总结一
2010-12-10 14:54 895引入: 模型不匹配(阻 ... -
HF servlet&jsp 前6章要点总结
2010-11-21 11:58 935今天有时间把前6章主要讲servlet的内容坐下总结。好了,开 ... -
jquery源码分析之属性篇
2010-11-20 20:09 1954jquery提供了一些快捷函 ... -
HF servelt&jsp 定制标记开发 要点总结
2010-11-13 11:41 13351.标记文件使用一个页 ... -
bean相关标准动作总结+复习
2010-11-07 23:22 7951.<jsp:useBean>动作会定义一个变量, ... -
HF servlet&jsp ---include 指令和动作元素
2010-11-07 23:02 8371.include的2种方式 include多用于网站中可重用 ...
相关推荐
Struts2 源码分析 Struts2 是一个基于MVC 模式的Web 应用程序框架,它的源码分析可以帮助我们更好地理解框架的内部机制和工作流程。下面是Struts2 源码分析的相关知识点: 1. Struts2 架构图 Struts2 的架构图...
这篇博文“Struts2源码解读”深入剖析了Struts2的核心机制,帮助开发者更好地理解和利用这个框架。源码分析是提升编程技能和解决问题的关键,特别是对于复杂的框架如Struts2,理解其内部工作原理能够帮助我们优化...
通过阅读Struts2的源码,我们可以深入了解框架如何处理请求、如何调度Action以及如何应用拦截器来扩展功能。这有助于开发者更好地定制和优化他们的应用程序,提高代码质量和性能。在实际开发中,对源码的理解能帮助...
最新版的Struts2源码可以从GitHub的Apache官方仓库获取,这为我们提供了深入理解其内部工作原理和定制功能提供了可能。 Struts2的核心特性包括: 1. **Action与结果**:在Struts2中,业务逻辑处理主要由Action类...
struts2源码详细解析51CTO下载-struts2源代码分析(个人觉得非常经典)
在深入理解Struts2的工作原理时,源码分析是必不可少的步骤。Struts2的核心设计理念和设计模式相比Struts1.x有了显著的变化,这使得它成为一个独立且成熟的框架。 首先,Struts2的架构基于WebWork的核心,这意味着...
将Struts 2源码导入Eclipse工程,对于学习和理解框架的工作原理以及进行自定义开发具有重要意义。 首先,导入Struts 2源码到Eclipse需要遵循以下步骤: 1. 下载Struts 2的源码包,通常可以从Apache官方网站获取...
STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析...
压缩包中的"org"目录可能包含了Struts2框架的源码文件,按照包结构组织。这通常包括核心组件、拦截器、结果类型、动作支持、配置处理等模块的源代码。开发者可以深入研究这些源码,了解其工作原理,进行自定义扩展...
Struts2是一个流行的Java Web框架,它简化了MVC(模型-视图-控制器)架构的实现。本文将深入探讨Struts2的...通过深入研究Struts2的源码,我们可以发现其内部工作原理,这对于解决复杂问题和开发自定义插件非常有帮助。
深入理解Struts2的源码对于提升Java Web开发技能,尤其是在面试中讨论底层实现时,具有非常重要的价值。 首先,我们来看看Struts2的核心组件和设计理念: 1. **Action**:在Struts2中,Action类是业务逻辑处理的...
本项目源码提供了一个基础的Struts2应用程序实例,对于初学者来说,这是一个很好的学习资源,可以深入理解Struts2的工作原理和架构。 Struts2的核心组件包括: 1. **Action类**:Action类是业务逻辑的载体,它是...
在深入研究Struts2源码时,我们可以关注以下几个关键部分: 1. **org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter**:这是Struts2的核心过滤器,它初始化并调用Struts2的生命周期。 2. **...
在"struts2源码解析.pdf"文档中,主要探讨了以下几个关键组件及其功能: 1. **ActionContext**: - `ActionContext`是Struts2的核心上下文,它存储了与当前Action执行相关的所有信息,如请求参数、session数据等。...
在深入理解Struts 2的源码之前,我们需要先了解其核心概念和组件。 1. **Action类与ActionMapping** Struts 2的核心是Action类,它是业务逻辑处理的中心。每个Action类对应一个用户请求,处理后返回一个Result。...
深入研究Struts2源码有助于提升对Java Web开发的理解,尤其是对于MVC框架的设计思想、AOP(面向切面编程)的应用以及依赖注入等方面有深刻认识。同时,源码学习也能帮助你更好地定位和解决问题,提高开发效率。
深入学习Struts2的源码,有助于理解其运行机制,从而更好地优化代码、调试问题,甚至开发自己的扩展。对于Java Web开发者来说,掌握Struts2的基本原理和使用技巧,能够显著提高开发效率和应用质量。
此压缩包文件包含的是Struts2的源码,特别适合初学者研究和学习,其中涵盖了拦截器和验证等关键组件的实现。 首先,我们来深入了解Struts2的核心概念: 1. **Action类**:在Struts2中,业务逻辑通常由Action类执行...
在这个"Struts2演示源码"中,我们可以深入理解Struts2的一些核心特性。 首先,关于`Action result`,它是Struts2中的一个关键概念,用于控制请求后的视图呈现。四种转发类型通常包括:`dispatcher`(默认),将请求...
Apache Struts 2 源码(struts-2.5.28.3-src.zip),Apache Struts 2.5.28.3是一个优雅的、可扩展的框架,用于创建企业级 Java Web 应用程序。它可以在完整发行版中使用,也可以作为单独的库、源代码、示例和文档...