使用SpringExt擴展Webx的示例

1. Webx和SpringExt分別是什麼

Webx是一套基於Java Servlet API的通用Web框架。它在Alibaba集團內部被普遍使用。從2010年末,向社會開放源碼。SpringExt則是Spring的一個擴展,在Spring的基礎上提供了一種擴展功能的新方法,是Webx的基礎。關於Webx和SpringExt的完整介紹,能夠參考Webx的官方文檔WebxSpringExt html

2. SpringExt中的基本概念

SpringExt中的兩個核心概念是擴展點和捐獻,其中擴展點(Configuration Point)表明一個可被擴展的接口,捐獻(Contriubtion)則是對擴展點的具體擴展。一個擴展(我的傾向使用「擴展」,「捐獻」聽起來很彆扭)通常對應着3個東西,分別是實現類、用於校驗配置的Schema以及配置解析器,其中後二者是可選的,不過通常都會用到。關於SpringExt的原理和概念,官方文檔已經有了很詳細的說明,前面這些介紹性的文字不少都是從上面Copy的,你們能夠直接查看SpringExtjava

3. 一個簡單的回顯服務擴展

一個簡單得不能再簡單的服務,用於把傳入的消息返回,沒有什麼特別的。若是你輸入「XXXX」它將返回"[Echo]: XXXX",其中"["爲preTitle,"Echo"爲title,"]"爲postTitle,":"爲separator,它們都是能夠在配置中自定義的。 web

3.1. 示例代碼的獲取以及使用

代碼在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

image

3.1.1. 類圖

image

其中,EchoService和EchoServiceImpl分別是回顯服務的接口和實現。EchoServiceImpl的靜態內部類DefinitionParser爲XML配置解析器,用於解析XML配置,生成回顯服務的BeanDefinition,並註冊到Spring容器中。DefinitionParser的父類是Webx提供的抽象基類,簡化配置解析類的開發。 app

3.1.2. 資源文件

image

資源文件主要有4個,echo-service.xsd是回顯服務配置的schema文件,用於定義和校驗配置文件格式;services.bean-definition-parsers是解析器對應的配置文件;configuration.xml是項目運行時Bean的配置,Webx服務的配置也在其中;logback.xml則是日誌的配置。 框架

3.2. 示例說明

3.2.1. 擴展點

Webx的全部可用擴展點定義在spring.configuration-points文件中。 eclipse

image

能夠直接從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。 函數

3.2.2. 配置校驗

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對象的屬性中。

3.2.3. 配置解析

一個擴展點下定義了不一樣的元素,每一個元素都對應一個解析器。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完成。

3.2.4. 回顯服務的實現以及運行測試

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的值,看看輸出效果的不一樣。

3.2.5. 運行結果

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!
============================

4. 其餘

4.1. 小記

絮絮不休寫了這些文字,目的是想鍛鍊一下本身寫技術Blog的能力,同時也給你們介紹一下Webx這個框架。從此若是有時間,會陸續寫一些文章來介紹Webx的其餘方面。經驗尚淺,不免會有些疏漏,歡迎你們指正及討論。

4.2. Webx論壇

Webx官網上有一個小論壇http://openwebx.org/forum/,Webx的做者常年在上面解答問題,若是有對Webx的指教、問題或是建議均可以直接在上面提出來。

4.3. 參考

Webx文檔http://openwebx.org/docs/index.html

4.4. 相關文章

在Webx中添加擴展點的示例http://my.oschina.net/joshuazhan/blog/84206

相關文章
相關標籤/搜索