扩展spring 的 xml schema,实现自己的标签

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/xml-custom.html

扩展spring 的 xml schema,如

<lzm:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm:ss"
        lenient="true" />

使用时,需要在xml头部加入扩展的命名空间、该命名空间的别名(简称)、以及该命名空间对应的在线xsd地址。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:lzm="http://www.lzm.com/schema/lzm" 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://www.lzm.com/schema/lzm http://www.lzm.com/schema/lzm/lzm.xsd">
    <!-- as a top-level bean -->
    <lzm:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm:ss"
        lenient="true" />
    <bean id="jobDetailTemplate" abstract="true">
        <property name="dateFormat">
            <!-- as an inner bean -->
            <lzm:dateformat pattern="HH:mm MM-dd-yyyy" />
        </property>
    </bean>
</beans>
  1. xmlns:lzm=”http://www.lzm.com/schema/lzm”
    表示声明一个命名空间,值是http://www.lzm.com/schema/lzm,它有一个别名(简称)lzm,用以在这个xml文件里代替该命名空间。
  2. http://www.lzm.com/schema/lzm http://www.lzm.com/schema/lzm/lzm.xsd
    前面表示该命名空间,后面表示该命名空间对应的xsd(schema)的在线地址。
    spring启动时,并不会立即使用该地址下载xsd,而是到META-INF/spring.schemas找该在线xsd地址对应的本地xsd位置。
    http://www.lzm.com/schema/lzm/lzm.xsd=com/lzm/demo/extensible/xml/lzm.xsd
    如果本地地址com/lzm/demo/extensible/xml/lzm.xsd找不到,才到使用这个http://www.lzm.com/schema/lzm/lzm.xsd地址去下载xsd。
    3.<lzm:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm:ss" lenient="true" />
    使用这个命名空间,lzm:dateformat,即命名空间的别名:element名称(在xsd里定义)。

扩展spring的xml schema,分以下几步:
1. 创建maven工程,引入spring 依赖。

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.lzm</groupId>
    <artifactId>demo_extensible_xml</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <org.springframework.version>3.2.2.RELEASE</org.springframework.version>
    </properties>
    <dependencies>   
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>web</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.创建xsd(schema)文件。
lzm.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.lzm.com/schema/lzm"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
    targetNamespace="http://www.lzm.com/schema/lzm"
    elementFormDefault="qualified" attributeFormDefault="unqualified">
    <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="lenient" type="xsd:boolean" />
                    <xsd:attribute name="pattern" type="xsd:string" use="required" />
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

定义了一个element,名称是dateformat。每个element都得有一个处理类(生成bean)。

3.创建命名空间处理类。
LzmNamespaceHandler.java

package com.lzm.demo.extensible.xml;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**   
 * @author 爱不留    
 * @date 2016年12月29日 上午10:56:38 
 * @Description: TODO 
 */
public class LzmNamespaceHandler extends NamespaceHandlerSupport {
    public void init() {
        registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());
    }
}

将每个elelment及其对应的处理类都注册一下。
4.创建schema的element处理类(每个element对应1个处理类)。
SimpleDateFormatBeanDefinitionParser.java

package com.lzm.demo.extensible.xml;
import java.text.SimpleDateFormat;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**   
 * @author 爱不留    
 * @date 2016年12月29日 上午10:57:01 
 * @Description: TODO 
 */
public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { 
    protected Class getBeanClass(Element element) {
        return SimpleDateFormat.class;
    }
    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        // this will never be null since the schema explicitly requires that a value be supplied
        String pattern = element.getAttribute("pattern");
        bean.addConstructorArgValue(pattern);
        // this however is an optional property
        String lenient = element.getAttribute("lenient");
        if (StringUtils.hasText(lenient)) {
            bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
        }
    }
}

getBeanClass返回该element对应的bean的类型。
doParse设置该bean的构造参数或属性。该element的attribute可以用来当构造参数construct arg,也可以用于设置属性property value。
5.创建spring schema注册文件。
/META-INF/spring.handlers
http://www.lzm.com/schema/lzm=com.lzm.demo.extensible.xml.LzmNamespaceHandler
前面的表示命名空间,后面的表示命名空间处理类。

/META-INF/spring.schemas
http://www.lzm.com/schema/lzm/lzm.xsd=com/lzm/demo/extensible/xml/lzm.xsd

前面的表示命名空间对应的在线xsd地址(xsi:schemaLocation的后半部分),后面的表示本地xsd的位置。

6.使用命名空间
applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:lzm="http://www.lzm.com/schema/lzm" 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://www.lzm.com/schema/lzm http://www.lzm.com/schema/lzm/lzm.xsd">
    <!-- as a top-level bean -->
    <lzm:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm:ss"
        lenient="true" />
    <bean id="jobDetailTemplate" abstract="true">
        <property name="dateFormat">
            <!-- as an inner bean -->
            <lzm:dateformat pattern="HH:mm MM-dd-yyyy" />
        </property>
    </bean>
</beans>

7.测试
ExtensiableXmlTest.java

package com.lzm.demo.extensible.xml;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author 爱不留
 * @date 2016年12月29日 上午11:14:15
 * @Description: TODO
 */
@Configuration
// @Import(ConfigA.class)
@ImportResource("classpath:/*.xml")  
public class ExtensiableXmlTest {
    public void init() {
        System.out.println("init...");
    }
    public void cleanup() {
        System.out.println("cleanup...");
    }
    @Bean(initMethod = "init", destroyMethod = "cleanup")
    public ExtensiableXmlTest ex() {
        return new ExtensiableXmlTest();
    }
    public static void main(String[] args) {
        // ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/bean.xml");
        ApplicationContext ctx = new AnnotationConfigApplicationContext(
                ExtensiableXmlTest.class);
        ExtensiableXmlTest ex = (ExtensiableXmlTest) ctx.getBean("ex");

        SimpleDateFormat sdf = (SimpleDateFormat) ctx.getBean("defaultDateFormat");
        String today = sdf.format(new Date());
        System.out.println(today);


    }
}

运行结果:

init...
2016-12-29 15:46:54

注意:
1. META-INF文件夹要在src/main/resources上右键,new一个folder(不是source folder)。
这里写图片描述

2.applicationContext.xml会识别不了新的命名空间,需要在eclipse里引入它的xsd。
Window - Preferences - XML - XML Catalog - User Specified Entries,Add 加入该xsd。
Location 是本地xsd位置,Key是在线xsd地址。
这里写图片描述

  1. lzm.xsd会报错:src-resolve: Cannot resolve the name ‘beans:identifiedType’ to a(n) ‘type definition’ component.
    不妨事,可以忽略。如果不想看到错误,可以取消schema的验证。
    Window - Preferences - Validation - XML Schema Validator,把两个勾去掉。

    这里写图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大爱不留

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值