2.1.7 XML,语法, 约束, DTD,Schema, XML解析,dom4j, xpath, JDBC自定义XML

目录

1. XML基本介绍

1.1 概述

1.2 XML的作用

2. XML的语法

2.1 XML文档声明格式

2.2 元素

2.3 属性

2.4 注释

2.5 使用XML 描述数据表中的数据

3. XML约束

3.1 DTD约束

3.1.1 编写DTD

3.1.2 引入DTD

3.2 Schema约束

3.2.1 什么是Schema

3.2.2 Schema约束示例

3.2.3 XML引入Schema约束

4. XML 解析

4.1 解析概述

4.2 XML解析方式

4.3 XML常见的解析器

4.4 dom4j 的使用

4.4.1 导入JAR包

4.4.2 API介绍

4.4.3 准备xml文件

4.4.4 读取XML

4.5 xpath方式读取xml

4.5.1 xpath介绍

4.5.2 XPath基本语法介绍

4.5.3 API介绍

4.5.4 Xpath读取XML

5. JDBC自定义XML

5.1 定义配置文件

5.2 编写工具类(配置式)

5.3 测试工具类


1. XML基本介绍

1.1 概述

XML即可扩展标记语言(Extensible Markup Language)
W3C在1998.2发布v1.0,2004.2发布v1.1。 v1.1版本不兼容v1.0,故v1.1没人用。另外,W3C在2004.2又发布了v1.0第三版。此处学习是v1.0 !

特点
可扩展的, 标签自定义
语法严格

 

1.2 XML的作用

XML能做什么?

 

2. XML的语法

2.1 XML文档声明格式

文档声明必须为结束;
文档声明必写在第一行;

1) 语法格式:

<?xml version="1.0" encoding="UTF-8"?>

2) 属性说明:
versioin:
指定XML文档版本。必须属性,只选择1.0;
encoding:指定当前文档的编码。可选属性,默认utf-8;

 

2.2 元素

Element 元素: 是XML文档中最重要的组成部分

元素的命名规则:

        1. 不能使用空格,不能使用冒号
        2. xml 标签名称区分大小写
        3. XML 必须有且只有一个根元素

语法格式:

<users><users>

1) XML 必须有且只有一个根元素,它是所有其他元素的父元素,比如以下实例中 users 就是根元素:

<?xml version="1.0" encoding="utf-8" ?>
<users>
 
</users>

2) 普通元素的结构开始标签、元素体、结束标签组成。

<hello> 大家好 </hello>

3) 元素体:元素体可以是元素,也可以是文本 

<hello>
  <a>你好</a>
</hello>

4) 空元素:空元素只有开始标签,而没有结束标签,但元素必须自己闭合

<close/>

完整例:

<?xml version="1.0" encoding="UTF-8" ?>

<users>
    <user id="123" number="">
        <name>张百万</name>
        <age>15</age>
    </user>

    <user>
        <name>小斌</name>
        <age>18</age>
        <hobby>
            <pingpong>

            </pingpong>
        </hobby>
    </user>

    <!-- 空元素 没有结束标签 -->
    <close/>
</users>


<!-- XML的注释
    1. XML中必须进行文档声明
        version     版本信息
        encoding    编码

    2. XML中的文档声明必须写在第一行

    3. XML中的元素标签 命名规则
        a, 标签定义,不能使用空格或者冒号
        b, XML标签名称, 区分大小写

    4. XML中有且只有一个根元素

    5. 元素体 可以是文本, 或者还是一个标签

    6. 属性是元素的一部分, 只能出现在元素的开始标签中
        属性值必须使用单引号或者双引号包裹
        一个元素标签,可以定义多个属性
-->

 

2.3 属性

<bean id="" class=""> </bean>

1. 属性是元素的一部分,它必须出现在元素的开始标签中
2. 属性的定义格式:属性名=属性值,其中属性值必须使用单引或双引
3. 一个元素可以有0~N个属性,但一个元素中不能出现同名属性
4. 属性名不能使用空格、冒号等特殊字符,且必须以字母开头

 

2.4 注释

XML的注释,以“ <!--”开始,以“--> ”结束。注释内容会被XML解析器忽略!

 

2.5 使用XML 描述数据表中的数据

<?xml version="1.0" encoding="UTF-8" ?>
<employees>
  <employee eid="2">
    <ename>林黛玉</ename>
    <age>20</age>
    <sex>女</sex>
    <salary>5000</salary>
    <empdate>2019-03-14</empdate>
  </employee>
  <employee eid="3">
    <ename>杜甫</ename>
    <age>40</age>
    <sex>男</sex>
    <salary>15000</salary>
    <empdate>2010-01-01</empdate>
  </employee>
</employees>

 

3. XML约束

在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束。

常见的xml约束:DTD   /  Schema

作为程序员, 不用自己编写, 只要掌握两点:
        会阅读
        会引入

 

3.1 DTD约束

DTD(Document Type Definition),文档类型定义,用来约束XML文档。

规定XML文档中元素的名称,子元素的名称及顺序,元素的属性等。

 

3.1.1 编写DTD

开发中,我们不会自己编写DTD约束文档

正常情况我们都是通过框架提供的DTD约束文档,编写对应的XML文档。

常见框架使用DTD约束有:Struts2、hibernate等。

创建约束文件 student.dtd

<!ELEMENT students (student+) >
        <!ELEMENT student (name,age,sex)>
        <!ELEMENT name (#PCDATA)>
        <!ELEMENT age (#PCDATA)>
        <!ELEMENT sex (#PCDATA)>
        <!ATTLIST student number ID #REQUIRED>

        <!--
            ELEMENT 定义元素
             students (student+):  students 代表根元素
             student+ : 根标签中 至少有一个 student子元素
             student (name,age,sex) : student标签中可以 包含的子元素  按顺序出现
             #PCDATA : 普通的文本内容
             ATTLIST : 用来定义属性
             student number ID : student标签中 有一个ID属性 叫做 number
             #REQUIRED : number的属性必须填写
             ID 唯一的值 不能重复 值只能是字母或者下划线开头
        -->

 

3.1.2 引入DTD

引入dtd文档到xml文档中,两种方式
内部dtd:将约束规则定义在xml文档中
外部dtd:将约束的规则定义在外部的dtd文件中(开发中一般会下载下来放入本地)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "D:\lagou\jdbc_work\xml_task03\src\com\lg\xml02\dtd\student.dtd">
<students>
    <student number="S1">
        <name>长海</name>
        <age>20</age>
        <sex>男</sex>
    </student>

    <student number="S2">
        <name>大玲</name>
        <age>18</age>
        <sex>女</sex>
    </student>
</students>

 

3.2 Schema约束

3.2.1 什么是Schema

1. Schema是新的XML文档约束, 比DTD强大很多,是DTD 替代者;
2. Schema本身也是XML文档,但Schema文档的扩展名为xsd,而不是xml。
3. Schema 功能更强大,内置多种简单和复杂的数据类型
4. Schema 支持命名空间 (一个XML中可以引入多个约束文档)

 

3.2.2 Schema约束示例

student.xsd

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.lagou.com/xml"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.lagou.com/xml" elementFormDefault="qualified">

    <xsd:element name="students" type="studentsType"/>
    <xsd:complexType name="studentsType">
        <xsd:sequence>
            <xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="studentType">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="age" type="ageType" />
            <xsd:element name="sex" type="sexType" />
        </xsd:sequence>
        <xsd:attribute name="number" type="numberType" use="required"/>
    </xsd:complexType>
    <xsd:simpleType name="sexType">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="male"/>
            <xsd:enumeration value="female"/>
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="ageType">
        <xsd:restriction base="xsd:integer">
            <xsd:minInclusive value="0"/>
            <xsd:maxInclusive value="200"/>
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="numberType">
        <xsd:restriction base="xsd:string">
        <xsd:pattern value="hehe_\d{4}"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

Xml Schema的根元素:

 

3.2.3 XML引入Schema约束

xml中引入schema约束的步骤:

1) 查看schema文档,找到根元素,在xml中写出来

<?xml version="1.0" encoding="UTF-8" ?>
<students>

</students>

2) 根元素来自哪个命名空间。使用xmlns指令来声明

<?xml version="1.0" encoding="UTF-8" ?>
<students
  xmlns="http://www.lagou.com/xml"
>
 
</students>

3) 引入 w3c的标准命名空间, 复制即可

<?xml version="1.0" encoding="UTF-8" ?>
<students
  xmlns="http://www.lagou.com/xml"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
</students>

4) 引入的命名空间跟哪个xsd文件对应?
使用schemaLocation来指定:两个取值:第一个为命名空间 第二个为xsd文件的路径

<?xml version="1.0" encoding="UTF-8" ?>
<students
  xmlns="http://www.lagou.com/xml"    
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.lagou.com/xml student.xsd"
>
</students>

5) 命名空间

指的是一个环境,所用的标签来自于哪个环境定义的。

6) student.xml

<?xml version="1.0" encoding="UTF-8" ?>
<students
        xmlns="http://www.lagou.com/xml"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.lagou.com/xml student.xsd"
>
    <student number="hehe_1234">
        <name>张三</name>
        <age>20</age>
        <sex>male</sex>
    </student>

    <student number="hehe_4567">
        <name>张三</name>
        <age>20</age>
        <sex>male</sex>
    </student>

</students>

 

4. XML 解析

4.1 解析概述

当将数据存储在XML后,我们就希望通过程序获得XML的内容。

如果我们使用Java基础所学习的IO知识是可以完成的,不过需要非常繁琐的操作才可以完成,且开发中会遇到不同问题(只读、读写)。
人们为不同问题提供不同的解析方式,并提交对应的解析器,方便开发人员操作XML。

 

4.2 XML解析方式

开发中比较常见的解析方式有两种,如下:

DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象。
优点:元素与元素之间保留结构关系,故可以进行增删改查操作。
缺点:XML文档过大,可能出现内存溢出显现。

SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进行具体解析,每执行一行,都将触发对应的事件。(了解)
优点:占用内存少 处理速度快,可以处理大文件
缺点:只能读,逐行后将释放资源。

 

4.3 XML常见的解析器

解析器:就是根据不同的解析方式提供的具体实现。有的解析器操作过于繁琐,为了方便开发人员,有提供易于操作的解析开发包

JAXP:sun公司提供的解析器,支持DOM和SAX两种思想

DOM4J:一款非常优秀的解析器 , Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。
它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。

Jsoup:jsoup 是一款Java 的HTML解析器 ,也可以解析XML

PULL:Android内置的XML解析方式,类似SAX。

 

4.4 dom4j 的使用

4.4.1 导入JAR包

 

4.4.2 API介绍

使用核心类SaxReader加载xml文档获得Document,通过Document 对象获得文档的根元素,然后就可操作

常用API如下:
SaxReader对象
read(…) 加载执行xml文档
Document对象
getRootElement() 获得根元素
Element对象
elements(…) 获得指定名称的所有子元素。可以不指定名称
element(…) 获得指定名称的第一个子元素。可以不指定名称
getName() 获得当前元素的元素名
attributeValue(…) 获得指定属性名的属性值
elementText(…) 获得指定名称子元素的文本值
getText() 获得当前元素的文本内容

 

4.4.3 准备xml文件

编写user.xsd schema约束

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.lagou.com/xml"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.lagou.com/xml"
            elementFormDefault="qualified">
    <xsd:element name="users" type="usersType"/>
    <xsd:complexType name="usersType">
        <xsd:sequence>
            <xsd:element name="user" type="userType" minOccurs="0"
                         maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="userType">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="age" type="ageType" />
            <xsd:element name="hobby" type="hobbyType" />
        </xsd:sequence>
        <xsd:attribute name="id" type="numberType" use="required"/>
    </xsd:complexType>
    <xsd:simpleType name="ageType">
        <xsd:restriction base="xsd:integer">
            <xsd:minInclusive value="0"/>
            <xsd:maxInclusive value="100"/>
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="hobbyType">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="抽烟"/>
            <xsd:enumeration value="喝酒"/>
            <xsd:enumeration value="烫头"/>
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="numberType">
        <xsd:restriction base="xsd:string">
            <xsd:pattern value="\d{3}"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

编写user.xml 引入约束

<?xml version="1.0" encoding="UTF-8" ?>
<users xmlns="http://www.lagou.com/xml"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.lagou.com/xml user.xsd"
>
    <user id="001">
        <name>张百万</name>
        <age>25</age>
        <hobby>抽烟</hobby>
    </user>

    <user id="002">
        <name>于谦</name>
        <age>55</age>
        <hobby>烫头</hobby>
    </user>

    <user id="003">
        <name>小兵</name>
        <age>25</age>
        <hobby>喝酒</hobby>
    </user>


</users>

 

4.4.4 读取XML

package com.lg.xml03;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;

import java.util.List;


/**
 * @author CH
 * @date 2020/11/4 18:05
 */
public class TestDOM4j {

    // 获取XML文件中的 所有的元素(标签)
    @Test
    public void test1() throws DocumentException {

        //1. 获取XML解析对象
        SAXReader reader = new SAXReader();

        //2. 解析XML 获取文档对象
        Document document = reader.read("D:\\lagou\\jdbc_work\\xml_task03\\src\\com\\lg\\xml03\\user.xml");

        //3. 获取根元素
        Element rootElement = document.getRootElement();

        // 获取根元素名称
        System.out.println(rootElement.getName());

        // 获取根元素下的标签
        List<Element> elements = rootElement.elements();
        for (Element element : elements) {
            System.out.println("根标签下的子节点: " + element.getName());

            List<Element> elements1 = element.elements();
            for (Element element1 : elements1) {
                System.out.println("user标签下的子节点: " + element1.getName());
            }
            break;
        }
    }

    // 获取XML中  标签的文本信息 和 属性信息
    @Test
    public void test2() throws DocumentException {

        //1. 获取解析XML的 SAXReader
        SAXReader reader = new SAXReader();

        //2. 获取文档对象
        Document doucument = reader.read("D:\\lagou\\jdbc_work\\xml_task03\\src\\com\\lg\\xml03\\user.xml");

        //3. 获取根节点
        Element rootElement = doucument.getRootElement();

        //4. 获取子节点 user
        List<Element> elements = rootElement.elements();

        //5. 获取集合中的第一个 子节点
        Element user = elements.get(0);

        //6. 获取节点中信息
        String id = user.attributeValue("id");  // 获取属性 id 的值
        String name = user.elementText("name");
        String age = user.elementText("age");
        String hobby = user.element("hobby").getText();

        //打印
        System.out.println(id +" " + name + " " + age + " " + hobby);
    }
}

 

4.5 xpath方式读取xml

4.5.1 xpath介绍

XPath 是一门在 XML 文档中查找信息的语言。 可以是使用xpath查找xml中的内容。

XPath 的好处
由于DOM4J在解析XML时只能一层一层解析,所以当XML文件层数过多时使用会很不方便,结合XPATH就可以直接获取到某个元素

(1) 需要再导入 jaxen-1.1-beta-6.jar

 

4.5.2 XPath基本语法介绍

使用dom4j支持xpath的操作的几种主要形式

 

4.5.3 API介绍

2) 常用方法:
selectSingleNode(query): 查找和 XPath 查询匹配的一个节点。
参数是Xpath 查询串。

selectNodes(query): 得到的是xml根节点下的所有满足 xpath 的节点;
参数是Xpath 查询串。

Node: 节点对象

 

4.5.4 Xpath读取XML

3) 数据准备 book.xml

<?xml version="1.0" encoding="UTF-8" ?>
<bookstore>
    <book id="book1">
        <name>金瓶梅</name>
        <author>金圣叹</author>
        <price>99</price>
    </book>
    <book id="book2">
        <name>红楼梦</name>
        <author>曹雪芹</author>
        <price>69</price>
    </book>
    <book id="book3">
        <name>Java编程思想</name>
        <author>埃克尔</author>
        <price>59</price>
    </book>
</bookstore>

 

4) 代码示例

1. 使用selectSingleNode方法 查询指定节点中的内容

2.使用selectSingleNode方法 获取属性值,或者属性值对应的节点

3. 使用 selectNodes()方法 获取对应名称的所有节点

package com.lg.xml04;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;

import java.util.List;

/**
 * @author CH
 * @date 2020/11/4 18:30
 */
public class TestXPath {

    /*
    *   使用selectSingleNode()方法 查询指定的节点信息
    *
    * */
    @Test
    public void test1() throws DocumentException {

        //1. 创建XML解析对象
        SAXReader reader = new SAXReader();

        //2. 解析XML 获取文档对象
        Document document = reader.read("D:\\lagou\\jdbc_work\\xml_task03\\src\\com\\lg\\xml04\\book.xml");

        //3. 通过selectSingleNode() 方法获取 name 节点
        Node node1 = document.selectSingleNode("/bookstore/book/name");
        System.out.println("节点的名称: " + node1.getName());
        System.out.println("书名: " + node1.getText());

        //4. 获取第二本书的书名
        Node node2 = document.selectSingleNode("/bookstore/book[2]/name");
        System.out.println("第二本书的书名: " + node2.getText());
    }

    /*
    * 使用selectSingleNode()方法获取 属性值, 或者通过属性值获取节点信息
    *
    * */
    @Test
    public void test2() throws DocumentException {

        SAXReader reader = new SAXReader();

        Document document = reader.read("D:\\lagou\\jdbc_work\\xml_task03\\src\\com\\lg\\xml04\\book.xml");

        //1. 获取 第一个 book 节点中的 id属性值
        Node node1 = document.selectSingleNode("bookstore/book/attribute::id");
        System.out.println("第一个book的id属性值是: " + node1.getText());

        //2. 获取 最后一个book节点的 id属性值
        Node node2 = document.selectSingleNode("bookstore/book[last()]/attribute::id");
        System.out.println("最后一个book的id属性值是: " + node2.getText());

        //3. 通过 id 获取book2 节点中的书名
        Node node3 = document.selectSingleNode("/bookstore/book[@id='book2']");

        String name = node3.selectSingleNode("name").getText();
        System.out.println("id为book2的节点的书名是: " + name);
    }

    /*
    * 使用selectNodes() 方法获取所有指定名称的节点
    *
    * */
    @Test
    public void test3() throws DocumentException {

        SAXReader reader = new SAXReader();

        Document document = reader.read("D:\\lagou\\jdbc_work\\xml_task03\\src\\com\\lg\\xml04\\book.xml");

        //1. 查询所有节点
        List<Node> list = document.selectNodes("//*");
        for (Node node : list) {
            System.out.println("节点名: " + node.getName());
        }

        //2. 获取所有的书名
        List<Node> list1 = document.selectNodes("//name");
        for (Node node : list1) {
            System.out.println("书名: " + node.getText());
        }

        //3. 获取 id 值为 book1 的节点中的所有内容
        List<Node> list2 = document.selectNodes("/bookstore/book[@id='book1']//*");
        for (Node node : list2) {
            System.out.println(node.getName() + ": " + node.getText());
        }
    }
}

 

5. JDBC自定义XML

5.1 定义配置文件

1) 创建自定义xml 文件, 保存 数据库连接信息

jdbc-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<jdbc>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db5?characterEncoding=UTF-8</property>
    <property name="user">root</property>
    <property name="password">123456</property>
</jdbc>

 

5.2 编写工具类(配置式)

2) 编写工具类 ,使用xpath 读取数据库信息

package com.lg.xml05;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import javax.xml.transform.sax.SAXResult;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * @author CH
 * @date 2020/11/4 19:00
 */
public class JDBCUtils {

    //1. 定义字符串变量, 保存连接信息
    public static String DRIVERNAME;
    public static String URL;
    public static String USER;
    public static String PASSWORD;

    //2. 静态代码块
    static {
        //使用XPath语法, 对xml中的数据进行读取
        SAXReader reader = new SAXReader();

        try {
            Document document = reader.read("D:\\lagou\\jdbc_work\\xml_task03\\src\\com\\lg\\xml05\\jdbc-config.xml");

            //1. 获取驱动名称
            Node driverClass = document.selectSingleNode("jdbc/property[1]");
            //Node driverClass = document.selectSingleNode("jdbc/property[@name='driverClass']");
            DRIVERNAME = driverClass.getText();

            //2. 获取URL
            Node jdbcUrl = document.selectSingleNode("jdbc/property[@name='jdbcUrl']");
            URL = jdbcUrl.getText();

            //3. 获取user
            Node user = document.selectSingleNode("jdbc/property[@name='user']");
            USER = user.getText();

            //4. 获取password
            Node password = document.selectSingleNode("jdbc/property[@name='password']");
            PASSWORD = password.getText();

            // 注册驱动
            Class.forName(DRIVERNAME);

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

    public static Connection getConnection() {

        try {
            Connection connection = DriverManager.getConnection(URL,USER,PASSWORD);
            return connection;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            return null;
        }
    }
}

 

5.3 测试工具类

3) 测试 : 获取所有员工的姓名

package com.lg.xml05;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author CH
 * @date 2020/11/4 19:24
 */
public class TestJDBC {

    // 查询所有员工信息
    public static void main(String[] args) throws SQLException {

        //1. 获取连接
        Connection connection = JDBCUtils.getConnection();

        //2. 获取语句执行对象, 执行SQL
        PreparedStatement ps = connection.prepareStatement("select * from employee");

        ResultSet resultSet = ps.executeQuery();

        while(resultSet.next()) {
            String ename = resultSet.getString("ename");
            System.out.println("员工的姓名: " + ename);
        }

        resultSet.close();
        ps.close();
        connection.close();
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值