web编写自定义标签

2020-11-25  本文已影响0人  GG_lyf

前言

  在上一个寒假,我学会了自定义标签和解析标签,时隔近11个月,我又拿起了他,之前的想法又重新在脑海中浮现--想自己做一个类似于springMVC的框架。虽然没做成,但是这个让我认识到了自己的不足啊!!!


开搞

1.idea中创建一个普通的java项目

2.编写dtd文件

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT users (user*)>
<!ELEMENT user (property*)>
<!ATTLIST user
    id ID #REQUIRED
    class CDATA #REQUIRED
    scope (singlton|prototypr|session|request) "singlton"
>
    <!--
    CDATA  表示可以放入文本
    ID  表示属性的值,不能重复,同时不要用数字开头.
    IDREF/IDREFS 当一个元素的属性值,需要去引用另外一个ID ,则使用IDREF,如果希望引用多个,则使用IDREFS,请用空格隔开.
    Enumerated 表示属性的值,只能是例举出了-->
    <!--id属性值,类型是ID,限制是必须写-->
    <!--singlton单例  prototypr原型  session会话  request请求-->
<!ELEMENT property (#PCDATA)>
    <!--CDATA是文本类型 , #PCDATA是段落类型-->
    <!--
    CDATA 的意思是字符数据(character data)
    PCDATA 的意思是被解析的字符数据(parsed character data)。
    PDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
    -->
    <!--#IMPLIED可选类型-->
<!ATTLIST property
    name CDATA #REQUIRED
    value CDATA #REQUIRED
    type (int|float|double|string|long) #IMPLIED
>

3.编写对应的.xml文件(引入对应的dtd可以有提示)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users SYSTEM "D:\idea\idea-workspace\springmvc_project\src\main\resources\users.dtd">
<users  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <user id="id1" class="org.lyf.bean.User" scope="singlton">
    <property name="id" value="1001" type="int"/>/
    <property name="username" value="张三" type="string"/>
    <property name="password" value="123456" type="string"/>
    <property name="phone" value="15993596768" type="string"/>
    <property name="email" value="11111@qq.com" type="string"/>
  </user>
  <user id="id2" class="org.lyf.bean.User" scope="singlton">
    <property name="id" value="1002" type="int"/>/
    <property name="username" value="李四" type="string"/>
    <property name="password" value="654321" type="string"/>
    <property name="phone" value="12589658745" type="string"/>
    <property name="email" value="22222@qq.com" type="string"/>
  </user>
</users>

4.编写实体类

public class User {
  private int id;
  private String username;
  private String password;
  private String phone;
  private String email;
  //get,set和toString
}

5.编写xml属性对应的实体类,用于实体的封装

public class UserInfo {
  private String id;
  private String clazz;
  private String scope;

  private List<PropInfo> propInfos;
 //get,set和toString
}
public class PropInfo {
  private String name;
  private String value;
  private String type;
  //get,set和toString
}

6.编写xml的解析类

public class Factorys {
  private HashMap<String, UserInfo> userInfoHashMap;
  private static ArrayList<String> list = new ArrayList<>();//用于存储user标签的id

  public Factorys(String xmlPath) {//获取文件路径
    try {
      if (xmlPath.equals("") || !new File(xmlPath).exists()) {//如果为空或不存在就返回空
        return;
      }
      SAXParserFactory factory = SAXParserFactory.newInstance();//.创建SAXParser解析器对象
      SAXParser saxParser = factory.newSAXParser();//.创建SAXParser解析器类对象
      saxParser.parse(new FileInputStream(xmlPath), new DefaultHandler() {//DefaultHandler默认的处理器
        UserInfo userInfo;

        //xml文档开始解析
        public void startDocument() {
          userInfoHashMap = new HashMap<>();
        }

        //标签开始解析
        public void startElement(String uri, String localName, String qName, Attributes attr) {
          if ("user".equals(qName)) {
            userInfo = new UserInfo();
            userInfo.setId(attr.getValue("id"));
            userInfo.setClazz(attr.getValue("class"));
            userInfo.setScope(attr.getValue("scope"));
            userInfo.setPropInfos(new ArrayList<>());
          } else if ("property".equals(qName)) {
            userInfo.getPropInfos().add(new PropInfo(attr.getValue("name"), attr.getValue("value"), attr.getValue("type")));
          }
        }

        //标签结束
        public void endElement(String uri, String localName, String qName) {
          if ("user".equals(qName)) {
            userInfoHashMap.put(userInfo.getId(), userInfo);
            list.add(userInfo.getId());
            userInfo = null;
          }
        }

      });
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public ArrayList<String> getList(){//返回id集合
    return list;
  }


  public Factory newFactory() {//返回一个新创建的类对象
    return new Factory();
  }

  public class Factory {

    public Object getUser(String id) {//获取id
      UserInfo userInfo = userInfoHashMap.get(id);//通过id获取map集合里的用户对象
      if (userInfo == null) {
        return null;
      }
      try {
        Class<?> userClass = Class.forName(userInfo.getClazz());//new出来一个动态对象
        Object newInstance = userClass.newInstance();
        for (PropInfo propInfo : userInfo.getPropInfos()) {
          Field declaredField = userClass.getDeclaredField(propInfo.getName());
          declaredField.setAccessible(true);
          if (propInfo.getType().equals("int")) {
            declaredField.set(newInstance, Integer.parseInt(propInfo.getValue()));
          } else {
            declaredField.set(newInstance, propInfo.getValue());
          }
        }
        return newInstance;//返回对象
      } catch (Exception e) {
        e.printStackTrace();
      }
      return null;
    }

  }
}

7.编写测试类进行测试

public class FactoryTest {
  public static void main(String[] args) {
    String file = Objects.requireNonNull(FactoryTest.class.getClassLoader().getResource("user.xml")).getFile();//类加载器
    Factorys factorys = new Factorys(file);
    Factorys.Factory factory = factorys.newFactory();
    factorys.getList().forEach((item) -> {
      User id1 = (User) factory.getUser(item);
      System.out.println(id1);
    });
  }
}
运行结果
上一篇 下一篇

猜你喜欢

热点阅读