web编写自定义标签

前言

  在上一个寒假,我学会了自定义标签和解析标签,时隔近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);
    });
  }
}
运行结果
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容