SpringBoot之自定义Schema扩展方式

目录
  • SpringBoot 自定义Schema扩展
    • 1. 配置ServiceConfig属性
    • 2. 编写XSD文件
    • 3. 编写NamespaceHandler
    • 4. 编写BeanDefinitionParser
    • 5. 配置spring.handlers和spring.schemas
    • 6. 配置spring的加载文件
    • 7. 测试
  • Spring Schema扩展机制
    • 1. 概述
    • 2. 步骤
    • 3. 示例如下

SpringBoot 自定义Schema扩展

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

1. 配置ServiceConfig属性

@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定义的属性

<?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对象解析

public class LinkNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        this.registerBeanDefinitionParser("service", new LinkServiceBeanDefinitionParser());
    }
}

4. 编写BeanDefinitionParser

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

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

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

<?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. 测试

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文件

<?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类映射关系。

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文件命名空间和文件路径映射关系。

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

(5) 测试

NamespaceHandler实现类

public class MynsNamespaceHandler extends NamespaceHandlerSupport {​
    @Override
    public void init() {
        registerBeanDefinitionParser("dateFormat", new MynsBeanDefinitionParser());
    }
}

BeaDefinitionParser实现类

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);
    }
}

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

(0)

相关推荐

  • Spring中自定义Schema如何解析生效详解

    前言 随着 Spring Boot 的日渐流行,应用里的大部分配置都被隐藏了起来,我们仅需要关心真正的业务内容, Controller, Service, Repository,拿起键盘就是一通业务代码的Coding,具体的 Component Scan,View,PlaceHolder ... 都可以抛在脑后.但其实这种零配置在 Java 应用开发中,还真不太久. 「由奢入俭难」,不少开发者都经历过 Spring XML 配置的冗长,再回到这种配置确实不好受. 但有些时候,由于配置的内容在 S

  • Spring中XML schema扩展机制的深入讲解

    前言 很久没有写关于 Spring 的文章了,最近在系统梳理 Dubbo 代码的过程中发现了 XML schema 这个被遗漏的知识点.由于工作中使用 SpringBoot 比较多的原因,几乎很少接触 XML,此文可以算做是亡羊补牢,另一方面,也为后续的 Dubbo 源码解析做个铺垫. XML schema 扩展机制是啥?从Spring2.0开始,Spring提供了XML Schema可扩展机制,用户可以自定义XML Schema文件,并自定义XML Bean解析器,并集成到Spring Ioc

  • 关于Spring自定义XML schema 扩展的问题(Spring面试高频题)

    引言 自从SpringBoot时代的到来,去除了Spring的各种繁琐的XML配置,让我们可以腾出双手以便于更加专注的搬砖.记得那时候刚学Spring的时候,每天被Spring的各种XMl配置文件折磨的不行,每引入一个新的框架,最担心的就是jar冲突.哪个配置文件又配的不对.配置文件没有起作用.所以每次搭建好一个项目就把配置文件用小笔记记录下来, 方便下次在整合项目的时候直接copy复制就好.下面我们就以Spring整合dubbo的事例看下 <beans xmlns:xsi="http:/

  • Spring XML Schema扩展机制的使用示例

    前言 在当前Java生态,Spring算的上是最核心的框架,所有的开发组件想要得到大范围更便捷的使用,都要和Spring进行整合,比如我们熟知的Mybatis.Dubbo等,以及内部封装的各类组件包括Redis.MQ.配置中心等. 有了整合这一步,我们只需引入相应的jar,比如mybatis-spring,然后进行简单的配置后即可在Spring工程中使用Mybatis的功能,也正是由于这样的便捷性,导致很多时候我们没有对其进行深究. XML Schema扩展 打开mybatis-spring.d

  • SpringBoot之自定义Schema扩展方式

    目录 SpringBoot 自定义Schema扩展 1. 配置ServiceConfig属性 2. 编写XSD文件 3. 编写NamespaceHandler 4. 编写BeanDefinitionParser 5. 配置spring.handlers和spring.schemas 6. 配置spring的加载文件 7. 测试 Spring Schema扩展机制 1. 概述 2. 步骤 3. 示例如下 SpringBoot 自定义Schema扩展 最近在写RPC框架时,用到了自定义的xsd配置.

  • SpringBoot @JsonDeserialize自定义Json序列化方式

    目录 @JsonDeserialize自定义Json序列化 1.问题 2.现象 3.解决办法 @JsonSerialize与@JsonDeserialize使用 1.以注解方式使用 2.自定义实现类 @JsonDeserialize自定义Json序列化 1.问题 在项目上使用SpringBoot为框架,调用第三方接口时,返回的参数Date类型,需要自定义进行Json序列化,需要进行处理,接受数据 2.现象 调用第三方接口,返回参数类型为Date类型,格式如下: { "created":

  • SpringBoot多种自定义错误页面方式小结

    目录 以前web.xml方式 SpringBoot中实现方式 1.实现EmbeddedServletContainerCustomizer的bean 2.通过拦截器方式 3.自定义静态error页面方法 在项目中为了友好化,对于错误页面,我们常常会使用自定义的页面.SSM框架组合时代,我们通常通过拦截或者在web.xml中设置对于错误码的错误页面,然而到了SpringBoot,web.xml消失了,SpringBootServletInitializer初始化servlet代替了web.xml.

  • 手把手教你SpringBoot过滤器N种注册方式

    要说在 Spring Boot 中注册过滤器有三种方式,你都能想到哪些呢?今天松哥就来和大家聊一聊 Spring Boot 中注册过滤器的三种方式! 其实本来是想和大家聊 Spring Security 过滤器链的问题的,结果看源码看着看着就跑题了,索性就先和大家聊一聊 Spring Boot 中注册过滤器的三种方式,算是给 后面的 Spring Security 打一点基础. 1.@WebFilter 通过 @WebFilter 注解来标记一个过滤器,这种方式相信大家很容易想到.这是将 Ser

  • SpringBoot如何自定义starter

    目录 1. 什么是starter 2. 自动配置原理 2.1 自动配置生效 3. 自定义starter 3.1 命名规范 4.总结 4.1为什么要自定义starter? 4.2 自定义starter的案例 1. 什么是starter Springboot的出现极大的简化了开发人员的配置,而这之中的一大利器便是springboot的starter,starter是springboot的核心组成部分,为什么说引入如下依赖就满足了日常web开发? <dependency>   <groupId

  • SpringBoot统一功能处理的方式详解

    目录 SpringMVC统一处理的三种方式 1.基于SpringMVC的配置类扩展 2.统一的响应数据格式封装 3.统一异常处理 基于SpringAOP已经实现统一功能增强,但如果希望对Controller增强,就无法获取其中的http请求数据.因此,实现以下这些统一增强的业务,就不能使用SpringAOP: 响应数据统一封装 统一异常处理(返回错误信息的http响应) http请求日志记录 SpringMVC统一处理的三种方式 SpringMVC在SpringBoot项目中,是默认进行了配置,

  • SpringBoot应用自定义logback日志详解

    目录 概述 logback配置详解 配置内容概念介绍 配置介绍 SpringBoot中自定义logback 多环境输出日志文件 读取配置文件配置 概述 默认情况下,SpringBoot内部使用logback作为系统日志实现的框架,将日志输出到控制台,不会写到日志文件.如果在application.properties或application.yml配置,这样只能配置简单的场景,保存路径.日志格式等.复杂的场景(区分 info 和 error 的日志.每天产生一个日志文件等)满足不了,只能自定义配

  • SpringBoot使用自定义注解实现数据脱敏过程详细解析

    目录 前言 一.引入hutool工具类 二.定义常用需要脱敏的数据类型的枚举 三.定义脱敏方式枚举 四.自定义脱敏的注解 五.自定义Jackson的序列化方式 六.使用 七.脱敏效果 前言 对于某些接口返回的信息,涉及到敏感数据的必须进行脱敏操作,例如银行卡号.身份证号.手机号等,脱敏方式有多种方式.可以修改SQL语句,也可以写硬代码,也可以修改JSON序列化,这里介绍通过修改Jackson序列化方式实现数据脱敏. 一.引入hutool工具类 maven: <dependency> <g

随机推荐