如何在Spring中使用自定义标签
最近学习了一下如何在spring的xml文件中使用自定义的标签,把自己操作的过程记录下来。开始之前,最好先对spring的xml文件的格式有所了解,已经有文章写得很好了,这里不再赘述,详见:https://www.cnblogs.com/gonjan-blog/p/6637106.html。
接下来我们开始:
1、首先,pom文件中导入spring相关依赖:
pom.xml
1 <dependencies> 2 3 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> 4 <dependency> 5 <groupId>org.springframework</groupId> 6 <artifactId>spring-context</artifactId> 7 <version>5.1.3.RELEASE</version> 8 </dependency> 9 10 <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> 11 <dependency> 12 <groupId>org.springframework</groupId> 13 <artifactId>spring-core</artifactId> 14 <version>5.1.3.RELEASE</version> 15 </dependency> 16 17 <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> 18 <dependency> 19 <groupId>org.springframework</groupId> 20 <artifactId>spring-beans</artifactId> 21 <version>5.1.3.RELEASE</version> 22 </dependency> 23 24 <!-- https://mvnrepository.com/artifact/org.springframework/spring-web --> 25 <dependency> 26 <groupId>org.springframework</groupId> 27 <artifactId>spring-web</artifactId> 28 <version>5.1.3.RELEASE</version> 29 </dependency> 30 31 </dependencies>
2、定义一个User类,我们的目的就是通过自定义的标签将这个类注册到spring容器中,使其成为spring中的一个Bean。
1 package com.example 2 3 public class User { 4 5 private String id; 6 7 private String name; 8 9 private String email; 10 11 public String getId() { 12 return id; 13 } 14 15 public void setId(String id) { 16 this.id = id; 17 } 18 19 public String getName() { 20 return name; 21 } 22 23 public void setName(String name) { 24 this.name = name; 25 } 26 27 public String getEmail() { 28 return email; 29 } 30 31 public void setEmail(String email) { 32 this.email = email; 33 } 34 }
3、定义一个User类的解析器UserBeanDefinitionParser,这个类继承了spring中的AbstractSingleBeanDefinitionParser,并重写了其中的getBeanClass和doParse方法。之所以这么做是因为我们待会将user类注册到spring容器的时候,spring会调用我们重写的doParse方法对xml文件进行解析,然后将xml文件中的属性值按我们在doParse中定义的方式注入到Bean中。
1 package com.example; 2 3 import org.springframework.beans.factory.support.BeanDefinitionBuilder; 4 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; 5 import org.springframework.util.StringUtils; 6 import org.w3c.dom.Element; 7 8 public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { 9 @Override 10 protected Class<?> getBeanClass(Element element) { 11 return User.class; 12 } 13 14 @Override 15 protected void doParse(Element element, BeanDefinitionBuilder builder) { 16 String id=element.getAttribute("id"); 17 String name=element.getAttribute("name"); 18 String email=element.getAttribute("email"); 19 if(StringUtils.hasText(id)){ 20 builder.addPropertyValue("id", id); 21 } 22 if(StringUtils.hasText(name)){ 23 builder.addPropertyValue("name", name); 24 } 25 if(StringUtils.hasText(email)){ 26 builder.addPropertyValue("email", email); 27 } 28 } 29 }
4、定义UserNamespaceHandler类,这个类继承了spring中的NamespaceHandlerSupport类,并重写了其中的init方法,这个类的作用就是将标签中自定义的user标签和我们上一步定义的UserBeanDefinitionParser类绑定起来,表示解析到xml中的user标签的时候,要调用UserBeanDefinitionParser这个解析器来解析。
1 package com.example; 2 3 import org.springframework.beans.factory.xml.NamespaceHandlerSupport; 4 5 public class UserNamespaceHandler extends NamespaceHandlerSupport { 6 7 public void init() { 8 registerBeanDefinitionParser("user", new UserBeanDefinitionParser()); 9 } 10 }
5、在resources目录下新建一个xsd文件:spring-user.xsd,xsd文件是用来描述xml文档结构的,我们在这个文件里定义了xml文件中的user标签应该有哪些属性。关于xsd文件的详细语法,参考:http://www.w3school.com.cn/schema/index.asp。
spring-user.xsd
1 <?xml version="1.0" encoding="UTF-8"?> 2 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 3 xmlns="http://www.example.com/schema/user" 4 targetNamespace="http://www.example.com/schema/user" 5 elementFormDefault="qualified"> 6 <xsd:element name="user"> 7 <xsd:complexType> 8 <xsd:attribute name="id" type="xsd:string" /> 9 <xsd:attribute name="name" type="xsd:string" /> 10 <xsd:attribute name="email" type="xsd:string" /> 11 </xsd:complexType> 12 </xsd:element> 13 </xsd:schema>
6、在resources目录下新建一个目录:META-INF,在META-INF目录下新建两个文件:spring.handlers和spring.schemas文件,这两个文件的文件名是不能更改的,因为spring会自动去META-INF下寻找这两个文件,然后读取文件中定义的内容。下面是这两个文件的内容:
spring.handlers
http\://www.example.com/schema/user=com.example.UserNamespaceHandler
spring.schemas
http\://www.example.com/schema/spring-user.xsd=spring-user.xsd
注意反斜杠转义字符,是为了转义冒号。可以看到spring.handlers文件其实就是为了将"http://www.example.com/schema/user"这个命名空间与我们之前定义的UserNamespaceHandler类绑定起来,而spring.schemas文件则指明了"http://www.example.com/schema/spring-user.xsd"这个文件的本地位置,即resources目录下的spring-user.xsd文件。毕竟"http://www.example.com/schema/spring-user.xsd"这个网址是不存在的嘛,如果不指明一个本地文件与其对应,spring就真的会去这个网址上找xsd文件。
7、接下来就可以在resources目录下的application.xml文件中使用自己的标签了:
application.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:myTag="http://www.example.com/schema/user" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 7 http://www.example.com/schema/user 8 http://www.example.com/schema/spring-user.xsd"> 9 <myTag:user id="testUser" name="jeysin" email="jeysin@qq.com"/> 10 </beans>
在MyApplication的main函数中试着获取这个Bean
1 package com.example; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 public class MyApplication { 7 8 public static void main(String[] args){ 9 ApplicationContext context=new ClassPathXmlApplicationContext("application.xml"); 10 User user=(User)context.getBean("testUser"); 11 System.out.println(user.getId()); 12 System.out.println(user.getName()); 13 System.out.println(user.getEmail()); 14 } 15 }
整个的目录结构应该是这个样子:
-java
-com
-example
User
UserBeanDefinitionParser
UserNamespaceHandler
MyApplication
-resources
-META-INF
spring.handlers
spring.schemas
application.xml
spring-user.xsd
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现