如何在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

 

posted @ 2018-12-02 13:58  jeysin  阅读(378)  评论(0编辑  收藏  举报