MySQL之JDBC

一、JDBC是什么?

Java DataBase Connectivity(Java语言连接数据库)

二、JDBC的本质是什么?

JDBC是SUN公司制定的一套接口(interface)。

接口都有调用者和实现者。

面向接口调用、面向接口写实现类,这都属于面向接口编程。

三、为什么要面向接口编程?

解耦合:降低程序的耦合度,提高程序的扩展力。

多态机制就是非常典型的:面向抽象编程。(不要面向具体编程)

四、为什么SUN制定一套JDBC接口呢?

因为每一个数据库产品都有自己独特的实现原理

五、JDBC编程六步(需要背会)

1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)

2.获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)。

3.获取数据库操作对象(专门执行sql语句的对象)

4.执行SQL语句(DQL,DML…)

5.处理查询结果集 (只有当第四步执行的是select语句的时候,才有本步)

6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)

六、IDEA编写JDBC连接MySQL

6.1 mysql-connector-java的不同版本对比

MySQL Connector / J 5.1 5.1版本支持java5及其以上的版本,支持5.6、5.7、8.0版本的mysql数据库,支持3.0、4.0、4.1、4.2版本的jdbc。在5.1中,Driver的实现类的全路径名是com.mysql.jdbc.Driver。

MySQL Connector / J 8.0 8.0版本支持java8及其以上的版本,支持5.6、5.7、8.0版本的mysql数据库,支持4.2版本的jdbc。在8.0中,Driver的实现类的全路径名是com.mysql.cj.jdbc.Driver。

下图是官网上mysql-connector-java的版本对应的mysql版本和jdk的版本。

6.2 下载驱动jar包 mysql-connector-java

要使用mysql连接器,就要先下载它。如果是一般的项目,那我们需要下载jar包,然后放到项目的lib目录下。如果使用maven构建的项目,我们可以通过maven直接安装。不同的下载方式有不同的操作,常见的有直接官网下载和maven下载(下周讲解maven)。 下载jar包最直接的方式是从官网下载,官网地址是:MySQL :: Download MySQL Connector/J (Archived Versions)。直接点链接进入mysql官网,选择所需的版本和操作系统(要下载jar包就要选:Platform Independent),然后点击download按钮就可以下载了。为java提供的连接器是Connector / J,也就是mysql-connector-java,它分为5.1版本和8.0版本。Connector / J实现了JDBC,为使用java开发的程序提供连接,方便java程序操作数据库。

此处我们使用5.1.49版本,网盘链接也一并贴在这里

mysql-connector-java-5.1.49.jar - 蓝奏云

2、从maven安装 使用maven安装mysql-connector-java就简单很多,直接打开maven的中央仓库地址,输入mysql-connector-java就可以找到不同版本的依赖。地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java

  

6.3 IDEA导入jar包

先检查jar包位置:在目录里新建一个文件夹 libs,把jar包复制进去

然后右键选择新建文件夹libs转成library

然后就可以写代码啦!

根据六步编写代码

6.4 JDBC连接mysql 程序编写

这里在数据库中有一个dept表,结构如下:

6.4.1 第一种注册驱动方式

package com.learn;


/*
    1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
    2.获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)。
    3.获取数据库操作对象(专门执行sql语句的对象)
    4.执行SQL语句(DQL,DML…)
    5.处理查询结果集 (只有当第四步执行的是select语句的时候,才有本步)
    6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)
 */

import com.mysql.jdbc.Driver;

import java.sql.*;

public class JDBCDemo1 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement state = null;
        //1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
        //第一种注册驱动的方式
        //jdk本身提供了一个工具类DriverManager来给我们使用
        // 其中有一个方法:registerDriver(Driver driver)用于注册驱动
        //通过观察发现,jdk本身并没有实现Driver接口的类,但mysql驱动中有实现该接口的驱动类。
        try {
            DriverManager.registerDriver(new Driver());
            //2.获取连接(表示JVM的进程和数据库进程之间的通道被打开了,这属于进程之间的通信,使用完后要关闭通道)
            //jdk中提供了一个工具类DriverManager,其中有一个静态的方法,可以让我们调用并且获取与要使用的数据的连接对象
            //static Connection getConnection(String url, String user, String password)
            //尝试建立与给定数据库URL的连接。
            /**
             * url: 统一资源定位系统
             *      http/https  通过网络去请求网络上的资源
             *      jdbc:mysql  驱动包提供的请求头
             *      请求的地址    指定mysql数据库安装的服务器地址:192.168.169.100
             *      端口号       3306
             *      useUnicode=true&characterEncoding=utf8
             *
             * jdbc:mysql://192.168.111.11:3306/bigdata23?useUnicode=true&characterEncoding=utf8&useSSL=false
             */
//            Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.111.11:3306/bigdata23?useUnicode=true&useSSL=false", "root", "123456");
            String url = "jdbc:mysql://192.168.111.11:3306/bigdata23?useUnicode=true&characterEncoding=utf8&useSSL=false";
            String user = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url, user, password);
            //如果连接不上可能导致的问题
            //1、检查虚拟机,服务器是否启动
            //2、检查防火墙是否关闭,指的是虚拟机或者服务器的防火墙
            //3、检查url地址,用户名,密码
            System.out.println("与数据库<" + conn + ">连接成功!!!");
            //3.获取数据库操作对象(专门执行sql语句的对象)
            state = conn.createStatement();
            //4.执行SQL语句(DQL,DML…)
            //DQL
            //ResultSet executeQuery(String sql)
            //执行sql语句,该语句返回查询的结果,只能是查(select)

            //DML
            //int executeUpdate(String sql)
            //执行给定的SQL语句,这里可以是增(insert),删(delete),更新(update)
            //该方法的返回值指的是受影响的行数
            String sql1 = "insert into dept values(99,'董事会','安徽合肥')";
            int count = state.executeUpdate(sql1);
            if (count == 1) {
                System.out.println("数据插入成功!");
            } else {
                System.out.println("数据插入失败,请重试。");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)
            if (state != null) {
                try {
                    state.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                } finally {
                    if (conn != null) {
                        try {
                            conn.close();
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}

6.4.2 第二种注册驱动方式

使用反射的方式加载驱动类

package com.learn;

//驱动注册的第二种方式

import com.mysql.jdbc.Driver;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCDemo2 {
    public static void main(String[] args) throws Exception{
        //使用反射的第三种方式直接获取mysql数据库的驱动类,今后最常用的方式
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = null;
        Statement state = null;
        //1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
        //第一种注册驱动的方式
        //jdk本身提供了一个工具类DriverManager来给我们使用
        // 其中有一个方法:registerDriver(Driver driver)用于注册驱动
        //通过观察发现,jdk本身并没有实现Driver接口的类,但mysql驱动中有实现该接口的驱动类。
        try {
            DriverManager.registerDriver(new Driver());
            //2.获取连接(表示JVM的进程和数据库进程之间的通道被打开了,这属于进程之间的通信,使用完后要关闭通道)
            //jdk中提供了一个工具类DriverManager,其中有一个静态的方法,可以让我们调用并且获取与要使用的数据的连接对象
            //static Connection getConnection(String url, String user, String password)
            //尝试建立与给定数据库URL的连接。
            /**
             * url: 统一资源定位系统
             *      http/https  通过网络去请求网络上的资源
             *      jdbc:mysql  驱动包提供的请求头
             *      请求的地址    指定mysql数据库安装的服务器地址:192.168.169.100
             *      端口号       3306
             *      useUnicode=true&characterEncoding=utf8
             *
             * jdbc:mysql://192.168.111.11:3306/bigdata23?useUnicode=true&characterEncoding=utf8&useSSL=false
             */
//            Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.111.11:3306/bigdata23?useUnicode=true&useSSL=false", "root", "123456");
            String url = "jdbc:mysql://192.168.111.11:3306/bigdata23?useUnicode=true&characterEncoding=utf8&useSSL=false";
            String user = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url, user, password);
            //如果连接不上可能导致的问题
            //1、检查虚拟机,服务器是否启动
            //2、检查防火墙是否关闭,指的是虚拟机或者服务器的防火墙
            //3、检查url地址,用户名,密码
            System.out.println("与数据库<" + conn + ">连接成功!!!");
            //3.获取数据库操作对象(专门执行sql语句的对象)
            state = conn.createStatement();
            //4.执行SQL语句(DQL,DML…)
            //DQL
            //ResultSet executeQuery(String sql)
            //执行sql语句,该语句返回查询的结果,只能是查(select)

            //DML
            //int executeUpdate(String sql)
            //执行给定的SQL语句,这里可以是增(insert),删(delete),更新(update)
            //该方法的返回值指的是受影响的行数
//            String sql1 = "insert into dept values(98,'保卫科','安徽合肥')";
//            int count = state.executeUpdate(sql1);
//            if (count == 1) {
//                System.out.println("数据插入成功!");
//            } else {
//                System.out.println("数据插入失败,请重试。");
//            }

            //修改数据
//            String sql2 = "update dept set loc='安徽淮南' where deptno = 98";
//            int count2 = state.executeUpdate(sql2);
//            if (count2 == 1) {
//                System.out.println("数据修改成功!");
//            } else {
//                System.out.println("数据修改失败,请重试。");
//            }

            //删除数据
            String sql3 = "delete from dept where deptno = 98";
            int count3 = state.executeUpdate(sql3);
            if (count3 == 1) {
                System.out.println("数据删除成功!");
            } else {
                System.out.println("数据删除失败,请重试。");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)
            if (state != null) {
                try {
                    state.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                } finally {
                    if (conn != null) {
                        try {
                            conn.close();
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

    }
}

//mysql5.7之后警告用户不要直接访问数据库服务器,于是运行时会有红色警告

解决方法:连接数据库时在url中添加参数&useSSL=false

String url = "jdbc:mysql://192.168.111.11:3306/bigdata23?useUnicode=true&characterEncoding=utf8&useSSL=false";

6.4.3 将连接数据库的所有信息配置到配置文件中

为了方便日后修改数据库信息,我们将数据库参数存到配置文件中。

我们另外创建一个配置文件:mysqlinfo.properties

url = jdbc:mysql://192.168.111.11:3306/bigdata23?useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
password=123456
package com.learn;

import com.mysql.jdbc.Driver;

import java.io.BufferedReader;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Properties;

/*
通过读取配置文件获取数据库连接信息
 */
public class JDBCDemo3 {
    public static void main(String[] args) throws Exception{
        //1、加载数据库驱动
        Class.forName("com.mysql.jdbc.Driver");
        //读取配置文件获取url,用户名以及密码
        Properties prop = new Properties();
        prop.load(new BufferedReader(new FileReader("E:\\Project\\IDEAProject\\bigdata23-learn\\bigdata23-jdbc\\src\\main\\java\\com\\learn\\utils\\mysqlinfo.properties")));
        String url = prop.getProperty("url");
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        //2、获取数据库连接对象
        Connection conn = DriverManager.getConnection(url, username, password);

        //3、获取数据库操作对象
        Statement state = conn.createStatement();

        //4、编写sql语句,执行sql
        String sql = "insert into dept values(97,'保洁','安徽淮南')";

        int count = state.executeUpdate(sql);
        if (count==1){
            System.out.println("数据插入成功");
        }else {
            System.out.println("数据插入失败");
        }

        //6、释放资源
        state.close();
        conn.close();

    }

}

使用工具类改进获取连接代码

package com.learn.utils;

import java.io.BufferedReader;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

public class MysqlTool {
    private MysqlTool(){}
    public static Connection getConnection(){
        Connection conn = null;
        try{
            //1、加载数据库的驱动
            Class.forName("com.mysql.jdbc.Driver");

            //读取配置文件获取url,用户名和密码
            Properties prop = new Properties();
            prop.load(new BufferedReader(new FileReader("E:\\Project\\IDEAProject\\bigdata23-learn\\bigdata23-jdbc\\src\\main\\java\\com\\learn\\utils\\mysqlinfo.properties")));
            String url = prop.getProperty("url");
            String username = prop.getProperty("username");
            String password = prop.getProperty("password");

            //2、获取数据库的连接对象
            conn = DriverManager.getConnection(url, username, password);
        }catch (Exception e){
            e.printStackTrace();
        }

        if (conn!=null){
            System.out.println("与数据库建立连接成功");
        }else {
            System.out.println("建立连接失败,请重试!");
        }


        return conn;
    }
}

6.4.4 处理查询结果集

package com.learn;

import com.learn.utils.MysqlTool;

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

public class JDBCDemo4 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement state = null;
        try{
            //获取连接对象
            conn = MysqlTool.getConnection();

            //获取数据库操作对象
            state = conn.createStatement();

            //查询
            String sql = "select deptno,dname,loc from dept";
            ResultSet rs = state.executeQuery(sql);
            while (rs.next()){
                //第一种方式:通过索引获取列(索引下标从1开始)
//                String deptno = rs.getString(1);
//                String dname = rs.getString(2);
//                String loc = rs.getString(3);
                //第二张方式:通过列名来获取
                //如果查询语句中有别名的列存在,第二种方式查询的时候,使用别名获取这一列
                String deptno = rs.getString("deptno");
                String dname = rs.getString("dname");
                String loc = rs.getString("loc");
                System.out.println("部门编号:"+deptno+",部门名称:"+dname+",地址:"+loc);
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (state!=null){
                try {
                    state.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }if (conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

登录注册案例

package com.learn;

import com.learn.utils.MysqlTool;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import java.util.UUID;

public class JDBCDemo5 {
    public static void main(String[] args) throws SQLException {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        System.out.println("====================欢迎来到美联储后台管理系统!=====================");
        System.out.println("请输入您的用户名:");
        String username = sc.nextLine();
        System.out.println("请输入您的密码:");
        String pwd = sc.nextLine();

        //查询数据库中的users表,判断该用户是否存在
        //获取数据库的连接对象
        Connection conn = MysqlTool.getConnection();
        //获取数据库操作对象
        Statement state = conn.createStatement();
        //编写sql查询语句
        String sql = "select username,password from users where username='"+username+"'and password='"+pwd+"'";
        //执行sql语句
        ResultSet rs = state.executeQuery(sql);
            boolean flag = rs.next();
            if (flag){
                System.out.println("登陆成功,您的余额为36415481518.25美元,祝您生活愉快!");
            }else {
                System.out.println("登陆失败,是否注册?(Y/N)");
                String s = sc.nextLine();
                if ("Y".equals(s)){
                    System.out.println("请输入您的姓名:");
                    String name =sc.nextLine();
                    System.out.println("请输入您的用户名:");
                    String uname =sc.nextLine();
                    System.out.println("请输入您的密码:");
                    String password =sc.nextLine();
                    System.out.println("请确认您的密码:");
                    String password2 =sc.nextLine();
                    if (password.equals(password2)){
                        //开始进行注册(即把数据插入到数据库中)
                        //Java中提供一个类用于生成随机id:UUID
                        UUID uuid = UUID.randomUUID();
                        String id = uuid.toString();
                        String sql2 = "insert into users values('"+id+"','"+name+"','"+uname+"','"+password+"')";
//                        System.out.println(sql2);
                        int count = state.executeUpdate(sql2);
                        if (count==1){
                            System.out.println("注册成功,系统随机赠送您36415481518.25美元初始资金,祝您生活愉快!");
                        }else {
                            System.out.println("系统繁忙,请您稍后再试!");
                        }
                    }
                }else {
                    System.out.println("欢迎下次光临。");
                }
            }

//        System.out.println(sql);
        conn.close();

    }
}
可以实现简单的注册登录。

​

 

6.4.5 解决sql注入问题

​SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

在上面案例中,我们查询登录语句是

String sql = "select username,password from users where username='"+username+"'and password='"+pwd+"'";

此时我们登录,应该是用户名为president,密码为666

然而读者观察以下结果:

我们神奇的发现,输入的密码并不是666,竟然也能登陆成功,这就是SQL注入。

此时我们再将登陆语句拿过来

select username,password from users where username='"+username+"'and password='"+pwd+"'

我们将输入的内容拼接上去

select username,password from users where username='president'and password='123' or '1'

此时语句最后变成了password='123' or '1',而'1'是个字符串,显然恒为true,导致password='123' or '1'也为true,于是就登陆进了系统

我们再换种方式:

同理:

 select username,password from users where username='president'and password='123' or '1'='1'

如果我们是先进行sql拼接,然后再对sql整体做编译的话,会将一些拼接的内容作为sql语法关键字进行处理。但是我们实际上输入的字符就是普通的字符串,不应该当作sql语法的编译。 

于是java和mysql团队提供了另一种方式获取数据库操作对象。 解决方案:将原来的先拼接再编译sql的步骤换成:先编译再拼接。
//提前编译好sql,将需要传参数的地方使用问号进行处理
PreparedStatement state = conn.prepareStatement("select name,password from users where name=? and password=?");
state.setString(1,username);
state.setString(2,pwd);

改进后的代码如下:

package com.learn;

import com.learn.utils.MysqlTool;

import java.sql.*;
import java.util.Scanner;
import java.util.UUID;

public class JDBCDemo5_2 {
    public static void main(String[] args) throws SQLException {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        System.out.println("====================欢迎来到美联储后台管理系统!=====================");
        System.out.println("请输入您的用户名:");
        String username = sc.nextLine();
        System.out.println("请输入您的密码:");
        String pwd = sc.nextLine();

        //查询数据库中的users表,判断该用户是否存在
        //获取数据库的连接对象
        Connection conn = MysqlTool.getConnection();
        //获取数据库操作对象
//        Statement state = conn.createStatement();
//        //编写sql查询语句
//        String sql = "select username,password from users where username='"+username+"'and password='"+pwd+"'";
        //提供了预编译对象进行处理
        //提前编译好sql,将需要传参数的地方使用问号进行处理
        PreparedStatement state = conn.prepareStatement("select name,password from users where name=? and password=?");
        state.setString(1,username);
        state.setString(2,pwd);
        //执行sql语句
        ResultSet rs = state.executeQuery();
        boolean flag = rs.next();
        if (flag){
            System.out.println("登陆成功,您的余额为36415481518.25美元,祝您生活愉快!");
        }else {
            System.out.println("登陆失败,是否注册?(Y/N)");
            String s = sc.nextLine();
            if ("Y".equals(s)){
                System.out.println("请输入您的姓名:");
                String name =sc.nextLine();
                System.out.println("请输入您的用户名:");
                String uname =sc.nextLine();
                System.out.println("请输入您的密码:");
                String password =sc.nextLine();
                System.out.println("请确认您的密码:");
                String password2 =sc.nextLine();
                if (password.equals(password2)){
                    //开始进行注册(即把数据插入到数据库中)
                    //Java中提供一个类用于生成随机id:UUID
                    UUID uuid = UUID.randomUUID();
                    String id = uuid.toString();
                    String sql2 = "insert into users values('"+id+"','"+name+"','"+uname+"','"+password+"')";
//                        System.out.println(sql2);
                    int count = state.executeUpdate(sql2);
                    if (count==1){
                        System.out.println("注册成功,系统随机赠送您36415481518.25美元初始资金,祝您生活愉快!");
                    }else {
                        System.out.println("系统繁忙,请您稍后再试!");
                    }
                }
            }else {
                System.out.println("欢迎下次光临。");
            }
        }

//        System.out.println(sql);
        conn.close();

    }
}

 测试:

 发现已经无法使用原来的漏洞登录了。

JDBC事物机制: 1.JDBC中的事务自动提交的,什么是自动提交? 只要执行任意一条 DML

语句,则自动提交一次。这是JDBC默认的事务行为。 但是在实际的业务中,通常都是N条DML语句共同联合才能完成,必须 保证这些DML语句在同一个事务中同时成功或者同时失败 解决方案:三行重要的代码 conn.setAutoCommit(false);//手动提交事务 conn.commit();//提交事务 conn.rooback;当发生异常时或者程序错误时,进行回滚。

 

6.4.6 JDBC实现模糊查询

package com.learn;

import com.learn.utils.MysqlTool;

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

public class JDBCDemo6 {
    public static void main(String[] args) throws Exception {
        //获取数据库连接对象
        Connection conn = MysqlTool.getConnection();

        //获取预编译数据库操作对象
        PreparedStatement pps = conn.prepareStatement("select id,name,password from users where name like ?");

        pps.setString(1,"川%");

        ResultSet resultSet = pps.executeQuery();
        while (resultSet.next()){
            String name = resultSet.getString(1);
            String password = resultSet.getString(2);
            System.out.println(name+"--"+password);
        }

        pps.close();
        conn.close();
    }
}

6.5 悲观锁和乐观锁的概念

事务1–>读取到版本号1.1 事务2—>读取到版本号1.1

其中事务1先修改了,修改之后看了版本号是1.1 ,于是提交修改的数据,将版本号修改为1.2 其中事务2后修改的,修改之后准备提交的时候,发现版本号是1.2 ,和它最初读的版本号不一致。回滚。

悲观锁:事务必须排队执行。数据锁住了,不允许并发。 (行级锁: select后面添加for update ) 乐观锁:支持并发,事务也不需要排队,只不过需要一个版本号。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值