今天尝试在spring框架下自定义一个标签,为以后定义一组标签,来控制流程处理做准备。
自定义一个标签需要以下步骤:
- 确定标签的属性,编写对应的java bean
- 根据java bean编写对应xsd文件
- 编写标签注册类NamespaceHandler和标签解析类BeanDefinitionParser
- 配置spring.handlers和spring.schmas
- 在spring的配置文件中使用标签
第一步:编写对应的java bean
我计划定一个标签facade,其属性包括id,interCode,reqEvent,resEvent
所以我的java bean如下:
public class Facade {
private String id;
private String interCode;
private String reqEvent;
private String resEvent;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getInterCode() {
return interCode;
}
public void setInterCode(String interCode) {
this.interCode = interCode;
}
public String getReqEvent() {
return reqEvent;
}
public void setReqEvent(String reqEvent) {
this.reqEvent = reqEvent;
}
public String getResEvent() {
return resEvent;
}
public void setResEvent(String resEvent) {
this.resEvent = resEvent;
}
}
第二步:根据java bean编写对应xsd文件
对应的xsd文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.luxy.org/li" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://www.luxy.org/li" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:element name="facade" type="facadeType"></xsd:element>
<xsd:complexType name="facadeType">
<xsd:attribute name="id" type="xsd:ID" use="required" />
<xsd:attribute name="interCode" type="xsd:string"></xsd:attribute>
<xsd:attribute name="reqEvent" type="xsd:string"></xsd:attribute>
<xsd:attribute name="resEvent" type="xsd:string"></xsd:attribute>
</xsd:complexType>
</xsd:schema>
第三步:编写标签注册类NamespaceHandler和标签解析类BeanDefinitionParser
NamespaceHandler:
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import com.slys.core.schema.parser.FacadeParser;
public class LiNamespaceHandler extends NamespaceHandlerSupport {
public void init()
{
registerBeanDefinitionParser("facade", new FacadeParser());
}
}
BeanDefinitionParser:
public class FacadeParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected Class<Facade> getBeanClass(Element element) {
return Facade.class;
}
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
try
{
builder.addPropertyValue("id", element.getAttribute("id"));
builder.addPropertyValue("interCode", element.getAttribute("interCode"));
builder.addPropertyValue("reqEvent", element.getAttribute("reqEvent"));
builder.addPropertyValue("resEvent", element.getAttribute("resEvent"));
} catch (Exception e) {
parserContext.getReaderContext().error("class " + FacadeParser.class.getName() + " can not be create", element, null, e);
}
}
}
第四步:配置spring.handlers和spring.schmas
spring.handlers:
http\://www.luxy.org/li=com.slys.core.schema.LiNamespaceHandler
spring.schemas:
http\://www.luxy.org/li.xsd=com/slys/core/schema/li.xsd
第五步:在spring的配置文件中使用标签
<?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:li="http://www.luxy.org/li" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.luxy.org/li http://www.luxy.org/li.xsd">
<li:facade id="abcd" interCode="1234" reqEvent="test" resEvent="res"></li:facade>
</beans>
大功告成!!!
测试:
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-config.xml");
Facade facade = (Facade) context.getBean("abcd");
System.out.println(facade.getId());
System.out.println(facade.getInterCode());
System.out.println(facade.getReqEvent());
System.out.println(facade.getResEvent());
}
输出结果:
abcd
1234
test
res
在尝试过程中遇到的问题:
1、xsd中没有加id属性,报错:cvc-complex-type.3.2.2: 元素 ‘li:facade’ 中不允许出现属性 ‘id’,加上后错误消失
2、id的值使用“1234”,报错:cvc-datatype-valid.1.2.1: ‘1234’ 不是 ‘NCName’ 的有效值,理解为不能使用纯数字为id赋值
3、spring.handlers和spring.schmas的存放位置,放在src/main/resources目录下,新建META-INF文件夹
4、使用maven打jar包时,发现不能将li.xsd文件打进去jar中,解决办法:
在pom.xml增加
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.xsd</include>
</includes>
</resource>
</resources>
</build>