好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SpringBoot之自定义Schema扩展方式

SpringBoot 自定义Schema扩展

最近在写RPC框架时,用到了自定义的xsd配置。我们平时习惯于使用bean配置实例化对象,因此把xsd这种方式单独拎出来。

1. 配置ServiceConfig属性

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

@Data

public class ServiceConfig {

     /** 接口 */

     private String interfaceClass;

 

     /** 引用 */

     private String ref;

 

     /** 版本 */

     private String version;

 

     @Override

     public String toString() {

         return "ServiceConfig{" +

                 "interfaceClass='" + interfaceClass + '\ '' +

                 ", ref='" + ref + '\ '' +

                 ", version='" + version + '\ '' +

                 '}' ;

     }

}

2. 编写XSD文件

配置element的name为service,配置的attribute对应ServiceConfig定义的属性

?

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

<? xml version = "1.0" encoding = "UTF-8" ?>

< xsd:schema xmlns = "http://gitee.com/schema/link"

                 xmlns:xsd = "http://www.w3.org/2001/XMLSchema"

                 xmlns:beans = "http://www.springframework.org/schema/beans"

                 targetNamespace = "http://gitee.com/schema/link"

                 elementFormDefault = "qualified" >

     < xsd:import namespace = "http://www.springframework.org/schema/beans" />

     < xsd:import namespace = "http://www.springframework.org/schema/tool" />

 

     < xsd:element name = "service" >

         < xsd:complexType >

             < xsd:complexContent >

                 < xsd:extension base = "beans:identifiedType" >

                     < xsd:attribute name = "ref" type = "xsd:string" use = "required" >

                         < xsd:annotation >

                             < xsd:documentation > <![CDATA[ 服务接口实现类]]> </ xsd:documentation >

                         </ xsd:annotation >

                     </ xsd:attribute >

                     < xsd:attribute name = "interfaceClass" type = "xsd:string" use = "required" >

                         < xsd:annotation >

                             < xsd:documentation > <![CDATA[服务接口]]> </ xsd:documentation >

                         </ xsd:annotation >

                     </ xsd:attribute >

                     < xsd:attribute name = "version" type = "xsd:string" />

                 </ xsd:extension >

             </ xsd:complexContent >

         </ xsd:complexType >

     </ xsd:element >

</ xsd:schema >

3. 编写NamespaceHandler

registerBeanDefinitionParser方法的key是xsd配置的element的name,表示service元素由LinkServiceBeanDefinitionParser对象解析

?

1

2

3

4

5

6

public class LinkNamespaceHandler extends NamespaceHandlerSupport {

     @Override

     public void init() {

         this .registerBeanDefinitionParser( "service" , new LinkServiceBeanDefinitionParser());

     }

}

4. 编写BeanDefinitionParser

从element中解析出属性,注册到BeanDefinitionBuilder

?

1

2

3

4

5

6

7

8

9

10

11

12

public class LinkServiceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

     @Override

     protected Class getBeanClass(Element element) {

         return ServiceConfig. class ;

     }

     @Override

     protected void doParse(Element element, BeanDefinitionBuilder bean) {

         bean.addPropertyValue( "ref" , element.getAttribute( "ref" ));

         bean.addPropertyValue( "interfaceClass" , element.getAttribute( "interfaceClass" ));

         bean.addPropertyValue( "version" , element.getAttribute( "version" ));

     }

}

5. 配置spring.handlers和spring.schemas

?

1

2

http\://gitee.com/schema/link=com.test.xsd.handler.LinkNamespaceHandler

http\://gitee.com/schema/link/link.xsd=META-INF/link.xsd

6. 配置spring的加载文件

在文件头部需要引入link的schema

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<? xml version = "1.0" encoding = "UTF-8" ?>

< beans xmlns = "http://www.springframework.org/schema/beans"

        xmlns:link = "http://gitee.com/schema/link"

        xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans.xsd

        http://gitee.com/schema/link http://gitee.com/schema/link/link.xsd">

 

     <!-- rpc服务 -->

     < link:service id = "serviceConfig"

                   ref = "helloService"

                   interfaceClass = "com.test.service.HelloService"

                   version = "1.0.0" />

</ beans >

7. 测试

?

1

2

3

4

5

6

7

public class App {

  public static void main(String[] args) {

   ApplicationContext context = new ClassPathXmlApplicationContext( "link-server.xml" );

   ServiceConfig config = (ServiceConfig) context.getBean( "serviceConfig" );

   System.out.println(config.toString());

  }

}

Spring Schema扩展机制

1. 概述

Spring2.0开始,Spring提供XML Schema可扩展机制,用户可以自定义XML Schema文件,并自定义

XML Bean解析器,集成到Spring IOC容器中。

2. 步骤

创建一个XML Schema文件,描述自定义的合法构建模块,也就是xsd文件。

自定义处理器类,并实现NamespaceHandler接口。

自定义一个或者多个解析器,实现BeanDefinitionParser接口(关键部分)。

注册上面的组建到Spring IOC容器。

3. 示例如下

(1) 自定义XML Schema文件

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<? xml version = "1.0" encoding = "UTF-8" ?>​

< xsd:schema xmlns = "http://www.liuenyuan.com/schema/myns"

             xmlns:xsd = "http://www.w3.org/2001/XMLSchema"

             xmlns:beans = "http://www.springframework.org/schema/beans"

             targetNamespace = "http://www.liuenyuan.com/schema/myns"

             elementFormDefault = "qualified" >

     < xsd:import namespace = "http://www.springframework.org/schema/beans" />

     < xsd:element name = "dateFormat" >

         < xsd:complexType >

             < xsd:complexContent >

                 < xsd:extension base = "beans:identifiedType" >

                     < xsd:attribute name = "pattern" type = "xsd:string" use = "required" />

                 </ xsd:extension >

             </ xsd:complexContent >

         </ xsd:complexType >

     </ xsd:element >

</ xsd:schema >

自定义targetNamespace是http://www.liuenyuan.com/schema/myns,xmlns与命名空间必须一致。

(2) 自定义NamespaceHandler

NamespaceHandler接口只有三个方法

init() :在NamespaceHandler被使用之前调用,完成初始化 parse() :解析元素 decorate() :嵌套元素时候调用

Spring提供一个默认实现类NamespaceHandlerSupport,注入每个元素的解析器即可。

用到了代理委托概念。NamespaceHandlerSupport可以注册任意个BeanDefinitionParser,负责所有自定义元素编排,实际XML解析工作委托给各个BeanDefinitioParser负责。

(3) 自定义BeanDefinitionParser

BeanDefinitionParser 将被调用,如果NamespapceHandler遇到元素类型已经有对应注册的parser(例如上面的handler如果遇到dateformat,DateformatDefinitionParser会被调用,

解析相应的属性设置到Bean中)将会被调用。BeanDefinitionParser负责解析一个顶级元素。

Spring提供AbstractSingleBeanDefinitionParser处理繁重的解析工作。

getBeanClass() :返回元素Class类型 doParse() :添加元素属性或者构造参数

(4) 注册handler和schema

把实现的NamespaceHandler和xsd文件配置到指定的配置文件中。位于META-INF目录中。

spring.handlers文件包含xml schema uri和Handler类映射关系。

?

1

2

http\://www.liuenyuan.com/schema/myns=\

   com.ley.springboot.schema.xml.MynsNamespaceHandler

遇到http\://www.liuenyuan.com/schema/myns命名空间的时候会交给MynsNamespaceHandler来处理,key部分必须和xsd文件中的targetNamespace值保持一致

spring.schemas文件包含xml schema xsd文件命名空间和文件路径映射关系。

?

1

http\://www.liuenyuan.com/schema/myns.xsd=META-INF/myns.xsd

(5) 测试

NamespaceHandler实现类

?

1

2

3

4

5

6

public class MynsNamespaceHandler extends NamespaceHandlerSupport {​

     @Override

     public void init() {

         registerBeanDefinitionParser( "dateFormat" , new MynsBeanDefinitionParser());

     }

}

BeaDefinitionParser实现类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

import org.springframework.beans.factory.support.BeanDefinitionBuilder;

import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;

import org.w3c.dom.Element;​

import java.text.SimpleDateFormat;​

public class MynsBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {​

     @Override

     protected Class<?> getBeanClass(Element element) {

         return SimpleDateFormat. class ;

     }

     @Override

     protected void doParse(Element element, BeanDefinitionBuilder builder) {

         String pattern = element.getAttribute( "pattern" );

         builder.addConstructorArgValue(pattern);

     }

}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/ghaohao/article/details/81116761

查看更多关于SpringBoot之自定义Schema扩展方式的详细内容...

  阅读:15次