Struts2提供了一种非常灵活的扩展方式,这种被称之为plugin的扩展方式与Eclipse或者Firefox的plugin具备相同的概念,通过独立于主体之外的程序,来扩展或者增强主体的自身功能。
无疑,plugin的扩展方式是当前最为流行,也最为合理的一种扩展方式。通过plugin,你可以扩展、替换Struts2中的某些功能点,你也可以加入自己的实现类,从而使得Struts2具备新的功能。而plugin的方式也使得任何的功能扩展,都与Struts2的主体程序保持独立性。也使得任何人都可以按照自己的意愿去实现自己的plugin。
无疑,plugin的扩展方式是当前最为流行,也最为合理的一种扩展方式。通过plugin,你可以扩展、替换Struts2中的某些功能点,你也可以加入自己的实现类,从而使得Struts2具备新的功能。而plugin的方式也使得任何的功能扩展,都与Struts2的主体程序保持独立性。也使得任何人都可以按照自己的意愿去实现自己的plugin。
plugin的方方面面 ![Top](https://i-blog.csdnimg.cn/blog_migrate/7f1a3d9cf45c3326107b8157ca0d0046.gif)
依赖关系
这段摘自Struts2自身reference的描述已经比较清晰的告诉我们:Struts2的plugin为Struts2的主程序本身提供额外的功能支持。所以 plugin本身是依赖于Struts2的主程序,也就是struts-core.jar。当然,针对某个特定功能的plugin可能还会有其他的library的依赖,不过这些依赖绝不应该影响到Struts2主程序本身。但是, 不同的plugin之间,互相之间不应该形成依赖。
表现形式
很显然,Struts2的plugin以JAR包的形式存在。
安装使用
如果你要获得某个plugin的功能支持,你只需要将plugin的JAR包放到classpath下即可,同时别忘记了plugin自身所依赖的JAR包。
构成要素
清楚的不要再清楚了。plugin的内部需要一个名为struts-plugin.xml的文件,这个文件与struts.xml的格式相同。在这个文件中,可以对这个plugin对Struts2的扩展点进行配置,而这些扩展点包含上面提到的三种不同的类型。
运行机制
这段话也摘自Struts2自身的reference,它其实已经深刻的描述了Struts2内部是如何处理plugin的。从这里,我们也可以看到plugin之所以能够以JAR包的形式如此简单的对Struts2自身进行扩展,其核心原因在于Struts2会在系统启动的时候load所有自身以及plugin的配置文件,并且根据这些配置文件来决定Struts2运行期到底具备何种特性。
从这些话中,我们实际上也可以挖掘出来很多东西:
1. 位于struts-core.jar包内部的struts-default.xml永远会被先加载,从而保证Struts2具备许多默认的行为方式。
2. 所有的plugin互相之间是平等的,所以他们互相之间不应该存在依赖关系。同时,Struts2在系统启动时加载plugin的配置文件并没有特定的顺序。
3. Struts2最后会加载位于你自身程序classpath下的名为struts.xml的文件。所以,我见到论坛上有很多朋友问类似这样的问题,都可以迎刃而解了:
1)struts2默认的配置文件是不是只能叫"struts.xml"? ———— 是
2)struts2默认的配置文件是不是只能放在classpath根目录下? ———— 是
不过,struts2提供了完善的配置文件管理机制,所以,你可以在struts.xml中通过extends方式定义任何你需要覆盖其默认行为的配置方式,当然也可以通过import等方式将配置文件分开。
Struts2 Reference 写道
Plugins are not loaded in any particular order. Plugins should not have dependencies on each other. A plugin may depend on classes provided by Struts Core, but it should not depend on classes loaded by another plugin.
这段摘自Struts2自身reference的描述已经比较清晰的告诉我们:Struts2的plugin为Struts2的主程序本身提供额外的功能支持。所以 plugin本身是依赖于Struts2的主程序,也就是struts-core.jar。当然,针对某个特定功能的plugin可能还会有其他的library的依赖,不过这些依赖绝不应该影响到Struts2主程序本身。但是, 不同的plugin之间,互相之间不应该形成依赖。
表现形式
Struts2 Reference 写道
A Struts 2 plugin is a single JAR that contains classes and configuration that extend, replace, or add to existing Struts framework functionality.
很显然,Struts2的plugin以JAR包的形式存在。
安装使用
Struts2 Reference 写道
A plugin can be installed by adding a JAR file to the application's class path, in addition to the JAR files to fulfill whatever dependencies the plugin itself may have.
如果你要获得某个plugin的功能支持,你只需要将plugin的JAR包放到classpath下即可,同时别忘记了plugin自身所依赖的JAR包。
构成要素
Struts2 Reference 写道
To configure the plugin, the JAR should contain a struts-plugin.xml file, which follows the same format as an ordinary struts.xml file.
Since a plugin can contain the struts-plugin.xml file, it has the ability to:
* Define new packages with results, interceptors, and/or actions
* Override framework constants
* Introduce new extension point implementation classes
Since a plugin can contain the struts-plugin.xml file, it has the ability to:
* Define new packages with results, interceptors, and/or actions
* Override framework constants
* Introduce new extension point implementation classes
清楚的不要再清楚了。plugin的内部需要一个名为struts-plugin.xml的文件,这个文件与struts.xml的格式相同。在这个文件中,可以对这个plugin对Struts2的扩展点进行配置,而这些扩展点包含上面提到的三种不同的类型。
运行机制
Struts2 Reference 写道
The framework loads its default configuration first, then any plugin configuration files found in others JARs on the classpath, and finally the "bootstrap" struts.xml.
1. struts-default.xml (bundled in the Core JAR)
2. struts-plugin.xml (as many as can be found in other JARs)
3. struts.xml (provided by your application)
Since the struts.xml file is always loaded last, it can make use of any resources provided by the plugins bundled with the distribution, or any other plugins available to an application.
1. struts-default.xml (bundled in the Core JAR)
2. struts-plugin.xml (as many as can be found in other JARs)
3. struts.xml (provided by your application)
Since the struts.xml file is always loaded last, it can make use of any resources provided by the plugins bundled with the distribution, or any other plugins available to an application.
这段话也摘自Struts2自身的reference,它其实已经深刻的描述了Struts2内部是如何处理plugin的。从这里,我们也可以看到plugin之所以能够以JAR包的形式如此简单的对Struts2自身进行扩展,其核心原因在于Struts2会在系统启动的时候load所有自身以及plugin的配置文件,并且根据这些配置文件来决定Struts2运行期到底具备何种特性。
从这些话中,我们实际上也可以挖掘出来很多东西:
1. 位于struts-core.jar包内部的struts-default.xml永远会被先加载,从而保证Struts2具备许多默认的行为方式。
2. 所有的plugin互相之间是平等的,所以他们互相之间不应该存在依赖关系。同时,Struts2在系统启动时加载plugin的配置文件并没有特定的顺序。
3. Struts2最后会加载位于你自身程序classpath下的名为struts.xml的文件。所以,我见到论坛上有很多朋友问类似这样的问题,都可以迎刃而解了:
1)struts2默认的配置文件是不是只能叫"struts.xml"? ———— 是
2)struts2默认的配置文件是不是只能放在classpath根目录下? ———— 是
不过,struts2提供了完善的配置文件管理机制,所以,你可以在struts.xml中通过extends方式定义任何你需要覆盖其默认行为的配置方式,当然也可以通过import等方式将配置文件分开。
Struts2常见的plugin ![Top](https://i-blog.csdnimg.cn/blog_migrate/7f1a3d9cf45c3326107b8157ca0d0046.gif)
Struts2 Reference 写道
Many popular but optional features of the framework are distributed as plugins. An application can retain all the plugins provided with the distribution, or just include the ones it uses. Plugins can be used to organize application code or to distribute code to third-parties.
按照Struts2的reference中的指示,其实许多常见的Struts2的扩展功能都是通过plugin来实现的,而这些常见的plugin已经由很多先辈贡献出来,并且作为Struts2的分发包的一部分共同发布,所以,其实你可以在Struts2的发布包中找到这些plugin以及他们的源码进行学习。
当然,你也可以自己实现自己的plugin。有很多的Struts2的plugin就不是hosting在apache上的,但是在apache的plugin的列表中,我们可以找到他们:
http://cwiki.apache.org/S2PLUGINS/home.html
面对这些纷繁复杂的plugin,许多程序员可能会不知所措。所以我在这里对plugin进行了简单的分类,并且列出一些典型的plugin,提供给大家进行学习:
1. 框架整合类
这类的plugin提供了Struts2与其他许多开源框架的整合方式。所以,那些在论坛上提问Struts2与Spring怎么整合、Struts2与DWR怎么整合的朋友,不妨先看看这些plugin的说明,试着跑一下这些plugin的例子,或许你会很有收获。
Spring Plugin: http://cwiki.apache.org/S2PLUGINS/spring-plugin.html
Guice Plugin: http://cwiki.apache.org/S2PLUGINS/guice-plugin.html
JRuby Plugin: http://cwiki.apache.org/S2PLUGINS/jruby-plugin.html
2. 简化配置类
这类的plugin的主旨是为了简化Struts2原有的配置结构,这些简化可能包含使用CoC的方式省略XML配置,使得Struts2支持Restful等等。不过这类的plugin中许多都会涉及到Struts2比较底层的内部实现,所以使用的时候请大家慎重选择。
Codebehind Plugin: http://cwiki.apache.org/S2PLUGINS/codebehind-plugin.html
SmartURLs plugin: http://cwiki.apache.org/S2PLUGINS/smarturls-plugin.html
Convention Plugin: http://cwiki.apache.org/S2PLUGINS/convention-plugin.html
3. 页面装饰类
这类plugin没什么好说的,是为了整合类似Tiles或者Sitemesh的框架,提供一个良好的页面结构化的环境整合。
Sitemesh Plugin: http://cwiki.apache.org/S2PLUGINS/sitemesh-plugin.html
Tiles Plugin: http://cwiki.apache.org/S2PLUGINS/tiles-plugin.html
4. 功能扩展类
这类的plugin最为丰富,包含了各种各样的额外功能扩展,例如整合JFreechart做图表整合输出、整合Open Flash Chart做Flash样式的报表输出、整合JasperReport做PDF输出等等。
JFreeChart Plugin: http://cwiki.apache.org/S2PLUGINS/jfreechart-plugin.html
JasperReports Plugin: http://cwiki.apache.org/S2PLUGINS/jasperreports-plugin.html
Connext Graph Plugin: http://cwiki.apache.org/S2PLUGINS/connext-graph-plugin.html
在之后的章节中,我会挑选其中几个觉有代表性的plugin做详细的分析和说明。
Struts2的扩展点 ![Top](https://i-blog.csdnimg.cn/blog_migrate/7f1a3d9cf45c3326107b8157ca0d0046.gif)
上面我们看到了通过plugin,可以对Struts2的许多默认行为进行扩展。那么Struts2的哪些行为可以进行扩展呢?在Struts2的内部,又是如何支持这些扩展的呢?
我按照我的理解,将Struts2的可扩展点分成了三类:
1. 自定义Interceptor,Result等,对运行程序进行扩展
自定义的Interceptor和Result非常简单,只需要分别实现XWork的Interceptor接口和Result接口即可。然后,在你的struts.xml中,定义这些实现类,使得他们被Struts2默认加载。对于Interceptor,你可能需要特别留心它在整个Interceptor Stack中的位置。
这类扩展本身并不涉及到Struts2内部自身的运行机制,所改变的只是Action的运行方式和运行结构,所以,这类扩展属于 应用级别的扩展。
2. 覆盖Struts2的静态变量
Struts2内部定义了很多静态变量,这些静态变量定义了Struts2许多的默认行为。这些静态变量可以以多种不同的方式定义。下面的来自于Struts2 Reference的例子展示了在不同的的文件中定义这些静态变量。
这是在struts.xml中进行定义:
这是在struts.properties中进行定义:
这是在web.xml中进行定义:
所有的这些定义都会被Struts2接受并作为参数改变Struts2的默认行为。不过,在Struts2启动的时候,会按照一定的顺序按文件进行加载。
Struts2的reference告诉我们,Struts2默认按照上面的顺序去加载所有的静态变量的值,并且允许后加载的定义覆盖之前的定义。
由于我们无法修改struts-default.xml和struts-plugin.xml中的定义、而struts.xml通常又被用于放置应用程序相关的一些配置、与此同时,为了保持web.xml的独立性,所以,我们在这里可以总结出一条最佳实践来: 把你自定义需要加载的静态变量定义或者需要覆盖struts默认的静态变量的定义尽量放在struts.properties中。这样就可以使得你的配置变得更加清晰。
3. 覆盖Struts2或者XWork自身的接口实现,替换默认行为机制
无论是Struts2还是XWork,都是面向接口编程的框架(请读者在读完这段后,自行理解面向接口的好处)。而这些定义的接口,我们可以编写自己的实现类实现这些接口,从而替换Struts的默认行为机制。
在Struts2的Reference中,也指出了一些Struts2的接口扩展点,请参考下面的链接: http://struts.apache.org/2.0.14/docs/plugins.html
在这里,我想提出的是,上面的链接其实只是列出了Struts2的一些可扩展接口,除此之外,还有XWork的很多接口也具备可扩展性。所以,我们还可以参考XWork的相关配置文件,寻找更多的扩展点,这些就留给读者自行去研究了。
在之后的章节,也会根据具体的实例进行讲解,如何扩展这些接口,从而替换Struts2的默认行为。
我按照我的理解,将Struts2的可扩展点分成了三类:
1. 自定义Interceptor,Result等,对运行程序进行扩展
自定义的Interceptor和Result非常简单,只需要分别实现XWork的Interceptor接口和Result接口即可。然后,在你的struts.xml中,定义这些实现类,使得他们被Struts2默认加载。对于Interceptor,你可能需要特别留心它在整个Interceptor Stack中的位置。
这类扩展本身并不涉及到Struts2内部自身的运行机制,所改变的只是Action的运行方式和运行结构,所以,这类扩展属于 应用级别的扩展。
2. 覆盖Struts2的静态变量
Struts2内部定义了很多静态变量,这些静态变量定义了Struts2许多的默认行为。这些静态变量可以以多种不同的方式定义。下面的来自于Struts2 Reference的例子展示了在不同的的文件中定义这些静态变量。
这是在struts.xml中进行定义:
- <struts>
- <constant name="struts.devMode" value="true" />
- ...
- </struts>
这是在struts.properties中进行定义:
- struts.devMode = true
这是在web.xml中进行定义:
- <web-app id="WebApp_9" version="2.4"
- xmlns="http://java.sun.com/xml/ns/j2ee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
- <filter>
- <filter-name>struts</filter-name>
- <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
- <init-param>
- <param-name>struts.devMode</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
- ...
- </web-app>
所有的这些定义都会被Struts2接受并作为参数改变Struts2的默认行为。不过,在Struts2启动的时候,会按照一定的顺序按文件进行加载。
Struts2 Reference 写道
Constants can be declared in multiple files. By default, constants are searched for in the following order, allowing for subsequent files to override previous ones:
1. struts-default.xml
2. struts-plugin.xml
3. struts.xml
4. struts.properties
5. web.xml
1. struts-default.xml
2. struts-plugin.xml
3. struts.xml
4. struts.properties
5. web.xml
Struts2的reference告诉我们,Struts2默认按照上面的顺序去加载所有的静态变量的值,并且允许后加载的定义覆盖之前的定义。
由于我们无法修改struts-default.xml和struts-plugin.xml中的定义、而struts.xml通常又被用于放置应用程序相关的一些配置、与此同时,为了保持web.xml的独立性,所以,我们在这里可以总结出一条最佳实践来: 把你自定义需要加载的静态变量定义或者需要覆盖struts默认的静态变量的定义尽量放在struts.properties中。这样就可以使得你的配置变得更加清晰。
3. 覆盖Struts2或者XWork自身的接口实现,替换默认行为机制
无论是Struts2还是XWork,都是面向接口编程的框架(请读者在读完这段后,自行理解面向接口的好处)。而这些定义的接口,我们可以编写自己的实现类实现这些接口,从而替换Struts的默认行为机制。
在Struts2的Reference中,也指出了一些Struts2的接口扩展点,请参考下面的链接: http://struts.apache.org/2.0.14/docs/plugins.html
在这里,我想提出的是,上面的链接其实只是列出了Struts2的一些可扩展接口,除此之外,还有XWork的很多接口也具备可扩展性。所以,我们还可以参考XWork的相关配置文件,寻找更多的扩展点,这些就留给读者自行去研究了。
在之后的章节,也会根据具体的实例进行讲解,如何扩展这些接口,从而替换Struts2的默认行为。