JavaWeb——黑马程序员课程笔记

视频地址:点击跳转
全程使用开发工具:IDEA Mysql
此篇几乎所有需要的配置文件都可以区黑马公众号找到

JavaWeb介绍

  • JavaWeb:是用Java技术来解决相关web互联网领域的技术栈

数据库

数据库相关概念

数据库

  • 存储数据的仓库,数据是有组织的进行存储
  • 英文:DataBase,简称DB

数据库管理系统

  • 管理数据库的大型软件
  • 英文:DataBase Management System,简称DBMS

SQL

  • 英文: Structured Query Language,简称SQL,结构化查询语言。操作关系型数据库的编程语言。
  • 定义操作所有关系型数据库的统一标准
    常见的关系型数据库
  • Oracle:收费的大型数据库,Oracle 公司的产品
  • MySQL:开源免费的中小型数据库。后来Sun公司收购了MySQL,而Sun公司又被Oracle 收购.
  • SQL Server: MicroSoft 公司收费的中型的数据库。C#、.net等语言常使用
  • PostgresQL:开源免费中小型的数据库
  • DB2: IBM公司的大型收费数据库产品
  • SQLite:嵌入式的微型数据库。如:作为Android内置数据库
  • MariaDB:开源免费中小型的数据库

关系型数据库

关系型数据库是建立在关系模型基础上的数据库,简单说,关系型数据库是由多张能互相连接的二维表组成的数据库

优点

  • 都是使用表结构,格式一致,易于维护。
  • 使用通用的SQL语言操作,使用方便,可用于复杂查询。
  • 数据存储在磁盘中,安全。

SQL

SQL简介

  • 英文: Structured Query Language,简称SQL
  • 结构化查询语言,一门操作关系型数据库的编程语言定义操作所有关系型数据库的统一标准
  • 对于同一个需求,每一种数据库操作的方式可能会存在一些不一样的地方,我们称为“方言”"

SQL通用语法

  • SQL语句可以单行或多行书写分号结尾。
  • MySQL 数据库的SQL语句不区分大小写,关键字建议使用大写
  • 注释
     单行注释:– 注释内容或#注释内容(MySQL特有)
     多行注释:/* 注释 */

SQL分类

  • DDL:操作数据库,表等
  • DML:对表中的数据进行增删改
  • DQL:对表中的数据进行查询
  • DCL:对数据库进行权限控制
DDL
DDL——操作数据库

DDL——操作表


数据类型


图形化客户端工具

DML

添加(insert)

修改(update)


注意:如果update语句没有加where条件,则会将表中所有数据全部修改

删除(delete)


注意:如果update语句没有加where条件,则会将表中所有数据全部删除

DQL

基础查询


drop table if exists stu;

create table stu (
id int,
name varchar(20),
age int,
sex varchar(5),
address varchar(100),
math double(5,2),
english double(5,2),
hire_date date
);

insert into stu(id,name,age,sex,address,math,english,hire_date)
values
(1,'马运',55,'男','杭州',66,78, '1995-09-01'),
(2,'马花疼',45, '女','深圳',98,87, '1998-09-01'),
(3,'马斯克',55, '男','香港',56,77, '1999-09-02 '),
(4,'柳白',20,'女','湖南',76,65, '1997-09-05'),
(5,'柳青',20,'男','湖南',86,NULL, ' 1998-09-01'),
(6,'刘德花',57,'男','香港',99,99, '1998-09-01'),
(7,'张学右',22,'女','香港',99,99, ' 1998-09-01'),
(8,'德玛西亚',18,'男','南京',56,65,'1994-09-02');





但公司一般不使用*



这时的查询结果有重复,我们用DISTINCT需要去除重复


条件查询






这里判断相等直接用=,不同于java中的==


null值的比较不能使用=,!=,需要使用is


![](https://img-blog.csdnimg.cn/723def160fd24702b0dcb8cc5a581560.png)

排序查询(ORDER BY)







如果有多个排序条件,当前边的条件值一样时,才会根据第二条件进行排序

分组查询(GROUP BY)
聚合函数
  • 概念:将一列数据作为一个整体,进行纵向计算
  • 聚合函数分类
  • 聚合函数语法

    注意:null值不参与所有聚合函数运算



    count统计的列名不能为null
    count:
    取值:
    1. 主键
    2. *



where 和have区别:





分页查询





约束

概念和分类


MySQL不支持检查约束

非空约束


默认约束

外键约束


数据库设计

数据库设计简介
  • 软件的研发步骤
  • 数据库设计概念
    · 数据库设计就是根据业务系统的具体需求,结合我们所选用的DBMS,为这个业务系统构造出最优的数据存储模型。
    · 建立数据库中的表结构以及表与表之间的关联关系的过程。
    · 有哪些表?表里有哪些字段?表和表之间有什么关系?
    3.数据库设计的步骤
表关系之一对多(多对一)

如:部门和员工

  • 实现方式:在多的一方建立外键,指向一的一方的主键
表关系之多对多

如:商品和订单

  • 实现方式:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
表关系之一对一

如:用户和用户详情
一对一关系多用于表拆分,将一个实体中经常使用的字段放一张表,不经常使用的字段放另一张表,用于提升查询性能

  • 实现方式:在任意一方加入外键,关联另一方主键,并且设置外键为唯一(UNIQUE)

多表查询

多表查询简介

内连接




外连接


子查询






多表查询案例

DROP TABLE IF EXISTS emp;
DROP TABLE IF EXISTS dept;
DROP TABLE IF EXISTS job;
DROP TABLE IF EXISTS salarygrade;

CREATE TABLE dept (
id INT PRIMARY KEY ,
dname VARCHAR(50),
loc VARCHAR (50)

);

CREATE TABLE job (
id INT PRIMARY KEY,
jname VARCHAR(20),
description VARCHAR(50)
);



CREATE TABLE emp (

id INT PRIMARY KEY, 
ename VARCHAR( 50), 
job_id INT, 

mgr INT , 

joindate DATE,
salary DECIMAL(7,2),
bonus DECIMAL (7,2),
dept_id INT,
CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY(dept_id)REFERENCES dept (id)

);

CREATE TABLE salarygrade (

grade INT PRIMARY KEY,
losalary INT,
hisalary INT 
) ;


INSERT INTO dept (id, dname , loc)VALUES
(10,'教研部','北京'),

(20,'学工部','上海'),
( 30,'销售部','广州'),
(40,'财务部','深圳');


INSERT INTO job (id,jname,description) VALUES
( 1,'董事长','管理整个公司,接单'),

(2,'经理','管理部门员工'),

( 3,'销售员','向客人推销产品'),
(4,'文员','使用办公软件' );


INSERT INTO emp (id,ename,job_id,mgr,joindate,salary,bonus, dept_id)VALUES
(1001,'孙悟空',4,1004, ' 2000-12-17' ,'8000.00',NULL,20),

(1002,'卢俊义',3,1006,' 2001-02-20','16000.00 ', ' 3000.00' , 30),
(1003,'林冲',3,1006, ' 2001-02-22', '12500.00 ' , ' 5000.00 ',30),
(1004,'唐僧',2,1009,' 2001-04-02','29750.00 ',NULL,20),

(1005,'李逵' ,4,1006, '2001-09-28','12500.00 ' , '14000.00',30),
(1006,'宋江',2,1009, '2001-05-01',' 28500.00',NULL,30),

(1007,'刘备',2,1009,' 2001-09-01','24500.00',NULL,10),
(1008,'猪八戒',4,1004, ' 2007-04-19',' 30000.00 ',NULL,20) ,
(1009,'罗贯中',1,NULL,' 2001-11-17',' 50000.00 ',NULL,10),
(1010,'吴用',3,1006, '2001-09-08', '15000.00' , '0.00',30) ,
(1011,'沙僧',4,1004, '2007-05-23' ,'11000.00 ',NULL,20) ,
(1012,'李逵',4,1006, '2001-12-03', '9500.00',NULL,30) ,
(1013,'小白龙',4,1004, ' 2001-12-03', ' 30000.00',NULL,20) ,
(1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10) ;


INSERT INTO salarygrade (grade ,losalary, hisalary) VALUES
( 1,3000,12000) ,
( 2,12010, 14000) ,(3,14010,20000) ,( 4,20010,30000) ,( 5,30013,99990) ;








事务

事务简介
  • 数据库的事务(Transaction)是一种机制、一个操作序列,包含了一组数据库操作命令
  • 事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么同时成功,要么同时失败
  • 事务是一个不可分割的工作逻辑单元
事务操作

事务四大特征:ACID
  • 原子性(Atomicity):事务是不可分割的最小操作单位,要么同时成功,要么同时失败
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态
  • 隔离性(lsolation):多个事务之间,操作的可见性
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的
    MYSQL事务默认是自动提交的
    查询事物的默认提交方式(手动提交0,自动提交1)
select @@autocommit;

修改事物的提交方式

set @@autocommit = 0;

JDBC

JDBC就是使用Java语言操作关系型数据库的一套API

JDBC简介

JDBC概念:

  • JDBC 就是使用Java语言操作关系型数据库的一套API·
  • 全称: ( Java DataBase Connectivity ) Java 数据库连接
  • (驱动就是实现类)

JDBC 本质:

  • 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包
  • 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类

JDBC好处:

  • 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
  • 可随时替换底层数据库,访问数据库的Java代码基本不变

JDBD快速入门


创建工程后进行简单的配置

给项目添加模块



将驱动jar包放在lib目录下

让当前工程识别jar包


写代码

package com.it.jdbc;

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

public class JDBCDemo {
    public static void main(String[] args) throws Exception{
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        String url = "jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC";//固定写法url是这个:
        String username = "root";
        String password = "******";
        Connection conn = DriverManager.getConnection(url,username,password);

        //3.定义
        String sql = "update db1 set money = 2000 where id = 1";

        //4.获取执行sql的对象Statement()
        Statement stmt = conn.createStatement();

        //5.执行sql
        int count = stmt.executeUpdate(sql);

        //6.处理结果
        System.out.println(count);

        //7.释放资源
        stmt.close();
        conn.close();
    }
}


JDBC API详解

DriverManager

DriverManager(驱动管理类)作用:
1. 注册驱动


提示:
MySQL 5之后的驱动包,可以省略注册驱动的步骤
自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类

2. 获取数据库连接


Connection

Connection(数据库连接对象)作用
1. 获取执行SQL的对象


2. 管理事务

package com.it.jdbc;

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

public class JDBCDemo3_Connection {
    public static void main(String[] args) throws Exception{
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        String url = "jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC";//固定写法url是这个:
        String username = "root";
        String password = "*****";
        Connection conn = DriverManager.getConnection(url,username,password);

        //3.定义
        String sql1 = "update db1 set money = 3000 where id = 1";
        String sql2 = "update db1 set money = 3000 where id = 2";
        //4.获取执行sql的对象Statement()
        Statement stmt = conn.createStatement();


        try {
            //开启事务
            conn.setAutoCommit(false);

            //5.执行sql
            int count1 = stmt.executeUpdate(sql1);
            int count2 = stmt.executeUpdate(sql2);
            //6.处理结果
            System.out.println(count1);
            System.out.println(count2);
            //提交事务
            conn.commit();
        } catch (Exception throwables) {
            //回滚事务
            conn.rollback();
            throwables.printStackTrace();
        }

        //7.释放资源
        stmt.close();
        conn.close();
    }
}



出现异常情况

最终数据库的信息没有被修改

Statement

Statement作用
1.执行SQL操作




DDL不能用count判断

ResultSet

ResultSet(结果集对象)作用
封装了DDL查询语句的结果


package com.it.jdbc;

import org.junit.Test;

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

public class JDBCDemo5_ResultSet {
    //单元测试
    @Test
    public void testDML() throws Exception{
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接
        String url = "jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC";//固定写法url是这个:
        String username = "root";
        String password = "*****";
        Connection conn = DriverManager.getConnection(url,username,password);

        //3.定义
        String sql = "select * from db1";

        //4.获取执行sql的对象Statement()
        Statement stmt = conn.createStatement();

        //5.执行sql
        ResultSet rs =  stmt.executeQuery(sql);//执行完DML后,受影响的行数
        //6.处理结果,遍历rs中所有数据
        while(rs.next()){
            //获取数据
            int id = rs.getInt(1);
            String name = rs.getString(2);
            double money = rs.getDouble(3);

            System.out.println(id);
            System.out.println(name);
            System.out.println(money);

            System.out.println("______________");
        }

        //7.释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}


案例

  1. 定义交体类bd1
  2. 查询数据,封装到db1对象中
  3. 将db1对象存入ArrayList集合中



添加如下


添加如下

至此实体类写好,完整代码

package com.it.pojo;

public class db1 {
    private int id;
    private String name;
    private double money;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "db1{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

package com.it.jdbc;

import com.it.pojo.db1;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class JDBCDemo5_ResultSet {
    //单元测试
    @Test
    public void testDML() throws Exception{
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接
        String url = "jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC";//固定写法url是这个:
        String username = "root";
        String password = "*****";
        Connection conn = DriverManager.getConnection(url,username,password);

        //3.定义
        String sql = "select * from db1";

        //4.获取执行sql的对象Statement()
        Statement stmt = conn.createStatement();

        //5.执行sql
        ResultSet rs =  stmt.executeQuery(sql);//执行完DML后,受影响的行数
        //创建集合
        List<db1> list = new ArrayList<>();
        //6.处理结果,
        while(rs.next()){
            db1 a = new db1();
            //获取数据
            int id = rs.getInt(1);
            String name = rs.getString(2);
            double money = rs.getDouble(3);

            //赋值
            a.setId(id);
            a.setName(name);
            a.setMoney(money);

            //存入集合
            list.add(a);
        }
        System.out.println(list);

        //7.释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}

PreparedStatement

PreparedStatement作用
  1. 预编译SQL语句并执行;
  2. 预防SQL注入问题

    预防注入的代码
package com.it.jdbc;

import java.sql.*;

import org.junit.Test;

public class JDBCDemo4_Statement {
    //单元测试DML
    @Test
    public void testDML() throws Exception{
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接
        String url = "jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC";//固定写法url是这个:
        String username = "root";
        String password = "*****";
        Connection conn = DriverManager.getConnection(url,username,password);

        //接收用户名和密码
        String name = "张三";
        String pwd = "'1 or '1'='1'";

        //3.定义
        String sql = "select * from db1 where username = ? and password = ?";
        //获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
        //设置?值
        pstmt.setString(1,name);
        pstmt.setString(2,pwd);

        //5.执行sql
        ResultSet rs = pstmt.executeQuery();
        //6.处理结果
        //System.out.println(count);
        if(rs.next()){
            System.out.println("登录成功!");
        }else{
            System.out.println("登录失败!");
        }

        //7.释放资源
        rs.close();
        pstmt.close();
        conn.close();

    }
}

PreparedStatement原理

SQL注入

SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。
演示注入(自行去黑马公众号寻找)


SQL注入

数据库连接池

数据库连接池简介

  • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
  • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;
  • 放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。
  • 好处:
    资源重用
    提升系统响应速度
    避免数据库连接遗漏

数据库连接池的实现

Druid使用步骤

  1. 导入jar包druid-1.1.12.jar(和之前导入包的方法相同)
  2. 定义配置文件
    将配置文件导入至src目录下(记住配置文件改为自己数据库的密码,这里我忘改了)
  3. 加载配置文件
  4. 获取数据库连接池对象
  5. 获取连接

案例


  1. 数据库表tb_brand
  2. 实体类brand
    在实体类中,基本数撼类型建议使用其对应的包装类型
package com.it.pojo;

public class brand {
    private Integer id;
    private String brandName;
    private String compangName;
    private Integer ordered;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }

    public String getCompangName() {
        return compangName;
    }

    public void setCompangName(String compangName) {
        this.compangName = compangName;
    }

    public Integer getOrdered() {
        return ordered;
    }

    public void setOrdered(Integer ordered) {
        this.ordered = ordered;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    private String description;
    private Integer status;

    @Override
    public String toString() {
        return "brand{" +
                "id=" + id +
                ", brandName='" + brandName + '\'' +
                ", compangName='" + compangName + '\'' +
                ", ordered=" + ordered +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
}
  • 查询所有数据

    将配置文件中修改成对应的数据库
package com.it.demo;
import com.it.pojo.brand;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class brandTest {

    @Test
    public void testSelectAll() throws Exception {
        //1.获取Connection
        Properties prop = new Properties();
        prop.load(new FileInputStream("F:/jdbctest/src/druid.properties"));
        //获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //获取数据库连接Connection
        Connection conn = dataSource.getConnection();

        //2.定义SQL
        String sql = "select * from tb_brand";

        //3.获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);

        //4.设置参数
        //5.执行参数
        ResultSet rs = pstmt.executeQuery();

        //6.处理结果,装置List
        brand b = null;
        List<brand>list = new ArrayList<>();
        while(rs.next()){
            //获取数据
            int id = rs.getInt("id");
            String brandName = rs.getString("brand_name");
            String companyName = rs.getString("company_name");
            int ordered = rs.getInt("ordered");
            String description = rs.getString("description");
            int status = rs.getInt("status");

            //封装brand对象
            b = new brand();
            b.setId(id);
            b.setBrandName(brandName);
            b.setCompanyName(companyName);
            b.setDescription(description);
            b.setOrdered(ordered);
            b.setStatus(status);

            //装载集合
            list.add(b);

        }
        //打印集合
        System.out.println(list);
        //7.释放资源
        rs.close();
        pstmt.close();
        conn.close();


    }

}

  • 添加
    在这里插入图片描述
   @Test
    public void testAdd() throws Exception {
        String brandName = "香飘飘";
        String companyName = "香飘飘";
        int ordered = 1;
        String description = "绕地球一圈";
        int status = 1;

        //1.获取Connection
        Properties prop = new Properties();
        prop.load(new FileInputStream("F:/jdbctest/src/druid.properties"));
        //获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //获取数据库连接Connection
        Connection conn = dataSource.getConnection();

        //2.定义SQL
        String sql = "insert into tb_brand(brand_name,company_name,ordered,description,status) values (?,?,?,?,?)";

        //3.获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);

        //4.设置参数
        pstmt.setString(1,brandName);
        pstmt.setString(2,companyName);
        pstmt.setInt(3,ordered);
        pstmt.setString(4,description);
        pstmt.setInt(5,status);
        //5.执行SQL
        int count = pstmt.executeUpdate();

        //6.处理结果
        System.out.println(count>0);
        //7.释放资源
        pstmt.close();
        conn.close();


    }


Maven

  • Maven是专门用于管理和构建Java项目的工具,它的主要功能有:
  1. 提供了一套标准化的项目结构

  2. 提供了一套标准化的构建流程(编译,测试,打包,发布)
  3. 提供了一套依赖管理机制
     依赖管理
     依赖管理其实就是管理你项目所依赖的第三方资源(jar包、插件…)
     

Maven简介


官网地址

中央仓库地址

Maven安装配置

  1. 下载好安装包,找到对应目录
  2. 找到高级系统设置——》环境变量

  3. 在这里插入图片描述
  4. 最后在cmd窗口输入mvn -version查看是否配置成功
  5. 配置本地仓库

    点开conf/settings.xml
  6. 配置阿里云私服
    点开conf/settings.xml
    官方点这里
<mirror>
  <id>aliyunmaven</id>
  <mirrorOf>*</mirrorOf>
  <name>阿里云公共仓库</name>
  <url>https://maven.aliyun.com/repository/public</url>
</mirror>

Maven基本使用

Maven常用命令

  1. compile:编译
    在公众号找到对应的项目,在pom.xml所在文件夹,按住shift点击右键,选择Powershell


    以下显示为编译成功

    产生一个target目录
  2. clean:清理

  3. package:打包

    注意:这里使用公众号下载的资源会失败,是因为目录名中含有&,重命名文件删去&,即可成功

  4. test:测试

  5. install:安装
    安装到本地仓库


Maven使用周期


IDEA配置Maven

IDEA配置Maven环境

Maven坐标详解

IDEA 创建Maven项目

创建成功测试

IDEA导入Maven项目

将你想要导入的工程放在你的工程目录下


依赖管理

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

King✪ω✪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值