Java基础篇--XML简介

目录

什么是 XML

XML 用途

XML 语法

XML文档声明

根元素

元素

属性

注释

转义字符

CDATA区

处理指令

XML的解析

开发中比较常见的解析方式有三种

DOM解析方式:

SAX解析方式:

PULL解析方式:

常见的解析开发包

DOM解析原理及结构模型

dom4j技术栗子

XML的约束

约束语法:

内部关联:

外部关联:

DTD约束:

XML Schema约束:

注意点:


什么是 XML

  1. 可扩展标记语言 (EXtensible Markup Language, XML) 是一种用于创建标记语言的标记语言。这些标记可用于表示结构化数据。XML 的设计目的是为了传输和存储数据,而不是仅仅显示数据。
  2. XML 与 HTML 有一些相似之处,但 XML 的标记可以由用户自行定义,这意味着你可以创建适合你数据的特定标记,这是 HTML 所不具备的特性。
  3. XML 的标签没有被预定义,这是它与 HTML 的主要区别。在 XML 中,你需要自行定义标签,这些标签可以描述你的数据。例如,在上面的学生列表示例中,我们定义了 <students>, <student>, <name>, <age> 和 <gender> 标签。
  4. XML 被设计为具有自我描述性。这意味着,通过使用 XML 文件中的内部描述性信息,其他程序可以理解 XML 文件的内容和结构。
  5. 可扩展标记语言 (XML) 是万维网联盟 (World Wide Web Consortium, W3C) 的推荐标准。这意味着,XML 已经成为在 Web 上进行数据表示和数据交换的标准之一。

总的来说,XML 是一种用于存储和传输数据的强大工具,它使得数据可以被机器理解和处理,而不仅仅是人类阅读。

XML 用途

XML(Extensible Markup Language,可扩展标记语言)在 Java 中的主要用途包括以下几个方面:

  1. 数据存储和传输:XML 可以用于存储和传输数据。它提供了一种通用格式,使得不同系统之间可以交换数据。例如,XML 可以用于在 Web 浏览器和 Web 服务器之间传输数据。
  2. 数据绑定:XML 可以用于数据绑定,即将数据与 XML 文档中的元素和属性关联起来。这使得开发人员可以轻松地读取和操作 XML 数据。
  3. Web 服务:XML 也被广泛用于构建 Web 服务。通过使用 SOAP(Simple Object Access Protocol)协议和 WSDL(Web Services Description Language)规范,开发人员可以创建跨平台、跨语言的服务。
  4. 配置文件:XML 可以用于创建配置文件,这些文件可以用于指定应用程序的参数和设置。使用 XML 作为配置文件格式可以提高可读性,并减少错误。
  5. 数据建模:XML 可以用于数据建模,即描述数据结构并定义数据之间的关系。这有助于开发人员更好地理解和操作数据。
  6. Web 页面开发:XML 还被用于创建 HTML 和 CSS(层叠样式表)文件,这些文件构成了 Web 页面的基础。

总之,XML 在 Java 开发中扮演着重要角色,它提供了一种通用的数据格式,使得不同系统之间可以方便地交换数据。

XML数据存储示例:

import java.io.File;  
import javax.xml.parsers.DocumentBuilder;  
import javax.xml.parsers.DocumentBuilderFactory;  
import org.w3c.dom.Document;  
import org.w3c.dom.Element;  
  
public class XMLDataStorage {  
    public static void main(String[] args) {  
        try {  
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();  
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();  
            Document doc = dBuilder.newDocument();  
  
            // 创建根元素  
            Element rootElement = doc.createElement("employees");  
            doc.appendChild(rootElement);  
  
            // 创建员工元素并添加到根元素下  
            Element employee = doc.createElement("employee");  
            rootElement.appendChild(employee);  
  
            // 设置员工属性  
            Element id = doc.createElement("id");  
            id.appendChild(doc.createTextNode("1"));  
            employee.appendChild(id);  
  
            Element name = doc.createElement("name");  
            name.appendChild(doc.createTextNode("John Doe"));  
            employee.appendChild(name);  
  
            Element position = doc.createElement("position");  
            position.appendChild(doc.createTextNode("Developer"));  
            employee.appendChild(position);  
  
            // 将文档写入XML文件  
            File file = new File("employees.xml");  
            javax.xml.transform.TransformerFactory tf = javax.xml.transform.TransformerFactory.newInstance();  
            javax.xml.transform.Transformer transformer = tf.newTransformer();  
            transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");  
            javax.xml.transform.dom.DOMSource source = new javax.xml.transform.dom.DOMSource(doc);  
            javax.xml.transform.stream.StreamResult result = new javax.xml.transform.stream.StreamResult(file);  
            transformer.transform(source, result);  
  
            System.out.println("XML文件已创建成功!");  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
}

这是一个简单的XML配置文件示例:

<?xml version="1.0" encoding="UTF-8"?>  
<config>  
    <server>  
        <hostname>localhost</hostname>  
        <port>8080</port>  
    </server>  
    <database>  
        <name>mydatabase</name>  
        <username>username</username>  
        <password>password</password>  
    </database>  
</config>

XML 语法

XML文件主要由XML文档声明,元素,属性,注释,转义字符,CDATA区,处理指令组成。

XML文档声明

XML文档总是以一个声明开始,这个声明告诉解析器这是一个XML文件。声明看起来是这样的:

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

注意:

  1. 文档声明必须为<?xml开头,以?>结束;
  2. 文档声明必须从文档的0行0列位置开始;
  3. 文档声明只有三个属性:
  • versioin:指定XML文档版本。必须属性,因为我们不会选择1.1,只会选择1.0;
  • encoding:指定当前文档的编码。可选属性,默认值是utf-8;
  • standalone:指定文档独立性。可选属性,默认值为yes,表示当前文档是独立文档。如果为no表示当前文档不是独立的文档,会依赖外部文件。

根元素

XML文档必须包含一个根元素,它包含了所有其他元素。根元素是可选的,但如果没有根元素,XML解析器将无法确定文档的结构和内容。

元素

元素是XML文档的基本构建块,它们由开始标签、结束标签和元素内容组成。元素可以包含属性,属性提供了关于元素的额外信息。例如:<book>、</book>、<title>、</title>、<author>、</author>等。

<book>、</book>、<title>、</title>、<author>、</author>、<servlet>、</servlet>等。
  • 开始标签、元素体和结束标签都是可见的。例如:"大家好" 是一个包含文本内容的元素。
  • 开始标签和结束标签是隐含的,只通过文本内容来识别。例如:"你好" 也是一个元素,但它只包含文本,没有子元素。
  • "空元素" 是一个只有开始标签而没有结束标签的元素,但它必须自我闭合。例如,"<br/>" 是 HTML 中表示换行的空元素,它在 XML 中同样有效。

关于元素命名的规则:

  1. 在 XML 中,元素名是区分大小写的。也就是说,"myElement" 和 "MyElement" 在 XML 中会被视为两个不同的元素名。
  2. 元素名不能包含空格或者冒号。例如,"my:element" 或者 "my element" 都是不合法的。
  3. 不建议以 "XML"、"xml" 或 "Xml" 开头作为元素名。这是为了避免与未来的 XML 标准版本冲突。

最后,每个有效的 XML 文档都必须有一个根元素,这是文档的入口点。所有的其他元素必须位于根元素之下。

属性

属性是元素的附加信息。它们通过名称和值对的形式出现,总是包含在开始标签中,并且它们为元素提供更多的信息。例如:

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

注释

注释是对XML文档中的一部分内容进行解释或说明。它们不会被解析器处理,也不会显示在输出中。注释以<!--开始,以-->结束。例如:

<!-- This is a comment -->

转义字符

转义字符是XML中用于表示特殊字符的一种方法。由于XML中已经使用了某些符号(如尖括号、引号等),因此当需要在元素体或属性值中使用这些符号时,就需要使用转义字符来表示它们。以下是一些常用的转义字符及其含义:

  1. &lt;               代表小于符号(<)
  2. &gt;              代表大于符号(>)
  3. &amp;         代表和号(&)
  4. &apos;        代表单引号(')
  5. &quot;         代表双引号(")
  6. &nbsp;        代表空格

例如,如果想在XML文档中表示 "5 < 10",可以这样写:

<value>5 &lt; 10</value>

CDATA区

<![CDATA[
    任意内容
]]>

当大量的转义字符出现在xml文档中时,会使xml文档的可读性大幅度降低。这时如果使用CDATA段就会好一些。
在CDATA段中出现的“<”、“>”、“””、“’”、“&”,都无需使用转义字符。这可以提高xml文档的可读性。
在CDATA段中不能包含“]]>”,即CDATA段的结束定界符。
例如:

<![CDATA[<title>Example Book</title>]]>

处理指令

处理指令是用来给处理XML的特定应用程序提供指令的。处理指令不会影响XML解析器,它们被忽略。例如:

<?xml-stylesheet type="text/xsl" href="styles.xsl"?>

这个指令告诉解析器使用名为"styles.xsl"的XSL样式表对XML文档进行格式化。

XML的解析

开发中比较常见的解析方式有三种

DOM解析方式:

DOM方式是将整个XML文档读入内存,然后将其结构化成一个DOM树。这样,开发人员可以方便地访问和修改XML文档的各个部分。DOM方式的优点是易于操作,可以方便地进行增删改查操作。但是,如果XML文档非常大,将整个文档读入内存可能会造成内存溢出。

SAX解析方式:

SAX是一种基于事件的解析方式,它逐行扫描XML文档,每次扫描都会触发一个相应的事件。开发人员可以通过注册事件处理器来处理这些事件,从而获取XML文档的内容。SAX方式的优点是可以处理大型的XML文档,而且不会占用太多的内存。但是,由于是逐行解析,处理速度可能会比DOM慢一些。

PULL解析方式:

PULL是Android内置的XML解析方式,它的工作原理类似于SAX,但是更加简单易用。PULL方式是通过在XML文档中寻找特定的标签,然后读取标签之间的内容。PULL方式的优点是处理速度较快,而且可以处理大型的XML文档。但是,由于只能读取内容,不能进行增删改查操作,因此在某些情况下可能会不太方便。

常见的解析开发包

根据不同的解析方式提供的具体实现。

  • JAXP:sun公司提供支持DOM和SAX开发包
  • JDom:dom4j兄弟
  • jsoup:一种处理HTML特定解析开发包
  • dom4j:比较常用的解析开发包,hibernate底层采用。

这些解析器都是基于以上三种解析方式实现的,开发人员可以根据需要选择合适的解析器和解析方式。

DOM解析原理及结构模型

XML DOM和HTML DOM类似,DOM将XML文档加载到内存中,并构建一个DOM树来代表XML文档的结构。这个DOM树以节点的方式表示XML的元素属性文本等内容。

在DOM中,节点是一个非常重要的概念,它代表了XML文档中的各个元素、属性和文本等内容。每个节点都有其特定的类型和属性,比如元素节点、属性节点和文本节点等。通过操作DOM树中的节点,我们可以实现对XML文档的读取、修改、添加和删除等操作。

除了节点,DOM还提供了一系列的方法和接口,让我们可以方便地操作DOM树。比如,我们可以使用appendChild()方法向DOM树中添加一个新的子节点,或者使用removeChild()方法删除一个指定的节点。此外,DOM还提供了诸如获取节点值、获取节点名称、获取节点类型等常用方法,使得我们能够方便地操作DOM树。

总之,DOM提供了一种方便快捷的方式来解析和操作XML文档,使得开发人员可以轻松地读取、修改、添加和删除XML文档中的内容。

下面的示例,演示如何使用DOM解析器读取XML文件中的元素和属性:  

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;

public class MyClass {
    public static void main(String[] args) {
        try {
            // 创建DocumentBuilderFactory对象
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 创建DocumentBuilder对象
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 加载XML文件并解析
            Document doc = builder.parse(new File("example.xml"));

            // 获取根元素
            Element root = doc.getDocumentElement();
            // 获取所有子节点
            NodeList children = root.getChildNodes();
            for (int i = 0; i < children.getLength(); i++) {
                Node child = children.item(i);
                if (child.getNodeType() == Node.ELEMENT_NODE) {
                    // 如果是元素节点,获取元素名称和属性值
                    Element childElement = (Element) child;
                    System.out.println("元素名称: " + childElement.getTagName());
                    System.out.println("属性值: " + childElement.getAttribute("name"));
                } else if (child.getNodeType() == Node.TEXT_NODE) {
                    // 如果是文本节点,获取文本内容
                    System.out.println("文本内容: " + child.getTextContent());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,我们使用DocumentBuilderFactory和DocumentBuilder来创建一个DOM树,并加载XML文件。然后,我们通过访问根元素和子节点,遍历DOM树,并获取元素名称、属性值和文本内容。

dom4j技术栗子

首先,需要将dom4j库添加到您的项目依赖中。如果使用的是Maven,可以在pom.xml文件中添加以下依赖:

<dependency>  
    <groupId>org.dom4j</groupId>  
    <artifactId>dom4j</artifactId>  
    <version>2.1.3</version>  
</dependency>

然后,假设我们有一个XML文件,其内容如下:

<root>  
    <element1>Text1</element1>  
    <element2>Text2</element2>  
</root>

我们可以使用以下Java代码来读取和解析这个XML文件:

import org.dom4j.Document;  
import org.dom4j.DocumentException;  
import org.dom4j.Element;  
import org.dom4j.io.SAXReader;  
  
import java.io.File;  
import java.io.IOException;  
  
public class Dom4jExample {  
    public static void main(String[] args) {  
        try {  
            // 创建SAXReader对象,用于读取XML文件  
            SAXReader reader = new SAXReader();  
            // 读取XML文件,获取Document对象  
            Document document = reader.read(new File("path/to/your/xmlfile.xml"));  
            // 获取根元素  
            Element root = document.getRootElement();  
            // 获取所有子节点  
            Element[] elements = root.elements();  
            for (Element element : elements) {  
                System.out.println(element.getName() + ": " + element.getText());  
            }  
        } catch (DocumentException | IOException e) {  
            e.printStackTrace();  
        }  
    }  
}

请注意,需要将"path/to/your/xmlfile.xml"替换为你的XML文件的实际路径。 

运行这段代码将输出:

element1: Text1  
element2: Text2

XML的约束

XML约束是指在XML技术中用来约束XML文档书写规范的文件。这种约束可以确保XML文档遵循特定的规则,有助于保证XML文档在预期的范围内正确地被使用和理解。

在XML中,有两种常见的约束:DTD(Document Type Definition)和XML Schema。

约束语法:

在XML技术中,约束可以用来确保XML文档遵循特定的规则,以确保XML文档在预期的范围内正确地被使用和理解。下面是对XML约束的详细的解释:

内部关联:

内部关联是指在XML文档内部定义约束规则。这可以通过使用DTD(文档类型定义)或XML Schema来实现。

a. DTD:

* DTD是一种XML约束的格式,用于定义XML文档的语法规则。  
* 它允许你定义元素和属性,以及它们之间的关系。  
* 一个DTD文档包含一系列声明,描述了XML文档的结构。例如,以下是一个简单的DTD,它定义了一个名为“book”的元素应该包含“title”和“price”元素:
<!DOCTYPE book [  
   <!ELEMENT book (title, price)>  
   <!ELEMENT title (#PCDATA)>  
   <!ELEMENT price (#PCDATA)>  
]>

 b. XML Schema:

* XML Schema是另一种XML约束的格式,用于定义XML文档的数据类型和结构。  
* 它提供了比DTD更强大的数据类型和命名空间支持,可以更好地描述复杂的XML文档结构。  
* XML Schema使用XML语法来描述XML文档的结构,包括元素、属性、数据类型等。例如,以下是一个简单的XML Schema,它定义了一个名为“Person”的元素应该包含“name”和“age”元素:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">  
   <xs:element name="Person">  
      <xs:complexType>  
         <xs:sequence>  
            <xs:element name="name" type="xs:string"/>  
            <xs:element name="age" type="xs:int"/>  
         </xs:sequence>  
      </xs:complexType>  
   </xs:element>  
</xs:schema>

外部关联:

外部关联是指将约束定义放在XML文档外部,并与XML文档通过引用或导入关联起来。有两种外部关联的方式:系统关联和公共关联。

系统关联:

系统关联是指将约束定义放在XML文档外部,并通过系统标识符(如URL)进行引用。在XML文档中使用系统引用指示符( SYSTEM)来引用外部约束定义。例如,在XML文档中使用以下语法引用外部XML Schema:

<schema location="schema.xsd" />

举例:

<?xml version="1.0" encoding="UTF-8" ?>  
<!ELEMENT web-app (servlet*, servlet-mapping*, welcome-file-list?) >  
<!ELEMENT servlet (servlet-name, description?, (servlet-class | jsp-file)) >  
<!ELEMENT servlet-mapping (servlet-name, url-pattern) >  
<!ELEMENT servlet-name (#PCDATA) >  
<!ELEMENT servlet-class (#PCDATA) >  
<!ELEMENT url-pattern (#PCDATA) >  
<!ELEMENT welcome-file-list (welcome-file+) >  
<!ELEMENT welcome-file (#PCDATA) >  
<!ATTLIST web-app version CDATA #IMPLIED>

公共关联:

公共关联是指将约束定义放在XML文档外部,并通过公共标识符(如命名空间URI)进行关联。在XML文档中使用公共标识符来引用外部约束定义。例如,在XML文档中使用以下语法引用外部XML Schema:

<schema namespace="http://www.example.com/schema" />

DTD约束:

标签(元素)语法:

<!Element 元素名称 数据类型|包含内容>

<!ELEMENT> 声明了一个XML元素,定义了元素名称和它可以包含的内容。其中,元素名称是元素的标签名称,数据类型指定了该元素可以包含的内容类型,包含内容列出了该元素可以包含的其他元素或内容。 

注意#PCDATA 表示元素包含的文本是普通的文本字符,通常需要用括号 () 括起来。

符号:

  • * 表示元素可以出现任意次数,包括零次。
  • ? 表示元素可以出现一次或者不出现。
  • + 表示元素可以出现至少一次。
  • | 表示元素可以单独出现,也可以从另一个选项中选择。
  • () 用于将多个选项组合在一起,表示元素可以从这些选项中选择一个或多个。
  • , 用于分隔多个选项,表示元素可以从这些选项中选择一个或多个。

以下是一个示例的进一步解释:

<!ELEMENT web-app (servlet*, servlet-mapping*, welcome-file-list?) >

这个声明表示web-app元素可以包含servlet元素、servlet-mapping元素和welcome-file-list元素,它们的出现顺序没有特定要求。servlet*表示可以出现零个或多个servlet元素,servlet-mapping*表示可以出现零个或多个servlet-mapping元素,welcome-file-list?表示可以出现零个或一个welcome-file-list元素。 

注意:元素名就是xml中能够出现的元素标签名。

属性约束语法:

<!ATTLIST 元素名 属性名 属性类型 属性是否必须出现>
  • <!ATTLIST>: 声明了一个XML元素的属性,定义了属性的名称、类型和是否必须出现。
  • 属性名 :是属性的标签名称。
  • 属性类型: 指定了属性的数据类型。常见的属性类型包括 CDATA(普通文本)和 ID(唯一标识符)。
  • 属性是否必须出现 :指定了属性是否必须出现在元素中。常见的值包括 REQUIRED(必须出现)和 IMPLIED(可以选择出现)。 

以下是一个示例的进一步解释:

<!ATTLIST web-app version CDATA #IMPLIED>

这个声明表示web-app元素有一个名为version的属性,它的数据类型是普通文本,可以选择出现。 

XML Schema约束:

XML(可扩展标记语言)和Schema(模式)是用于描述和传输数据的两种技术。XML是一种标记语言,而Schema是用于定义XML文档结构的语言。

XML是一种可以用来表示数据的标记语言,其标记可以是预定义的,也可以是用户自定义的。XML文档通常包含一个根元素和若干子元素,这些元素可以包含文本、数字、布尔值等数据。

<根标签 xmlns="..." ...>
<根标签 xmlns:别名="..." ...>

Schema是用来定义XML文档结构的语言。Schema可以用来验证XML文档的格式是否正确,还可以用来规定XML文档中元素的顺序、数量、类型等。

在XML和Schema的关联中,XML文档中的元素和Schema中的元素是对应的。例如,如果Schema中定义了一个名为"table"的元素,那么在XML文档中,如果使用了名为"table"的元素,那么这个元素就符合了Schema中对"table"的定义。

名称空间是用来区分不同的XML元素和Schema的。在XML中,通过使用xmlns属性来指定名称空间。在Schema中,通过为元素指定一个targetNamespace来指定名称空间。

如果在一个XML文件中引用了多个Schema,那么可以通过给其中一个Schema起个别名的方式来指定使用哪个Schema。在XML文件中,通过为根元素指定一个xmlns别名的方式来起个别名。例如,如果将名为"table"的Schema别名为"a",那么在XML文件中,所有名为"table"的元素都表示使用了名为"a"的Schema。

注意,Schema本身也是XML文件,因此可以像处理其他XML文件一样处理Schema文件。

以下是一个示例XML Schema的约束文档: 

<!-- XML Schema定义开始 -->  
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">  
  
  <!-- 定义根元素 -->  
  <xs:element name="root">  
  
    <!-- 定义根元素的复杂类型 -->  
    <xs:complexType>  
  
      <!-- 定义元素的顺序 -->  
      <xs:sequence>  
  
        <!-- 定义一个名为child1的元素,出现次数为零次或一次 -->  
        <xs:element name="child1" minOccurs="0">  
  
          <!-- 定义child1元素的复杂类型 -->  
          <xs:complexType>  
  
            <!-- 定义child1元素的内容为简单内容 -->  
            <xs:simpleContent>  
  
              <!-- 在简单内容的基础上进行扩展 -->  
              <xs:extension base="xs:string">  
  
                <!-- 定义一个名为attr1的属性,数据类型为字符串,默认值为value1 -->  
                <xs:attribute name="attr1" type="xs:string" default="value1" />  
  
              </xs:extension>  
  
            </xs:simpleContent>  
  
          </xs:complexType>  
  
        </xs:element>  
  
        <!-- 定义一个名为child2的元素,出现次数为零次或一次 -->  
        <xs:element name="child2" minOccurs="0">  
  
          <!-- 定义child2元素的复杂类型 -->  
          <xs:complexType>  
  
            <!-- 定义child2元素的内容为简单内容 -->  
            <xs:simpleContent>  
  
              <!-- 在简单内容的基础上进行扩展 -->  
              <xs:extension base="xs:int">  
  
                <!-- 定义一个名为attr2的属性,数据类型为布尔,默认值为false -->  
                <xs:attribute name="attr2" type="xs:boolean" default="false" />  
  
              </xs:extension>  
  
            </xs:simpleContent>  
  
          </xs:complexType>  
  
        </xs:element>  
  
      </xs:sequence>  
  
    </xs:complexType>  
  
  </xs:element>  
  
</xs:schema>

在这个示例中,我们定义了一个名为"root"的元素,它包含两个子元素:"child1"和"child2"。这些子元素都有一些约束和属性。例如,"child1"是一个复杂类型,它扩展了字符串类型,并包含一个名为"attr1"的字符串属性,默认值为"value1"。同样,"child2"也是一个复杂类型,它扩展了整数类型,并包含一个名为"attr2"的布尔属性,默认值为"false"。

注意点:

  1. 一个XML文档只能包含一个DTD约束,但可以包含多个Schema约束。
  2. XML Schema本身也是XML文件,因此可以使用XML语法来编写和修改。
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员老李头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值