基于Spring Boot + MyBatis + MySQL的Java开发实战:从搭建到部署

一、开发环境搭建

(一)安装Java开发工具包(JDK)

  1. 下载JDK
    • 访问Oracle官网或其他开源JDK提供商(如OpenJDK)的网站,根据自己的操作系统版本选择合适的JDK版本进行下载。目前,Spring Boot推荐使用JDK 11及以上版本。
    • 以Windows系统为例,下载完成后,运行安装程序,按照提示完成安装。在安装过程中,建议将JDK安装到一个没有空格和特殊字符的路径,例如C:\Java\jdk-11
  2. 配置环境变量
    • 安装完成后,需要配置环境变量,以便在命令行中能够直接使用javajavac命令。
    • 打开系统的环境变量设置(在Windows中可以通过“控制面板”或右键点击“此电脑”选择“属性”来进入),找到“系统变量”中的Path变量,点击“编辑”。
    • 在“编辑环境变量”窗口中,点击“新建”,添加JDK的bin目录路径(例如C:\Java\jdk-11\bin),然后点击“确定”保存。
    • 同时,还需要设置JAVA_HOME环境变量。在“系统变量”中点击“新建”,变量名为JAVA_HOME,变量值为JDK的安装路径(例如C:\Java\jdk-11)。
    • 配置完成后,打开命令行窗口,输入以下命令进行验证:
      java -version
      javac -version
      
      如果配置正确,将显示JDK的版本信息,例如:
      java version "11.0.12" 2021-07-20 LTS
      Java(TM) SE Runtime Environment 18.9 (build 11.0.12+8-LTS-237)
      Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.12+8-LTS-237, mixed mode)
      

(二)安装IntelliJ IDEA

  1. 下载IntelliJ IDEA
    • 访问JetBrains官网,选择“Community”(社区版)或“Ultimate”(专业版)。对于Spring Boot开发,社区版已经足够使用。
    • 根据自己的操作系统选择对应的安装包进行下载。
  2. 安装IntelliJ IDEA
    • 下载完成后,运行安装程序,按照提示完成安装。在安装过程中,可以接受默认设置,也可以根据自己的需求进行自定义配置。
    • 安装完成后,启动IntelliJ IDEA。首次启动时,可以选择“Import Settings”来导入之前的配置,或者直接点击“Do not import settings”开始新的配置。
  3. 配置IntelliJ IDEA
    • 设置JDK:在IntelliJ IDEA中,点击菜单栏的“File” -> “Project Structure”,在弹出的窗口中选择“Project”选项卡,点击“Project SDK”旁边的“New…”,选择刚才安装的JDK路径(例如C:\Java\jdk-11),完成JDK的配置。
    • 安装插件:为了更好地支持Spring Boot和MyBatis开发,建议安装以下插件:
      • Spring Initializr:用于快速生成Spring Boot项目。
      • MyBatis Plugin:提供MyBatis相关的代码提示和语法检查功能。
      • 在IntelliJ IDEA中,点击菜单栏的“File” -> “Settings”(Windows)或“IntelliJ IDEA” -> “Preferences”(Mac),在弹出的窗口中选择“Plugins”,搜索并安装上述插件。

(三)安装MySQL数据库

  1. 下载MySQL
    • 访问MySQL官网,根据自己的操作系统版本选择合适的MySQL版本进行下载。建议选择“MySQL Community Server”版本。
    • 以Windows系统为例,下载完成后,运行安装程序,按照提示完成安装。在安装过程中,可以选择“Developer Default”安装配置,该配置会自动安装MySQL Server、MySQL Workbench等常用组件。
  2. 配置MySQL
    • 安装完成后,启动MySQL服务。在Windows系统中,可以通过“服务”管理工具(在“运行”中输入services.msc)找到“MySQL”服务,右键点击选择“启动”。
    • 使用MySQL Workbench或命令行工具连接到MySQL数据库。默认情况下,MySQL的用户名为root,密码在安装过程中设置。
    • 为了方便开发,建议创建一个专门的数据库和用户。例如,创建一个名为test_db的数据库和一个名为test_user的用户,密码为test_password
      CREATE DATABASE test_db;
      CREATE USER 'test_user'@'localhost' IDENTIFIED BY 'test_password';
      GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'localhost';
      FLUSH PRIVILEGES;
      

二、创建Spring Boot项目

(一)使用Spring Initializr生成项目

  1. 访问Spring Initializr
  2. 配置项目信息
    • 在Spring Initializr页面中,填写以下信息:
      • Project:选择“Maven”(推荐使用Maven作为项目构建工具)。
      • Language:选择“Java”。
      • Spring Boot Version:选择最新的稳定版本(例如2.7.0)。
      • Group:输入项目的包名,例如com.example
      • Artifact:输入项目的名称,例如demo
      • Name:输入项目的显示名称,例如DemoApplication
      • Description:输入项目的描述信息,例如Demo project for Spring Boot
      • Package name:输入项目的包路径,例如com.example.demo
    • 在“Dependencies”部分,添加以下依赖:
      • Spring Web:用于构建基于Spring MVC的Web应用。
      • Spring Boot DevTools:提供热部署功能,方便开发时快速重启应用。
      • MyBatis Framework:集成MyBatis作为持久层框架。
      • MySQL Driver:提供MySQL数据库的驱动支持。
  3. 生成项目
    • 配置完成后,点击“Generate”按钮,下载生成的项目压缩包。
    • 将下载的压缩包解压到本地指定目录。

(二)导入项目到IntelliJ IDEA

  1. 打开IntelliJ IDEA
    • 启动IntelliJ IDEA,点击“Open”按钮,选择刚才解压的项目目录,然后点击“OK”。
  2. 导入项目
    • IntelliJ IDEA会自动识别这是一个Maven项目,并开始导入依赖。在导入过程中,可能会弹出提示框,询问是否启用自动导入功能,建议选择“Enable Auto-Import”。
    • 导入完成后,项目结构如下:
      demo
      ├── src
      │   ├── main
      │   │   ├── java
      │   │   │   └── com.example.demo
      │   │   │       └── DemoApplication.java
      │   │   └── resources
      │   │       └── application.properties
      │   └── test
      │       └── java
      │           └── com.example.demo
      │               └── DemoApplicationTests.java
      └── pom.xml
      

(三)配置项目

  1. 配置application.properties

    • 打开src/main/resources/application.properties文件,添加以下配置信息,用于连接MySQL数据库:
      # 数据库配置
      spring.datasource.url=jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC
      spring.datasource.username=test_user
      spring.datasource.password=test_password
      spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
      
      # MyBatis配置
      mybatis.mapper-locations=classpath:mappers/*.xml
      mybatis.type-aliases-package=com.example.demo.entity
      
      • spring.datasource.url:指定MySQL数据库的连接URL,其中test_db是数据库名称,localhost:3306是数据库服务器地址和端口。
      • spring.datasource.usernamespring.datasource.password:指定数据库的用户名和密码。
      • mybatis.mapper-locations:指定MyBatis的Mapper文件存放路径。
      • mybatis.type-aliases-package:指定MyBatis的实体类存放路径。
  2. 配置pom.xml

    • 打开pom.xml文件,确认已经添加了以下依赖:
      <!-- Spring Boot Starter Web -->
      
       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      
      <!-- Spring Boot DevTools -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
          <scope>runtime</scope>
          <optional>true</optional>
      </dependency>
      
      <!-- MyBatis Starter -->
      <dependency>
          <groupId>org.mybatis.spring.boot</groupId>
          <artifactId>mybatis-spring-boot-starter</artifactId>
          <version>2.2.0</version>
      </dependency>
      
      <!-- MySQL Driver -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <scope>runtime</scope>
      </dependency>
      
      • 如果版本号与生成项目时的版本不一致,可以根据实际情况进行调整。

三、设计数据库

(一)创建数据库表

  1. 设计表结构
    • 假设我们要开发一个简单的用户管理系统,需要一个user表来存储用户信息。表结构如下:
      • id:主键,自增。
      • username:用户名,字符串类型,唯一。
      • password:密码,字符串类型。
      • email:邮箱,字符串类型。
      • created_at:创建时间,时间戳类型。
      • updated_at:更新时间,时间戳类型。
  2. 创建表
    • 使用MySQL Workbench或命令行工具,执行以下SQL语句创建user表:
      CREATE TABLE user (
          id INT AUTO_INCREMENT PRIMARY KEY,
          username VARCHAR(50) NOT NULL UNIQUE,
          password VARCHAR(100) NOT NULL,
          email VARCHAR(100),
          created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
          updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
      );
      

(二)插入测试数据

  1. 插入数据
    • 为了方便测试,可以插入一些测试数据。执行以下SQL语句:
      INSERT INTO user (username, password, email) VALUES
      ('user1', 'password1', 'user1@example.com'),
      ('user2', 'password2', 'user2@example.com'),
      ('user3', 'password3', 'user3@example.com');
      

四、开发应用

(一)创建实体类

  1. 创建User类
    • src/main/java/com/example/demo/entity目录下创建User.java文件,内容如下:
      package com.example.demo.entity;
      
      import java.util.Date;
      
      public class User {
          private Integer id;
          private String username;
          private String password;
          private String email;
          private Date createdAt;
          private Date updatedAt;
      
          // Getters and Setters
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public String getUsername() {
              return username;
          }
      
          public void setUsername(String username) {
              this.username = username;
          }
      
          public String getPassword() {
              return password;
          }
      
          public void setPassword(String password) {
              this.password = password;
          }
      
          public String getEmail() {
              return email;
          }
      
          public void setEmail(String email) {
              this.email = email;
          }
      
          public Date getCreatedAt() {
              return createdAt;
          }
      
          public void setCreatedAt(Date createdAt) {
              this.createdAt = createdAt;
          }
      
          public Date getUpdatedAt() {
              return updatedAt;
          }
      
          public void setUpdatedAt(Date updatedAt) {
              this.updatedAt = updatedAt;
          }
      }
      
      • 这个类对应数据库中的user表,每个字段对应表中的一个列。

(二)创建Mapper接口

  1. 创建UserMapper接口
    • src/main/java/com/example/demo/mapper目录下创建UserMapper.java文件,内容如下:
      package com.example.demo.mapper;
      
      import com.example.demo.entity.User;
      import org.apache.ibatis.annotations.Mapper;
      import org.apache.ibatis.annotations.Select;
      
      import java.util.List;
      
      @Mapper
      public interface UserMapper {
          @Select("SELECT * FROM user")
          List<User> findAll();
      
          User findById(Integer id);
      
          int insert(User user);
      
          int update(User user);
      
          int deleteById(Integer id);
      }
      
      • 使用MyBatis的@Mapper注解标记这是一个Mapper接口。
      • 使用@Select注解定义了一个查询所有用户的方法findAll
      • 其他方法(findByIdinsertupdatedeleteById)将在后续通过XML文件定义SQL语句。

(三)创建Mapper XML文件

  1. 创建UserMapper.xml
    • src/main/resources/mappers目录下创建UserMapper.xml文件,内容如下:
      <?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.example.demo.mapper.UserMapper">
          <select id="findById" parameterType="int" resultType="com.example.demo.entity.User">
              SELECT * FROM user WHERE id = #{id}
          </select>
      
          <insert id="insert" parameterType="com.example.demo.entity.User">
              INSERT INTO user (username, password, email) VALUES (#{username}, #{password}, #{email})
          </insert>
      
          <update id="update" parameterType="com.example.demo.entity.User">
              UPDATE user SET username = #{username}, password = #{password}, email = #{email} WHERE id = #{id}
          </update>
      
          <delete id="deleteById" parameterType="int">
              DELETE FROM user WHERE id = #{id}
          </delete>
      </mapper>
      
      • <mapper>标签中,namespace属性值为UserMapper接口的全限定名。
      • 定义了findByIdinsertupdatedeleteById四个方法的SQL语句。

(四)创建Service层

  1. 创建UserService接口

    • src/main/java/com/example/demo/service目录下创建UserService.java文件,内容如下:
      package com.example.demo.service;
      
      import com.example.demo.entity.User;
      
      import java.util.List;
      
      public interface UserService {
          List<User> findAll();
      
          User findById(Integer id);
      
          User save(User user);
      
          User update(User user);
      
          void deleteById(Integer id);
      }
      
      • 定义了用户相关的业务方法。
  2. 创建UserServiceImpl类

    • src/main/java/com/example/demo/service/impl目录下创建UserServiceImpl.java文件,内容如下:
      package com.example.demo.service.impl;
      
      import com.example.demo.entity.User;
      import com.example.demo.mapper.UserMapper;
      import com.example.demo.service.UserService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      import java.util.List;
      
      @Service
      public class UserServiceImpl implements UserService {
          @Autowired
          private UserMapper userMapper;
      
          @Override
          public List<User> findAll() {
              return userMapper.findAll();
          }
      
          @Override
          public User findById(Integer id) {
              return userMapper.findById(id);
          }
      
          @Override
          public User save(User user) {
              userMapper.insert(user);
              return user;
          }
      
          @Override
          public User update(User user) {
              userMapper.update(user);
              return user;
          }
      
          @Override
          public void deleteById(Integer id) {
              userMapper.deleteById(id);
          }
      }
      
      • 使用@Service注解标记这是一个Service类。
      • 通过@Autowired注解注入UserMapper接口。
      • 实现了UserService接口中的所有方法,调用了Mapper层的方法来操作数据库。

(五)创建Controller层

  1. 创建UserController类
    • src/main/java/com/example/demo/controller目录下创建UserController.java文件,内容如下:
      package com.example.demo.controller;
      
      import com.example.demo.entity.User;
      import com.example.demo.service.UserService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.*;
      
      import java.util.List;
      
      @RestController
      @RequestMapping("/users")
      public class UserController {
          @Autowired
          private UserService userService;
      
          @GetMapping
          public List<User> getAllUsers() {
              return userService.findAll();
          }
      
          @GetMapping("/{id}")
          public User getUserById(@PathVariable Integer id) {
              return userService.findById(id);
          }
      
          @PostMapping
          public User createUser(@RequestBody User user) {
              return userService.save(user);
          }
      
          @PutMapping("/{id}")
          public User updateUser(@PathVariable Integer id, @RequestBody User user) {
              user.setId(id);
              return userService.update(user);
          }
      
          @DeleteMapping("/{id}")
          public void deleteUser(@PathVariable Integer id) {
              userService.deleteById(id);
          }
      }
      
  • 使用@RestController注解标记这是一个Controller类。
    • 使用@RequestMapping("/users")注解定义了Controller的根路径。
    • 定义了五个方法,分别对应CRUD操作:
      • getAllUsers:获取所有用户。
      • getUserById:根据ID获取用户。
      • createUser:创建新用户。
      • updateUser:更新用户信息。
      • deleteUser:删除用户。
    • 使用@Autowired注解注入UserService接口。
    • 使用@RequestBody注解接收JSON格式的请求体,并将其转换为User对象。
    • 使用@PathVariable注解获取路径中的参数。

五、运行和测试应用

(一)运行应用

  1. 启动应用
    • 在IntelliJ IDEA中,点击DemoApplication.java文件中的main方法旁边的“运行”按钮,或者在终端中运行以下命令:
      mvn spring-boot:run
      
    • 应用启动后,控制台会输出日志信息,表示应用已经成功启动。默认情况下,应用会运行在http://localhost:8080

(二)测试接口

  1. 使用Postman测试
    • 打开Postman,创建以下请求进行测试:
      • 获取所有用户
        • 请求类型:GET
        • 请求地址:http://localhost:8080/users
        • 预期响应:返回一个包含所有用户信息的JSON数组。
      • 根据ID获取用户
        • 请求类型:GET
        • 请求地址:http://localhost:8080/users/1(假设用户ID为1)
        • 预期响应:返回一个用户对象的JSON数据。
      • 创建新用户
        • 请求类型:POST
        • 请求地址:http://localhost:8080/users
        • 请求体(JSON格式):
          {
              "username": "newuser",
              "password": "newpassword",
              "email": "newuser@example.com"
          }
          
        • 预期响应:返回创建的用户对象的JSON数据。
      • 更新用户信息
        • 请求类型:PUT
        • 请求地址:http://localhost:8080/users/1(假设用户ID为1)
        • 请求体(JSON格式):
          {
              "username": "updateduser",
              "password": "updatedpassword",
              "email": "updateduser@example.com"
          }
          
        • 预期响应:返回更新后的用户对象的JSON数据。
      • 删除用户
        • 请求类型:DELETE
        • 请求地址:http://localhost:8080/users/1(假设用户ID为1)
        • 预期响应:无返回数据,用户被删除。
  2. 使用浏览器测试
    • 打开浏览器,访问http://localhost:8080/users,可以直接查看返回的JSON数据。

六、优化和扩展

(一)添加日志功能

  1. 配置日志

    • application.properties文件中添加以下配置:
      # 日志配置
      logging.level.root=INFO
      logging.level.org.springframework=DEBUG
      logging.level.com.example.demo=DEBUG
      
      • logging.level.root:设置全局日志级别为INFO
      • logging.level.org.springframework:设置Spring框架的日志级别为DEBUG
      • logging.level.com.example.demo:设置项目包的日志级别为DEBUG
  2. 使用日志工具

    • 在代码中,可以通过org.slf4j.Loggerorg.slf4j.LoggerFactory来记录日志。例如,在UserServiceImpl类中添加日志记录:
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      @Service
      public class UserServiceImpl implements UserService {
          private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
      
          @Override
          public List<User> findAll() {
              logger.info("Finding all users");
              return userMapper.findAll();
          }
      
          @Override
          public User findById(Integer id) {
              logger.info("Finding user by id: {}", id);
              return userMapper.findById(id);
          }
      
          @Override
          public User save(User user) {
              logger.info("Saving user: {}", user);
              userMapper.insert(user);
              return user;
          }
      
          @Override
          public User update(User user) {
              logger.info("Updating user: {}", user);
              userMapper.update(user);
              return user;
          }
      
          @Override
          public void deleteById(Integer id) {
              logger.info("Deleting user by id: {}", id);
              userMapper.deleteById(id);
          }
      }
      

(二)添加异常处理

  1. 创建全局异常处理器
    • src/main/java/com/example/demo/controller目录下创建GlobalExceptionHandler.java文件,内容如下:
      package com.example.demo.controller;
      
      import org.springframework.http.HttpStatus;
      import org.springframework.web.bind.annotation.ControllerAdvice;
      import org.springframework.web.bind.annotation.ExceptionHandler;
      import org.springframework.web.bind.annotation.ResponseBody;
      import org.springframework.web.bind.annotation.ResponseStatus;
      
      import java.util.HashMap;
      import java.util.Map;
      
      @ControllerAdvice
      public class GlobalExceptionHandler {
          @ExceptionHandler(Exception.class)
          @ResponseBody
          @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
          public Map<String, String> handleException(Exception e) {
              Map<String, String> error = new HashMap<>();
              error.put("error", "Internal Server Error");
              error.put("message", e.getMessage());
              return error;
          }
      
          @ExceptionHandler(RuntimeException.class)
          @ResponseBody
          @ResponseStatus(HttpStatus.BAD_REQUEST)
          public Map<String, String> handleRuntimeException(RuntimeException e) {
              Map<String, String> error = new HashMap<>();
              error.put("error", "Bad Request");
              error.put("message", e.getMessage());
              return error;
          }
      }
      
      • 使用@ControllerAdvice注解标记这是一个全局异常处理器。
      • 定义了两个异常处理方法:
        • handleException:处理所有Exception类型的异常,返回500 Internal Server Error状态码。
        • handleRuntimeException:处理所有RuntimeException类型的异常,返回400 Bad Request状态码。
      • 每个方法返回一个包含错误信息的JSON对象。

(三)添加分页功能

  1. 修改Mapper接口

    • UserMapper接口中添加分页查询方法:
      List<User> findByPage(@Param("offset") int offset, @Param("limit") int limit);
      
      • UserMapper.xml文件中添加对应的SQL语句:
        <select id="findByPage" parameterType="map" resultType="com.example.demo.entity.User">
            SELECT * FROM user LIMIT #{offset}, #{limit}
        </select>
        
  2. 修改Service层

    • UserService接口中添加分页查询方法:
      List<User> findByPage(int page, int size);
      
      • UserServiceImpl类中实现该方法:
        @Override
        public List<User> findByPage(int page, int size) {
            int offset = (page - 1) * size;
            return userMapper.findByPage(offset, size);
        }
        
  3. 修改Controller层

    • UserController类中添加分页查询接口:
      @GetMapping("/page")
      public List<User> getUsersByPage(@RequestParam int page, @RequestParam int size) {
          return userService.findByPage(page, size);
      }
      

(四)添加数据校验

  1. 添加校验注解

    • User类中添加校验注解:
      package com.example.demo.entity;
      
      import javax.validation.constraints.Email;
      import javax.validation.constraints.NotBlank;
      import javax.validation.constraints.Size;
      
      public class User {
          private Integer id;
      
          @NotBlank(message = "Username cannot be blank")
          @Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
          private String username;
      
          @NotBlank(message = "Password cannot be blank")
          @Size(min = 6, max = 100, message = "Password must be between 6 and 100 characters")
          private String password;
      
          @Email(message = "Invalid email format")
          private String email;
      
          // Getters and Setters
      }
      
  2. 在Controller层启用校验

    • UserController类中,使用@Valid注解启用校验:
      @PostMapping
      public User createUser(@Valid @RequestBody User user) {
          return userService.save(user);
      }
      
      @PutMapping("/{id}")
      public User updateUser(@PathVariable Integer id, @Valid @RequestBody User user) {
          user.setId(id);
          return userService.update(user);
      }
      
  3. 处理校验失败

    • GlobalExceptionHandler类中添加校验失败的处理方法:
      @ExceptionHandler(MethodArgumentNotValidException.class)
      @ResponseBody
      @ResponseStatus(HttpStatus.BAD_REQUEST)
      public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) {
          Map<String, String> errors = new HashMap<>();
          ex.getBindingResult().getAllErrors().forEach((error) -> {
              String fieldName = ((FieldError) error).getField();
              String errorMessage = error.getDefaultMessage();
              errors.put(fieldName, errorMessage);
          });
          return errors;
      }
      

七、部署应用

(一)打包应用

  1. 使用Maven打包
    • 在项目根目录下运行以下命令:
      mvn clean package
      
    • 打包完成后,会在target目录下生成一个demo-0.0.1-SNAPSHOT.jar文件(版本号根据实际情况可能不同)。

(二)运行打包后的应用

  1. 运行JAR文件
    • 在终端中运行以下命令:
      java -jar target/demo-0.0.1-SNAPSHOT.jar
      
    • 应用启动后,可以通过浏览器或Postman访问接口进行测试。

(三)部署到服务器

  1. 上传JAR文件
    • 将打包后的JAR文件上传到服务器的指定目录。
  2. 在服务器上运行
    • 在服务器上运行以下命令启动应用:
      nohup java -jar demo-0.0.1-SNAPSHOT.jar > app.log 2>&1 &
      
    • 使用nohup命令可以让应用在后台运行,并将日志输出到app.log文件中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值