SpringBoot入门实战(项目搭建、配置、功能接口实现等一篇通关)

🤟致敬读者

  • 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉

📘博主相关



📃文章前言

  • 🔷文章均为学习工作中整理的笔记。
  • 🔶如有错误请指正,共同学习进步。

SpringBoot入门实战(项目搭建、配置、功能接口实现等一篇通关)

SpringBoot入门实战系列篇专栏
SpringBoot入门实战(第一篇:环境准备和项目初始化)
SpringBoot入门实战(第二篇:MySQL集成配置)
SpringBoot入门实战(第三篇:MyBatis集成配置,自动生成代码配置)
SpringBoot入门实战(第四篇:Redis集成配置)
SpringBoot入门实战(第五篇:项目接口-用户管理)
SpringBoot入门实战(第六篇:项目接口-登录)
SpringBoot入门实战(第七篇:项目接口-商品管理)
SpringBoot入门实战(第八篇:项目接口-订单管理)完结篇
SpringBoot入门实战(项目搭建、配置、功能接口实现等一篇通关)


1. 环境准备


2. 项目创建和初始化

使用IDEA开发工具创建spring boot项目

2.1 创建项目

打开idea社区版
左上角菜单栏打开,选择FileNewProject...
在这里插入图片描述

创建界面如下(默认打开的界面)
在这里插入图片描述

按照顺序定义或者修改配置参数

  • 1 新建项目类型 默认Java
  • 2 项目名称(Name) 默认untitled 自定义为sb_demo
  • 3-4 项目位置(Location) 自定义项目位置,下方一行提示信息中会有创建后的项目路径
  • 5 构建系统(Build system) 默认Maven,如果不是,则选择Maven
  • 6 Java JDK选择(JDK) 选择自己安装的JDK版本,这里选择的是1.8版本
  • 7 新增示例代码(Add sample code) 默认不勾选,这里无需示例代码
  • 8 项目组织架构(Advanced Settings)
    GroupId默认org.example这里自定义为com.xh
    ArtifactId默认项目名称,这里无需修改
  • 9 最后选择Create创建项目

参数配置后如下
在这里插入图片描述创建后的项目界面如下
在这里插入图片描述

2.2 项目依赖配置

配置spring boot相关依赖,这里直接配置三个依赖,分别对应spring boot的依赖、lombok依赖、fastjson依赖。

注1:lombok依赖通过注解方式简化样板代码的编写,可自动生成getter、setter、构造函数、toString等方法
注2:fastjson依赖是为了实现Java对象和json格式字符转之间的相互转换

在pom.xml中配置如下代码

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.7.18</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

配置后的完整代码
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xh</groupId>
    <artifactId>sb_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.7.18</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

    </dependencies>

</project>

配置依赖后不要忘了右上角maven刷新按钮点一下
如图
在这里插入图片描述

2.3 项目包结构预设

提前创建项目的包结构,这里简单创建几个常用包,后续有需要可继续新建包
打开src/main/java包,在Java包下创建如下包

com.xh.user
com.xh.product
com.xh.analystic

创建后如下
在这里插入图片描述

2.4 项目启动类创建

在com.xh包下创建启动类
SbApplication.java

package com.xh;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @func: 项目启动类
 * @author: LiBai
 * @version: v1.0
 * @createTime: 2025/4/10 10:45
 */
@SpringBootApplication
public class SbApplication {

    public static void main(String[] args) {
        SpringApplication.run(SbApplication.class, args);
    }

}

2.5 启动项目

鼠标选中启动类文件右键选择Run’SbApplication()'执行项目
在这里插入图片描述

如下,表示项目正常启动,一切配位配置的参数都为默认,如默认端口8080
在这里插入图片描述


3. 配置文件(application.yml)

src/main/resources包下创建文件application.yml(右键NewFile,然后填写文件名,带后缀)
在这里插入图片描述

在application.yml中配置端口号如下

server:
  port: 8088

配置后重启服务,右上角有启动类名和绿色启动按钮,现在项目正在运行,直接点击可重启
在这里插入图片描述

服务端口即变为8088
如下
在这里插入图片描述


4. 数据库MySQL集成

4.1 依赖引入

pom.xml中引入所需依赖

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <version>2.7.18</version>
        </dependency>

引入后重新加载依赖
完整pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xh</groupId>
    <artifactId>sb_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.7.18</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <version>2.7.18</version>
        </dependency>

    </dependencies>

</project>

4.2 参数配置

在配置文件application.yml中配置MySQL连接参数
localhost是本机地址,也可换成远程IP地址
3306是端口号,根据自己mysql服务配置
sb_demo是数据库名称,根据自己数据名称配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/sb_demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 1234

完整application.yml

server:
  port: 8088

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/sb_demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 1234

5. 数据库框架MyBatis集成(自动生成代码配置)

5.1 依赖引入

引入相关依赖和插件
依赖部分

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

插件部分

	 <build>
        <finalName>app</finalName>
        <plugins>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
<!--                <version>2.3.4.RELEASE</version>-->
            </plugin>

            <!--添加mybatis generator maven插件-->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.7</version>
                <configuration>
                    <!--generatorConfig.xml位置-->
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                    <verbose>true</verbose>
                    <!--                    如果本来就有mapper、dao文件了就覆盖-->
                    <overwrite>true</overwrite>
                </configuration>

                <executions>
                    <execution>
                        <id>Generate MyBatis Artifacts</id>
                        <phase>deploy</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <!--此处必须添加mysql驱动包-->
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <scope>runtime</scope>
                        <version>8.0.31</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.csv</include>
                    <include>**/*.yml</include>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                    <include>**/*.json</include>
                    <include>**/*.js</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.csv</include>
                    <include>**/*.yml</include>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                    <include>**/*.json</include>
                    <include>**/*.js</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>

    </build>

引入后完整pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xh</groupId>
    <artifactId>sb_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.7.18</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <version>2.7.18</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
<!--            <version>1.3.2</version>-->
        </dependency>
        



    </dependencies>


    <build>
        <finalName>app</finalName>
        <plugins>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
<!--                <version>2.3.4.RELEASE</version>-->
            </plugin>

            <!--添加mybatis generator maven插件-->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.7</version>
                <configuration>
                    <!--generatorConfig.xml位置-->
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                    <verbose>true</verbose>
                    <!--                    如果本来就有mapper、dao文件了就覆盖-->
                    <overwrite>true</overwrite>
                </configuration>

                <executions>
                    <execution>
                        <id>Generate MyBatis Artifacts</id>
                        <phase>deploy</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <!--此处必须添加mysql驱动包-->
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <scope>runtime</scope>
                        <version>8.0.31</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.csv</include>
                    <include>**/*.yml</include>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                    <include>**/*.json</include>
                    <include>**/*.js</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.csv</include>
                    <include>**/*.yml</include>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                    <include>**/*.json</include>
                    <include>**/*.js</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>

    </build>


</project>

5.2 代码生成配置(generatorConfig.xml)

自动生成代码的配置文件在resources包下创建generatorConfig.xml
内容如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>

    <properties resource="jdbc.properties"/>

    <context id="sqlserverTables" targetRuntime="MyBatis3">

        <!-- 生成的pojo,将implements Serializable-->
        <plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>

        <!--替换默认生成的dao-Example-->
        <plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">
            <property name="searchString" value="Example$" />
            <property name="replaceString" value="Impl" />
        </plugin>

        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!-- 数据库链接URL、用户名、密码 -->
        <jdbcConnection driverClass="${spring.datasource.driverClassName}"
                        connectionURL="${spring.datasource.url}"
                        userId="${spring.datasource.username}"
                        password="${spring.datasource.password}">
        </jdbcConnection>

        <!--默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer-->
        <!--true,把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal-->

        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>


        <!--生成model模型,对应的包路径,以及文件存放路径(targetProject),targetProject可以指定具体的路径,如./src/main/java,-->
        <!--也可以使用“MAVEN”来自动生成,这样生成的代码会在target/generatord-source目录下-->
        <!--<javaModelGenerator targetPackage="com.joey.mybaties.test.pojo" targetProject="MAVEN">-->
        <!--<javaModelGenerator targetPackage="${daopackage}" targetProject="./src/main/java">-->

        <javaModelGenerator targetPackage="${daopackage}" targetProject="./src/main/java">
            <property name="enableSubPackages" value="true"/>
            <!-- 从数据库返回的值被清理前后的空格  -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!--对应的mapper.xml文件  -->
        <sqlMapGenerator targetPackage="${daopackage}" targetProject="./src/main/java">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>

        <!-- 对应的Mapper接口类文件 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="${daopackage}" targetProject="./src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>

        <table tableName="${tableName}"
               enableCountByExample="false"
               enableUpdateByExample="true"
               enableDeleteByExample="true"
               enableSelectByExample="true"
               selectByExampleQueryId="false">
            <property name="useActualColumnNames" value="false"/>
        </table>

    </context>
</generatorConfiguration>

5.3 数据库配置文件jdbc.properties

resources包下创建文件jdbc.properties

spring.datasource.driverLocation=mysql-connector-java-8.0.21.jar
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/sb_demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=1234

daopackage = com.user.dao
tableName = tb_user

其中daopackage是生成代码后存储的位置
tableName是表名

5.4 建表

在MySQL表中新建用户表tb_user
建表语句

CREATE TABLE tb_user(
	id INT AUTO_INCREMENT PRIMARY KEY,
	username VARCHAR(255) NOT NULL COMMENT "密码",
	pass_word VARCHAR(255) NOT NULL COMMENT "账号",
	gender VARCHAR(255) NOT NULL COMMENT "性别",
	address VARCHAR(255) NOT NULL COMMENT "地址",
	p_number VARCHAR(255) NOT NULL COMMENT "手机号",
	vip_class INT DEFAULT 0 COMMENT "vip等级,共4级,0-1-2-3"
);

执行后建表完成

5.5 生成代码

修改jdbc.properties中的daopackage和tableName,然后到IDEA工具找到Maven工具窗口,一般在右侧
打开sb_demo—Plugins—mybatis-generator—mybatis-generator:generate,如下(双击即可)
在这里插入图片描述

生成成功的控制台界面
在这里插入图片描述

或者在终端窗口(Terminal)使用maven命令

mvn mybatis-generator:generate

在这里插入图片描述

生成的代码文件如下
在这里插入图片描述

5.6 添加注解

分别对TbUser.java、TbUserImpl.java、TbUserMapper.interface添加注解
TbUser.java添加@Component注解
在这里插入图片描述

TbUserImpl.java添加@Service注解
在这里插入图片描述

TbUserMapper.interface添加@Mapper注解
在这里插入图片描述

完成以上即可进行数据库表相关操作的代码编写

5.7 调用测试

代码编写:
编写接口进行数据添加
在user包下创建controller包,并在controller包下新建Java代码
代码如下

package com.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.user.dao.TbUser;
import com.user.dao.TbUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @func:
 * @author: LiBai
 * @version: v1.0
 * @createTime: 2025/4/16 15:36
 */
@RestController
@RequestMapping(value = "/xh/v1/user")
public class UserAddTest {

    @Autowired
    TbUserMapper tbUserMapper;
    
    
    @PostMapping(value = "/addUser")
    public JSONObject addUser(@RequestBody JSONObject requestBody){
        System.out.println("add user info ----> ");
        TbUser tbUser = new TbUser();
        tbUser.setUsername(requestBody.getString("username"));
        tbUser.setPassWord(requestBody.getString("passWord"));
        tbUser.setGender(requestBody.getString("gender"));
        tbUser.setAddress(requestBody.getString("address"));
        tbUser.setpNumber(requestBody.getString("pNumber"));
        tbUser.setVipClass(requestBody.getInteger("vipClass"));
        
        tbUserMapper.insert(tbUser);
        
        return requestBody;
    }

}

接口调用:
postman调用接口
URL地址

127.0.0.1:8088/xh/v1/user/addUser

请求体内容

{
	"username":"libai",
    "passWord":"352894",
    "gender":"男",
    "address":"上海市浦东新区",
    "pNumber":"13122993366",
    "vipClass":2
}

如下(postman中截图)
在这里插入图片描述

数据查看:
在mysql表中查看数据是否成功添加
在这里插入图片描述

mysql可用,生成代码可用


6. 数据库Redis集成

6.1 依赖引入(pom.xml)

所需依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.7.18</version>
        </dependency>

6.2 参数配置(application.yml)

配置文件中配置redis相关参数
application.yml

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: xh.1234
    database: 0
    jedis:
      pool:
        max-idle: 8
        min-idle: 1
        max-active: 8
        max-wait: -1
    timeout: 20000

6.3 配置类(RedisConfig.java)

在com.xh.common.config包下创建redis配置类RedisConfig.java

package com.xh.common.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @func:
 * @author: LiBai
 * @version: v1.0
 * @createTime: 2025/4/17 9:47
 */
@Configuration
public class RedisConfig {

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){

        RedisTemplate<String, Object> template = new RedisTemplate<>();

        template.setConnectionFactory(connectionFactory);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        template.setKeySerializer(stringRedisSerializer);

        template.setValueSerializer(stringRedisSerializer);

        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

        template.setHashKeySerializer(stringRedisSerializer);

        template.setHashValueSerializer(genericJackson2JsonRedisSerializer);

        template.afterPropertiesSet();

        return template;
    }
}

6.4 工具类(RedisUtils.java)

在com.xh.common.utils包下创建Redis工具类RedisUtils.java

package com.xh.common.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @func:
 * @author: LiBai
 * @version: v1.0
 * @createTime: 2025/4/17 9:46
 */
@Component
public class RedisUtils {

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    public static RedisTemplate<String, Object> _redisTemplate;

    @PostConstruct
    public void init(){
        _redisTemplate = redisTemplate;
    }

    // =============================common============================

    /** 设置失效时间 */
    public static void setexpire(String key, long time) {
        _redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    /** 获取过期时间 */
    public static long getexpire(String key) {
        return _redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /** 判断key是否存在 */
    public static boolean haskey(String key) {
        return _redisTemplate.hasKey(key);
    }

    /** 查询key */
    public static Set<String> search(String keyword){
        return _redisTemplate.keys(keyword);
    }

    /** 删除key */
    @SuppressWarnings("unchecked")
    public static void delete(String... key) {
        if (key.length == 1) {
            _redisTemplate.delete(key[0]);
        } else {
            _redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
        }
    }

    // =============================String============================

    /** 获取普通类型缓存 */
    public static Object get(String key) {
        return key == null ? null : _redisTemplate.opsForValue().get(key);
    }

    /** 设置普通类型缓存 */
    public static void set(String key, Object value) {
        _redisTemplate.opsForValue().set(key, value);
    }

    /** 设置普通类型缓存 带失效时间*/
    public static void set(String key, Object value, long time) {
        _redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    // =============================Hash==============================

    /** 从hashmap中返回键位item的值 */
    public static Object hget(String key, String item) {
        return _redisTemplate.opsForHash().get(key, item);
    }

    /** 向hashmap写入一个键值对 */
    public static void hset(String key, String item, Object value) {
        _redisTemplate.opsForHash().put(key, item, value);
    }

    /** 从hashmap中删除名为item的key */
    public static void hremove(String key, Object... item) {
        _redisTemplate.opsForHash().delete(key, item);
    }

    /** 判断hashmap里面是否包含item的key */
    public static boolean hhasitem(String key, String item) {
        return _redisTemplate.opsForHash().hasKey(key, item);
    }

    /** 一次性从hashmap中返回所有的键值对 */
    public static Map<Object, Object> hmget(String key) {
        return _redisTemplate.opsForHash().entries(key);
    }

    /** 向hashmap写入多个个键值对 */
    public static void hmset(String key, Map<String, Object> map) {
        _redisTemplate.opsForHash().putAll(key, map);
    }

    // =============================List==============================

    /** 返回一个list的长度 */
    public static long lgetsize(String key) {
        return _redisTemplate.opsForList().size(key);
    }

    /** 返回一个list 给定开始index和结束index */
    public static List<Object> lget(String key, long start, long end) {
        return _redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * jwh-20241022-获取列表第一个元素并从redis中移除
     * @param key redis数据的键
     * @return 返回移除的数据
     */
    public static Object lGetPop(String key) {
        return _redisTemplate.opsForList().leftPop(key);
    }

    /** 通过索引index获取list中的值 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素 */
    public static Object lgetindex(String key, long index) {
        return _redisTemplate.opsForList().index(key, index);
    }

    /** 将list放入缓存 */
    public static void lset(String key, Object value) {
        _redisTemplate.opsForList().rightPush(key, value);
    }

    /** 将list放入缓存 */
    public static void lset(String key, List<Object> value) {
        _redisTemplate.opsForList().rightPushAll(key, value);
    }

    /** 根据索引修改list中的某条数据 */
    public static void lupdateindex(String key, long index, Object value) {
        _redisTemplate.opsForList().set(key, index, value);
    }

    /** 移除N个值为value */
    public static long lRemove(String key, long count, Object value) {
        return _redisTemplate.opsForList().remove(key, count, value);
    }

    // =============================Set===============================

    /** 获取set的长度 */
    public static long sgetsetsize(String key) {
        return _redisTemplate.opsForSet().size(key);
    }

    /** 获取set中的全部元素 */
    public static Set<Object> sget(String key) {
        return _redisTemplate.opsForSet().members(key);
    }

    /** 判断set中是否包含value */
    public static boolean shaskey(String key, Object value) {
        return _redisTemplate.opsForSet().isMember(key, value);
    }

    /** set中添加对象*/
    public static long sset(String key, Object... values) {
        return _redisTemplate.opsForSet().add(key, values);
    }

    /** 删除set中的values元素*/
    public static long sremove(String key, Object... values) {
        return _redisTemplate.opsForSet().remove(key, values);
    }

}

6.5 接口代码

创建接口,新增数据到redis中,以存储字符串类型数据为例
com.xh.user.controller包下创建RedisTest.java

package com.xh.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.xh.common.utils.RedisUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @func:
 * @author: LiBai
 * @version: v1.0
 * @createTime: 2025/4/17 9:59
 */
@RestController
@RequestMapping(value = "/xh/v1/redis")
public class RedisTest {

    @RequestMapping(value = "/strAdd")
    public JSONObject strAdd(){

        RedisUtils.set("RedisTest001","this is a test for redis util");
        System.out.println("this is a test for redis util");

        return null;
    }
}

6.6 调用测试

请求地址

127.0.0.1:8088/xh/v1/redis/strAdd

请求参数为空
在这里插入图片描述

调用后并查看redis客户端
在这里插入图片描述
可以看到数据已存入,其余方法类似

以上就是spring boot集成redis内容


7. 项目接口

完成以上配置集成,可进行项目接口编写

7.1 用户管理接口

在com.xh.user.controller包下创建用户管理类UserInfoController.java

7.1.1 UserInfoController.java

UserInfoController.java代码

package com.xh.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.xh.user.dao.TbUser;
import com.xh.user.dao.TbUserImpl;
import com.xh.user.dao.TbUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @func:
 * @author: LiBai
 * @version: v1.0
 * @createTime: 2025/4/17 10:53
 */
@CrossOrigin
@RestController
@RequestMapping(value = "/xh/v1/user")
public class UserInfoController {

    @Autowired
    TbUserMapper tbUserMapper;

    @RequestMapping(value = "/addUserInfo")
    public JSONObject addUserInfo(@RequestBody JSONObject requestBody){

        TbUser tbUser = JSONObject.parseObject(requestBody.toJSONString(), TbUser.class);
        tbUserMapper.insert(tbUser);

        JSONObject result = new JSONObject();
        result.put("code", 200);
        result.put("data", requestBody);
        result.put("msg", "新增用户数据");

        return result;
    }
    @GetMapping(value = "/readUserInfo")
    public JSONObject readUserInfo(){

        TbUserImpl tbUserImpl = new TbUserImpl();
        List<TbUser> tbUsers = tbUserMapper.selectByExample(tbUserImpl);
        JSONObject result = new JSONObject();
        if (!tbUsers.isEmpty()){
            result.put("code", 200);
            result.put("data", tbUsers);
            result.put("msg", "查询所有用户数据");
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "数据为空");
        }

        return result;
    }
    @PutMapping(value = "/changeUserInfo")
    public JSONObject changeUserInfo(@RequestBody JSONObject requestBody){

        String username = requestBody.getString("username");
        TbUserImpl tbUserImpl = new TbUserImpl();
        TbUserImpl.Criteria criteria = tbUserImpl.createCriteria();
        criteria.andUsernameEqualTo(username);
        List<TbUser> tbUsers = tbUserMapper.selectByExample(tbUserImpl);
        JSONObject result = new JSONObject();
        if (!tbUsers.isEmpty()){
            // 这里使用updateByExampleSelective
            // 不能使用updateByExample,不然必须要含有id参数才能插入成功
            tbUserMapper.updateByExampleSelective(JSONObject.parseObject(requestBody.toJSONString(),TbUser.class), tbUserImpl);
            result.put("code", 200);
            result.put("data", requestBody);
            result.put("msg", "修改用户数据");
            return result;
        }else {
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "修改用户数据失败,未找到对应数据");
            return result;
        }

    }
    @DeleteMapping(value = "/removeUserInfo")
    public JSONObject removeUserInfo(@RequestBody JSONObject requestBody){
        String username = requestBody.getString("username");
        TbUserImpl tbUserImpl = new TbUserImpl();
        TbUserImpl.Criteria criteria = tbUserImpl.createCriteria();
        criteria.andUsernameEqualTo(username);
        List<TbUser> tbUsers = tbUserMapper.selectByExample(tbUserImpl);
        JSONObject result = new JSONObject();
        if (!tbUsers.isEmpty()){
            tbUserMapper.deleteByExample(tbUserImpl);
            result.put("code", 200);
            result.put("data", requestBody);
            result.put("msg", "删除用户数据");
            return result;
        }else {
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "删除用户数据失败,未找到对应数据");
            return result;
        }

    }

}
7.1.2 接口测试

添加数据(注册账号)
url

127.0.0.1:8088/xh/v1/user/addUserInfo

请求类型

POST

请求参数

{
	"username":"baijuyi",
    "passWord":"965825",
    "gender":"男",
    "address":"上海市长宁区",
    "pNumber":"18898985858",
    "vipClass":1
}

postman截图
在这里插入图片描述

查询数据
url

127.0.0.1:8088/xh/v1/user/readUserInfo

请求类型

GET

请求参数 空


postman截图
在这里插入图片描述

更新数据
url

127.0.0.1:8088/xh/v1/user/updateUserInfo

请求类型

PUT

请求参数

{
	"username":"baijuyi",
    "passWord":"965825",
    "gender":"男",
    "address":"上海市杨浦区",
    "pNumber":"18898985858",
    "vipClass":1
}

postman截图
在这里插入图片描述

移除数据
url

127.0.0.1:8088/xh/v1/user/removeUserInfo

请求类型

DELETE

请求参数

{
	"username":"libai"
}

postman截图
在这里插入图片描述

7.2 登录接口

在com.xh.user.controller包下创建类UserLogin.java

7.2.1 UserLogin.java

UserLogin.java代码

package com.xh.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.xh.user.dao.TbUser;
import com.xh.user.dao.TbUserImpl;
import com.xh.user.dao.TbUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

/**
 * @func:
 * @author: LiBai
 * @version: v1.0
 * @createTime: 2025/4/17 10:33
 */
@CrossOrigin
@RestController
@RequestMapping(value = "/xh/v1/user")
public class UserLoginController {

    @Autowired
    TbUserMapper tbUserMapper;

    @RequestMapping(value = "/login")
    public JSONObject login(@RequestBody JSONObject requestBody){
        String username = requestBody.getString("username");
        String passWord = requestBody.getString("passWord");
        TbUserImpl tbUserImpl = new TbUserImpl();
        TbUserImpl.Criteria criteria = tbUserImpl.createCriteria();
        criteria.andUsernameEqualTo(username);
        criteria.andPassWordEqualTo(passWord);
        List<TbUser> tbUsers = tbUserMapper.selectByExample(tbUserImpl);
        JSONObject result = new JSONObject();
        if (!tbUsers.isEmpty()){
            result.put("code", 200);
            result.put("data", tbUsers.get(0));
            result.put("msg", "账号密码正确,校验通过");
            return result;
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "账号密码错误,校验未通过,请确认账号密码并重新输入");
            return result;
        }
    }
}

注意,登录前必须先注册,注册接口包含在下一步的用户管理类中

7.2.2 接口测试

url

127.0.0.1:8088/xh/v1/user/login

请求类型

POST

请求参数

{
	"username":"libai",
	"passWord":"352894"
}

postman截图
在这里插入图片描述

7.3 商品管理接口

商品管理部分

7.3.1 建表

创建商品表tb_goods

CREATE TABLE tb_goods(
	id INT AUTO_INCREMENT PRIMARY KEY,
	g_id INT NOT NULL COMMENT "商品id",
	g_name VARCHAR(255) NOT NULL COMMENT "商品名称",
	g_category VARCHAR(255) NOT NULL COMMENT "商品分类",
	g_price DOUBLE NOT NULL COMMENT "商品价格",
	g_inventory INT NOT NULL COMMENT "商品库存",
	g_status VARCHAR(255) NOT NULL COMMENT "商品状态"
);
7.3.2 接口创建(GoodsInfoController.java)

原来项目的商品包名叫product,不是很准确,现在改成goods
在com.xh.goods.dao包下根据表tb_goods生成代码,配置好注解后
在com.xh.goods.controller包下创建商品管理类GoodsInfoController.java
代码如下

package com.xh.goods.controller;

import com.alibaba.fastjson.JSONObject;
import com.xh.goods.dao.TbGoods;
import com.xh.goods.dao.TbGoodsImpl;
import com.xh.goods.dao.TbGoodsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @func:
 * @author: LiBai
 * @version: v1.0
 * @createTime: 2025/4/18 10:55
 */
@CrossOrigin
@RestController
@RequestMapping(value = "/xh/v1/goods")
public class GoodsInfoController {

    @Autowired
    TbGoodsMapper tbGoodsMapper;

    @PostMapping(value = "/addGoodsInfo")
    public JSONObject addGoodsInfo(@RequestBody JSONObject requestBody){

        String gName = requestBody.getString("gName");
        TbGoodsImpl tbGoodsImpl = new TbGoodsImpl();
        TbGoodsImpl.Criteria criteria = tbGoodsImpl.createCriteria();
        criteria.andGNameEqualTo(gName);
        List<TbGoods> tbGoodsList = tbGoodsMapper.selectByExample(tbGoodsImpl);
        JSONObject result = new JSONObject();
        if (tbGoodsList.isEmpty()){
            tbGoodsMapper.insert(JSONObject.parseObject(requestBody.toJSONString(),TbGoods.class));
            result.put("code", 200);
            result.put("data", requestBody);
            result.put("msg", "新增商品信息");
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "新增商品信息失败,此商品数据已存在");
        }
        return result;
    }

    @GetMapping(value = "/readGoodsInfo")
    public JSONObject readGoodsInfo(){

        TbGoodsImpl tbGoodsImpl = new TbGoodsImpl();
        List<TbGoods> tbGoodsList = tbGoodsMapper.selectByExample(tbGoodsImpl);
        JSONObject result = new JSONObject();
        if (!tbGoodsList.isEmpty()){
            result.put("code", 200);
            result.put("data", tbGoodsList);
            result.put("msg", "查询商品信息");
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "查询商品信息失败,无商品数据");
        }
        return result;
    }

    @PutMapping(value = "/changeGoodsInfo")
    public JSONObject changeGoodsInfo(@RequestBody JSONObject requestBody){
        int gId = requestBody.getInteger("gId");
        TbGoodsImpl tbGoodsImpl = new TbGoodsImpl();
        TbGoodsImpl.Criteria criteria = tbGoodsImpl.createCriteria();
        criteria.andGIdEqualTo(gId);
        List<TbGoods> tbGoodsList = tbGoodsMapper.selectByExample(tbGoodsImpl);
        JSONObject result = new JSONObject();
        if (!tbGoodsList.isEmpty()){
            tbGoodsMapper.updateByExampleSelective(JSONObject.parseObject(requestBody.toJSONString(), TbGoods.class),tbGoodsImpl);
            result.put("code", 200);
            result.put("data", requestBody);
            result.put("msg", "更新商品数据");
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "更新商品数据失败,无此商品数据");
        }
        return result;
    }

    @DeleteMapping(value = "/removeGoodsInfo")
    public JSONObject removeGoodsInfo(@RequestBody JSONObject requestBody){

        int gId = requestBody.getInteger("gId");
        TbGoodsImpl tbGoodsImpl = new TbGoodsImpl();
        TbGoodsImpl.Criteria criteria = tbGoodsImpl.createCriteria();
        criteria.andGIdEqualTo(gId);
        List<TbGoods> tbGoodsList = tbGoodsMapper.selectByExample(tbGoodsImpl);
        JSONObject result = new JSONObject();
        if (!tbGoodsList.isEmpty()){
            tbGoodsMapper.deleteByExample(tbGoodsImpl);
            result.put("code", 200);
            result.put("data", requestBody);
            result.put("msg", "删除商品数据");
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "删除商品数据失败,无此商品数据");
        }
        return result;
    }
}

7.3.3 接口测试

新增商品数据
url

127.0.0.1:8088/xh/v1/goods/addGoodsInfo

请求类型

POST

请求参数

{
    "gId": 100001,
    "gName": "海洋至尊洗面奶",
    "gCategory": "护肤品",
    "gPrice": 46.90,
    "gInventory": 98,
    "gStatus": "上架"
 }

postman截图
在这里插入图片描述

查询商品数据
url

127.0.0.1:8088/xh/v1/goods/readGoodsInfo

请求类型

GET

请求参数 空


postman截图
在这里插入图片描述

更新商品数据
url

127.0.0.1:8088/xh/v1/goods/updateGoodsInfo

请求类型

PUT

请求参数

{
    "gId": 100002,
    "gName": "韩束男士补水保湿乳",
    "gCategory": "护肤品",
    "gPrice": 90.98,
    "gInventory": 58,
    "gStatus": "上架"
 }

postman截图
在这里插入图片描述

移除商品数据
url

127.0.0.1:8088/xh/v1/goods/removeGoodsInfo

请求类型

DELETE

请求参数

{
	"gId":"100001"
}

postman截图
在这里插入图片描述

7.4 订单管理接口

7.4.1 建表

创建商品表tb_order

CREATE TABLE tb_order(
	id INT AUTO_INCREMENT PRIMARY KEY,
	o_id INT NOT NULL COMMENT "订单号(订单id)",
	username VARCHAR(255) NOT NULL COMMENT "客户名称",
	o_price DOUBLE NOT NULL COMMENT "订单价格",
	o_time VARCHAR(255) NOT NULL COMMENT "下单时间",
	o_status VARCHAR(255) NOT NULL COMMENT "订单状态"
);
7.4.2 接口创建(OrderInfoController.java)

在com.xh.order.dao包下根据表tb_order生成代码,配置好注解后
在com.xh.order.controller包下创建商品管理类OrderInfoController.java
代码如下

package com.xh.order.controller;

import com.alibaba.fastjson.JSONObject;
import com.xh.order.dao.TbOrder;
import com.xh.order.dao.TbOrderImpl;
import com.xh.order.dao.TbOrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @func:
 * @author: LiBai
 * @version: v1.0
 * @createTime: 2025/4/18 14:10
 */
@CrossOrigin
@RestController
@RequestMapping(value = "/xh/v1/order")
public class OrderInfoController {

    @Autowired
    TbOrderMapper tbOrderMapper;

    @PostMapping(value = "/addOrderInfo")
    public JSONObject addOrderInfo(@RequestBody JSONObject requestBody){
        TbOrderImpl tbOrderImpl = new TbOrderImpl();
        TbOrderImpl.Criteria criteria = tbOrderImpl.createCriteria();
        criteria.andOIdEqualTo(requestBody.getString("oId"));
        List<TbOrder> tbOrders = tbOrderMapper.selectByExample(tbOrderImpl);
        JSONObject result = new JSONObject();
        if (tbOrders.isEmpty()){
            tbOrderMapper.insert(JSONObject.parseObject(requestBody.toJSONString(), TbOrder.class));
            result.put("code", 200);
            result.put("data", requestBody);
            result.put("msg", "新增订单数据");
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "新增订单数据失败,此订单数据已存在");
        }

        return result;
    }


    @GetMapping(value = "/readOrderInfo")
    public JSONObject readOrderInfo(){
        TbOrderImpl tbOrderImpl = new TbOrderImpl();
        List<TbOrder> tbOrders = tbOrderMapper.selectByExample(tbOrderImpl);
        JSONObject result = new JSONObject();
        if (!tbOrders.isEmpty()){
            result.put("code", 200);
            result.put("data", tbOrders);
            result.put("msg", "查询订单数据");
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "查询订单数据失败,未查询到订单数据");
        }

        return result;
    }

    @PutMapping(value = "/changeOrderInfo")
    public JSONObject changeOrderInfo(@RequestBody JSONObject requestBody){
        TbOrderImpl tbOrderImpl = new TbOrderImpl();
        TbOrderImpl.Criteria criteria = tbOrderImpl.createCriteria();
        criteria.andOIdEqualTo(requestBody.getString("oId"));
        List<TbOrder> tbOrders = tbOrderMapper.selectByExample(tbOrderImpl);
        JSONObject result = new JSONObject();
        if (!tbOrders.isEmpty()){
            tbOrderMapper.updateByExampleSelective(JSONObject.parseObject(requestBody.toJSONString(), TbOrder.class),tbOrderImpl);
            result.put("code", 200);
            result.put("data", requestBody);
            result.put("msg", "更新订单数据");
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "更新订单数据失败,未查询到此订单数据");
        }

        return result;
    }

    @DeleteMapping(value = "/removeOrderInfo")
    public JSONObject removeOrderInfo(@RequestBody JSONObject requestBody){
        TbOrderImpl tbOrderImpl = new TbOrderImpl();
        TbOrderImpl.Criteria criteria = tbOrderImpl.createCriteria();
        criteria.andOIdEqualTo(requestBody.getString("oId"));
        List<TbOrder> tbOrders = tbOrderMapper.selectByExample(tbOrderImpl);
        JSONObject result = new JSONObject();
        if (!tbOrders.isEmpty()){
            tbOrderMapper.deleteByExample(tbOrderImpl);
            result.put("code", 200);
            result.put("data", requestBody);
            result.put("msg", "移除订单数据");
        }else{
            result.put("code", 4000);
            result.put("data", "");
            result.put("msg", "移除订单数据失败,此订单数据不存在");
        }

        return result;
    }


}
7.4.3 接口测试

新增商品数据
url

127.0.0.1:8088/xh/v1/order/addOrderInfo

请求类型

POST

请求参数

{
    "oId": "20250418152634000001",
    "username": "libai",
    "oPrice": 121.20,
    "oTime": "2025-04-18,15:26:34",
    "oStatus": "配送中"
 }

postman截图
在这里插入图片描述

查询商品数据
url

127.0.0.1:8088/xh/v1/order/readOrderInfo

请求类型

GET

请求参数 空


postman截图
在这里插入图片描述

更新商品数据
url

127.0.0.1:8088/xh/v1/order/updateOrderInfo

请求类型

PUT

请求参数

{
    "oId": "20250418154624000002",
    "username": "liqingzhao",
    "oPrice": 166.89,
    "oTime": "2025-04-18,15:46:24",
    "oStatus": "未配送"
 }

postman截图
在这里插入图片描述

移除商品数据
url

127.0.0.1:8088/xh/v1/order/removeOrderInfo

请求类型

DELETE

请求参数

{
    "oId": "20250418154624000002"
 }

postman截图
在这里插入图片描述

以上就是入门实战全部内容


📜文末寄语

  • 🟠关注我,获取更多内容。
  • 🟡技术动态、实战教程、问题解决方案等内容持续更新中。
  • 🟢《全栈知识库》技术交流和分享社区,集结全栈各领域开发者,期待你的加入。
  • 🔵​加入开发者的《专属社群》,分享交流,技术之路不再孤独,一起变强。
  • 🟣点击下方名片获取更多内容🍭🍭🍭👇

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值