spring万恶的xml配置虽然恶心,但是也不乏良好的设计。如何自定义xml呢?
创建XML Schema文件 什么是XML Schema
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?xml version="1.0" encoding="UTF-8" standalone="no"?> <xsd:schema xmlns:xsd ="http://www.w3.org/2001/XMLSchema" xmlns:beans ="http://www.springframework.org/schema/beans" xmlns:tool ="http://www.springframework.org/schema/tool" xmlns ="http://code.alibabatech.com/schema/dubbo" targetNamespace ="http://code.alibabatech.com/schema/dubbo" > <xsd:import namespace ="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace ="http://www.springframework.org/schema/beans" /> <xsd:import namespace ="http://www.springframework.org/schema/tool" /> <xsd:complexType name ="annotationType" > <xsd:attribute name ="id" type ="xsd:ID" > <xsd:annotation > <xsd:documentation > <![CDATA[ The unique identifier for a bean. ]]></xsd:documentation > </xsd:annotation > </xsd:attribute > <xsd:attribute name ="package" type ="xsd:string" use ="optional" > <xsd:annotation > <xsd:documentation > <![CDATA[ The scan package. ]]></xsd:documentation > </xsd:annotation > </xsd:attribute > </xsd:complexType > <xsd:element name ="annotation" type ="annotationType" > <xsd:annotation > <xsd:documentation > <![CDATA[ The annotation config ]]></xsd:documentation > </xsd:annotation > </xsd:element > </xsd:schema >
简易元素 语法
1 <xsd:element name ="xxx" type ="yyy" />
这里的xsd:element 被称为简易元素。name是名称,type是类型。XML Schema 拥有很多内建的数据类型。
实例
这是一些 XML 元素:
1 2 3 <lastname > Refsnes</lastname > <age > 36</age > <dateborn > 1970-03-27</dateborn >
这是相应的简易元素定义:
1 2 3 <xsd:element name ="lastname" type ="xsd:string" /> <xsd:element name ="age" type ="xsd:integer" /> <xsd:element name ="dateborn" type ="xsd:date" />
XSD 属性 简易元素无法拥有属性。假如某个元素拥有属性,它就会被当作某种复合类型。但是属性本身总是作为简易类型被声明的。
语法
1 <xsd:attribute name ="xxx" type ="yyy" />
实例
这是一些 XML 元素:
1 2 3 <lastname > Refsnes</lastname > <age > 36</age > <dateborn > 1970-03-27</dateborn >
这是相应的简易元素定义:
1 2 3 <xsd:element name ="lastname" type ="xsd:string" /> <xsd:element name ="age" type ="xsd:integer" /> <xsd:element name ="dateborn" type ="xsd:date" />
默认值 当没有其他的值被规定时,默认值就会自动分配给元素。
在下面的例子中,缺省值是 “red”:
1 <xsd:element name ="color" type ="xsd:string" default ="red" />
固定值 固定值同样会自动分配给元素,并且您无法规定另外一个值。
在下面的例子中,固定值是 “red”:
1 <xsd:element name ="color" type ="xsd:string" fixed ="red" />
可选的和必需的属性 在缺省的情况下,属性是可选的。如需规定属性为必选,请使用 “use” 属性:
1 <xsd:attribute name ="lang" type ="xsd:string" use ="required" />
XSD 限定 / Facets 限定(restriction)用于为 XML 元素或者属性定义可接受的值。对 XML 元素的限定被称为 facet。
对值的限定(minInclusive/maxInclusive) 下面的例子定义了带有一个限定且名为 “age” 的元素。age 的值不能低于 0 或者高于 120:
1 2 3 4 5 6 7 8 <xsd:element name ="age" > <xsd:simpleType > <xsd:restriction base ="xsd:integer" > <xsd:minInclusive value ="0" /> <xsd:maxInclusive value ="120" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
对一组值的限定(enumeration) 如需把 XML 元素的内容限制为一组可接受的值,我们要使用枚举约束(enumeration constraint)。
下面的例子定义了带有一个限定的名为 “car” 的元素。可接受的值只有:Audi, Golf, BMW:
1 2 3 4 5 6 7 8 9 <xsd:element name ="car" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:enumeration value ="Audi" /> <xsd:enumeration value ="Golf" /> <xsd:enumeration value ="BMW" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
上面的例子也可以被写为:
1 2 3 4 5 6 7 8 <xsd:element name ="car" type ="carType" /> <xsd:simpleType name ="carType" > <xsd:restriction base ="xsd:string" > <xsd:enumeration value ="Audi" /> <xsd:enumeration value ="Golf" /> <xsd:enumeration value ="BMW" /> </xsd:restriction > </xsd:simpleType >
注意: 在这种情况下,类型 “carType” 可被其他元素使用,因为它不是 “car” 元素的组成部分。
对一系列值的限定(pattern) 如需把 XML 元素的内容限制定义为一系列可使用的数字或字母,我们要使用模式约束(pattern constraint)。
下面的例子定义了带有一个限定的名为 “letter” 的元素。可接受的值只有小写字母 a - z 其中的一个:
1 2 3 4 5 6 7 <xsd:element name ="letter" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:pattern value ="[a-z]" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
下一个例子定义了带有一个限定的名为 “initials” 的元素。可接受的值是大写字母 A - Z 其中的三个:
1 2 3 4 5 6 7 <xsd:element name ="initials" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:pattern value ="[A-Z][A-Z][A-Z]" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
下一个例子也定义了带有一个限定的名为 “initials” 的元素。可接受的值是大写或小写字母 a - z 其中的三个:
1 2 3 4 5 6 7 <xsd:element name ="initials" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:pattern value ="[a-zA-Z][a-zA-Z][a-zA-Z]" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
下一个例子定义了带有一个限定的名为 “choice 的元素。可接受的值是字母 x, y 或 z 中的一个:
1 2 3 4 5 6 7 <xsd:element name ="choice" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:pattern value ="[xyz]" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
下一个例子定义了带有一个限定的名为 “prodid” 的元素。可接受的值是五个阿拉伯数字的一个序列,且每个数字的范围是 0-9:
1 2 3 4 5 6 7 <xsd:element name ="prodid" > <xsd:simpleType > <xsd:restriction base ="xsd:integer" > <xsd:pattern value ="[0-9][0-9][0-9][0-9][0-9]" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
对一系列值的其他限定 下面的例子定义了带有一个限定的名为 “letter” 的元素。可接受的值是 a - z 中零个或多个字母:
1 2 3 4 5 6 7 <xsd:element name ="letter" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:pattern value ="([a-z])*" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
下面的例子定义了带有一个限定的名为 “letter” 的元素。可接受的值是一对或多对字母,每对字母由一个小写字母后跟一个大写字母组成。举个例子,”sToP”将会通过这种模式的验证,但是 “Stop”、”STOP” 或者 “stop” 无法通过验证:
1 2 3 4 5 6 7 <xsd:element name ="letter" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:pattern value ="([a-z][A-Z])+" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
下面的例子定义了带有一个限定的名为 “gender” 的元素。可接受的值是 male 或者 female:
1 2 3 4 5 6 7 <xsd:element name ="gender" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:pattern value ="male|female" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
下面的例子定义了带有一个限定的名为 “password” 的元素。可接受的值是由 8 个字符组成的一行字符,这些字符必须是大写或小写字母 a - z 亦或数字 0 - 9:
1 2 3 4 5 6 7 <xsd:element name ="password" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:pattern value ="[a-zA-Z0-9]{8}" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
对空白字符的限定(whiteSpace) 如需规定对空白字符(whitespace characters)的处理方式,我们需要使用 whiteSpace 限定。
下面的例子定义了带有一个限定的名为 “address” 的元素。这个 whiteSpace 限定被设置为 “preserve”,这意味着 XML 处理器不会移除任何空白字符:
1 2 3 4 5 6 7 <xsd:element name ="address" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:whiteSpace value ="preserve" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
这个例子也定义了带有一个限定的名为 “address” 的元素。这个 whiteSpace 限定被设置为 “replace”,这意味着 XML 处理器将移除所有空白字符(换行、回车、空格以及制表符):
1 2 3 4 5 6 7 <xsd:element name ="address" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:whiteSpace value ="replace" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
这个例子也定义了带有一个限定的名为 “address” 的元素。这个 whiteSpace 限定被设置为 “collapse”,这意味着 XML 处理器将移除所有空白字符(换行、回车、空格以及制表符会被替换为空格,开头和结尾的空格会被移除,而多个连续的空格会被缩减为一个单一的空格):
1 2 3 4 5 6 7 <xsd:element name ="address" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:whiteSpace value ="collapse" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
对长度的限定(length/minLength/maxLength) 如需限制元素中值的长度,我们需要使用 length、maxLength 以及 minLength 限定。
本例定义了带有一个限定且名为 “password” 的元素。其值必须精确到 8 个字符:
1 2 3 4 5 6 7 <xsd:element name ="password" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:length value ="8" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
这个例子也定义了带有一个限定的名为 “password” 的元素。其值最小为 5 个字符,最大为 8 个字符:
1 2 3 4 5 6 7 8 <xsd:element name ="password" > <xsd:simpleType > <xsd:restriction base ="xsd:string" > <xsd:minLength value ="5" /> <xsd:maxLength value ="8" /> </xsd:restriction > </xsd:simpleType > </xsd:element >
数据类型的限定
限定
描述
enumeration
定义可接受值的一个列表
fractionDigits
定义所允许的最大的小数位数。必须大于等于0。
length
定义所允许的字符或者列表项目的精确数目。必须大于或等于0。
maxExclusive
定义数值的上限。所允许的值必须小于此值。
maxInclusive
定义数值的上限。所允许的值必须小于或等于此值。
maxLength
定义所允许的字符或者列表项目的最大数目。必须大于或等于0。
minExclusive
定义数值的下限。所允许的值必需大于此值。
minInclusive
定义数值的下限。所允许的值必需大于或等于此值。
minLength
定义所允许的字符或者列表项目的最小数目。必须大于或等于0。
pattern
定义可接受的字符的精确序列。
totalDigits
定义所允许的阿拉伯数字的精确位数。必须大于0。
whiteSpace
定义空白字符(换行、回车、空格以及制表符)的处理方式。
复合元素(complexType) 复合元素指包含其他元素及/或属性的 XML 元素。
有四种类型的复合元素:
空元素
1 2 3 4 5 <xsd:element name ="product" type ="prodtype" /> <xsd:complexType name ="prodtype" > <xsd:attribute name ="pid" type ="xsd:positiveInteger" /> </xsd:complexType >
包含其他元素的元素
1 2 3 4 <employee > <firstname > John</firstname > <lastname > Smith</lastname > </employee >
1 2 3 4 5 6 7 8 <xsd:element name ="employee" type ="employeetype" /> <xsd:complexType name ="employeetype" > <xsd:sequence > <xsd:element name ="firstname" type ="xsd:string" /> <xsd:element name ="lastname" type ="xsd:string" /> </xsd:sequence > </xsd:complexType >
仅包含文本的元素
1 <food type ="dessert" > Ice cream</food >
1 2 3 4 5 6 7 8 9 <xsd:element name ="food" type ="foodtype" /> <xsd:complexType name ="foodtype" > <xsd:simpleContent > <xsd:extension base ="xs:string" > <xsd:attribute name ="dessert" type ="xsd:string" /> </xsd:extension > </xsd:simpleContent > </xsd:complexType >
包含元素和文本的元素
1 2 3 <description > It happened on <date > 03.03.99</date > </description >
1 2 3 4 5 6 7 <xsd:element name ="description" type ="descriptiontype" /> <xsd:complexType name ="descriptiontype" mixed ="true" > <xsd:sequence > <xsd:element name ="date" type ="xs:date" /> </xsd:sequence > </xsd:complexType >
指示器 有七种指示器:
Order 指示器:
All 规定子元素可以按照任意顺序出现,且每个子元素必须只出现一次
Choice 指示器规定可出现某个子元素或者可出现另外一个子元素(非此即彼)
Sequence 规定子元素必须按照特定的顺序出现
Occurrence 指示器:
maxOccurs 指示器可规定某个元素可出现的最大次数
minOccurs 指示器可规定某个元素能够出现的最小次数
Group 指示器:
Group name 定义相关的数批元素
attributeGroup name
元素 元素使我们有能力通过未被 schema 规定的元素来拓展 XML 文档
1 2 3 4 5 6 7 8 9 <xsd:element name ="person" > <xsd:complexType > <xsd:sequence > <xsd:element name ="firstname" type ="xsd:string" /> <xsd:element name ="lastname" type ="xsd:string" /> <xsd:any minOccurs ="0" /> </xsd:sequence > </xsd:complexType > </xsd:element >
假如有另一个xsd定义了chidren节点,我们就可以通过any把children加入person节点之下
1 2 3 4 5 6 7 8 9 10 11 12 <person > <firstname > Hege</firstname > <lastname > Refsnes</lastname > <children > <childname > Cecilie</childname > </children > </person > <person > <firstname > Stale</firstname > <lastname > Refsnes</lastname > </person >
元素 元素使我们有能力通过未被 schema 规定的属性来扩展 XML 文档
构造Bean 如:http://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd
继承NamespaceHandlerSupport实现处理器
继承NamespaceHandlerSupport后需要实现init方法
如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class DubboNamespaceHandler extends NamespaceHandlerSupport { public void init () { registerBeanDefinitionParser("application" , new DubboBeanDefinitionParser(ApplicationConfig.class, true )); registerBeanDefinitionParser("module" , new DubboBeanDefinitionParser(ModuleConfig.class, true )); registerBeanDefinitionParser("registry" , new DubboBeanDefinitionParser(RegistryConfig.class, true )); registerBeanDefinitionParser("monitor" , new DubboBeanDefinitionParser(MonitorConfig.class, true )); registerBeanDefinitionParser("provider" , new DubboBeanDefinitionParser(ProviderConfig.class, true )); registerBeanDefinitionParser("consumer" , new DubboBeanDefinitionParser(ConsumerConfig.class, true )); registerBeanDefinitionParser("protocol" , new DubboBeanDefinitionParser(ProtocolConfig.class, true )); registerBeanDefinitionParser("service" , new DubboBeanDefinitionParser(ServiceBean.class, true )); registerBeanDefinitionParser("reference" , new DubboBeanDefinitionParser(ReferenceBean.class, false )); registerBeanDefinitionParser("annotation" , new AnnotationBeanDefinitionParser()); } }
这样实现了:
1 2 3 4 5 6 7 8 9 10 * dubbo:application->ApplicationConfig * dubbo:module->ModuleConfig * dubbo:registry->RegistryConfig * dubbo:monitor->MonitorConfig * dubbo:provider->ProviderConfig * dubbo:consumer->ConsumerConfig * dubbo:protocol->ProtocolConfig * dubbo:service->ServiceBean * dubbo:reference->ReferenceBean * dubbo:annotation ->使用继承了AbstractSingleBeanDefinitionParser的解析器AnnotationBeanDefinitionParser
实现BeanDefinitionParser接口实现多个解析器 1 2 3 4 5 public interface BeanDefinitionParser { BeanDefinition parse (Element element, ParserContext parserContext) ; }
BeanDefinitionParser只有一个接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class LightningXCacheBeanParser implements BeanDefinitionParser { private final Class<?> beanClass; public LightningXCacheBeanParser (Class<?> beanClass) { this .beanClass = beanClass; } @Override public BeanDefinition parse (Element element, ParserContext parserContext) { RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClass(beanClass); beanDefinition.setLazyInit(false ); String application = element.getAttribute("application" ); beanDefinition.getPropertyValues().addPropertyValue("application" , application); parserContext.getRegistry().registerBeanDefinition(beanClass.getName(), beanDefinition); return beanDefinition; } }
如:http://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
参考:
http://www.runoob.com/schema/schema-tutorial.html