Webx是一套基於Java Servlet API的通用Web框架。它在Alibaba集團內部被普遍使用。從2010年末,向社會開放源碼。SpringExt則是Spring的一個擴展,在Spring的基礎上提供了一種擴展功能的新方法,是Webx的基礎。關於Webx和SpringExt的完整介紹,能夠參考Webx的官方文檔Webx和SpringExt html
SpringExt中的兩個核心概念是擴展點和捐獻,其中擴展點(Configuration Point)表明一個可被擴展的接口,捐獻(Contriubtion)則是對擴展點的具體擴展。一個擴展(我的傾向使用「擴展」,「捐獻」聽起來很彆扭)通常對應着3個東西,分別是實現類、用於校驗配置的Schema以及配置解析器,其中後二者是可選的,不過通常都會用到。關於SpringExt的原理和概念,官方文檔已經有了很詳細的說明,前面這些介紹性的文字不少都是從上面Copy的,你們能夠直接查看SpringExt。 java
一個簡單得不能再簡單的服務,用於把傳入的消息返回,沒有什麼特別的。若是你輸入「XXXX」它將返回"[Echo]: XXXX",其中"["爲preTitle,"Echo"爲title,"]"爲postTitle,":"爲separator,它們都是能夠在配置中自定義的。 web
代碼在Google Code上,對應SVN路徑爲http://joshuazhan.googlecode.com/svn/trunk/webx/springext/contribution.echo。Check Out後請使用Maven建立eclipse工程,類me.joshua.webx.springext.contribution.echo.Launcher包含Main函數,用於運行示例。關於具體SVN、Maven的使用請直接Google,須要注意的是我編寫示例時用的是JDK1.7,若是你機器上的JDK不是1.7的,請在POM配置文件中把「java.version」的值修改爲你對應的版本。 spring
其中,EchoService和EchoServiceImpl分別是回顯服務的接口和實現。EchoServiceImpl的靜態內部類DefinitionParser爲XML配置解析器,用於解析XML配置,生成回顯服務的BeanDefinition,並註冊到Spring容器中。DefinitionParser的父類是Webx提供的抽象基類,簡化配置解析類的開發。 app
資源文件主要有4個,echo-service.xsd是回顯服務配置的schema文件,用於定義和校驗配置文件格式;services.bean-definition-parsers是解析器對應的配置文件;configuration.xml是項目運行時Bean的配置,Webx服務的配置也在其中;logback.xml則是日誌的配置。 框架
Webx的全部可用擴展點定義在spring.configuration-points文件中。 eclipse
能夠直接從Webx的Jar包中查看,包相對路徑爲「/META-INF/spring.configuration-points」。 ide
Webx中的全部組件都是從services這個頂級擴展點派生出來的,它的定義以下 svn
services=http://www.alibaba.com/schema/services; defaultElement=service
其中「services」是擴展點的名稱,「http://www.alibaba.com/schema/services」爲對應的namespace,「defaultElement」則指定了默認元素的名字,在這裏是service。 函數
Webx在解析配置前,首先會根據擴展點名稱定位到擴展元素對應Schema的文件夾,再根據元素名尋找Schema進行格式校驗,回顯服務的Schema配置以下。
<?xml version="1.0" encoding="UTF-8"?> <!-- 定義echo-service元素的格式 包括一個title子元素和preTitle, postTitle,separator三個屬性,屬性都是可選的,且提供了默認值 --> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xsd:element name="echo-service" type="EchoServiceType" /> <xsd:complexType name="EchoServiceType"> <xsd:all> <xsd:element name="title" type="xsd:string" default="Echo" /> </xsd:all> <xsd:attribute name="preTitle" type="xsd:string" default="[" /> <xsd:attribute name="postTitle" type="xsd:string" default="]" /> <xsd:attribute name="separator" type="xsd:string" default=":" /> </xsd:complexType> </xsd:schema>
Schema中定義了echo-service元素有一個title子元素以及三個可選屬性,子元素和屬性在解析時都會被設置到EchoService對象的屬性中。
一個擴展點下定義了不一樣的元素,每一個元素都對應一個解析器。services的元素解析器定義在services.bean-definition-parsers中,在Webx Jar包中的相對路徑爲「/META-INF/services.bean-definition-parsers」,其內容以下所示,裏面指定了每一個services Namespace下的元素的配置解析器類。
services=http://www.alibaba.com/schema/services; defaultElement=service services/data-resolver/factories=http://www.alibaba.com/schema/services/data-resolver/factories; defaultElement=factory; nsPrefix=dr-factories services/form/validators=http://www.alibaba.com/schema/services/form/validators; defaultElement=validator; nsPrefix=fm-validators services/form/conditions=http://www.alibaba.com/schema/services/form/conditions; defaultElement=condition; nsPrefix=fm-conditions ……
由於示例的回顯服務是services的擴展,因此須要在本身Jar包中對應的services.bean-definition-parsers文件(見3.1.2)中添加自定義標籤的解析器配置。
# services命名空間下echo-service元素的解析器 echo-service=me.joshua.webx.springext.contribution.echo.EchoServiceImpl$DefinitionParser
解析器的代碼以下
/** * 用於解析Echo Service的XML配置,生成對應的Bean Definition */ public static class DefinitionParser extends AbstractNamedBeanDefinitionParser<EchoServiceImpl> { @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { // 調用工具類SpringExtUtil中的方法,分別把子元素和屬性值設置到EchoService中 subElementsToProperties(element, builder, sameNs(element)); attributesToProperties(element, builder, "preTitle", "postTitle", "separator"); } @Override protected String getDefaultName() { return EchoService.DEFAULT_NAME; } }
DefinitionParser自己只借助工具類SpringExtUtil完成XML元素的子元素和屬性到類屬性的設置,其他BeanDefinition的生成和註冊都由抽象父類AbstractNamedBeanDefinitionParser完成。
A. 回顯服務
package me.joshua.webx.springext.contribution.echo; …… /** * EchoServiceImpl回顯的內容示例以下:<br> * <code>"[Echo]: XXXX"</code><br> * 其中"["爲preTitle,"Echo"爲title,"]"爲postTitle,":"爲separator,"XXXX"則是消息內容 * * @author <a href="mailto:daonan.zhan@gmail.com">Joshua Zhan</a> 2012-10-5 */ public class EchoServiceImpl implements EchoService { private String title; private String preTitle; private String postTitle; private String separator; @Override public String echo(String message) { StringBuilder sb = new StringBuilder(); sb.append(preTitle).append(title).append(postTitle).append(separator) .append(' ').append(message); return sb.toString(); } …… }
B. 測試類
package me.joshua.webx.springext.contribution.echo; …… /** * 運行示例的類 * * @author <a href="mailto:daonan.zhan@gmail.com">Joshua Zhan</a> 2012-10-5 */ public class Launcher { private final static String LINE_SEPARATOR = "============================"; private final static String GREETING_MESSAGE = "Hello World!"; public static void main(String[] args) { ApplicationContext context = new XmlApplicationContext( new ClassPathResource("configuration.xml")); testEchoService(context); } public static void testEchoService(ApplicationContext context) { EchoService echoService = (EchoService) context.getBean("echoService"); System.out.println(); System.out.println(LINE_SEPARATOR); System.out.println(echoService.echo(GREETING_MESSAGE)); System.out.println(LINE_SEPARATOR); } }
Webx的使用和Spring基本一致,不一樣之處在於XmlApplicationContext是Webx擴展自Spring的實現。
C. 配置文件
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.alibaba.com/schema/services http://localhost:8080/schema/services.xsd http://www.springframework.org/schema/beans http://localhost:8080/schema/www.springframework.org/schema/beans/spring-beans.xsd" > <echo-service xmlns="http://www.alibaba.com/schema/services" > <title>Echo</title> </echo-service> </beans>
Webx自己兼容Spring,它的配置也是寫在Bean配置中,不一樣的地方在於使用了本身的標籤,這點和Spring自身的擴展機制有些相似。在這個例子中,你能夠本身嘗試着給echo-service添加preTitle、postTitle的屬性或是改變子元素title的值,看看輸出效果的不一樣。
2012-10-06 18:22:26.079 : INFO [com.alibaba.citrus.springext.support.context.XmlApplicationContext] [main] Refreshing com.alibaba.citrus.springext.support.context.XmlApplicationContext@17df9ec: startup date [Sat Oct 06 18:22:26 CST 2012]; root of context hierarchy 2012-10-06 18:22:28.233 : INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] [main] Loading XML bean definitions from class path resource [configuration.xml] 2012-10-06 18:22:29.123 : INFO [com.alibaba.citrus.springext.support.context.InheritableListableBeanFactory] [main] Pre-instantiating singletons in com.alibaba.citrus.springext.support.context.InheritableListableBeanFactory@110609a: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,echoService,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy ============================ [Echo]: Hello World! ============================
絮絮不休寫了這些文字,目的是想鍛鍊一下本身寫技術Blog的能力,同時也給你們介紹一下Webx這個框架。從此若是有時間,會陸續寫一些文章來介紹Webx的其餘方面。經驗尚淺,不免會有些疏漏,歡迎你們指正及討論。
Webx官網上有一個小論壇http://openwebx.org/forum/,Webx的做者常年在上面解答問題,若是有對Webx的指教、問題或是建議均可以直接在上面提出來。
Webx文檔http://openwebx.org/docs/index.html
在Webx中添加擴展點的示例http://my.oschina.net/joshuazhan/blog/84206