SpringBoot系列:6. SpringBoot整合JDBC,Druid,Mybatis

前言

  1. 下面讲解内容为:对数据库的整合
    ⑴ 整合JDBC使用
    ⑵ 整合Druid数据源
    ⑶ 整合Mybatis框架
  2. 注意:只要是Java其数据库的底层永远的都是JDBC。

1. 整合JDBC

1.1 了解JDBC

1. JDBC详解
⑴ jdbc用来连接我们的java应用程序和数据库,用jdbc 我们能用java
应用程序读取数据库里面的数据,还能够存储数据。
⑵ 能通过jdbc连接到不同的数据库,像OracleMysql和sql Server 
等数据库。连接到的数据库实现CRUD操作。

2. JDBC、SQL、Mysql三者的关系是:
⑴ JDBC用于连接数据库,
⑵ SQL语句用于对数据库进行增删改查等操作,肯定是需要先连接数据
库,才能对其进行操作。
⑶ Mysql只是数据库中的一种,还有Oracle、DB2等数据库可选择。

3. JDBC连接数据库的步骤(具体步骤如下的a~f)
a、加载数据库驱动,运用的是Class类的forName()静态方法来加载驱
动。
b、通过DriverManager获取数据库连接。
c、通过Connection对象创建Statement对象。
d、使用Statement执行sql语句。
e、操作结果集
f、回收数据库资源

1.2 Spring整合JDBC使用

1. Spring Data
⑴ 其实跟数据库打交道,就是Spring Data
- 对于数据访问层,无论是SQL(关系型数据库)还是 NOSQL(非关系型数
据库)Spring Boot底层都是采用Spring Data的方式进行统一处理。

- Spring Boot 底层都是采用Spring Data的方式进行统一处理各种数据库,Spring Data也是Spring中与Spring BootSpring Cloud等齐名的知名项目。

- 通过Spring思想来实现Spring Data 数据库的操作,实际上就是将涉
及到的类对象注册成一个一个的bean,只要有bean你就能拿到,能做任何
事情。

⑵ Spring Data:统一了所有访问数据库的接口,为开发者提供一个更
加简便的开发方式。
- Spring DataSpring 的一个子项目。
- Spring Data用于简化数据库访问,支持NoSQL和关系数据库存储。
- Spring Data其主要目标是使数据库的访问变得方便快捷。
⑶ Spring Data 项目所支持NoSQL(非关系型数据库)存储:
- MongoDB(文档数据库)
- Neo4j (图形数据库)
- Redis(键/值存储)
- Hbase(列族数据库).Spring Data 项目支持数据库操作的存储的技术,有如下两种:
- 第一种:JDBC
- 第二种:JPA (继承"extends Repository<T, ID> "便可操作数据库)

1.3 代码实现Spring整合JDBC

. 首先创建一个SpringBoot-IDEA项目
- 在创建JDBC演示项目的时候,有个注意点,再选择依赖的时候要勾选
MySql Driver(这个是MySql的驱动)- MySql Driver不勾选加入依赖,数据库是连接不上的。
--"图ms1"
- 对于如果遇到"xxxxTemplate"-->就是一种模板,SpringBoot已经帮我们配置好的模板bean,
拿来即用接口!即可实现数据库的CRUD操作。

----------------------------------------------

② 演示Spring整合JDBC连接测试代码,步骤如下所示:

⑴ 第一步:IDEA创建一个项目,且引入了以下依赖
<dependency> 
   <groupId>org.springframework.boot</groupId>  
   <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>  
   <groupId>mysql</groupId>   
   <artifactId>mysql-connector-java</artifactId>  
   <scope>runtime</scope>
</dependency>

⑵ 第二步:配置数据库连接文件(创建一个.yaml配置文件)
spring:  
    datasource:    
    username: xxxxx
    password: xxxxx    
#?serverTimezone=UTC解决时区的报错    
    url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8   
    driver-class-name: com.mysql.cj.jdbc.Driver
    
⑶ 第三步:配置完这一些东西后,我们就可以直接去使用了,
因为SpringBoot已经默认帮我们进行了自动配置;去测试类测试一下。

@SpringBootTest
class SpringbootDataJdbcApplicationTests {
    //DI注入数据源    
    @Autowired 
    DataSource dataSource;
    @Test    
    public void contextLoads() throws SQLException {
            //看一下默认数据源        
            System.out.println(dataSource.getClass());        
            //获得连接        
            Connection connection = dataSource.getConnection(); 
            System.out.println(connection);        
            //关闭连接        
            connection.close();    
            }
}

⑷ 第四步:Spring 本身也对原生的JDBC 做了轻量级的封装,即JdbcTemplate
- 数据库操作的所有 CRUD 方法都在 JdbcTemplate 中。
- Spring Boot 不仅提供了默认的数据源,同时默认已经配置好了 
JdbcTemplate 放在了容器中,程序员只需自己注入即可使用
- JdbcTemplate主要提供以下几类方法:
* execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
* update方法及batchUpdate方法:update方法用于执行新增、修改、
删除等语句;
batchUpdate方法用于执行批处理相关语句;
* query方法及queryForXXX方法:用于执行查询相关语句;
* call方法:用于执行存储过程、函数相关语句。
- 我们直接创建一个controller类,引入JdbcTemplate依赖,执行CRUD操作即可!

/**
 * JdbcTemplate实现CRUD操作
 */
@RestController
public class JDBCController {
    @Autowired
    JdbcTemplate jdbcTemplate;
    /**
     * 1.查询数据库的所有信息,并显示在网页上
     *      -->没有实体类,从数据库获取的东西怎么返回呢?==>使用Map来返回
     */
    @GetMapping("/userList")
    public List<Map<String,Object>> userList() {
        String sql= "select * from user";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
        // 将执行sql语句,查询到的数据丢给前端即可!
        return maps;
    }
    /**
     * 增加
     */
    @GetMapping("/addUser")
    public String addUser(){
        String sql = "insert into study.user(id,name,pwd) value (4,'赵云','113366')";
        jdbcTemplate.update(sql);
        return "add-ok";
    }
    /**
     * 修改
     */
    @GetMapping("/updateUser/{id}")
    public String updateUser(@PathVariable("id") int id){
        String sql = "update study.user set name =?,pwd = ? where id=" + id;
        //封装
        Object[] objects = new Object[2];
        objects[0] = "马超";
        objects[1] = "223377";
        jdbcTemplate.update(sql,objects);
        return "update-ok";
    }
    /**
     * 删除
     */
    @GetMapping("/deleteUser/{id}")
    public String deleteUser(@PathVariable("id") int id){
        String sql = "delete from study.user where id = ?";
        jdbcTemplate.update(sql,id);
        return "delete-ok";
    }
}  

⑸ 第五步:测试
- http://localhost:8080/输入URL-->测试CRUD请求。


在这里插入图片描述图ms1

2. 整合Druid数据源

2.1 什么是数据源

① 数据源解释一
⑴ 就是通过数据库的用户名、密码等信息建立的数据库连接,来构建数据库连接池。
⑵ 普通的连接数据库是建立一个连接,执行完sql之后,就会关闭,
再次连接还需要重复上述步骤。

⑶ 而数据源连接池会根据你的参数建立多个数据库连接并缓存,
你每次连接数据库的时候就可以从连接池中获取一个连接,去执行sql,
用完会放入连接池。这样,就避免了连接数据库的开销,也减少了对数据库的压力。

------------------------------------------------------

② 数据源解释二
⑴ 数据源,顾名思义,数据的来源。在数据源中存储了所有建立数据库连接的信息。
⑵ 作用就是你可以操作数据库,数据源里面存放了你要连接哪个库以及数据库的账号和密码。
⑶ 数据源定义的是连接到实际数据库的一条路径而已,数据源中并无真正的数据,
它仅仅记录的是你连接到哪个数据库,以及如何连接的,如jdbc数据源。
也就是说数据源仅仅是数据库的连接名称,一个数据库可以有多个数据源连接。

◆:小结:所以在配置文件中可以配置多个数据源。在平时开发中,一般有测
试环境和生产环境。测试环境用的数据库Mysql地址和生产环境用到的
Mysql地址是不一样的,因此我们就需要在配置文件中配置两个Mysql的
数据源,开发人员在开发的时候用的数据测试环境的Mysql数据源,而部
署上线就需要切换到生产环境Mysql数据源。

2.2 Druid介绍

Druid介绍
⑴ Druid 是阿里巴巴开源平台上一个数据库连接池实现,
结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。
⑶ Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,
天生就是针对监控而生的 DB 连接池。
⑵ Spring Boot 2.0 以上默认使用 Hikari 数据源,
可以说 HikariDriud 都是当前 Java Web 上最优秀的数据源。

2.3 SpringBoot集成Druid数据源和监控

1. 以下介绍 Spring Boot-->
⑴ 如何集成Druid数据源,
⑵ 如何实现数据库监控。

② SpringBoot集成Druid数据源
⑴ 第一步:pom.xml添加Druid数据源依赖
<dependency>  
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>    
 <version>1.1.21</version>
</dependency>
⑵ 第二步:切换数据源;
- 之前已经说过 Spring Boot 2.0 以上默认使用com.zaxxer.hikari.HikariDataSource
数据源
- 因此可以在.yml配置文件通过spring.datasource.type 指定数据源。
- 配置Druid作为数据源↓:
spring:
  datasource:
    username: xxxxx
    password: xxxxxx
    #?serverTimezone=UTC解决时区的报错
    url: jdbc:mysql://localhost:3306/study?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource # 自定义数据源

⑶ 第三步:设置数据源连接初始化大小、最大连接数、等待时间、
最小连接数 等设置项;可以查看源码:
spring:
  datasource:
    username: xxxxx
    password: xxxxxx
    #?serverTimezone=UTC解决时区的报错
    url: jdbc:mysql://localhost:3306/study?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource # 自定义数据源
    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;
    druid.stat.slowSqlMillis=500


⑷ 第四步:配置文件配置了log4j(Druid的监控机制),因此要导入Log4j的依赖
<dependency>  
  <groupId>log4j</groupId>  
  <artifactId>log4j</artifactId>  
  <version>1.2.17</version>
</dependency>

⑸ 第五步:Druid可以自定义一些配置(这是Druid的强大之处)
- 配置Druid的监控和过滤功能

/**
 * Druid的配置类
 */
@Configuration
public class DruidConfig {
    /*
      将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建
      绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效
      @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中
      前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
    */
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

    /*************************************************************/

    /**
     * 1. 利用Druid,实现后台监控功能
     *      -->下面的ServletRegistrationBean就相当于我们的web.xml
     *      -->因为SpringBoot内置了Servlet容器,所以没有web.xml,
     *      我们想使用web.xml的方式就要使用替代类:ServletRegistrationBean这个类,
     *      -->即:要拥有web.xml一样的功能,就要将ServletRegistrationBean这个类注册到Bean中(@Baen).
     *
     */
    //配置 Druid 监控管理 后台的Servlet;
    //内置 Servlet 容器时没有web.xml文件,所以使用 Spring Boot 的注册 Servlet 方式
    @Bean
    public ServletRegistrationBean statViewServlet() {
        /**
         * 2. 下面代码是固定的
         */
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        /**
         * 3. 后台需要有人登陆,下面完成账号密码配置
         */
        // 这些参数可以在 com.alibaba.druid.support.http.StatViewServlet
        // 的父类 com.alibaba.druid.support.http.ResourceServlet 中找到
        Map<String, String> initParams = new HashMap<>();
        /**
         * 3.1 后台管理界面的登录账号
         *      -->"loginUsername":这参数是固定的
         */
        initParams.put("loginUsername", "admin");
        /**
         * 3.2 后台管理界面的登录密码
         *      -->"loginPassword":这参数是固定的
         */
        initParams.put("loginPassword", "123456");

        //后台允许谁可以访问
        //initParams.put("allow", "localhost"):表示只有本机可以访问
        //initParams.put("allow", ""):为空或者为null时,表示允许所有访问
        initParams.put("allow", "");
        //deny:Druid 后台拒绝谁访问
        //initParams.put("kuangshen", "192.168.1.20");表示禁止此ip访问

        //设置初始化参数
        bean.setInitParameters(initParams);
        return bean;
    }

    /*************************************************************/
    /**
     * 1. 利用Druid,实现后台过滤功能
     *      -->下面的FilterRegistrationBean就相当于我们的web.xml
     *      -->因为SpringBoot内置了Servlet容器,所以没有web.xml,
     *      我们想使用web.xml的方式就要是用替代类:FilterRegistrationBean个类,
     *      -->即:要拥有web.xml一样的功能,就要将FilterRegistrationBean这个类注册到Bean中(@Baen).
     *
     * 2. 因此这边将过滤的类注册到bean的原因和上面一样,都是没有web.xml
     * 所以要使用@Bean注册到容器中。
     */
    //配置 Druid 监控 之  web 监控的 filter
    //WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计
    @Bean
    public FilterRegistrationBean webStatFilter() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        //exclusions:设置哪些请求进行过滤排除掉,从而不进行统计
        Map<String, String> initParams = new HashMap<>();
        initParams.put("exclusions", "*.js,*.css,/druid/*,/jdbc/*");
        bean.setInitParameters(initParams);

        //"/*" 表示过滤所有请求
        bean.setUrlPatterns(Arrays.asList("/*"));
        return bean;
    }
}

⑹ 第六步:测试登录Druid
- 网页输入:http://localhost:8080/druid
-->输入我们在配置类设置的账号和密码,即可登录成功!
- 登录成功,可以看到Druid里面的所有功能,如-"图druid1"
- 如果我们在网页上发起一个controller的Sql请求,就可以在登录成功的Druid里面
查看监控的到,如-"图druid2",以及可以看到其他类型的监控信息。


在这里插入图片描述
图druid1

在这里插入图片描述

图druid2

3. 整合Mybatis框架

SpringBoot整合Mybatis框架,代码实现↓
- 首先创建一个SpringBoot,在选择依赖的时候一定要选择MySql Driver
数据库驱动,不然无法成功连接数据库,如-"图mb1"
⑴ 第一步:导入 MyBatis 所需要的依赖
<dependency>  
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>2.1.1</version>
</dependency>

⑵ 第二步:,yml配置文件,配置数据库连接
spring:
  datasource:
    username: xxxxx
    password: xxxxx
    #?serverTimezone=UTC解决时区的报错
    url: jdbc:mysql://localhost:3306/study?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    #整合mybatis的别名
mybatis:
  type-aliases-package: com.xxxx.pojo
  mapper-locations: classpath:mybatis/mapper/*.xml  
  
    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;
    druid.stat.slowSqlMillis=500
⑶ 第三步:测试数据库是否连接成功!-->启动只要不报错就成功

@SpringBootTest
class MybatisApplicationTests {

    /**
     *  1. DI注入数据源
     *
     * DataSource:
     *      -->就是将我们在application.yml里配置连接数据库的数据注册过来
     */
    @Autowired
    DataSource dataSource;

    @Test
    public void contextLoads() throws SQLException {
        /**
         * 看一下默认数据源
         *      -->通过数据源拿到数据连接
         *      -->拿到数据库连接我们就可以利用原生的JDBC进行数据库操作了!
         */
        //
        System.out.println(dataSource.getClass());
        //获得数据库连接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        //关闭连接
        connection.close();
    }
}

⑷ 第五步:创建实体类(Department,Employee)
- Department/**
 * 部门类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Department {
    private Integer id;
    private String departmentName;
}

- Employee/**
 * 员工类
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    //1 male, 0 female
    private Integer gender;
    private Integer department;
    private Date birth;

    private Department eDepartment; // 冗余设计
}

⑸ 第六步:创建业务实现的接口(创建mapper目录以及对应的 Mapper 接口)
- 员工mapper接口
/**
 *  员工业务接口
 */
//@Mapper : 表示本类是一个 MyBatis 的 Mapper
@Mapper
@Repository
public interface EmployeeMapper {
    // 获取所有员工信息
    List<Employee> getEmployees();

    // 新增一个员工
    int save(Employee employee);

    // 通过id获得员工信息
    Employee get(Integer id);

    // 通过id删除员工
    int delete(Integer id);
}

- 部门mapper接口

/**
 * 部门业务接口
 *
 * @Mapper:这个注解表示了这是一个mybatis的mapper类 UserMapper接口是一个持久
 * 层的接口,因此要注入Spring容器中
 * -->使用@Compont或是@Repository其中一个注解均可
 */
@Mapper
@Repository
public interface DepartmentMapper {
    /**
     * 在接口中定义一个变量,就是一个静态的变量
     *      -->下面是临时扩展的知识点
     *      public static final int a = 10;
     */

    // 获取所有部门信息
    List<Department> getDepartments();

    // 通过id获得部门
    Department getDepartmentById(Integer id);
}

⑹ 第七步:实现业务接口的Mapper映射实现,执行数据库操作
- 员工mapper映射,实现数据库CRUD
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.lzk.mapper.EmployeeMapper">

    <resultMap id="EmployeeMap" type="Employee">
        <id property="id" column="eid"/>
        <result property="lastName" column="last_name"/>
        <result property="email" column="email"/>
        <result property="gender" column="gender"/>
        <result property="birth" column="birth"/>
        <association property="eDepartment"  javaType="Department">
            <id property="id" column="did"/>
            <result property="departmentName" column="dname"/>
        </association>
    </resultMap>

    <select id="getEmployees" resultMap="EmployeeMap">
        select e.id as eid,last_name,email,gender,birth,d.id as did,d.department_name as dname
        from department d,employee e
        where d.id = e.department
    </select>

    <insert id="save" parameterType="Employee">
        insert into employee (last_name,email,gender,department,birth)
        values (#{lastName},#{email},#{gender},#{department},#{birth});
    </insert>

    <select id="get" resultType="Employee">
        select * from employee where id = #{id}
    </select>

    <delete id="delete" parameterType="int">
        delete from employee where id = #{id}
    </delete>
</mapper>

+--------------------------------------------------------+

- 部门mapper映射,实现数据库CRUD
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.lzk.mapper.DepartmentMapper">

    <select id="getDepartments" resultType="Department">
       select * from department;
    </select>

    <select id="getDepartmentById" resultType="Department" parameterType="int">
       select * from department where id = #{id};
    </select>
</mapper>

⑺ 第八步:maven配置资源过滤问题
<resources>    
    <resource>        
    <directory>src/main/java</directory>        
    <includes>            
        <include>**/*.xml</include>        
    </includes>        
    <filtering>true</filtering>    
    </resource>
</resources>

⑻ 第九步:编写部门和员工的Controller 进行测试!
- 编写部门的 DepartmentController

/**
 * 部门Controller
 */
@RestController
public class DepartmentController {
    @Autowired
    DepartmentMapper departmentMapper;

    // 查询全部部门
    @GetMapping("/getDepartments")
    public List<Department> getDepartments(){
        return departmentMapper.getDepartments();
    }

    // 查询全部部门
    @GetMapping("/getDepartment/{id}")
    public Department getDepartmentById(@PathVariable("id") Integer id){
        return departmentMapper.getDepartmentById(id);
    }
}

- 编写员工的EmployeeController
/**
 * 员工Controller
 */
@RestController
public class EmployeeController {

    @Autowired
    EmployeeMapper employeeMapper;

    // 获取所有员工信息
    @GetMapping("/getEmployees")
    public List<Employee> getEmployees(){
        return employeeMapper.getEmployees();
    }

    @GetMapping("/save")
    public int save(){
        Employee employee = new Employee();
        employee.setLastName("linzk");
        employee.setEmail("linzkg@qq.com");
        employee.setGender(1);
        employee.setDepartment(101);
        employee.setBirth(new Date());
        return employeeMapper.save(employee);
    }

    // 通过id获得员工信息
    @GetMapping("/get/{id}")
    public Employee get(@PathVariable("id") Integer id){
        return employeeMapper.get(id);
    }

    // 通过id删除员工
    @GetMapping("/delete/{id}")
    public int delete(@PathVariable("id") Integer id){
        return employeeMapper.delete(id);
    }
}
⑼ 第九步:测试员工和部门的controller,请求访问!!

在这里插入图片描述
图mb1

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值