java.lang.Object
|
+--javax.servlet.GenericServlet
|
+--javax.servlet.http.HttpServlet
|
+--org.apache.struts.action.ActionServlet
Struts提供了一个缺省版本的ActionServlet类,你可以继承这个类,覆盖其中的一些方法来达到你的特殊处理的需要。ActionServlet继承与javax.servlet.http.HttpServlet,所以在本质上它和一个普通的servlet没有区别,你完全可以把它当做一个servlet来看待,只是在其中完成的功能不同罢了。ActionServlet主要完成如下功能:
将一个来自客户端的URI映射到一个相应的Action类
- 如果是这个Action类是第一次被调用,那么实例化一个并放入缓存
- 如果在配置文件(struts-config.xml)中指定了相应的ActionForm,那么从Request中抓取数据填充FormBean
- 调用这个Action类的perform()方法,传入ActionMapping的一个引用,对应的ActionForm、以及由容器传给ActionServlet的HttpServletRequest、HttpServletResponse对象。
确省版本的ActionServlet会从配置文件web.xml中读取如下初始化参数:
- application
应用使用的资源包(resources bundle)的基类
- factory
用于创建应用的MessageResources对象的MessageResourcesFactory的类名。确省是org.apache.struts.util.PropertyMessageResourcesFactory。
- config
Struts的配置文件,确省是/WEB-INF/struts-config.xml。注意这儿是与应用Context关联的相对路径。
- content
定义了确省的内容类型和编码格式,它会被自动地被设置到每个response中,如果JSP/Servlet中没有明确的设置。确省是text/html。
- debug
调试信息的级别。默认为0,比当前级别高的调试信息会被log到日志文件中。
- detail
与debug的作用类似,只是这个detail是initMapping()时专用的。调试信息会被打印到System.out,而不是日志文件。
- formBean
ActionFormBean的实现类,确省为org.apache.struts.action.ActionFormBean
- forward
应用中使用的ActionForward类,确省是org.apache.struts.action.ActionForward。
- locale
指定了确省使用的Locale对象。设为true,当得到一个session时,会自动在session中存储一个以Action.LOCALE_KEY标示的Locale对象,如果session中还没有与Action.LOCALE_KEY绑定的Locale对象。
- mapping
应用中使用的ActionMapping类,确省是org.apache.struts.action.ActionMapping。
- multipartClass
文件上传使用的MutipartRequestHandler的实现类。确省为org.apache.struts.upload.DiskMultipartRequestHandler
- nocache
如果设为true,那么ActionServlet会自动在每个到客户端的响应中添加nocache的HTML头,这样客户端就不会对应用中的页面进行缓存。确省为false
- null
如果设置为true,那么应用在得到一个未定义的message资源时,会返回null,而不是返回一个错误信息。确省是true。
- maxFileSize
文件上传的大小上限,确省为250M
- bufferSize
文件上传时的缓冲区的大小,确省为4M
- tempDir
设置用于上传时的临时目录。工作目录会作为一个Servlet环境(Context)的属性提供。
- validate
Are we using the new configuration file format?确省为true。
- validating
在解析配置XML文件是是否进行有效性的验证。确省为true
ActionServlet中应用了命令设计模式。
一个Servlet在由容器生成时,首先会调用init()方法进行初始化,在接到一个HTTP请求时,调用相应的方法进行处理;比如GET请求调用doGet()方法,POST请求调用doPost()方法。所以首先看看ActionServlet的init()方法,你就会很清楚为什么ActionServlet可以完成这些功能了。
init()
在它的init()方法中,ActionServlet依次调用如下protected的方法完成初始化:
- initActions() - 大家可能还曾有这个疑问:Struts为什么可以找到一个请求URI对应的action类呢?答案就在这儿,ActionServlet有一个actions属性,类型为org.apache.struts.util.FastHashMap,用于存储以类的全名为key的已实例化的Action类。在init()时首先调用的就是initActions()方法,在这个方法中只是简单的清除map中的所有的名值对,
-
- synchronized (actions) {
- actions.setFast(false);
- actions.clear();
- actions.setFast(true);
- }
首先把actions设为slow模式,这时对FastHashMap的访问是线程同步的,然后清除actions中的所有的已存在的名/值对,最后再把actions的模式设为fast。由于FastHashMap是struts在java.util.HashMap的基础上的一个扩展类,是为了适应多线程、并且对HashMap的访问大部分是只读的特殊环境的需要。大家知道java.util.HashMap是非线程安全的,所以HashMap一般适用于单线程环境下。org.apache.struts.FastHashMap就是继承于java.util.HashMap,在其中添加多线程的支持产生的。在fast模式下的工作方式是这样的:读取是非线程同步的;写入时首先克隆当前map,然后在这个克隆上做写入操做,完成后用这个修改后的克隆版本替换原来的map。那么在什么时候会把Actions类添加到这个map中呢?我们已经提到了struts是动态的生成Action类的实例的,在每次ActionServlet接收到一个GET或POST的HTTP请求时,会在这个map中查找对应的Action类的实例,如果不存在,那么就实例化一个,并放入map中。可见这个actions属性起到了对Action类实例的缓存的作用。
- initInternal() - 初始化ActionServlet内部使用的资源包MessageResources,使用MessageResources.getMessageResources(internalName)得到 internalName为"org.apache.struts.action.ActionResources"对应的ActionResources.properties文件。这个资源包主要用于ActionServlet处理过程中的用到的提示信息,这儿不展开讨论。
- initDebug() - 从web.xml中读取本应用的debug级别参数getServletConfig().getInitParameter("debug"),然后赋给debug属性。
- initApplication()- 初始化应用资源包,并放置入ServletContext中。
-
- String factory =getServletConfig().getInitParameter(“factory”);
- String oldFacory = MessageResourcesFactory.getFactoryClass();
- if (factory !=null)
- MessageResourcesFactory.setFactoryClass(factory);
- String value = getServletConfig().getInitParameter("application");
- MessageResourcesFactory factoryObject =
- MessageResourcesFactory.createFactory();
- application = factoryObject.createResources(value);
- MessageResourcesFactory.setFactory(oldFactory);
- getServletContext().setAttribute(Action.MESSAGES_KEY, application);
说明:文中引用的代码片断可能会省略了一些例外检查等非主线的内容,敬请注意。
首先从配置文件中读取factory参数,如果这个参数不为空,那么就在MessageResourcesFactory中使用这个指定的Factory类;否则,使用默认的工厂类org.apche.struts.util.PropertyMessageResourceFactory。然后调用MessageResourcesFactory的静态createFactory()方法,生成一个具体的MessageResourceFactory对象(注意:MessageResourcesFactory是抽象类)。这样就可以调用这个具体的MessageResourceFactory的createResource()方法得到配置文件(web.xml)中定义的资源文件了。
上面的application对象类型为MessageResources。在web.xml中在配置ActionServlet时可以指定一个特定的工厂类。不能直接MessageResourcesFactory的createResources()方法,因为这个方法是abstract的。创建factoryObject的过程如下:
-
- MessageResourceFactory factoryObject=
- MessageResourcesFactory.createFactory();
- application = factoryObject.createResources(value);
<li>initMapping() - 为应用初始化mapping信息ActionServlet有一个protected的属性:mapping,封装了一个ActionMapping的对象集合,以便于管理、查找ActionMapping。mappings是org.apache.struts.action.ActionMappings类的实例。主要有两个方法:addMapping(ActionMapping mapping)和findMapping(String path)。ActionMapping也是使用上面提到的org.apache.struts.util.FastHashMap类来存储所有的ActionMapping对象。
-
- mappings.setServlet(this);
- ……
- // Initialize the name of our ActionFormBean implementation class
- value = getServletConfig().getInitParameter("formBean");
- if (value != null)
- formBeanClass = value;
-
- // Initialize the name of our ActionForward implementation class
- value = getServletConfig().getInitParameter("forward");
- if (value != null)
- forwardClass = value;
-
- // Initialize the name of our ActionMapping implementation class
- value = getServletConfig().getInitParameter("mapping");
- if (value != null)
- mappingClass = value;
在initMapping()中,首先链接mappings对象到本servlet实例。其实这句话的作用很简单,在ActionMappings中会有一个ActionServlet类型的属性,这个属性就界定了这个ActionMappings对象所属的ActionServlet。Struts的实现比较灵活,其中的ActionFormBean、ActionForward、ActionMapping类你完全可以使用自己实现的子类,来定制Struts的工作方式。上面的代码就从配置文件(web.xml)中读取formBean、forward、mapping参数,这些参数就是你定制的ActionFormBean、ActionForward、ActionMapping类名。
-
- // Initialize the context-relative path to our configuration resources
- value = getServletConfig().getInitParameter("config");
- if (value != null)
- config = value;
- // Acquire an input stream to our configuration resource
- InputStream input = getServletContext().getResourceAsStream(config);
- Digester digester = null;
- digester = initDigester(detail);
- try {
- formBeans.setFast(false);
- forwards.setFast(false);
- mappings.setFast(false);
- digester.parse(input);
- mappings.setFast(true);
- forwards.setFast(true);
- formBeans.setFast(true);
- } catch (SAXException e) {
- throw new ServletException
- (internal.getMessage("configParse", config), e);
- } finally {
- input.close();
- }
从web.xml读取Struts的配置文件的位置。使用org.apache.struts.digester.Digester解析config参数标示的配置文件,通常为“/WEB-INF/struts-config.xml”,解析出所有的data-source、form-bean、action-mapping、forward。从上面的程序片断看到,Digester仅仅调用了一个parse()方法,那么,Digester是怎样把解析struts-config.xml文件并把解析的结果form-bean等信息存储到属性变量formBeans等中的呢?你可以注意到在调用digester.parse(InputStream)之前,首先调用了initDigester()方法:
-
- Digester digester = new Digester();
- digester.push(this);
- digester.addObjectCreate("struts-config/action-mappings/action",
- mappingClass, "className");
- digester.addSetProperties("struts-config/action-mappings/action");
- digester.addSetNext("struts-config/action-mappings/action",
- "addMapping",
- "org.apache.struts.action.ActionMapping");
-
- digester.addSetProperty
- ("struts-config/action-mappings/action/set-property",
- "property", "value");
在这个方法中首先生成一个Digester对象,然后设置解析的规则和回调,如果你对XML、SAX不是很熟,这儿不必纠缠太深。要注意的是addSetNext()方法,设置了每一个要解析元素的Set Next回调方法,而这个方法就是由digester解析器的父提供的。上面的片断中的“addMapping”就是ActionServlet本身定义的一个方法,将由Digester回调。Digester就是籍此把解析出的每一个FormBean、ActionForward、ActionMapping等存储到属性变量formBeans、forwards、mappings等中的。
- initUpload() - 初始化有关Upload的一些参数,比如:bufferSize、tempDir。
- initDataSource() -取出在initMapping()中从配置文件中读取的每一个DataSource,设置LogWriter,如果为GenericDataSource的实例,则打开数据源。然后,把每个dataSource放入Context中。
dataSource.setLogWriter(scw);
((GenericDataSource)dataSource).open();
getServletContext().setAttribute(key,dataSource);
- initOther() - 设置其它尚未初始化的的参数(content、locale、nocache),并发布formBeans、forwards、mappings到Context:
getServletContext().setAttribute(Action.FORM_BEANS_KEY, formBeans);
getServletContext().setAttribute(Action.FORWARDS_KEY, forwards);
getServletContext().setAttribute(Action.MAPPINGS_KEY, mappings);
- initServlet() - 初始化Controller Servlet的Servlet Mapping。这儿也使用了Digester工具,扫描web.xml所有的<web-app/servlet-mapping>,寻找servlet-name与当前Servlet相同的mapping,置入Context。代码如下;
-
- Digester digester = new Digester();
- digester.push(this);
- digester.setDebug(debug);
- digester.setValidating(validating);
- digester.addCallMethod(“web-appservlet-mapping”,“addServletMapping”, 2);
- digester.addCallParm(“web-appservlet-mappingservlet-name”, 0);
- digester.addCallParm(“web-appservlet-mappingurl-pattern”, 1);
- InputStream is = getServletContext().getResourceAsStream(“/WEB-INFweb.xml”);
- digester.parse(is);
- getServletContext().setAttribute(Action.SERVLET_KEY,servletMapping);
分享到:
相关推荐
### Struts 框架概览与 ActionServlet 深入探讨 #### 一、Struts框架简介 Struts框架自2000年3月起始,首个正式版本1.0于2001年7月发布。该框架的核心设计理念是支持基于MVC(Model-View-Controller)模式的应用...
此外,`web.xml`也需要配置以启动Struts的ActionServlet。 7. **Struts拦截器** 拦截器是Struts 2引入的一个重要特性,它们允许在Action执行前后插入自定义逻辑,如日志记录、事务管理、权限检查等。 8. **Tiles...
本篇学习笔记将深入探讨Struts的核心概念、工作原理以及如何在实际项目中应用Struts来构建高效、可维护的Web应用程序。 一、Struts框架概述 Struts作为经典的MVC框架,它为Java开发者提供了一种组织应用程序逻辑的...
在本学习笔记中,我们将深入探讨 Struts 1.3.8 的核心概念、功能以及实际应用。Struts 为开发者提供了构建动态 Web 应用程序的结构框架,简化了开发流程,增强了代码的可维护性和可扩展性。 首先,我们来了解 MVC ...
在探讨Struts2的学习心得之前,我们先来分析一下Struts2与Struts1之间的区别。 ##### 1.1 架构设计 - **Struts1**:采用MVC(Model-View-Controller)架构模式,其中控制器是由`ActionServlet`来实现的,该控制器...
Struts是Java Web开发中的一款经典MVC框架,由Apache...以上是对Struts学习笔记的简要概括,深入学习Struts,不仅可以提升Web开发技能,还能更好地理解MVC模式以及框架的设计思想,对后续学习其他Web框架也会有所帮助。
本笔记将深入探讨Struts2的核心概念、发展历程、使用方法以及与OGNL(Object-Graph Navigation Language)的结合应用。 **一、Struts2概述** 1.1 为什么要用Struts 在Java Web开发中,Struts2作为MVC框架,能够...
在深入探讨Struts框架的学习笔记之前,我们先简要回顾一下Struts框架的基本概念与重要性。Struts是一个开源的MVC(Model-View-Controller)框架,主要用于简化Java Web应用的开发。它提供了一套标准的方式来组织和...
1. **Struts 学习笔记.doc**:这部分可能包含了Struts框架的基础概念,如Action、Form Bean、Action Mapping、Action Forward等核心组件的介绍。可能会详细讲解它们在Web应用中的角色和配置方法。 2. **48_46.doc, ...
在本篇“Struts2学习笔记三”中,我们将探讨Struts2中处理文件上传的核心组件和拦截器,以及如何在实际应用中实现文件上传。 1. 文件上传组件: - jspSmartUpload:这是一个早期用于模型1的上传组件,现在已经被更...
在这个笔记中,我们将深入探讨 Struts 的工作原理、配置以及它如何简化 MVC(模型-视图-控制器)模式的实现。 首先,Struts 是一个基于 MVC 设计模式的框架,它的核心是 ActionServlet,这是 Struts 提供的一个定制...
在本篇笔记中,我们将深入探讨Struts2的核心概念和使用方法。 **一、Struts2概述** 1.1 为什么要用Struts? 在传统的JSP开发中,模型与视图、控制器的职责混杂,导致代码维护困难。Struts2作为MVC框架,将业务逻辑...
本文将深入探讨Struts2的基础知识,包括它的核心组件、配置文件以及如何在开发环境中设置Struts2的支持。 首先,Struts2框架的安装涉及到解压缩其发行版,例如struts-2.1.6-all.zip。在这个压缩包中,有以下几个...
本篇学习笔记将深入探讨Struts1的总体介绍、工作原理以及框架中的关键元素。 1. **总体介绍** Struts1是基于MVC架构的开源框架,旨在简化Java Servlet和JSP应用程序的开发。它提供了一种组织应用程序结构的方式,...
本笔记主要探讨了Struts2.2的核心概念,包括Action、拦截器、过滤器、国际化以及struts.xml配置文件的解析,尤其是类型转换的细节。 在Struts2.2中,每个HTTP请求都会创建一个Action对象,与Servlet不同,Servlet在...
SSH是Java开发中广泛使用的三大框架——Struts2、Hibernate和Spring的缩写。这三大框架结合使用,能够...通过学习这些笔记,可以深入了解每个框架的核心概念、用法以及它们如何协同工作,从而提升开发效率和项目质量。
1. **ActionServlet**:Struts1.2使用单一的ActionServlet处理所有请求,而Struts2引入了Front Controller模式,所有的请求都由StrutsPrepareAndExecuteFilter处理。 2. **表达式语言**:Struts2使用OGNL(Object-...
本文将深入探讨Struts框架中的文件上传机制,包括上传组件的选择、配置以及具体的实现步骤。 #### 二、Struts框架中的文件上传组件 Struts框架支持多种文件上传组件,这些组件各有优势,开发者可以根据项目需求选择...
本学习笔记结合测试源代码深入探讨了如何在Struts2框架下获取并使用`request`、`session`、`ServletContext`以及`response`对象,这些都是在Web开发中不可或缺的基础组件。 ### request对象 `HttpServletRequest`...