Spring自定义标签示例(亲测可运行)

网上也有很多示例代码,当然,有的能运行起来,有的却是不能测试运行。于是就自己动手写了这示例。但是走了不少弯路。希望对后来者也有所帮助。共勉。奋斗

首先,看这篇博文要有对spring有一定了解,还有对xsd schema文档定义语言也要有所知。不多说上代码。

定义一个普通的javaBean(很简单的,没有什么逻辑)如下:

package com.wjs.cosumertag;  
public class User {  
    private String id;  
    private String userName;  
    private String email;  
    public String getId() {  
        return id;  
    }  
    public void setId(String id) {  
        this.id = id;  
    }  
    public String getUserName() {  
        return userName;  
    }  
    public void setUserName(String userName) {  
        this.userName = userName;  
    }  
    public String getEmail() {  
        return email;  
    }  
    public void setEmail(String email) {  
        this.email = email;  
    }  
}

然后定义一个AbstractSingleBeanDefinitionParser,实现这个类里面的一个doParser和getBeanClass方法如下:

package com.wjs.cosumertag;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;  
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;  
import org.springframework.util.StringUtils;  
import org.w3c.dom.Element;  
public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {  
    @Override  
    protected Class<?> getBeanClass(Element element) {  
        return User.class;  
    }  
    @Override  
    protected void doParse(Element element, BeanDefinitionBuilder builder) {  
        String userName=element.getAttribute("userName");  
        String email=element.getAttribute("email");  
        if(StringUtils.hasText(userName)){  
            builder.addPropertyValue("userName", userName);  
        }  
        if(StringUtils.hasText(email)){  
            builder.addPropertyValue("email", email);  
        }  
    }  
}

注意:类不要导入错了。

接下来,定义一个nameSpaceHandler,用于注册到Spring框架里面,在spring解析算定义标签的时候可以用我们自定义的处理方式。如下:

package com.wjs.cosumertag;  
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;  
public class MyUserNamespaceHandler extends NamespaceHandlerSupport {  
  
    @Override  
    public void init() {  
        registerBeanDefinitionParser("user",new UserBeanDefinitionParser());  
    }  
}

以上这两个类,便是处理自定义标签的处理类。
接下来就是xml  schema definition  (xsd)文件以及一些配置文件的配置。 
创建一个xsd为后缀的文件spring-user.xsd,内容如下:

<?xml version="1.0" encoding="UTF-8"?>  
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
    xmlns="http://www.wjs.com/schema/user" targetNamespace="http://www.wjs.com/schema/user"  
    elementFormDefault="qualified">  
    <xsd:element name="user">  
        <xsd:complexType>  
            <xsd:attribute name="id" type="xsd:string" />  
            <xsd:attribute name="userName" type="xsd:string" />  
            <xsd:attribute name="email" type="xsd:string" />  
        </xsd:complexType>  
    </xsd:element>  
</xsd:schema>

其中,xmlns=xmlns="http://www.wjs.com/schema/user",targetNamespace="http://www.wjs.com/schema/user" 这两个是自己定义的值,作用下面叙述。
然后就是配置这个xsd文件,让spring能够找到这个约束文件。 
在classpath下创建一文件夹META-INF,然后创建两个文件spring.handlers和spring.schemas,
(注意:这两个文件名不能改的)其中:为什么要创建MEAT-INF文件夹,spring是默认的向这个文件夹里面寻找这两个文件,如果想修改,就要修改spring源码来实现。  

spring.handlers文件内容如下:

http\://www.wjs.com/schema/user=com.wjs.cosumertag.MyUserNamespaceHandler
spring.schemas文件内容如下:

http\://www.wjs.com/schema/user.xsd=META-INF/spring-user.xsd

注意:冒号要进行转义

接下来就是在spring核心配置文件配置使用,文件名application-customtag.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:myTag="http://www.wjs.com/schema/user"  
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd  
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd  
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
        http://www.wjs.com/schema/user http://www.wjs.com/schema/user.xsd">  
   
 <myTag:user id="testBean" userName="name" email="wjs@163.com"/>  
</beans>

其中,xmlns:myTag="http://www.wjs.com/schema/user";http://www.wjs.com/schema/user;http://www.wjs.com/schema/user.xsd,这三个地方是自己定义的值,为什么这样写:spring在解析xml的时候,会根据namespaceURI来判断是spring的默认标签,还是用户定义的标签。下面翻下spring代码来说明:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {  
    if (delegate.isDefaultNamespace(root)) {  
        NodeList nl = root.getChildNodes();  
        for (int i = 0; i < nl.getLength(); i++) {  
            Node node = nl.item(i);  
            if (node instanceof Element) {  
                Element ele = (Element) node;  
                if (delegate.isDefaultNamespace(ele)) {  
                    parseDefaultElement(ele, delegate);  
                }else {  
                    delegate.parseCustomElement(ele);  
                }  
            }  
        }  
    }else {  
        delegate.parseCustomElement(root);  
    }  
}

而parseCustomElement文件如下:

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {  
    String namespaceUri = getNamespaceURI(ele);  
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);  
    if (handler == null) {  
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);  
        return null;  
    }  
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));  
}
首先是获取 namespaceUri这个值就是在spring.handlers里面定义的http\://www.wjs.com/schema/user,在sping启动时,会加载所有的namespaceURL做为一个map的key,此时这个key=http://www.wjs.com/schema/user.xsd,也就是spring解析现来的SystemId,而值就是META-INF/spring-test.xml,去这个目录下读取相应的sxd文件。如对spring源码有兴趣可以自行去翻阅下,会有不少的收获。
然后就代码测试,运行了
测试代码如下:

package com.wjs.cosumertag;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
public class CustomerTagTest {  
    public static void main(String[] args) {  
        ApplicationContext beans=new ClassPathXmlApplicationContext("classpath:application-customtag.xml");  
        User user=(User)beans.getBean("testBean");  
        System.out.println("username:"+user.getUserName()+":"+"email:"+user.getEmail());  
    }  
} 
如果不出意外,运行结果会是这样: 
username:name:email:wjs@163.com
maven项目结构如下:


其中走过的弯路如下: 
1.META-INF下的文件夹下的两个文件名,写成了大写Spring.handlers和Spring.schemas,导致找不到文件;没有加上xsd:前缀,导致解析spring-user.xsd文件报错。  
2.在编写spring-test.xsd文件时,没有加xsd:导致提示文件提前结束报错问题。 3.在编写spring-customtag.xml时,一定按照spring.handler和spring.schemas文件里的定义内容去添加自定义标签的namespaceURI.

  • 9
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值