Java - XML & DOM4j & 自定义连接池

发布于:2022-12-22 ⋅ 阅读:(208) ⋅ 点赞:(0)

XML & DOM4j & 自定义连接池

一、XML

  1. XML简介

    • xml 与 properties 的区别 - 平铺的关系二者都行,但是如果有层级关系用xml 才行。

在这里插入图片描述

  1. XML组成

    • 文档声明

    • 注释

    • 元素(标签)

    • 标签属性

    • 转义字符

    • 字符区

    • 代码示例

      <?xml version="1.0" encoding="UTF-8" ?><!--这是一个文档声明-->
      
      <!--我是一个注释-->
      <!--我是
             一个
              多行注释-->
      
      <!--根标签  不能是 自闭和 标签-->
      <aa>
          <!--闭合标签-->
          <bb></bb>
          <!--自闭和标签-->
          <cc/>
          <!--标签不能交叉嵌套-->
          <!--<ee><dd></ee></dd>-->
      
          <!--属性:属性 = 属性值-->
          <bb id="b01"></bb>
          <bb id="b02" name="bb01" ></bb>
          <bb id="b03"/>
          <bb id="b04" name="bb02"/>
      
          <!--转义字符-->
         <bb>
            <!-- 1 < 10-->  <!--这里的小于号,与xml语法冲突,造成报错-->
             1 &lt; 10
             1 > 10  <!--省略号、单双引号和大于号等是合法的,但将其替换为转义字符是个好习惯-->
             <!--jdbc:mysql///day16?useSSL=false&encoding=utf-8;-->
             jdbc:mysql///day16?useSSL=false&amp;encoding=utf-8;
         </bb>
      
          <!--字符区--> <!--格式:<![CDATA[文本数据]]>-->
          <![CDATA[
              1<10
              jdbc:mysql///day16?useSSL=false&encoding=utf-8;
          ]]>
      </aa>
      
  2. XML约束

    • 概述

      · 这些约束会优先从本地去找,如果发现本地就有,那就不会去你写的那个网站去找。

    • DTD约束

      <1> 定义格式

      <2> 引用方式

      • 网络上公共的DTD,其实在第一次引用的时候,会从网上下载到本地

      • 内部DTD

        <?xml version="1.0" encoding="UTF-8" ?>
        <!--内部DTD:<!DOCTYPE 根元素名称 [元素约束] >-->
        <!DOCTYPE books [
                <!ELEMENT books (book,book2)>
                <!ELEMENT book ANY >
                <!ELEMENT book2 ANY >
        ]>
        
        <books>
            <book></book>
            <book2></book2>
        </books>
        
      • 本地DTD

        //book.dtd
        <!ELEMENT books (book,book2)>
        <!ELEMENT book ANY >
        <!ELEMENT book2 ANY >
            
        
        <?xml version="1.0" encoding="UTF-8" ?>
        <!--本地DTD:<!DOCTYPE 根元素名称 SYSTEM "文件名">-->
        <!DOCTYPE books SYSTEM "book.dtd">
        <books>
            <book></book>
            <book2></book2>
        </books>
        
      • 公共DTD

        <?xml version="1.0" encoding="UTF-8" ?>
        <!--公共DTD:<!DOCTYPE 根元素名称  PUBLIC  “DTD名称” “DTD文档URL”>-->
        
        <!DOCTYPE struts PUBLIC
                "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
                "http://struts.apache.org/dtds/struts-2.3.dtd">
        <struts>
        
        </struts>
        

      <3> 例子

      ~ 代码示例

      · book.dtd

      <?xml version="1.0" encoding="UTF-8" ?>
      <!ELEMENT 书架 (+)>
      <!ELEMENT 书 (书名,作者,售价)>
      <!ELEMENT 书名 (#PCDATA)>
      <!ELEMENT 作者 (#PCDATA)>
      <!ELEMENT 售价 (#PCDATA)>
      <!ATTLIST 书
              id ID #REQUIRED
              编号 CDATA #IMPLIED
              出版社 (清华|北大) "北大"
              type CDATA #FIXED "IT"
      >
      

      · book.xml

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE 书架 SYSTEM "book.dtd">
      <书架>
          <书 id="b01" 编号="book001" 出版社="北大" type="IT">
              <书名></书名>
              <作者></作者>
              <售价></售价>
          </>
          <书 id="b02" >
              <书名></书名>
              <作者></作者>
              <售价></售价>
          </>
      </书架>
      
    • Schema约束

      <1> 概述 与 定义

      <2> 引用方式

      · booka.xsd

      <?xml version="1.0" encoding="UTF-8" ?>
      <xs:schema
              xmlns:xs="http://www.w3.org/2001/XMLSchema"
              targetNamespace="http://www.xmltest.cn"
              elementFormDefault="qualified"
      >
                      <xs:element name='书'>
                          <xs:complexType>
                              <xs:sequence>
                                  <xs:element name='书名' type='xs:string'/>
                                  <xs:element name='作者' type='xs:string'/>
                                  <xs:element name='售价' type='xs:double'/>
                              </xs:sequence>
                              <xs:attribute name="bid" type="xs:int" use="optional"/>
                          </xs:complexType>
                      </xs:element>
      
      </xs:schema>
      

      · bookb.xsd

      <?xml version="1.0" encoding="UTF-8" ?>
      <xs:schema
              xmlns:xs="http://www.w3.org/2001/XMLSchema"
              targetNamespace="http://www.xmltest.cn"
              elementFormDefault="qualified"
      >
          <xs:element name='书'>
              <xs:complexType>
                  <xs:sequence>
                      <xs:element name='书名' type='xs:string'/>
                      <xs:element name='作者' type='xs:string'/>
                  </xs:sequence>
                  <xs:attribute name="bid" type="xs:int" use="optional"/>
              </xs:complexType>
          </xs:element>
      
      </xs:schema>
      

      · book.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <书架
              xmlns:aa="http://www.xmltest1.cn"
              xmlns:bb="http://www.xmltest.cn"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://www.xmltest1.cn booka.xsd http://www.itheima.cn bookb.xsd"
      >
          <aa:>
              <aa:书名>三国演义</aa:书名>
              <aa:作者>罗贯中</aa:作者>
              <aa:售价>199</aa:售价>
          </aa:>
          <bb:>
              <bb:书名>水浒传</bb:书名>
              <bb:作者>施耐庵</bb:作者>
              <!--<aa:售价>199</aa:售价>-->
          </bb:>
      </书架>
      

      <3> 对应关系

    • XML解析概述

二、DOM4j

  1. DOM4j 解析

    • books.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <books>
          <book id="0001">
              <name>JavaWeb开发教程</name>
              <author>张孝祥</author>
              <sale>100.00</sale>
          </book>
          <book id="0002">
              <name>三国演义</name>
              <author>罗贯中</author>
              <sale>100.00</sale>
          </book>
          <book2 id="0003">
              <name>三国演义</name>
              <author>罗贯中</author>
              <sale>100.00</sale>
          </book2>
      </books>
      
    • DOM4j 解析 - 代码示例

      public class Test {
          public static void main(String[] args) throws Exception {
              //1. 导入jar包: dom4j-1.6.1j.jar
              //2. 创建解析器:public SAXReader()
              SAXReader saxReader = new SAXReader();
              //3. 通过解析器对象读取xml,获得Document对象:Document  read(InputStream in) in是xml文件对应的输入流
              FileInputStream in = new FileInputStream("day18\\src\\books.xml");
              Document document = saxReader.read(in);
              //4. 通过树结构对象获取根元素:Element getRootElement();
              Element rootElement = document.getRootElement();
      
              //5. 操作元素节点(使用Element中的方法)
              //需求1:获取根标签的标签名
              System.out.println("rootElement.getName()=" + rootElement.getName());
      
              //需求2:获取books标签下面所有的book子标签
              //List<Element> elements = rootElement.elements();//获取所有子标签
              List<Element> elements = rootElement.elements("book");//获取所有book子标签
              for (Element element : elements) {
                  System.out.println("element.getName()=" + element.getName());
              }
              //需求3:获取books标签下面第一个book标签
              Element book = rootElement.element("book");
              System.out.println("book.getName()="+book.getName());
      
              //需求4:获取第1个book标签指定的属性值
              String id = book.attributeValue("id");
              System.out.println("id="+id);
              //需求5:获取第一个book标签的子标签name的内容
              Element name = book.element("name");
              System.out.println("name.getText()="+name.getText());
          }
      }
      
  2. Xpath解析

    • tianqi.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <天气预报>
          <北京 provide='京' id='1'>
              <温度>
                  <最高温度 level="A">18</最高温度>
                  <最低温度>6</最低温度>
              </温度>
              <湿度>20%</湿度>
          </北京>
          <深圳>
              <温度>
                  <最高温度 level="C">36</最高温度>
                  <最低温度>24</最低温度>
              </温度>
              <湿度>50%</湿度>
          </深圳>
          <广州>
              <温度>
                  <最高温度 level="C">32</最高温度>
                  <最低温度>21</最低温度>
              </温度>
              <湿度>50%</湿度>
              <黄浦区>
                  <温度>
                      <最高温度 level="C">31</最高温度>
                      <最低温度>22</最低温度>
                  </温度>
                  <湿度>50%</湿度>
              </黄浦区>
              <天河区>
                  <温度>
                      <最高温度 level="C">30</最高温度>
                      <最低温度>26</最低温度>
                  </温度>
                  <湿度>50%</湿度>
              </天河区>
          </广州>
      </天气预报>
      
    • Xpath 解析 - 代码示例

      public class Test {
          public static void main(String[] args) throws Exception {
              //导入dom4j-1.6.1j.jar和jaxen-1.1-beta-6.jar
              //创建解析器对象获取Document对象获取根节点
              SAXReader saxReader = new SAXReader();
              Document document = saxReader.read(new FileInputStream("day18\\src\\tianqi.xml"));
              Element rootElement = document.getRootElement();
      
              //Element对象支持以下方法
              //Node selectSingleNode("xpath语法"):获得一个节点(标签/元素)
              //List selectNodes("xpath语法"):获得多个节点(标签/元素)
      
              //操作元素节点
              //①基本使用
              //需求1:获取深圳的最低温度(绝对路径)
              Node node1 = rootElement.selectSingleNode("/天气预报/深圳/温度/最低温度");
              System.out.println(node1.getName()+"=="+node1.getText());
              //需求2:获取深圳的最低温度(相对路径)
              Node node2 = rootElement.selectSingleNode("深圳/温度/最低温度");
              System.out.println(node2.getName()+"=="+node2.getText());
              //需求3:获取深圳的最低温度(全文搜索)
              Node node3 = rootElement.selectSingleNode("//深圳//温度//最低温度");
              System.out.println(node3.getName()+"=="+node3.getText());
              //需求4:获取北京的最高温度(谓语)
              Node node4 = rootElement.selectSingleNode("//最高温度[@level='A']");
              System.out.println(node4.getName()+"=="+node4.getText());
      
              //②特殊情况
              //需求5:通过深圳最低温度节点,获取广州黄浦区的最低温度(相对路径)
              Node node5 = node1.selectSingleNode("../../../广州/黄浦区/温度/最低温度");
              System.out.println(node5.getName()+"=="+node5.getText());
              //需求6:获取所有最高温度(全文搜索)
              List list = rootElement.selectNodes("//最高温度");
              for (Object o : list) {
                  //System.out.println(o.getName()+"=="+o.getText());//error
                  Node node = (Node) o;
                  System.out.println("--->"+node.getName()+"=="+node.getText());
              }
              //需求7:获取属性level='C'的所有最高温度(谓语)
              List list2 = rootElement.selectNodes("//最高温度[@level='C']");
              for (Object o : list2) {
                  Node node = (Node) o;
                  System.out.println("===>"+node.getName()+"=="+node.getText());
              }
          }
      }
      

三、自定义连接池

  1. 概述

  2. 优化版

    • 自己写的获取连接的方法与别人定义的可能不一样,所以不够通用,但因为sun公司定义了一个接口DataSource,让所有自定义连接池有了统一的规范,我们只需要重写获取连接的方法。
    • 归还连接的方法也不够通用,而且DataSource接口没有定义归还连接的统一方法,那我们只能通过代理模式,对连接对象的close功能进行增强实现。

    • 代码示例

      public class MyDataSource implements DataSource {
          private static LinkedList<Connection> pool = new LinkedList<>();
          private static int initCount = 5;
      
          //定义静态代码块,添加连接对象
          static {
              try {
                  //注册驱动
                  Class.forName("com.mysql.jdbc.Driver");
                  //准备连接数据
                  String url = "jdbc:mysql:///day16?useSSL=false";
                  String username = "*********";
                  String password = "************";
      
                  for (int i = 0; i < initCount; i++) {
                      //获取连接对象
                      Connection conn = DriverManager.getConnection(url, username, password);
                      //将连接对象添加到连接池
                      pool.addLast(conn);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      
          @Override
          public Connection getConnection() throws SQLException {
              //被代理的连接对象
              Connection conn = pool.removeFirst();
      
              //准备获取代理对象的数据
              ClassLoader classLoader = conn.getClass().getClassLoader();
              Class<?>[] interfaces = conn.getClass().getInterfaces();
              InvocationHandler handler = new InvocationHandler() {
                  @Override
                  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                      //System.out.println("method===>"+ method.getName());
                      //对连接对象原有的close方法进行处理
                      if ("close".equals(method.getName())) {
                          pool.addLast(conn);
                          return null;
                      } else {
                          //千万注意,要对其他的方法,进行处理,不处理,意味着调用其他方法,啥也不做。
                          Object result = method.invoke(conn, args);
                          return result;
                      }
                  }
              };
      
              //获取代理对象
              Connection connProxy = (Connection) Proxy.newProxyInstance(classLoader, interfaces, handler);
      
              //返回连接对象的代理对象
              return connProxy;
          }
      
          //获取连接池中的连接对象个数
          public int size() {
              return pool.size();
          }
      
      
          @Override
          public Connection getConnection(String username, String password) throws SQLException {
              return null;
          }
      
          @Override
          public <T> T unwrap(Class<T> iface) throws SQLException {
              return null;
          }
      
          @Override
          public boolean isWrapperFor(Class<?> iface) throws SQLException {
              return false;
          }
      
          @Override
          public PrintWriter getLogWriter() throws SQLException {
              return null;
          }
      
          @Override
          public void setLogWriter(PrintWriter out) throws SQLException {
      
          }
      
          @Override
          public void setLoginTimeout(int seconds) throws SQLException {
      
          }
      
          @Override
          public int getLoginTimeout() throws SQLException {
              return 0;
          }
      
          @Override
          public Logger getParentLogger() throws SQLFeatureNotSupportedException {
              return null;
          }
      }
      
    • 测试类

      public class Test {
          public static void main(String[] args) throws SQLException {
              //获取连接池对象
              MyDataSource pool = new MyDataSource();
      
              //获取连接对象(实际获取的是代理对象)
              Connection conn = pool.getConnection();
      
              //打印连接对象
              System.out.println(conn);
              //执行sql操作 ...
      
              //打印归还前的连接池中的连接数量
              System.out.println("终极版-->连接池中的连接数:" + pool.size());
      
              //归还连接对象
              conn.close();
      
              //打印归还后的连接池中的连接数量
              System.out.println("终极版-->连接池中的连接数:" + pool.size());
      
          }
      }
      
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到