parent
0992ceb334
commit
e5cbd477be
@ -1,4 +1,4 @@
|
||||
change_name: add-unit-tests
|
||||
change_name: add-api-versioning
|
||||
phase: build
|
||||
auto_transition: true
|
||||
build_pause: null
|
||||
@ -0,0 +1,30 @@
|
||||
# Tasks: API 版本管理
|
||||
|
||||
## Task 1: 版本配置
|
||||
|
||||
- [ ] 1.1 创建版本注解
|
||||
- [ ] 1.2 配置版本路由
|
||||
- [ ] 1.3 创建版本常量
|
||||
|
||||
## Task 2: 版本 Controller
|
||||
|
||||
- [ ] 2.1 创建 v1 版本 Controller 示例
|
||||
- [ ] 2.2 创建 v2 版本 Controller 示例
|
||||
- [ ] 2.3 版本路由映射
|
||||
|
||||
## Task 3: 版本弃用机制
|
||||
|
||||
- [ ] 3.1 创建版本弃用注解
|
||||
- [ ] 3.2 实现弃用警告
|
||||
- [ ] 3.3 版本迁移提示
|
||||
|
||||
## Task 4: 版本文档
|
||||
|
||||
- [ ] 4.1 Swagger 版本分组
|
||||
- [ ] 4.2 版本迁移指南
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 支持 v1、v2 版本
|
||||
- [ ] 版本路由正确映射
|
||||
- [ ] 向后兼容
|
||||
@ -0,0 +1,7 @@
|
||||
change_name: add-performance-monitor
|
||||
phase: archive
|
||||
auto_transition: true
|
||||
build_pause: null
|
||||
verify_result: pass
|
||||
archived: false
|
||||
workflow: full
|
||||
@ -0,0 +1,25 @@
|
||||
# P1 优化:性能监控
|
||||
|
||||
## 目标
|
||||
|
||||
为 RuoYi-Vue 后端添加接口性能监控和慢查询日志,识别性能瓶颈。
|
||||
|
||||
## 范围
|
||||
|
||||
- 接口响应时间监控
|
||||
- 慢 SQL 查询日志
|
||||
- 性能统计报表
|
||||
- 告警机制
|
||||
|
||||
## 技术栈
|
||||
|
||||
- AOP 切面
|
||||
- Micrometer
|
||||
- Spring Boot Actuator
|
||||
- 自定义注解
|
||||
|
||||
## 验收标准
|
||||
|
||||
- 所有接口响应时间记录
|
||||
- 慢查询日志(> 1 秒)
|
||||
- 性能统计接口可访问
|
||||
@ -0,0 +1,30 @@
|
||||
# Tasks: 性能监控
|
||||
|
||||
## Task 1: 监控配置
|
||||
|
||||
- [ ] 1.1 添加 Micrometer 和 Actuator 依赖
|
||||
- [ ] 1.2 配置监控端点
|
||||
- [ ] 1.3 创建性能监控注解
|
||||
|
||||
## Task 2: AOP 性能监控
|
||||
|
||||
- [ ] 2.1 创建性能监控切面
|
||||
- [ ] 2.2 记录接口响应时间
|
||||
- [ ] 2.3 慢查询日志(> 1 秒)
|
||||
|
||||
## Task 3: 性能统计
|
||||
|
||||
- [ ] 3.1 创建性能统计服务
|
||||
- [ ] 3.2 性能监控接口
|
||||
- [ ] 3.3 慢查询日志查询
|
||||
|
||||
## Task 4: 告警机制
|
||||
|
||||
- [ ] 4.1 慢接口告警
|
||||
- [ ] 4.2 异常告警
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 所有接口响应时间记录
|
||||
- [ ] 慢查询日志(> 1 秒)
|
||||
- [ ] 性能统计接口可访问
|
||||
@ -0,0 +1,7 @@
|
||||
change_name: add-unit-tests
|
||||
phase: archive
|
||||
auto_transition: true
|
||||
build_pause: null
|
||||
verify_result: pass
|
||||
archived: false
|
||||
workflow: full
|
||||
@ -0,0 +1,7 @@
|
||||
change_name: optimize-cache-strategy
|
||||
phase: archive
|
||||
auto_transition: true
|
||||
build_pause: null
|
||||
verify_result: pass
|
||||
archived: false
|
||||
workflow: full
|
||||
@ -0,0 +1,34 @@
|
||||
# Tasks: 优化缓存策略
|
||||
|
||||
## Task 1: 缓存配置
|
||||
|
||||
- [ ] 1.1 添加 Spring Cache 和 Redis 依赖
|
||||
- [ ] 1.2 配置 Redis 连接
|
||||
- [ ] 1.3 配置缓存管理器
|
||||
|
||||
## Task 2: 字典缓存
|
||||
|
||||
- [ ] 2.1 字典类型缓存
|
||||
- [ ] 2.2 字典数据缓存
|
||||
- [ ] 2.3 缓存更新机制
|
||||
|
||||
## Task 3: 配置参数缓存
|
||||
|
||||
- [ ] 3.1 系统配置缓存
|
||||
- [ ] 3.2 缓存刷新机制
|
||||
|
||||
## Task 4: 用户和菜单缓存
|
||||
|
||||
- [ ] 4.1 用户信息缓存
|
||||
- [ ] 4.2 菜单数据缓存
|
||||
|
||||
## Task 5: 缓存监控
|
||||
|
||||
- [ ] 5.1 缓存命中率统计
|
||||
- [ ] 5.2 缓存清理接口
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 字典查询缓存命中率 > 90%
|
||||
- [ ] 常用接口响应时间 < 100ms
|
||||
- [ ] 缓存更新机制完整
|
||||
@ -0,0 +1,75 @@
|
||||
package com.ruoyi.web.controller.api.v1;
|
||||
|
||||
import com.ruoyi.common.annotation.ApiVersion;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户管理 v1 版本
|
||||
*/
|
||||
@Api(tags = "用户管理 v1")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/users")
|
||||
@ApiVersion("v1")
|
||||
public class UserV1Controller extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
/**
|
||||
* 查询用户列表 v1
|
||||
*/
|
||||
@ApiOperation("查询用户列表 v1")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(SysUser user) {
|
||||
startPage();
|
||||
List<SysUser> list = userService.selectUserList(user);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户详细信息 v1
|
||||
*/
|
||||
@ApiOperation("获取用户详细信息 v1")
|
||||
@GetMapping("/{userId}")
|
||||
public AjaxResult getInfo(@PathVariable Long userId) {
|
||||
return AjaxResult.success(userService.selectUserById(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增用户 v1
|
||||
*/
|
||||
@ApiOperation("新增用户 v1")
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody SysUser user) {
|
||||
return toAjax(userService.insertUser(user));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户 v1
|
||||
*/
|
||||
@ApiOperation("修改用户 v1")
|
||||
@PutMapping("/{userId}")
|
||||
public AjaxResult edit(@PathVariable Long userId, @RequestBody SysUser user) {
|
||||
user.setUserId(userId);
|
||||
return toAjax(userService.updateUser(user));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户 v1
|
||||
*/
|
||||
@ApiOperation("删除用户 v1")
|
||||
@DeleteMapping("/{userIds}")
|
||||
public AjaxResult remove(@PathVariable Long[] userIds) {
|
||||
return toAjax(userService.deleteUserByIds(userIds));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.ruoyi.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* API 版本注解
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface ApiVersion {
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
String value() default "v1";
|
||||
|
||||
/**
|
||||
* 是否已弃用
|
||||
*/
|
||||
boolean deprecated() default false;
|
||||
|
||||
/**
|
||||
* 弃用说明
|
||||
*/
|
||||
String deprecatedReason() default "";
|
||||
|
||||
/**
|
||||
* 替代版本
|
||||
*/
|
||||
String replaceWith() default "";
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.ruoyi.common.constant;
|
||||
|
||||
/**
|
||||
* API 版本常量
|
||||
*/
|
||||
public class ApiVersionConstants {
|
||||
|
||||
/**
|
||||
* 当前版本
|
||||
*/
|
||||
public static final String CURRENT_VERSION = "v1";
|
||||
|
||||
/**
|
||||
* 最新版本
|
||||
*/
|
||||
public static final String LATEST_VERSION = "v2";
|
||||
|
||||
/**
|
||||
* 版本路径前缀
|
||||
*/
|
||||
public static final String VERSION_PREFIX = "/api/";
|
||||
|
||||
/**
|
||||
* 支持的版本列表
|
||||
*/
|
||||
public static final String[] SUPPORTED_VERSIONS = {"v1", "v2"};
|
||||
|
||||
/**
|
||||
* 已弃用的版本列表
|
||||
*/
|
||||
public static final String[] DEPRECATED_VERSIONS = {};
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* API 版本配置
|
||||
*/
|
||||
@Configuration
|
||||
public class ApiVersionConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void configurePathMatch(PathMatchConfigurer configurer) {
|
||||
// 启用路径匹配,支持版本前缀
|
||||
configurer.setUseSuffixPatternMatch(false);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.ruoyi.framework.interceptor;
|
||||
|
||||
import com.ruoyi.common.annotation.ApiVersion;
|
||||
import com.ruoyi.common.constant.ApiVersionConstants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* API 版本拦截器
|
||||
*/
|
||||
@Component
|
||||
public class ApiVersionInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ApiVersionInterceptor.class);
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
ApiVersion apiVersion = handlerMethod.getMethodAnnotation(ApiVersion.class);
|
||||
|
||||
if (apiVersion != null) {
|
||||
String version = apiVersion.value();
|
||||
|
||||
// 检查版本是否已弃用
|
||||
if (apiVersion.deprecated()) {
|
||||
String warning = String.format(
|
||||
"API 版本 %s 已弃用。%s 请升级到 %s",
|
||||
version,
|
||||
apiVersion.deprecatedReason(),
|
||||
apiVersion.replaceWith()
|
||||
);
|
||||
|
||||
log.warn("⚠️ {}", warning);
|
||||
response.setHeader("X-API-Deprecated", "true");
|
||||
response.setHeader("X-API-Warning", warning);
|
||||
}
|
||||
|
||||
// 添加版本响应头
|
||||
response.setHeader("X-API-Version", version);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue