# springboot3-study
**Repository Path**: sparkle3021/springboot3-study
## Basic Information
- **Project Name**: springboot3-study
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 7
- **Forks**: 4
- **Created**: 2023-12-24
- **Last Updated**: 2025-02-28
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
> 源码地址:https://gitee.com/sparklers/springboot3-study
## 依赖版本
| 依赖 | 版本 | 描述 |
| :----------- | :------ | ---------------- |
| Java(JDK) | 17 | Java开发环境 |
| Spring Boot | 3.2.0 | Spring Boot版本 |
| MySQL | 8.x | 数据库 |
| Redisson | 3.25.0 | Redis工具库 |
| MyBaits-Plus | 3.5.4.1 | Mybatis 增强工具 |
| java-jwt | 4.4.0 | JWT 工具库 |
| SpringDoc | 2.3.0 | 接口文档 |
## 集成项
- [x] 集成 MyBatis-Plus
- [x] 集成 Redis 【Redisson】
- [x] 集成 Spring Security + JWT
- [x] 日志框架定制
- [x] 集成SpringDoc 接口文档
## 集成MyBatis-Plus
1. 导入依赖
```xml
3.0.3
3.5.4.1
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
com.baomidou
mybatis-plus-boot-starter
${mybatis-plus.version}
org.mybatis
mybatis-spring
org.mybatis
mybatis-spring
${mybatis-spring.version}
com.h2database
h2
runtime
org.projectlombok
lombok
```
2. 编写`application.yml`配置文件
```yml
# ======== 数据源配置 ========
spring:
datasource:
driver-class-name: org.h2.Driver
username: root
password: test
sql:
init:
schema-locations: classpath:db/schema-h2.sql
data-locations: classpath:db/data-h2.sql
# ======== MybatisPlus配置 ========
mybatis-plus:
# 搜索指定包别名
type-aliases-package: com.yiyan.study.domain
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapper-locations: classpath:mapper/**/*xml
# 配置驼峰
configuration:
# 是否开启自动驼峰命名规则(camel case)映射。默认值:true
map-underscore-to-camel-case: true
# 开启 Mybatis 二级缓存,默认为 true。
cache-enabled: true
# 日志输出实现。StdOutImpl 标准日志控制台输出
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 全局默认主键类型
id-type: assign_id
# 表名是否使用驼峰转下划线命名,只对表名生效。 默认true
table-underline: true
```
3. 编写mybatis plus文件
```sql
-- data-h2.sql
DELETE
FROM `user`;
INSERT INTO `user` (id, name, age, email)
VALUES (1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
-- schema-h2.sql
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`
(
id BIGINT NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
```
实体类
```java
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@TableName(value = "`user`")
@Data
public class User implements Serializable {
@TableId
private Long id;
private String name;
private Integer age;
private String email;
@Serial
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
```
DAO(mapper)
```java
import com.yiyan.study.domain.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface IUserDao extends BaseMapper {
}
```
Service
```java
import com.yiyan.study.domain.User;
import com.baomidou.mybatisplus.extension.service.IService;
public interface IUserService extends IService {
}
```
ServiceImpl
```java
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yiyan.study.domain.User;
import com.yiyan.study.service.IUserService;
import com.yiyan.study.dao.IUserDao;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl
implements IUserService{
}
```
mapper.xml
```xml
```
4. 编写测试用例
```java
package com.yiyan.study;
import com.yiyan.study.dao.IUserDao;
import com.yiyan.study.domain.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@Slf4j
@SpringBootTest
@DisplayName("MyBatis Plus Test")
public class MyBatisPlusTest {
@Autowired
private IUserDao userDao;
@Test
@DisplayName("MyBatis Plus Select Test")
public void testSelect() {
log.info(("----- selectAll method test ------"));
List userList = userDao.selectList(null);
for (User user : userList) {
log.info(user.toString());
}
}
@Test
@DisplayName("MyBatis Plus Insert Test")
public void testInsert() {
log.info(("----- insert method test ------"));
User user = new User();
user.setName("Alex");
user.setAge(18);
user.setEmail("alex@gmail.com");
int result = userDao.insert(user);
log.info("insert result: {}", result);
User selectedById = userDao.selectById(user.getId());
log.info("insert user info: {}", selectedById);
}
@Test
@DisplayName("MyBatis Plus Update Test")
public void testUpdate() {
log.info(("----- update method test ------"));
User user = userDao.selectList(null).get(0);
log.info("before update: {}", user);
user.setName("Updated Name");
int result = userDao.updateById(user);
log.info("update result: {}", result);
User selectedById = userDao.selectById(user.getId());
log.info("after update: {}", selectedById);
}
@Test
@DisplayName("MyBatis Plus Delete Test")
public void testDelete() {
log.info("----- delete method test ------");
List users = userDao.selectList(null);
log.info("before delete user list size: {}", users.size());
User user = users.get(0);
userDao.deleteById(user.getId());
log.info("delete user id: {}", user.getId());
List usersAfterDelete = userDao.selectList(null);
log.info("after delete user list size: {}", usersAfterDelete.size());
}
}
```

## 集成Redis【Redisson】
1. 导入依赖
```xml
3.25.0
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter
org.redisson
redisson-spring-boot-starter
${redisson.version}
org.springframework.boot
spring-boot-starter-test
test
```
2. 编写配置文件
```yml
# application.yml
spring:
# ======== Redis配置 ========
redis:
redisson:
file: classpath:redisson.yaml
```
```yaml
# redisson.yaml
# 编码。默认值: org.redisson.codec.JsonJacksonCodec
codec: ! {}
# 线程池数量。默认值: 当前处理核数量 * 2
threads: 16
# Netty线程池数量。默认值: 当前处理核数量 * 2
nettyThreads: 32
# 传输模式。默认值: NIO
transportMode: "NIO"
# 监控锁的看门狗超时,单位:毫秒。默认值: 30000
lockWatchdogTimeout: 30000
# 是否保持订阅发布顺序。默认值: true
keepPubSubOrder: true
# Redisson 单实例配置
singleServerConfig:
# 节点地址。格式:redis://host:port
address: "redis://127.0.0.1:6379"
# 密码。默认值: null
password: null
# 数据库编号。默认值: 0
database: 0
# 客户端名称(在Redis节点里显示的客户端名称)。默认值: null
clientName: null
# 连接超时,单位:毫秒。默认值: 10000
connectTimeout: 10000
# 命令等待超时,单位:毫秒。默认值: 3000
timeout: 3000
# 命令失败重试次数。默认值: 3
retryAttempts: 3
# 命令重试发送时间间隔,单位:毫秒。默认值: 1500
retryInterval: 1500
# 最小空闲连接数。默认值: 32
connectionMinimumIdleSize: 24
# 连接池大小。默认值: 64
connectionPoolSize: 64
# 单个连接最大订阅数量。默认值: 5
subscriptionsPerConnection: 5
# 发布和订阅连接的最小空闲连接数。默认值: 1
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小。默认值: 50
subscriptionConnectionPoolSize: 50
# DNS监测时间间隔,单位:毫秒。默认值: 5000
dnsMonitoringInterval: 5000
# 连接空闲超时,单位:毫秒。默认值: 10000
idleConnectionTimeout: 10000
```
3. 编写Redis操作工具
```java
package com.yiyan.study;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RAtomicDouble;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Redis工具类
*/
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class RedisService {
private final RedissonClient redissonClient;
// ============================= String类型操作 ============================
/**
* 将值存储到Redis中
*
* @param key 键
* @param value 值
*/
public void setString(String key, T value) {
RBucket bucket = redissonClient.getBucket(key);
bucket.set(value);
}
/**
* 将值存储到Redis中
*
* @param key 键
* @param value 值
* @param timeout 过期时间
* @param timeUnit 时间单位
*/
public void setString(String key, T value, long timeout, TimeUnit timeUnit) {
RBucket bucket = redissonClient.getBucket(key);
bucket.set(value, timeout, timeUnit);
}
/**
* 根据键获取Redis中的值
*
* @param key 键
* @return 值
*/
public T getString(String key) {
RBucket bucket = redissonClient.getBucket(key);
return bucket.get();
}
// ============================= Hash类型操作 ============================
/**
* 将值存储到Redis中
*
* @param key 键
* @param field hash键
* @param value 值
*/
public boolean addToHash(String key, Object field, T value) {
RMap