# R-Pan
**Repository Path**: fufu233/r-pan
## Basic Information
- **Project Name**: R-Pan
- **Description**: 仿网盘项目,有做这个慕课项目的朋友可以一起交流
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 6
- **Forks**: 1
- **Created**: 2023-10-14
- **Last Updated**: 2025-05-31
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 分布式商业存储系统
## 每日完成记录
### 2023-10-14&项目搭建
---
**目标:了解架构、技术原理**
#### 项目设计
1. 架构选型
2. 项目开发
3. 项目优化
4. 项目上线
#### 开发前的准备(开发环境准备)
**下载软件--->编译---->配置环境变量**
- **JDK1.8**
- JAVA_HOME:jdk所在文件夹
- CLASSPATH:指定JVM搜索class文件的位置,默认在当前目录下搜索,有很多“如何设置classpath”的文章会告诉你把JVM自带的`rt.jar`放入`classpath`,但事实上,根本不需要告诉JVM如何去Java核心库查找`class`,JVM怎么可能笨到连自己的核心库在哪都不知道?
- PATH:让系统能够搜索到JDK的可执行文件
- **Maven 3.6.3**
- MAVEN_HOME:指定存放Maven的文件夹
- PATH:让系统能够搜索到MAVEN的可执行文件
- mv -version查看版本
- **Git 任意版本**
- GIT_HOME:指定存放Git的文件夹
- PATH:让系统能够搜索到Git的可执行文件
- **IDEA 2019**
#### 创建Gitee仓库(R-Pan)
[](https://imgse.com/i/pi9VY7R)
#### 拉取项目到IDEA
`注意:如果是第一次拉取项目,一定是从远程仓库创建(Created)项目,而不是导入(Import),因为刚创建的仓库里面没有IDEA的配置文件,所以直接导入无法被IDEA识别成一个项目模块`
[](https://imgse.com/i/pi9VNA1)
#### 模块划分
**r-pan**:根目录
- **framework**:存放所有技术相关的子模块
- **core:** 技术核心模块 全局{常量类、异常类、响应类、工具类}
- **web:** web技术模块 各种过滤器、json序列化 {跨域过滤、日志处理、日期json序列化响应}
- **swagger2:** 自动生成接口文档
- **web:** 在这个模块处理所有与前端请求相关的配置,例如跨域cors过滤器、请求日志过滤器、异常处理器、序列化对象为json、统一的参数校验器
- **orm:** 在这个模块管理各种ORM框架,如Mybatis、Mybatis-plus......
- **server:** 存放所有业务相关的子模块(项目的启动器或入口)
- **distribution:** 打包模块,定义打包方式
### 2023-10-15&集成全局工具
---
#### 集成Swagger2接口测试
**引入依赖:**
```xml
com.hbpa.pan
r-pan-core
1.0
io.springfox
springfox-swagger2
io.springfox
springfox-swagger-ui
com.github.xiaoymin
swagger-bootstrap-ui
org.springframework.boot
spring-boot-configuration-processor
```
如果只引入了springfox-swagger2和springfox-swagger-ui,那么访问路径为:http://localhost:8080/swagger-ui.html
再引入http://localhost:8080/swagger-ui.html会对原本的ui进行优化,提升交互体验
**1、创建一个自定义的swagger2配置类,可以在其中配置自己想要实现的一些效果,然后将配置后的对象注册到spring容器中去**
```java
@Bean
public Docket panServerApi(){
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.enable(properties.isShow())
.groupName(properties.getGroupName())
.apiInfo(apiInfo())
.useDefaultResponseMessages(false)
.select()
.apis(RequestHandlerSelectors.basePackage(properties.getBasePackage()))
.paths(PathSelectors.any())
.build();
log.info("The swagger2 have been loaded successfully!");
return docket;
}
```
**2、也可以在additional-spring-configuration-metadata.json中配置Swagger2需要的属性,然后在application.yml中直接配置自己想要的效果(一、二的效果是一样的)**
```xml
swagger2:
show: true
group-name: ${spring.application.name}
base-package: com.hbpa.pan
title: r-pan-server docs
description: r-pan-server docs
terms-of-service-url: http://127.0.0.1:${server.port}
contact-email: hsf6661@163.com
contact-name: AoKi
contact-url: https://gitee.com/fufu233/r-pan
version: 1.0
#test: test The META-INF's json file(确实影响)
```
****
#### 集成Validator入参校验器(面向切面的高级用法)
`Validator` 是 Java 中的一个接口,通常与数据验证和校验相关。它的目的是验证数据是否符合一定的规则、条件或约束,并在发现验证失败时报告错误。在 Java 中,常见的数据验证框架如 Hibernate Validator 和 Java Bean Validation (JSR-303) 提供了 `Validator` 接口的实现。
Hibernate Validator由spring-boot-starter-web提供,所以不需要额外引入依赖
**创建Validator配置类**
```java
@SpringBootConfiguration
@Log4j2
public class WebValidatorConfig {
/**
* 快速失败key(固定值)
*/
private static final String FAIL_FAST_KEY = "hibernate.validator.fail_fast";
/**
* validator校验方法的后置处理器(方法级别的参数校验)
* MethodValidationPostProcessor 是 Spring 的一个后处理器,用于启用方法参数校验。
* @return
*/
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor(){
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
//将自定义的验证器 rPanValidator() 与后处理器关联。这个验证器将用于验证方法的参数。
postProcessor.setValidator(rPanValidator());
log.info("The hibernation validator is loaded successfully!");
return postProcessor;
}
/**
* 构建rPan项目的方法参数校验器
* @return
*/
private Validator rPanValidator() {
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
.configure()
//第一个验证失败时停止验证。
.addProperty(FAIL_FAST_KEY, RPanConstants.TRUE_STR)
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
return validator;
}
}
```
`MethodValidationPostProcessor` 可以自动识别带有 `@Validated` 或 `@Valid` 注解的方法,并在调用这些方法之前对方法的参数进行验证。这有助于确保方法在执行之前参数是有效的。
`MethodValidationPostProcessor` 主要是在标有 `@Validated` 或 `@Valid` 注解的方法执行前执行验证。它的作用是在方法调用之前对方法的参数进行验证。如果验证失败,会在方法执行之前抛出验证相关的异常或提供错误信息。
具体来说,`MethodValidationPostProcessor` 在以下情况下执行验证:
- 在调用带有 `@Validated` 或 `@Valid` 注解的方法之前。
- 在调用方法之前,验证方法参数是否满足定义的验证规则。
- 如果参数验证失败,会在方法执行之前触发异常或提供错误信息。
它的目的是在方法执行之前,确保方法参数的有效性,以防止无效的数据进入方法,从而提高数据的质量和应用程序的安全性。
**两个关键注解**
- **@Validated**:是 Spring 框架提供的注解,通常用于方法级别的数据验证。它可以标注在方法上,==用于验证方法参数。== `@Validated` 不会自动验证实体类(Java Bean)的属性,它主要用于方法参数的验证。也可以标注在类上,这样类中所有的方法都默认应用该验证规则
- **@Valid:** 是 Java Bean Validation (JSR-303) 标准提供的注解,通常用于验证实体类的属性。`@Valid` 可以标注在实体类的属性上,以确保属性的有效性。它可以自动验证实体类的属性,并触发验证约束,如 `@NotNull`、`@Size` 等。
#### 集成ExceptionHandler全局异常处理器
**创建全局异常处理器类**
```java
@RestControllerAdvice
public class WebExceptionHandler {
/**
* R-Pan业务异常处理器:当应用程序中存在业务错误时,会抛出此异常。
* @param e 异常对象
* @return
*/
@ExceptionHandler(value = RPanBusinessException.class)
public ResponseEntity rPanBusinessExceptionHandler(RPanBusinessException e){
return ResponseEntity.fail(e.getCode());
}
}
```
`@RestControllerAdvice` 是 Spring 框架中的一个注解,用于定义全局性的控制器通知(Controller Advice)。控制器通知是一种全局的异常处理机制,它允许你定义一组通用的行为,以在控制器方法执行期间或在控制器方法抛出异常时执行。用于返回指定的响应体信息,而不是错误页面的兜底方法。便于与前端的交互
### 2023-10-16&集成打包分发插件&jar包运行项目&输出日志
#### 集成打包分发插件
##### 1.Maven构建配置Apache Maven Assembly Plugin。
该插件使开发人员能够将项目输出组合成一个单独的可分发存档,其中还包含依赖项、模块、站点文档和其他文件。您的项目可以使用预制的组装描述符轻松构建分发“组装件”。这些描述符处理许多常见操作,例如将项目的工件与生成的文档打包到单个zip存档中。或者,您的项目可以提供自己的描述符,并假定对依赖项、模块、文件集和单个文件在打包中有更高级别的控制。
```xml
r-pan-server
org.apache.maven.plugins
maven-assembly-plugin
assembly.xml
posix
make-assembly
install
single
```
##### 2.定制具体的打包&分发包方案(根据具体情况配置,可选)
创建一个assembly.xml文件用于配置打包方案,==通常情况下,该文件位于模块的根目录下,与pom文件同级==
在该文件中可以配置打包的格式、具体要将哪些文件打包、打好的包分发到哪些目录......
```xml
${project.version}
true
dir
tar.gz
zip
conf/**
bin/*
0755
../server/target/r-pan-server.jar
target/
true
com.hbpa.pan:r-pan-server
```
#### 通过jar包运行项目
**运行方式**
##### 1.DOS命令运行:
```java
java -jar your-app-name.jar
```
##### 2.Windows批处理文件运行(相当于同时执行多个DOS命令):
```bat
rem 关闭命令行窗口中的命令回显(不会显示命令的文本输出)。
@echo off
rem 判断有没有JAVA_HOME环境变量
if not exist "%JAVA_HOME%\bin\java.exe"
echo Please set the JAVA_HOME variable in your environment, We need java(x64)! jdk8 or later is better! & EXIT /B 1
rem 获取当前目录路径
set BASE_DIR=%~dp0
rem删除了最后5个字符(这意味着\bin\)以获得基本DIR。
set BASE_DIR="%BASE_DIR:~0,-5%"
rem 获取java的执行器
set "JAVA=%JAVA_HOME%\bin\java.exe"
rem 设置Java虚拟机参数,包括初始堆大小、最大堆大小和年轻代大小。
set "PAN_JVM_OPTS=-Xms512m -Xmx512m -Xmn256m"
rem 设置应用程序的启动选项。这包括应用程序的JAR文件的路径,可能还包括其他选项。
set "PAN_OPTS=%PAN_OPTS% -jar %BASE_DIR%\target\%SERVER%.jar"
set COMMAND="%JAVA%" %PAN_JVM_OPTS% %PAN_OPTS% pan.server %*
echo "your server is starting..."
rem 执行命令
%COMMAND%
```
### 2023-10-17&热部署&安装Mysql&数据库预热&配置ORM框架和代码生成器
#### springboot热部署
徒增性能消耗,个人认为完全没必要,如果一定要配置,参考下面配置
https://blog.csdn.net/lwj_07/article/details/126226074
#### 安装Mysql(Linux平台)
网上找找安装教材吧,都写项目了,不会还有人不会装mysql吧→_→
#### 数据预热
数据库预热(Database Warm-up)是指在应用程序启动或重启时,通过执行一些查询或操作,将数据库中的相关数据加载到内存中,以提前准备好数据库,以便后续的查询或操作可以更快地执行。
##### 配置数据库预热(预热脚本)
```sql
SELECT CONCAT('SELECT ', ndxcollist, ' FROM ', db, '.', tb, ' ORDER BY ', ndxcollist,
';') SelectQueryToLoadCache
FROM (SELECT ENGINE,
table_schema db,
table_name tb,
index_name,
GROUP_CONCAT(column_name ORDER BY seq_in_index) ndxcollist
FROM (SELECT B.ENGINE,
A.table_schema,
A.table_name,
A.index_name,
A.column_name,
A.seq_in_index
FROM information_schema.statistics A
INNER JOIN (SELECT ENGINE, table_schema, table_name
FROM information_schema.TABLES
WHERE ENGINE = 'InnoDB') B USING (table_schema, table_name)
WHERE B.table_schema NOT IN ('information_schema', 'mysql')
ORDER BY table_schema,
table_name,
index_name,
seq_in_index) A
GROUP BY table_schema,
table_name,
index_name) AA
ORDER BY db,
tb;
```
##### Mysql体系架构
MySQL 的体系架构包括以下几个主要组件和层次:
1. **客户端层(Client Layer):** 客户端层是用户与 MySQL 交互的部分,包括应用程序、MySQL 客户端工具和数据库管理工具。客户端通过 MySQL 协议与 MySQL 服务器通信,发送 SQL 查询和接收查询结果。
2. **连接池(Connection Pool):** 连接池是客户端应用程序和 MySQL 服务器之间的中介层,用于管理数据库连接。连接池负责分配连接、回收连接以及维护连接的生命周期。这有助于提高数据库访问效率,避免频繁地创建和销毁连接。
3. **SQL 层(SQL Layer):** SQL 层是 MySQL 数据库的核心,负责处理 SQL 查询、事务管理和权限控制。它包括以下组件:
- **Query Parser:** 用于解析 SQL 查询语句,验证语法和语义。
- **Optimizer:** 优化器负责选择执行查询的最佳方法,以提高查询性能。
- **Cache and Buffer:** MySQL 使用缓存和缓冲池来提高读取和写入性能。
- **InnoDB:** InnoDB 存储引擎是 MySQL 的默认存储引擎,提供事务支持和高级的并发控制。
4. **存储引擎层(Storage Engine Layer):** 存储引擎是 MySQL 的插件式存储引擎架构,负责处理数据的存储和检索。MySQL 支持多个存储引擎,每个存储引擎都有不同的特性和适用场景。常见的存储引擎包括 InnoDB、MyISAM、MEMORY、等等。
5. **物理文件层(Physical File Layer):** MySQL 数据库的实际数据和索引存储在文件系统中,每个存储引擎有自己的数据文件和索引文件。数据库文件通常存储在操作系统文件系统上。
6. **连接池层(Connection Pool Layer):** 在服务器端,MySQL 服务器维护一个连接池,以处理客户端连接请求。这一层负责监听来自客户端的连接请求、管理连接池、分发连接给 SQL 层等。
7. **存储引擎 API 层(Storage Engine API Layer):** 这一层提供了与存储引擎通信的 API,允许 SQL 层与不同的存储引擎进行通信。每个存储引擎都会实现这些 API。
8. **物理存储层(Physical Storage Layer):** 这一层负责实际的数据存储和检索,将数据从磁盘读取到内存中,或将数据写入到磁盘。不同的存储引擎会在这一层实现不同的存储和检索策略。
9. **文件系统层(File System Layer):** 数据库文件存储在操作系统的文件系统上,因此文件系统层负责处理数据文件的创建、读取、写入和删除。
##### Mysql运行机制
MySQL 的运行机制主要包括以下几个关键方面:
1. **连接管理(Connection Management):** MySQL 使用连接池管理客户端与服务器的连接。当客户端应用程序需要访问数据库时,它从连接池中获取一个数据库连接,执行 SQL 查询,然后将连接返回到连接池,以便其他客户端使用。连接池的使用可以降低连接的创建和销毁开销,提高性能。
2. **SQL 查询处理(SQL Query Processing):** 当客户端发送 SQL 查询到 MySQL 服务器时,服务器首先解析和验证查询,然后进行优化。查询优化器尝试找到执行查询的最佳执行计划,以提高查询性能。最后,MySQL 执行查询,检索所需的数据并返回结果。
3. **事务管理(Transaction Management):** MySQL 支持事务,客户端可以使用 `BEGIN`, `COMMIT`, 和 `ROLLBACK` 等命令来管理事务。事务管理确保了数据的一致性和完整性,它是关系数据库管理系统的核心功能。
4. **存储引擎管理(Storage Engine Management):** MySQL 具有插件式存储引擎架构,允许用户选择不同的存储引擎来存储数据。服务器负责管理不同存储引擎的数据,包括数据存储、检索、索引维护等。
5. **缓存管理(Caching Management):** MySQL 使用缓存来提高性能。它包括查询缓存(Query Cache)和缓冲池(Buffer Pool)。查询缓存存储查询结果,以便在后续相同查询时直接返回结果,从而减少数据库负载。缓冲池用于缓存数据块,减少从磁盘读取数据的次数,提高查询性能。
6. **索引管理(Index Management):** MySQL 使用索引来加速数据检索。数据库管理员和应用程序开发人员可以创建不同类型的索引,以提高查询效率。MySQL负责维护索引的完整性和性能。
7. **日志管理(Logging Management):** MySQL 记录各种日志,包括二进制日志(Binary Log)用于数据恢复和复制、慢查询日志(Slow Query Log)用于性能分析、错误日志(Error Log)用于记录错误消息等。这些日志对于监视和故障排除非常重要。
8. **权限控制和安全(Security and Authentication):** MySQL 提供了严格的权限控制,数据库管理员可以控制用户对数据库和表的访问权限。MySQL 还支持各种身份验证机制,包括用户名和密码、SSL/TLS 加密等,以确保数据的安全性。
9. **复制和高可用性(Replication and High Availability):** MySQL 支持主从复制(Master-Slave Replication)和其他高可用性解决方案,允许在多个服务器之间复制数据,提供冗余和故障恢复能力。
10. **备份和恢复(Backup and Recovery):** MySQL 提供多种备份和恢复工具,允许数据库管理员创建备份副本以便在数据丢失或损坏时进行恢复。
MySQL 的运行机制是一个复杂的协调系统,它确保了数据的完整性、一致性和可靠性,同时提供高性能和灵活性,使其成为广泛使用的关系型数据库管理系统。
##### InnoDB内存结构
InnoDB 存储引擎在内存中维护了多种内存结构,这些内存结构用于提高性能、管理数据、维护索引、处理事务和缓存数据。以下是 InnoDB 存储引擎中的一些重要内存结构:
1. **缓冲池(Buffer Pool):** 缓冲池是 InnoDB 存储引擎最重要的内存结构之一。它用于缓存数据库表和索引的数据块,以减少从磁盘读取数据的次数,从而提高读性能。缓冲池的大小可以通过配置参数 `innodb_buffer_pool_size` 来设置。较大的缓冲池可以提高性能,但也需要更多内存。
2. **重做日志缓存(Redo Log Buffer):** 重做日志缓存是一个小的内存区域,用于存储正在进行的事务的重做日志记录,以确保事务的持久性。这些记录稍后会被写入磁盘上的重做日志文件。
3. **自适应哈希索引(Adaptive Hash Index):** InnoDB 存储引擎维护了一个内存中的哈希索引结构,用于加速某些查询。这个哈希索引是自适应的,会根据查询的模式自动调整大小。
4. **附加内存池(Additional Memory Pool):** 附加内存池用于存储额外的数据结构,如锁信息、事务信息等。这有助于减少对缓冲池的竞争,提高并发性能。
5. **内部数据结构:** InnoDB 存储引擎还维护了许多内部数据结构,包括缓存目录、缓存表、数据字典缓存等。这些结构用于管理数据库对象、元数据和缓存数据。
6. **插件缓存(Plugin Cache):** InnoDB 支持插件机制,插件可以在内存中存储自己的数据结构。
7. **缓冲池管理器(Buffer Pool Manager):** 缓冲池管理器负责在缓冲池中分配、释放和管理数据块。
8. **自适应检查点(Adaptive Checkpointing):** InnoDB 存储引擎使用内存结构来维护检查点信息,以优化检查点操作,确保数据的一致性和持久性。
这些内存结构一起协同工作,以确保 InnoDB 存储引擎的高性能、高可用性和数据完整性。通过适当配置和调整这些内存结构的大小,可以优化数据库性能,提供更好的用户体验。不同的工作负载和硬件环境可能需要不同的内存结构配置。
##### BP Page管理机制
BP(Buffer Pool) Page 管理机制是 InnoDB 存储引擎中用于管理缓冲池(Buffer Pool)中数据页(Page)的一种机制。缓冲池是 InnoDB 存储引擎的内存部分,用于缓存数据库表和索引的数据页,从而加速数据库访问。以下是 BP Page 管理机制的一些关键概念和原理:
1. **数据页(Page):** 数据页是 InnoDB 存储引擎中的基本数据存储单位,通常大小为 16KB。每个数据页可以存储表的一部分数据或一个索引的一部分数据。
2. **脏页(Dirty Page):** 如果缓冲池中的数据页与磁盘上的数据页内容不一致,它就被称为脏页。脏页通常表示缓冲池中的数据已被修改但尚未写回到磁盘。
3. **LRU(Least Recently Used)算法:** LRU 算法是一种页面置换算法,它用于确定在需要从缓冲池中替换页时选择哪个页。InnoDB 使用 LRU 算法来管理缓冲池中的数据页。
4. **检查点(Checkpoint):** 检查点是将脏页写回磁盘的操作。InnoDB 定期执行检查点,以确保脏页的数据持久性。
5. **脏页列表(Dirty Page List):** InnoDB 使用脏页列表来跟踪缓冲池中的脏页。当需要执行检查点时,脏页列表上的脏页会被写回到磁盘。
6. **刷新(Flush):** 刷新是指将脏页写回到磁盘的操作。InnoDB 使用刷新来确保数据页的一致性和持久性。
BP Page 管理机制的核心目标是优化数据的读取和写入操作,以提高数据库的性能和数据完整性。InnoDB 存储引擎使用缓冲池来缓存数据页,当需要读取数据时,首先检查缓冲池中是否存在数据页。如果存在,数据可以直接从缓冲池中获取,而不必从磁盘读取,这提高了读取性能。当数据页被修改时,它会被标记为脏页,并在适当的时机写回磁盘以确保数据持久性。
检查点操作是 BP Page 管理机制的一个关键部分,它负责将脏页写回磁盘,以释放缓冲池中的内存空间并确保数据的一致性。检查点可以由系统自动触发,也可以由管理员手动触发。
通过合理配置缓冲池大小、脏页比例和检查点参数,可以优化 InnoDB 存储引擎的性能,确保数据库的高可用性和数据完整性。
#### 配置Mybatis-plus以及使用Mybatis-x插件生成代码
安装该插件就可以直接使用了,详细操作不展示了,百度一下
### 2023-10-18&Spring Framework缓存&JSR107规范(缓存)
#### JSR107规范
JSR 107,全称为"Java Specification Request 107",是Java平台的缓存规范,也被称为"Java Caching API"。该规范的目标是定义一组标准的API,用于在Java应用程序中管理对象缓存,从而提高应用程序性能和降低资源开销。JSR 107的主要组成部分是Java Caching Annotations和Java Caching SPI(Service Provider Interface)。
#### Spring Framework中的缓存
Spring Cache 的抽象使您能够轻松地切换不同的缓存提供程序,而无需更改应用程序代码。您可以选择与应用程序需求和性能要求相匹配的缓存提供程序,例如Ehcache、Caffeine、Redis等,然后通过简单地配置来集成它们。
需要注意的是,Spring Cache不是一个独立的缓存系统,而是一个在Spring应用程序中使用缓存的框架,它利用不同缓存提供程序的功能来实现缓存。您需要在项目中添加适当的缓存提供程序的依赖,以使Spring Cache能够与之集成。
Spring Framework中的缓存支持是一个强大的特性,允许您轻松地在应用程序中实现数据缓存。以下是有关Spring缓存的详细解释,包括每个重要的知识点和相关注解:
1. **缓存概述**:
- **Spring缓存是一种将方法的执行结果存储在内存中,以便以后请求相同数据时能够更快地返回响应的机制。**
- 它有助于减少对底层数据存储(如数据库)的频繁访问,提高应用程序性能。
2. **缓存管理器**:
- 缓存管理器是Spring缓存的核心组件,它负责创建、配置和管理缓存。
- Spring支持多种缓存提供程序,包括EhCache、Caffeine、Redis、Memcached等。
- 示例:`ConcurrentMapCacheManager`用于本地内存缓存。
3. **缓存注解**:
- Spring提供了一组注解,用于在方法级别配置缓存行为。这些注解包括:
- `@Cacheable`:用于标记方法的结果应该被缓存。
- `@CachePut`:用于标记方法的结果应该被存储或更新到缓存。
- `@CacheEvict`:用于标记方法的结果应该从缓存中删除。
- 这些注解可以与缓存名称、条件、键生成器等一起使用,以根据不同的需求进行更细粒度的控制。
4. **缓存的生命周期**:
- 缓存可以具有不同的生命周期,可以是基于时间的,也可以是基于操作的(如添加、更新、删除)。
- 使用`@Cacheable`时,缓存的生命周期通常是基于时间的,可以使用`@Cacheable`的`expire`属性来设置缓存过期时间。
- 使用`@CachePut`和`@CacheEvict`时,生命周期通常是基于操作的。
5. **条件缓存**:
- 您可以使用`@Cacheable`和`@CachePut`的`condition`属性来定义条件,只有当条件满足时才会进行缓存操作。
6. **缓存键生成器**:
- 缓存键是用于唯一标识缓存项的。Spring允许您自定义缓存键的生成方式,可以使用`key`属性和`keyGenerator`属性。
7. **多缓存支持**:
- Spring支持多个缓存管理器,允许您为不同的缓存区域配置不同的缓存管理器。
8. **缓存清除**:
- 使用`@CacheEvict`注解可以清除缓存中的数据,可以根据不同条件进行清除。
9. **缓存解析器**:
- Spring允许您自定义缓存解析器,以在方法调用时选择缓存区域。
10. **缓存的刷新**:
- 通常,缓存是在缓存项过期后自动刷新的,但您也可以手动刷新缓存。
11. **缓存监听器**:
- Spring支持缓存事件监听器,允许您监视缓存中的数据变化并采取适当的措施。
12. **缓存注解的用法**:
- 在方法上使用`@Cacheable`、`@CachePut`和`@CacheEvict`注解,以及通过指定缓存名称、条件、键生成器、缓存解析器等来定义缓存行为。
13. **配置缓存管理器**:
- 配置缓存管理器,指定缓存提供程序和缓存名称,以及其他缓存配置选项。
14. **错误处理**:
- 当缓存操作出现问题时,Spring提供了错误处理选项,以便您可以定义应该如何处理这些错误。
这些是关于Spring缓存的关键知识点和相关注解的详细解释。使用Spring的缓存特性可以显著提高应用程序的性能,并减少对底层数据存储的负担。根据项目需求,您可以选择合适的缓存提供程序和配置,以优化数据访问。
#### Spring Framework缓存与JSR107的区别
Spring缓存和JSR 107(Java Caching API,或简称JCache)是两种不同的缓存规范和框架,它们具有一些相似的目标,但也有一些不同之处。它们之间的关系可以总结如下:
1. **Spring缓存与JSR 107的关系**:
- Spring缓存是Spring框架提供的一种缓存抽象,允许在Spring应用程序中更容易地管理缓存。Spring缓存的核心部分是Spring的自定义缓存注解(如`@Cacheable`、`@CachePut`、`@CacheEvict`)以及相关的缓存管理器。
- JSR 107是Java平台的一项缓存规范,目的是定义一组标准API和注解,用于在Java应用程序中管理缓存。JSR 107定义了`javax.cache.Cache`接口以及一组标准注解(`@CacheResult`、`@CachePut`、`@CacheRemove`等)。
- Spring缓存可以集成JSR 107,这意味着Spring应用程序可以使用JSR 107的标准API和注解来进行缓存操作。这是通过在Spring中引入JSR 107的实现(如Caffeine、Ehcache等)来实现的。Spring 4.1及更高版本支持与JSR 107的集成。
2. **共同点**:
- Spring缓存和JSR 107都旨在提供一种标准化的方式来管理缓存,以提高应用程序性能和降低资源开销。
- 两者都支持不同的缓存提供程序,如Ehcache、Caffeine、Hazelcast等,以及标准的缓存注解,允许开发人员在方法级别配置缓存行为。
3. **区别**:
- Spring缓存是Spring框架的一部分,提供了更多的功能,如缓存清除、条件缓存、缓存解析器等,而JSR 107主要专注于定义核心的缓存API和注解。
- JSR 107是一项Java平台规范,不依赖于Spring框架,因此可以与其他Java框架和应用程序一起使用。
- Spring缓存提供了更多的扩展性和自定义选项,允许开发人员灵活地配置缓存管理器和其他组件。
总之,Spring缓存和JSR 107都是用于在Java应用程序中管理缓存的工具和规范。它们可以独立使用,但也可以集成在一起,具体取决于您的项目需求和偏好。如果您已经在使用Spring框架,Spring缓存可能是一个更方便的选择,但如果您想要更通用的、与平台无关的缓存规范,那么JSR 107可能更适合您。
#### 缓存分级理念
一种常见的分级缓存策略是:
1. **内存缓存**:将频繁访问的热门数据存储在应用程序的内存中。这可以通过使用应用程序内存中的数据结构或者使用本地缓存(如Spring的`CaffeineCache`)来实现。内存缓存能够提供非常快速的数据访问,但容量有限,适合存储短时间内频繁访问的数据。
2. **Redis缓存**:将相对频繁但不那么频繁的数据存储在Redis服务器中。Redis是一个高性能的缓存数据库,可以存储大量数据,同时提供持久性,数据可以在多个应用程序之间共享。
3. **数据库**:将不太频繁访问的数据存储在持久性数据库中。这些数据通常是重要但不需要频繁更新的数据,例如历史记录、配置数据等。
通过将数据分级存储,您可以在不同的数据访问模式之间实现性能和资源的平衡。热门数据可以快速从内存中获取,而不太频繁访问的数据可以存储在持久性存储中,以节省内存和提高性能。
要实施这种分级缓存策略,您需要在应用程序中编写逻辑来确定数据应该存储在哪个级别的缓存中,并在数据访问时选择适当的缓存。此外,您需要考虑缓存的过期策略,以确保数据不会长时间存在于缓存中,因为它可能会变得过时。
这种分级缓存策略是一种常见的缓存优化方法,可以根据应用程序的需求和性能要求来调整不同级别的缓存。
#### 相关注解说明
- @EnableCaching:开启缓存支持
- @Cacheable:用于标记方法的返回值应该被缓存。可以使用它来将方法的结果存储在缓存中,以便在后续调用相同方法时可以从缓存中获取。
- @CachePut:用于标记方法的返回值应该被存储或更新到缓存中。与 `@Cacheable` 不同,`@CachePut` 会始终执行方法,然后将其结果存储在缓存中。
- @CacheEvict:用于标记方法的返回值应该从缓存中删除。通常在执行与缓存数据无关的操作后使用,以清除缓存中的相关数据。
- @Caching:允许同时应用多个缓存注解到同一个方法上。这可以用于实现更复杂的缓存策略。
### 2023-10-19&集成Redis&创建定时模块schedule
#### Redis的集成以及相关理念
##### 简介
Redis 是一个高性能的开源内存数据库,它不仅可以用作缓存,还可以用作分布式数据库和消息中间件。虽然 Redis 可以用作缓存,但它不是一个纯粹的分布式缓存系统。
Redis 具有以下特点和用途:
1. **高性能缓存**:Redis 提供了内存中的数据存储,使其非常适合作为缓存。它的快速读写操作和支持丰富的数据结构,如字符串、哈希、列表、集合等,使其成为一个强大的缓存工具。
2. **分布式数据库**:Redis 具有分布式特性,可以配置为在多台服务器上运行,将数据分布在不同的节点上。这使得 Redis 能够用作分布式数据库,支持数据的持久化和复制,以及支持高可用性配置。
3. **消息中间件**:Redis 提供了发布/订阅机制,可以用作消息中间件,用于实现消息队列和事件处理。
虽然 Redis 可以用作缓存,但它不同于专门为缓存设计的系统(如 Memcached)。Redis 具有更多的功能,更适合用于多种用途,包括缓存、数据库、消息队列等。它在许多大型应用程序中被广泛用于不同的用途。
因此,Redis 可以用作分布式缓存,但它也可以用作分布式数据库和消息中间件,具有更广泛的用途。根据您的需求,您可以配置 Redis 以满足不同的用例。
##### 集成Redis
要在Spring Boot应用程序中集成Redis,您需要遵循以下步骤:
1. **添加依赖**:首先,您需要在项目的`pom.xml`文件中添加Spring Boot的Redis依赖。这将包括Spring Data Redis和您选择的具体的Redis客户端库,如Lettuce或Jedis。以下是一个示例依赖配置:
```
xmlCopy code
org.springframework.boot
spring-boot-starter-data-redis
```
2. **配置Redis连接**:在Spring Boot应用程序的配置文件(通常是`application.properties`或`application.yml`)中,配置Redis连接信息,包括主机、端口和密码(如果需要)。以下是一个示例配置:
```yaml
propertiesCopy codespring.redis.host=your-redis-host
spring.redis.port=6379
spring.redis.password=your-redis-password
```
3. **创建RedisTemplate**:您可以创建一个`RedisTemplate` bean,用于与Redis进行交互。通常,您需要配置`RedisTemplate`的序列化器,以确保数据能够正确地存储和检索。
```java
javaCopy codeimport org.springframework.context.annotation.Bean;
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;
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
```
4. **使用Redis**:您现在可以在应用程序中注入`RedisTemplate`,并使用它来执行Redis操作,如存储、检索和删除数据。以下是一个示例:
```java
javaCopy codeimport org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisService {
private final RedisTemplate redisTemplate;
public RedisService(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void setKey(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
public Object getKey(String key) {
return redisTemplate.opsForValue().get(key);
}
public void deleteKey(String key) {
redisTemplate.delete(key);
}
}
```
5. **使用缓存注解** :如果您想要使用Spring的缓存注解,您可以在您的服务方法上添加`@Cacheable`、`@CachePut`、`@CacheEvict`等注解来配置方法级的缓存。
**Spring Boot的Spring Data Redis默认支持包括连接池配置、序列化和反序列化支持、事务管理等。** 您可以根据项目的需要,通过配置文件或Java配置类进行自定义。**默认情况下,Spring Boot会使用Jedis作为Redis客户端,但您也可以选择使用Lettuce作为替代选项。**-
总之,Spring Boot提供了内置的支持,使Redis集成变得非常简单,无需过多的手动配置。
这就是如何在Spring Boot应用程序中集成Redis。通过这些步骤,您可以轻松地与Redis进行交互,存储和检索数据,实现缓存,以及处理其他与Redis相关的操作。
#### 定时任务schedule
##### 创建定时任务模块schedule
定时任务是在预定时间间隔或特定时间点执行的任务。在Java应用程序中,您可以使用不同的方法来创建和管理定时任务。Spring框架提供了内置的支持来处理定时任务,通常使用注解或XML配置来定义任务和执行计划。以下是Spring中使用注解的方法来创建定时任务的示例:
1. **使用`@Scheduled`注解**:Spring提供了`@Scheduled`注解,可以用于标记方法,以指定方法的执行计划。以下是一个示例:
```
javaCopy codeimport org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyScheduledTask {
@Scheduled(fixedRate = 5000) // 每5秒执行一次
public void doSomething() {
// 执行任务逻辑
}
}
```
在上述示例中,`@Scheduled(fixedRate = 5000)`指定了任务应该每5秒执行一次。
1. **使用`@EnableScheduling`注解**:要启用基于注解的定时任务,您需要在Spring配置类上添加`@EnableScheduling`注解。
```
javaCopy codeimport org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableScheduling
public class AppConfig {
// 配置类
}
```
这样,Spring会扫描被`@Scheduled`注解标记的方法并创建定时任务。
1. **更复杂的计划**:您可以使用`cron`表达式来指定更复杂的任务计划。例如:
```
javaCopy code@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
public void doSomething() {
// 执行任务逻辑
}
```
除了基于注解的定时任务,您还可以使用Spring的`TaskScheduler`接口和相关类来编程方式创建和管理定时任务。
请注意,Spring的定时任务是在应用程序的上下文中执行的,因此它们可以访问应用程序的其他组件和服务。这使得它们非常适合执行各种自动化和计划任务,例如数据备份、报告生成、数据同步等。
##### @Schedule底层原理
`@Scheduled`注解的底层实现依赖于Spring框架的任务调度功能。Spring使用`TaskScheduler`接口来实现任务调度,而`@Scheduled`注解是建立在此基础上的一种方便的方式,它将任务调度与方法关联在一起。
下面是`@Scheduled`注解的底层实现的主要步骤:
1. **Spring容器扫描**:Spring容器扫描应用程序中的组件,查找使用`@Scheduled`注解标记的方法。
2. **方法解析**:Spring会解析带有`@Scheduled`注解的方法,并确定注解中指定的执行计划,包括使用Cron表达式、固定速率或固定延迟等。
3. **任务调度器创建**:Spring会创建一个任务调度器,通常是`ThreadPoolTaskScheduler`的实例,用于执行定时任务。
4. **任务注册**:Spring将被标记的方法封装成一个任务对象,并将该任务对象注册到任务调度器中。
5. **任务触发**:任务调度器按照预定的时间表触发任务执行,执行任务方法。
6. **任务执行**:任务方法会在任务调度器触发时执行,这就是注解中定义的方法逻辑将被调用的地方。
7. **任务循环**:如果任务需要按照指定的执行计划重复执行,任务调度器将继续循环触发任务的执行。
8. **任务完成**:任务执行完成后,任务调度器将任务标记为完成,并在下一个触发时间点再次执行。
底层实现使用了Spring的任务调度框架,它允许执行简单或复杂的任务计划。任务调度框架提供了对不同类型的计划执行(如Cron表达式、固定速率、固定延迟等)的支持,并允许您动态管理任务。
总之,`@Scheduled`注解是Spring框架的一种高级抽象,它使得任务调度更加方便,允许您将方法与任务调度联系在一起,而无需手动配置任务调度器的详细信息。底层的任务调度框架提供了任务的创建、调度、执行和管理的基本功能,而`@Scheduled`注解将这些功能封装成一种易于使用的方式。
##### spring提供的任务调度器
Spring框架提供了多种任务调度器(`TaskScheduler`)的实现,除了`ThreadPoolTaskScheduler`之外,还有其他一些常见的实现。以下是一些Spring中可用的任务调度器:
1. **ThreadPoolTaskScheduler**:这是Spring框架默认的任务调度器,基于线程池。它可以并行执行多个任务,并提供了很多配置选项,如线程数、等待时间等。
2. **SimpleThreadPoolTaskExecutor**:这是另一种线程池实现,不同于`ThreadPoolTaskScheduler`,它通常在Spring集成的JMS(Java Message Service)中使用。
3. **TimerTaskExecutor**:基于Java的`java.util.Timer`类的任务调度器,适用于一些基本的定时任务。
4. **ConcurrentTaskScheduler**:基于`java.util.concurrent.ScheduledExecutorService`的任务调度器,它提供了线程池支持,适合并行执行任务。
5. **InheritableThreadLocalDecorator**:这是一个装饰器,它可以用于包装其他任务调度器以提供`InheritableThreadLocal`支持,以便子线程可以继承父线程的`ThreadLocal`变量。
6. **Custom TaskScheduler**:您还可以实现自定义的`TaskScheduler`接口,以根据特定需求创建自定义的任务调度器。
在选择任务调度器时,要考虑应用程序的需求,例如并发性、任务执行的时间和周期性等。不同的任务调度器提供了不同的特性和配置选项,因此应选择适合特定应用需求的实现。通常,`ThreadPoolTaskScheduler`是最常见的选择,因为它提供了广泛的配置选项,并允许并发执行多个任务。但对于特殊需求,其他任务调度器也可能更合适。
### 2023-10-22&用户模块
#### 接口文档
##### 注册用户信息
- URL:GET localhost:8080/user/register
- description:注册用户信息
- 请求参数:RPanUserRegister实体
- 响应:ResponseEntity
#### 业务分功能析
##### 用户注册
###### 注册用户信息
**分析:**用户注册需要保证幂等性,即客户端多次调用,但不会引起重复的注册或操作。同时,用户名应该是唯一的,不能出现同名的情况
**实现思路:**对数据库表的用户名添加唯一索引索引,当同一用户多次使用相同用户名注册时,上游业务应该将其作为异常捕获。
###### 创建新用户的根目录信息
## 知识点整理
### a.脚手架:
一个用于创建项目或应用程序的初始结构的工具或模板==(相当于framework模块,所有的工具类、配置类都准备好了,开发者只需要关注server模块的业务内容即可)==
### b.元数据:
描述数据的数据,它提供了关于数据的信息,如数据的属性、结构、内容等。元数据有助于更好地理解和管理数据。
### c.META-INF:
该目录通常用于存储与项目元数据相关的信息和配置文件
### d.additional-spring-configuration-metadata.json文件:
作用是帮助 Spring Boot 的自动配置(auto-configuration)机制更好地理解和处理你的自定义配置属性。这个文件允许你向 Spring Boot 添加自定义配置属性的元数据,以便在应用程序中使用这些属性时获得更好的智能 IDE 支持和文档化
### e.springboot的自动映射机制:
Spring Boot 在一定程度上会帮助自动映射 Swagger 的一些配置属性,但这取决于你的具体配置方式以及如何集成 Swagger。当你在 `application.yml` 或 `application.properties` 中设置了以 `swagger2.` 开头的属性时,Spring Boot 应用程序会自动识别这些属性并将它们映射到相应的配置类中,从而影响 Swagger 的行为。这是通过 Spring Boot 的属性绑定机制来完成的。
### f.@Configuration & @SpringBootConfiguration的区别
`@Configuration` 和 `@SpringBootConfiguration` 在功能上没有太大差异,但前者是 Spring Framework 的通用配置类注解,而后者是 Spring Boot 的特定配置类注解,用于更明确地表示配置类的用途。在 Spring Boot 项目中,使用 `@SpringBootConfiguration` 是一种更好的做法。
### g.构建打包分发插件时,为什么创建的xml文件能识别标签
XML(可扩展标记语言)是一种通用的标记语言,它允许用户定义自己的标签以表示数据的结构和语义。==XML本身并不具备特定的语义,而是一种用于表示数据的结构化格式。XML的标签通常是用户自定义的,只要它们遵循XML的语法规则。==
在你的示例中, **`` 标签是在Maven Assembly插件的上下文中使用的,而不是XML本身的一部分。** **Maven Assembly插件**定义了一种特定的XML配置文件结构,其中包括 `` 标签以及其他自定义标签和属性。这些标签和属性由Maven Assembly插件来解释和处理。
==Maven Assembly插件在构建过程中会读取你提供的配置文件(通常称为"assembly.xml"或其他名称)==,然后根据这些配置来执行特定的任务,如创建分发包。因此,XML文件中的 `` 标签之所以能够被识别,是因为Maven Assembly插件已经在其代码中实现了相关的逻辑,知道如何解释和处理这些特定的配置。
### h.若application或其他的配置文件不在Reources目录如何加载
在Spring Boot项目中,通常默认情况下`application.properties`(或`application.yml`)配置文件应位于`src/main/resources`目录下,因为Spring Boot使用这个默认位置来加载配置。如果你的配置文件不在`resources`目录下,你可以使用以下方法来加载配置文件:
1. **指定配置文件位置**:你可以通过在`application.properties`或`application.yml`中指定一个不同的配置文件位置来告诉Spring Boot从其他位置加载配置。在`application.properties`中,你可以添加如下配置:
```
propertiesCopy codespring.config.name=myconfig
spring.config.location=file:/path/to/your/config/directory/
```
这将告诉Spring Boot使用名为`myconfig`的配置文件,位于指定的目录`/path/to/your/config/directory/`。
2. **使用`@PropertySource`注解**:你可以在Spring Boot的配置类中使用`@PropertySource`注解来加载其他配置文件。这允许你加载不在`resources`目录下的配置文件。例如:
```
javaCopy code@Configuration
@PropertySource("file:/path/to/your/config/directory/myconfig.properties")
public class MyConfiguration {
// Configuration properties and beans
}
```
这将加载`/path/to/your/config/directory/myconfig.properties`文件中的属性。
3. **使用`SpringApplication.setDefaultProperties`**:你可以在应用程序的入口类中使用`SpringApplication.setDefaultProperties`方法来指定额外的配置文件位置,如下所示:
```
javaCopy codepublic static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setDefaultProperties(Collections.singletonMap("spring.config.name", "myconfig"));
application.run(args);
}
```
这将告诉Spring Boot加载名为`myconfig`的配置文件,你可以将文件路径指定为你希望的位置。
请注意,以上方法中的文件路径可以是绝对路径或相对路径,具体取决于你的需求。确保你有足够的权限来访问指定的文件路径。
### i.@ConfigurationProperties注解的作用
---
`@ConfigurationProperties` 是 Spring Boot 中的一个注解,用于绑定配置属性(Properties)到 Java 类的字段或方法。它允许您将应用程序的配置属性(通常是在 `application.properties` 或 `application.yml` 中定义的属性)映射到自定义的配置类中,以便在应用程序中方便地访问和使用这些属性。
`@ConfigurationProperties` 的主要作用包括:
1. **属性绑定**:它将应用程序的配置属性绑定到一个Java类的字段或方法。这意味着您可以在Java类中定义与配置属性相对应的字段,然后使用 `@ConfigurationProperties` 注解将它们关联起来。
2. **类型安全**:通过使用 `@ConfigurationProperties`,您可以实现类型安全的属性绑定,以避免在代码中直接访问配置属性的字符串键,减少了可能的拼写错误和类型错误。
3. **分组属性**:您可以将相关的配置属性分组到一个Java类中,这有助于组织和管理应用程序配置。
4. **IDE支持**:`@ConfigurationProperties` 提供了在集成开发环境中自动完成和验证属性的支持,使开发更加高效。
5. **自动提示**:在支持自动提示的IDE中,您可以获得关于配置属性的自动提示,以了解可用的配置选项。
使用 `@ConfigurationProperties` 的步骤如下:
1. 创建一个用于映射配置属性的自定义Java类,通常添加 `@ConfigurationProperties` 注解。
2. 在这个类中定义与配置属性相对应的字段或方法。
3. 在 `application.properties` 或 `application.yml` 文件中配置属性,使用前缀来区分不同的配置类。
4. 在应用程序中使用这个配置类,Spring Boot会自动将配置属性绑定到配置类的字段或方法。
示例:
```
javaCopy code@Configuration
@ConfigurationProperties(prefix = "myapp.datasource")
public class DataSourceProperties {
private String url;
private String username;
private String password;
// 省略 getter 和 setter 方法
}
```
在 `application.properties` 或 `application.yml` 文件中配置属性:
```
propertiesCopy codemyapp.datasource.url=jdbc:mysql://localhost:3306/mydb
myapp.datasource.username=myuser
myapp.datasource.password=mypassword
```
然后,您可以在应用程序中注入 `DataSourceProperties` 类,并访问配置属性。
```
javaCopy code@RestController
public class MyController {
@Autowired
private DataSourceProperties dataSourceProperties;
@GetMapping("/datasource")
public String getDataSourceInfo() {
return "URL: " + dataSourceProperties.getUrl() +
", Username: " + dataSourceProperties.getUsername();
}
}
```
这样,`@ConfigurationProperties` 允许您轻松管理和访问应用程序的配置属性,同时提供了类型安全和更好的可维护性。
### j.@ContextConfiguration注解的作用
---
`@ContextConfiguration`是Spring Framework中的一个注解,用于指定测试类的Spring应用程序上下文配置信息。它通常用于单元测试,以确保在测试期间正确配置和加载Spring应用程序上下文。
下面是有关`@ContextConfiguration`的详细解释:
1. **引入依赖**:首先,确保您的项目中包含了Spring Test相关的依赖,这通常包括`spring-test`库。在Maven项目的`pom.xml`中,您可以添加如下依赖:
```
xmlCopy code
org.springframework
spring-test
4.3.30.RELEASE
test
```
1. **使用`@ContextConfiguration`注解**:在您的测试类上,使用`@ContextConfiguration`注解指定Spring应用程序上下文的配置信息。这个注解允许您指定一个或多个XML配置文件或配置类。
```
javaCopy codeimport org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class MySpringTest {
// 测试代码
}
```
在上述示例中,`@ContextConfiguration`注解指定了一个XML配置文件 `applicationContext.xml`,它将被用来加载Spring应用程序上下文。
1. **SpringJUnit4ClassRunner**:通常,您还需要在测试类上使用`@RunWith(SpringJUnit4ClassRunner.class)`注解,以使用Spring提供的JUnit运行器来运行测试。
2. **加载配置信息**:`@ContextConfiguration`注解会告诉Spring从指定的配置文件或配置类中加载Spring应用程序上下文,使测试类能够访问应用程序上下文中的Spring bean。
3. **测试Spring应用程序上下文**:在测试方法中,您可以使用Spring容器中的bean进行测试,确保它们的行为符合预期。
`@ContextConfiguration`是一个强大的工具,允许您配置和加载Spring应用程序上下文,以便在单元测试中模拟应用程序的行为。这有助于确保应用程序在不同环境下的正确性和稳定性。您可以根据需要加载多个配置文件或配置类,以适应不同的测试需求。
### k.幂等性注册接口
幂等性注册接口指的是一种API或服务端点,它允许客户端多次调用,但不会引起重复的注册或操作。在这种接口上,无论客户端发送多少次请求,其效果都与仅发送一次请求相同。这是非常重要的,因为在分布式系统中,由于网络问题、客户端重试、服务端故障等原因,同一个请求可能被多次发送。
典型的幂等性注册接口应该满足以下特性:
1. **幂等性**:无论对同一资源进行多少次请求,结果都应该是相同的。即使客户端多次发送相同的请求,最终状态也不会发生变化。
2. **无副作用**:注册接口的执行不会引起不希望的副作用或状态更改。这意味着多次执行相同的请求不会对系统的状态造成不可逆的影响。
3. **幂等性检查**:服务端通常会在接收到请求时检查请求的幂等性,以确保重复请求不会导致重复操作。这可以通过检查请求中的唯一标识符、版本号或其他标志来实现。
幂等性注册接口在分布式系统中是非常有用的,因为它可以帮助防止重复注册、重复操作或重复数据创建,从而保证系统的一致性和可靠性。例如,金融交易、订单处理、用户注册等场景通常要求幂等性,以避免重复的交易或注册。
要实现幂等性注册接口,通常需要在服务端进行幂等性检查,同时客户端也应该能够处理重复请求的响应。这可以通过生成唯一的请求标识符、使用幂等HTTP方法(如PUT或DELETE)等方式来实现。
### l.实际开发中的模块的常用模板
在实际应用程序开发中,通常会使用一些常用的模板包含以下模块:
1. **Controller(控制器)**:
- 作用:接收客户端请求,处理请求参数,调用适当的业务逻辑,并将结果返回给客户端。
- 主要任务:请求路由、参数解析、响应构建。
2. **Service(服务)**:
- 作用:包含业务逻辑,协调数据访问、处理业务规则,执行数据操作。
- 主要任务:业务逻辑的实现,数据访问的协调。
3. **Repository/DAO(数据访问层)**:
- 作用:与数据库或其他数据存储系统交互,执行数据的增删改查操作。
- 主要任务:数据访问、持久化。
4. **Model/Entity(模型/实体)**:
- 作用:表示应用程序的数据模型,通常与数据库表或其他数据结构相对应。
- 主要任务:定义数据结构、持久化对象。
5. **DTO/VO(数据传输对象/视图对象)**:
- 作用:用于在控制器和服务之间传输数据,通常是用于界面呈现的数据对象。
- 主要任务:数据传输、数据展示。
6. **Mapper(映射器)**:
- 作用:用于将实体对象与数据传输对象之间进行映射,将数据从一种形式转换为另一种形式。
- 主要任务:实体对象与DTO/VO之间的映射。
7. **Exception(异常处理)**:
- 作用:处理应用程序中的异常,提供错误信息和异常处理策略。
- 主要任务:异常处理、错误消息返回。
8. **Context(上下文实体):**
- 作用:常用于在一定范围内传递和存储数据,以便在不同部分的应用程序中访问。
- 主要任务:不同部分的应用程序中的数据传输
9. **Security(安全性)**:
- 作用:处理身份验证和授权,保护应用程序免受未经授权的访问。
- 主要任务:用户身份验证、访问控制。
10. **Validation(验证)**:
- 作用:验证输入数据,确保数据符合应用程序的要求。
- 主要任务:数据验证、错误报告。
11. **Configuration(配置)**:
- 作用:用于配置应用程序的设置、依赖关系和第三方服务。
- 主要任务:配置管理、依赖注入。
12. **Util(工具类)**:
- 作用:包含通用工具函数,可重用的辅助方法。
- 主要任务:通用函数、工具方法。
13. **Test(测试)**:
- 作用:包含单元测试、集成测试和端到端测试,用于验证应用程序的正确性。
- 主要任务:测试用例、测试数据。
这些模块通常用于构建一个完整的应用程序,它们有助于将应用程序的不同部分分离开来,提高代码的可维护性、可扩展性和可测试性。当然,具体的应用程序可能还需要其他自定义模块,以满足特定需求。
## 遇到的问题(BUG)
### 使用批处理文件带额外配置文件启动项目,配置文件不生效
**报错背景:**
在distribution模块构建打包内容时,希望通过批处理文件startup.bat启动项目的jar包,项目启动没有问题,但是其中引入的额外配置文件不生效
**目前解决方案:**
因为读取不到该额外配置文件application.yml(不在resources目录下),所有直接将该配置文件里的日志相关的配置放到了server模块的application.yml里,另外还有一个r-pan-server-logback.xml配置文件,因为也不在resource目录下,所以将其也放到server模块的resources目录下,令其生效
**原因:批处理文件无法带入额外的配置文件启动**
文件如下:
```bat
@echo off
rem 设置Java运行时路径
set "JAVA_HOME=C:\Program Files\Java\jdk1.8.0_251"
rem 设置Java运行时参数
set "JAVA_OPTS=-Xms512m -Xmx512m"
rem 设置Spring Boot应用的JAR文件名称
set "APP_JAR=E:\IDEA_Project\r-pan\distribution\target\r-pan-server\target\r-pan-server.jar"
rem 设置外部配置文件的路径
set "EXTERNAL_CONFIG=E:\IDEA_Project\r-pan\distribution\target\r-pan-server\conf\application.yml"
rem 拼接启动命令
set "COMMAND="%JAVA_HOME%"\bin\java %JAVA_OPTS% -jar E:\IDEA_Project\r-pan\distribution\target\r-pan-server\target\r-pan-server.jar --spring.config.name=application --spring.config.location=file:E:\IDEA_Project\r-pan\distribution\target\r-pan-server\conf\application.yml"
echo "Starting your Spring Boot application..."
%COMMAND%
echo "Your Spring Boot application has started!"
```
### l.@Transactional与@Test一起使用自动回滚
当在测试方法上同时使用 `@Transactional` 和 `@Test` 注解时,默认情况下,Spring 测试框架会在测试方法执行完成后自动回滚事务,以确保测试环境的干净状态。这是 Spring 测试框架的一个有用功能,它确保测试方法不会对数据库或其他资源产生永久性更改,从而避免测试之间的相互干扰。
如果您的测试方法执行成功,事务会回滚,不会保留对数据库的更改。如果测试方法失败,也会回滚事务,从而不会留下不一致的数据。
这种行为可以确保每次运行测试时,测试环境都处于相同的初始状态,提供可重复的测试结果。但如果您希望禁用默认的事务回滚行为,可以在测试方法上添加 `@Rollback(false)` 注解,这样测试方法将不会回滚事务,对数据库的更改将会保留。
### Mysql 8版本时区异常
```java
java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
```
**原配置 :**
```yaml
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/r-pan?characterEncoding=utf-8&serverTimeZone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
```
**原因:时区设置应该是`serverTimezone` 而不是 `serverTimeZone`**