阅读视图

codebuddy.ai小试牛刀

project-rule.mdc


description: globs:

alwaysApply: true

X199508 项目开发规则

这是一个规则文件,用于帮助 AI 理解您的代码库和遵循项目约定。

项目概述

X199508是一个基于Spring Boot 3.3.10 + Java 21的多模块微服务架构项目,采用DDD(领域驱动设计)分层架构模式。

技术栈

后端技术栈: - 后端框架: Spring Boot 3.3.10 - Java版本: Java 21 - 数据库: MySQL + MyBatis-Plus - 缓存: Redis + Lettuce - 认证: Sa-Token - 文档: Knife4j (Swagger) - 构建工具: Maven - 日志: Logback

前端技术栈: - 前端框架: Vue 3.5.13 - 开发语言: TypeScript 5.6.3 - UI组件库: Element Plus 2.9.0 - 状态管理: Pinia 2.3.0 - 路由管理: Vue Router 4.5.0 - 构建工具: Vite 6.0.3 - 包管理器: pnpm >=9 - CSS框架: TailwindCSS 3.4.16 - HTTP客户端: Axios 1.7.9

模块架构

x199508/
├── api/           # Web层 - HTTP接口暴露
├── core/          # 核心层 - 通用响应、异常处理、工具类
├── auth/          # 认证授权模块 - 用户、管理员相关业务
├── common/        # 公共模块
│   ├── constant/  # 常量定义
│   ├── mybatis-plus/ # MyBatis-Plus配置
│   └── redis/     # Redis配置
└── web/           # 前端项目 - Vue3 + TypeScript + Element Plus
    ├── src/       # 源代码目录
    │   ├── api/   # API接口定义
    │   ├── components/ # 公共组件
    │   ├── views/ # 页面视图
    │   ├── utils/ # 工具函数
    │   └── store/ # 状态管理
    ├── build/     # 构建配置
    └── types/     # TypeScript类型定义

X199508 项目开发规则

这是一个规则文件,用于帮助 AI 理解您的代码库和遵循项目约定。

项目概述

X199508是一个基于Spring Boot 3.3.10 + Java 21的多模块微服务架构项目,采用DDD(领域驱动设计)分层架构模式。

技术栈

  • 后端框架: Spring Boot 3.3.10
  • Java版本: Java 21
  • 数据库: MySQL + MyBatis-Plus
  • 缓存: Redis + Lettuce
  • 认证: Sa-Token
  • 文档: Knife4j (Swagger)
  • 构建工具: Maven
  • 日志: Logback

强制性开发规范

1. 包命名约定

com.x199508.{模块名}.{分层}

分层结构: - controller - 控制器层 - service - 业务服务层 - model - 数据模型层 - entity - 实体类 - mapper - 数据访问层 - req - 请求参数类 - resp - 响应参数类 - dto - 数据传输对象 - config - 配置类 - utils - 工具类

2. 类命名规范

类型 命名规则 示例
Controller 以Controller结尾 AuthController
Service 业务服务以Service结尾 AdminService
DAO Service 数据访问服务以DaoService结尾 AdminDaoService
Entity 使用名词 Admin, User
DTO 以DTO结尾 LoginDTO, LoginResultDTO
Request 以Req结尾 AdminPageReq
Response 以Resp结尾 AdminPageResp

3. 方法命名规范

操作类型 命名规则 示例
Controller方法 使用动词 login, userInfo, logout
Service方法 动词+名词 userLoginInfo, getUserId
查询方法 get/find/query开头 getUserById, findUserList
新增方法 add/create/save开头 addUser, createAdmin
修改方法 update/modify/edit开头 updateUser, modifyStatus
删除方法 delete/remove开头 deleteUser, removeAdmin

代码模板规范

Controller层模板

@Tag(name = "模块名称")
@RestController
@RequestMapping(value = "模块路径")
@RequiredArgsConstructor
public class XxxController {

    private final XxxService xxxService;

    @PostMapping("action")
    @Operation(summary = "操作描述")
    public R<ResponseType> action(@Validated @RequestBody RequestType request) {
        return R.ok(xxxService.action(request));
    }
}

强制要求: - 必须使用 @Tag 注解标注模块名称 - 必须使用 @RequiredArgsConstructor 进行依赖注入 - 禁止使用 @Autowired - 统一使用 R<T> 作为响应包装类 - 请求参数必须使用 @Validated 进行校验 - 必须使用 @Operation 注解描述接口功能

Service层模板

@Service
@RequiredArgsConstructor
public class XxxService {

    private final XxxDaoService xxxDaoService;

    public ResponseDTO businessMethod(RequestDTO request) {
        // 1. 参数校验
        // 2. 业务逻辑处理
        // 3. 数据持久化
        // 4. 返回结果
    }
}

强制要求: - 业务服务层只处理业务逻辑,不直接操作数据库 - 必须通过DaoService进行数据访问 - 方法内部按照:校验→处理→持久化→返回的顺序组织代码

Entity层模板

@Data
public class XxxEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @TableId(type = IdType.AUTO)
    private Long id;

    @TableLogic(value = "null", delval = "now()")
    private LocalDateTime deletedDate;

    private Long creator;
    private Long editor;
    private LocalDateTime createDate;
    private LocalDateTime updateDate;
}

强制要求: - 必须实现 Serializable 接口 - 主键使用 @TableId(type = IdType.AUTO) - 逻辑删除使用 @TableLogic 注解 - 统一包含审计字段:creator、editor、createDate、updateDate、deletedDate

响应格式规范

统一响应类 R

public class R<T> {
    private int code;      // 响应码
    private String msg;    // 响应消息
    private T body;        // 响应数据
}

使用规范: - 成功响应: R.ok()R.ok(data) - 错误响应: R.error(msg)R.error(code, msg) - 参数错误: R.invalidParamError(msg) - 未找到: R.notFound(msg) - 认证错误: R.tokenError(msg)

响应码定义

  • 200: 成功
  • 400: 参数错误
  • 401: 未授权
  • 404: 资源不存在
  • 500: 服务器内部错误

异常处理规范

自定义异常类型

  • ToastException: 业务异常,用于用户友好提示
  • AuthException: 认证授权异常

全局异常处理

使用 @ControllerAdvice 统一处理异常,返回标准的错误响应格式。

数据库设计规范

表命名规范

  • 使用下划线命名法: sys_admin, sys_user
  • 主键字段统一命名为 id,类型为 BIGINT,自增

必需字段

所有表必须包含以下审计字段: - creator - 创建人ID (BIGINT) - editor - 修改人ID (BIGINT) - create_date - 创建时间 (DATETIME) - update_date - 修改时间 (DATETIME) - deleted_date - 删除时间 (DATETIME, 逻辑删除)

MyBatis-Plus配置

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted
      logic-delete-value: 1
      logic-not-delete-value: 0

认证授权规范

Sa-Token配置

  • Token名称: xxxxxxxxxxxx
  • Token有效期: 90天 (7776000秒)
  • 支持同一账号并发登录
  • Token风格: random-32

权限校验

  • 所有需要认证的接口必须进行权限校验
  • 使用 AuthService.getUserId() 获取当前用户ID
  • 认证失败统一抛出 AuthException

缓存规范

Redis配置

  • 连接池最大连接数: 8
  • 连接池最大空闲连接: 8
  • 连接池最小空闲连接: 0
  • 连接超时时间: 1分钟

缓存策略

  • 热点数据必须使用Redis缓存
  • 缓存key必须有明确的命名规范和过期时间
  • 必须考虑缓存穿透、击穿、雪崩问题

日志规范

日志级别

  • ERROR: 系统错误,需要立即处理
  • WARN: 警告信息,需要关注
  • INFO: 关键业务流程记录
  • DEBUG: 调试信息,仅开发环境使用

请求日志

使用AOP统一记录请求日志,包含: - 请求URL - 请求参数 - 响应结果 - 执行时间 - 客户端IP

注意: 敏感信息(如密码)不能记录到日志中

测试规范

单元测试

  • Service层方法必须编写单元测试
  • 测试覆盖率不能低于80%
  • 必须使用Mock进行依赖隔离
  • 测试方法命名: should_期望结果_when_测试条件

集成测试

  • 关键业务流程必须编写集成测试
  • 数据库操作测试必须使用事务回滚

配置管理规范

配置文件结构

  • application.yaml - 主配置文件
  • application-dev.yaml - 开发环境配置
  • application-prod.yaml - 生产环境配置

敏感信息处理

敏感信息使用环境变量注入:

spring:
  datasource:
    url: ${spring.datasource.url}
    username: ${spring.datasource.service}
    password: ${spring.datasource.password}

代码质量要求

注释规范

  • 类级别必须包含: 功能描述、作者、创建时间
  • 公共方法必须包含: 功能描述、参数说明、返回值说明
  • 复杂业务逻辑必须添加行内注释

代码复杂度限制

  • 单个方法行数不超过50行
  • 单个类行数不超过500行
  • 圈复杂度不超过10
  • 嵌套层级不超过4层

代码格式

  • 行长度不超过120字符
  • 使用4个空格缩进,不使用Tab
  • 提交前必须进行代码格式化

性能优化要求

数据库性能

  • 必须合理使用索引
  • 避免N+1查询问题
  • 大数据量查询必须使用分页
  • 禁止使用 SELECT *

连接池配置

  • HikariCP最大连接数: 10
  • Redis连接池最大连接数: 8
  • 必须设置合理的连接超时时间

安全要求

输入验证

  • 所有用户输入必须进行校验
  • 使用JSR-303注解进行参数约束
  • 必须防止SQL注入、XSS攻击

数据安全

  • 密码必须加密存储
  • 敏感数据传输必须加密
  • 日志中不能包含敏感信息

部署规范

Maven构建

clean install -DskipTests -T 12

环境配置

  • 开发环境: spring.profiles.active=dev
  • 生产环境: spring.profiles.active=prod

前端开发规范

1. 项目结构规范

web/
├── src/
│   ├── api/           # API接口定义
│   │   ├── auth.ts    # 认证相关接口
│   │   ├── user.ts    # 用户相关接口
│   │   ├── utils.ts   # API工具函数
│   │   └── types/     # 接口类型定义
│   ├── components/    # 公共组件
│   ├── views/         # 页面视图
│   │   ├── login/     # 登录页面
│   │   ├── system/    # 系统管理模块
│   │   │   ├── hooks.ts    # 系统模块公共hooks
│   │   │   └── role/       # 角色管理
│   │   │       ├── index.vue    # 角色列表页面
│   │   │       ├── form.vue     # 角色表单页面
│   │   │       └── utils/       # 角色管理工具
│   │   │           ├── hook.tsx     # 业务逻辑hooks
│   │   │           ├── types.ts     # 类型定义
│   │   │           └── rule.ts      # 表单验证规则
│   │   ├── permission/ # 权限管理模块
│   │   ├── error/     # 错误页面
│   │   └── welcome/   # 欢迎页面
│   ├── utils/         # 工具函数
│   │   ├── http/      # HTTP请求封装
│   │   └── auth.ts    # 认证工具
│   ├── store/         # Pinia状态管理
│   ├── router/        # 路由配置
│   └── style/         # 样式文件
├── types/             # 全局类型定义
└── build/             # 构建配置

2. 前端命名规范

  • 文件命名: 使用kebab-case,如user-list.vue
  • 组件命名: 使用PascalCase,如UserList
  • 变量命名: 使用camelCase,如userName
  • 常量命名: 使用UPPER_SNAKE_CASE,如API_BASE_URL
  • 接口命名: 以I开头,如IUserInfo

3. API接口规范

// API接口定义模板
export const getUserList = (data?: object) => {
  return http.request<IBaseResponse<IUserInfo[]>>("post", apiUrl("/admin/user/list"), {
    data
  });
};

// API工具函数
export const apiUrl = (url: string) =>
  process.env.NODE_ENV === "development" ? `/api${url}` : `${baseApiUrl}${url}`;

强制要求: - 所有API接口必须定义返回类型 - 使用统一的IBaseResponse<T>响应格式 - API路径必须使用apiUrl()函数包装,支持开发环境代理 - 请求方法必须明确指定(get、post等) - 开发环境使用/api前缀进行代理转发

4. 页面组件开发规范

4.1 页面组件结构

<template>
  <div class="main">
    <!-- 搜索表单 -->
    <el-form
      ref="formRef"
      :inline="true"
      :model="form"
      class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto"
    >
      <!-- 搜索条件 -->
    </el-form>

    <!-- 表格内容 -->
    <div ref="contentRef" :class="['flex', deviceDetection() ? 'flex-wrap' : '']">
      <PureTableBar title="页面标题" :columns="columns" @refresh="onSearch">
        <template #buttons>
          <el-button type="primary" @click="openDialog()">新增</el-button>
        </template>
        <template v-slot="{ size, dynamicColumns }">
          <pure-table
            ref="tableRef"
            :data="dataList"
            :columns="dynamicColumns"
            :pagination="pagination"
          >
            <template #operation="{ row }">
              <!-- 操作按钮 -->
            </template>
          </pure-table>
        </template>
      </PureTableBar>
    </div>
  </div>
</template>

<script setup lang="ts">
import { useHook } from "./utils/hook";

defineOptions({
  name: "PageName" // 必须定义组件名称
});

// 使用自定义hook处理业务逻辑
const {
  form,
  loading,
  columns,
  dataList,
  pagination,
  onSearch,
  resetForm,
  openDialog
} = useHook();
</script>

4.2 业务逻辑Hook规范

// utils/hook.tsx
export function useHook() {
  const form = reactive({
    name: "",
    status: ""
  });

  const dataList = ref([]);
  const loading = ref(false);

  // 表格列定义
  const columns: TableColumnList = [
    {
      label: "序号",
      type: "index",
      width: 70
    },
    {
      label: "名称",
      prop: "name"
    },
    {
      label: "操作",
      fixed: "right",
      slot: "operation"
    }
  ];

  // 分页配置
  const pagination = reactive<PaginationProps>({
    total: 0,
    pageSize: 10,
    currentPage: 1,
    background: true
  });

  // 搜索方法
  const onSearch = async () => {
    loading.value = true;
    try {
      // API调用逻辑
    } finally {
      loading.value = false;
    }
  };

  return {
    form,
    loading,
    columns,
    dataList,
    pagination,
    onSearch
  };
}

强制要求: - 必须使用<script setup>语法和defineOptions定义组件名 - 复杂业务逻辑必须抽离到独立的hook文件中 - 表格组件必须使用PureTableBarpure-table - 搜索表单必须使用统一的样式类名 - 必须使用TypeScript进行类型约束

5. 状态管理规范

// store模板
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    userInfo: null as IUserInfo | null,
    token: ''
  }),

  getters: {
    isLoggedIn: (state) => !!state.token
  },

  actions: {
    async login(loginData: ILoginData) {
      // 登录逻辑
    }
  }
});

6. HTTP请求规范

  • 统一使用封装的http实例
  • 请求拦截器自动添加Authorization头
  • 响应拦截器统一处理错误
  • 401错误自动跳转登录页
  • 支持token自动刷新机制

7. 路由配置规范

// 路由配置模板
{
  path: '/user',
  name: 'User',
  component: () => import('@/views/user/index.vue'),
  meta: {
    title: '用户管理',
    requiresAuth: true
  }
}

8. 类型定义规范

// 统一响应格式
export interface IBaseResponse<T = any> {
  code?: number;
  msg?: string;
  body: T;
}

// 分页响应格式
export type IListResponse<T> = { records: T[] } & IPagination;

interface IPagination {
  size: number;
  total: number;
  current: number;
  pages: number;
}

// 页面表单类型定义规范
interface FormItemProps {
  /** 字段名称 */
  name: string;
  /** 字段编码 */
  code: string;
  /** 备注信息 */
  remark: string;
}

interface FormProps {
  formInline: FormItemProps;
}

// 用户信息类型
export type UserResult = {
  success: boolean;
  data: {
    avatar: string;
    username: string;
    nickname: string;
    roles: Array<string>;
    permissions: Array<string>;
    accessToken: string;
    refreshToken: string;
    expires: Date;
  };
};

类型定义规范: - 接口字段必须添加JSDoc注释说明 - 复杂类型必须拆分为多个接口 - 表单相关类型统一使用FormItemPropsFormProps命名 - API响应类型必须明确定义success和data结构

9. 样式开发规范

  • 优先使用TailwindCSS工具类
  • 自定义样式必须使用scoped
  • 全局样式放在src/style/目录
  • 支持SCSS预处理器
  • 响应式设计必须考虑移动端适配

10. 构建和部署规范

# 开发环境
pnpm dev

# 构建生产环境
pnpm build

# 构建预发布环境
pnpm build:staging

环境配置: - 开发环境: .env.development - 生产环境: .env.production - 预发布环境: .env.staging

11. 代码质量规范

  • 必须通过ESLint检查
  • 必须通过Prettier格式化
  • 必须通过TypeScript类型检查
  • 提交前自动执行lint-staged检查
  • 使用Husky进行Git钩子管理

12. 系统管理模块开发规范

12.1 模块组织规范

src/views/system/
├── hooks.ts          # 系统模块公共hooks
├── role/             # 角色管理
│   ├── index.vue     # 列表页面
│   ├── form.vue      # 表单页面
│   └── utils/        # 工具文件
│       ├── hook.tsx  # 业务逻辑
│       ├── types.ts  # 类型定义
│       └── rule.ts   # 验证规则
└── user/             # 用户管理(类似结构)

12.2 公共Hooks规范

// system/hooks.ts
export function usePublicHooks() {
  const { isDark } = useDark();

  // 开关样式
  const switchStyle = computed(() => ({
    "--el-switch-on-color": "#6abe39",
    "--el-switch-off-color": "#e84749"
  }));

  // 标签样式
  const tagStyle = computed(() => (status: number) => ({
    "--el-tag-text-color": status === 1 ? "#389e0d" : "#cf1322",
    "--el-tag-bg-color": status === 1 ? "#f6ffed" : "#fff1f0"
  }));

  return { isDark, switchStyle, tagStyle };
}

12.3 表格操作规范

<template #operation="{ row }">
  <el-button link type="primary" @click="openDialog('修改', row)">
    修改
  </el-button>
  <el-popconfirm :title="`确认删除${row.name}?`" @confirm="handleDelete(row)">
    <template #reference>
      <el-button link type="primary">删除</el-button>
    </template>
  </el-popconfirm>
  <el-button link type="primary" @click="handlePermission(row)">
    权限
  </el-button>
</template>

12.4 权限树组件规范

<!-- 权限设置侧边栏 -->
<div v-if="isShow" class="permission-panel">
  <div class="panel-header">
    <div class="action-buttons">
      <IconifyIconOffline :icon="Close" @click="handleClose" />
      <IconifyIconOffline :icon="Check" @click="handleSave" />
    </div>
    <p class="panel-title">菜单权限({{ curRow?.name }})</p>
  </div>

  <el-input v-model="treeSearchValue" placeholder="搜索菜单" />

  <div class="tree-controls">
    <el-checkbox v-model="isExpandAll" label="展开/折叠" />
    <el-checkbox v-model="isSelectAll" label="全选/全不选" />
    <el-checkbox v-model="isLinkage" label="父子联动" />
  </div>

  <el-tree-v2
    ref="treeRef"
    show-checkbox
    :data="treeData"
    :check-strictly="!isLinkage"
    :filter-method="filterMethod"
  />
</div>

13. 前后端接口对接规范

  • 后端接口统一返回R<T>格式
  • 前端使用IBaseResponse<T>接收
  • 状态码约定:200成功,401未授权,400参数错误
  • 分页数据使用统一的分页格式
  • 错误信息必须用户友好
  • 开发环境API代理配置:/api -> http://127.0.0.1:19900

14. 组件库使用规范

14.1 Element Plus组件规范

  • 表格必须使用pure-table组件
  • 表格工具栏必须使用PureTableBar组件
  • 图标必须使用useRenderIcon函数渲染
  • 弹窗确认必须使用el-popconfirm组件

14.2 样式类名规范

// 搜索表单样式
.search-form {
  @apply bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto;

  :deep(.el-form-item) {
    margin-bottom: 12px;
  }
}

// 主内容区域
.main {
  // 主要内容样式
}

// 权限面板样式
.permission-panel {
  @apply min-w-[calc(100vw-60vw-268px)] w-full mt-2 px-2 pb-2 bg-bg_color ml-2 overflow-auto;
}

14.3 响应式设计规范

  • 必须使用deviceDetection()判断设备类型
  • 移动端必须使用flex-wrap布局
  • 表格宽度必须根据设备类型动态调整
  • 侧边栏显示必须考虑屏幕尺寸

15. 开发环境配置规范

15.1 Vite代理配置

// vite.config.ts
server: {
  port: VITE_PORT,
  host: "0.0.0.0",
  proxy: {
    "/api": {
      target: "http://127.0.0.1:19900",
      changeOrigin: true,
      rewrite: path => path.replace(/^\/api/, "")
    }
  }
}

15.2 环境变量配置

# .env.development
VITE_API_URL=http://127.0.0.1:19900
VITE_PORT=3000

# .env.production
VITE_API_URL=https://api.production.com

重要: 以上所有规则都是强制性的,在生成或修改代码时必须严格遵守,确保代码质量和项目的可维护性。

第一步提示词:

Role: RBAC系统架构师

Profile

  • language: 中文
  • description: 负责设计和实现基于角色的访问控制(RBAC)系统的全栈架构师
  • background: 具有5年以上Web系统开发经验,精通前后端分离架构
  • personality: 严谨、注重细节、善于系统思考
  • expertise: RBAC系统设计、数据库建模、API接口设计
  • target_audience: 开发团队、技术负责人

Skills

  1. 系统架构设计
  2. RBAC模型设计: 设计符合规范的RBAC核心模型
  3. 数据库设计: 设计高效的关系型数据库结构
  4. API设计: 设计RESTful风格的接口规范

  5. 开发实现

  6. 前端开发: 实现基于Vue/React的管理界面

  7. 后端开发: 实现基于Spring/Node.js的后端服务

  8. 权限控制: 实现细粒度的权限拦截机制

  9. 系统分析

  10. 代码审查: 分析现有代码结构和扩展点

  11. 集成方案: 设计与现有系统的无缝集成方案

Rules

  1. 基本原则:
  2. 遵循最小权限原则: 确保每个角色只拥有必要的权限
  3. 保持可扩展性: 设计应便于未来功能扩展
  4. 保证安全性: 所有接口必须经过严格权限验证

  5. 行为准则:

  6. 兼容现有系统: 充分利用已有admin和user表结构

  7. 清晰文档: 提供完整的API文档和数据库设计文档

  8. 代码规范: 遵循团队统一的代码风格和命名规范

  9. 限制条件:

  10. 不修改现有登录功能: 保持现有认证机制不变

  11. 不重复造轮子: 复用已有基础组件和工具类

  12. 性能约束: 确保权限检查不影响系统响应速度

Workflows

  • 目标: 开发完整的RBAC功能模块
  • 步骤 1: 分析现有代码结构,确定集成点
  • 步骤 2: 设计数据库模型(角色表、权限表、关联表等)
  • 步骤 3: 设计前后端API接口规范
  • 步骤 4: 实现后端核心权限控制逻辑
  • 步骤 5: 开发前端管理界面
  • 预期结果: 可用的RBAC系统,支持角色分配、权限管理等功能

Initialization

作为RBAC系统架构师,你必须遵守上述Rules和project-rule.md,按照Workflows执行任务

第二步提示词:

Role:Java全栈开发工程师

Background:企业需要将原有的分页结果对象从PageResult迁移到统一响应对象R,并开发前端权限管理界面,实现权限系统的可视化操作和管理。

Attention:注意前后端数据格式的一致性,确保权限系统的安全性和易用性,考虑系统的可扩展性。

Profile:

  • Author: nobita
  • Version: 1.0
  • Language: 中文
  • Description: 负责Java后端接口改造和前端权限管理界面开发的全栈工程师

Skills:

  • 精通Java Spring Boot框架开发
  • 熟悉前后端数据交互和接口设计
  • 掌握Vue.js或React等前端框架
  • 了解RBAC权限模型实现
  • 具备系统重构和代码优化能力

Goals:

  • 将后端PageResult对象替换为统一响应对象R
  • 设计并实现前端权限管理界面
  • 确保前后端数据交互的正确性
  • 实现权限的增删改查功能
  • 保证系统的安全性和性能

Constrains:

  • 保持与现有系统的兼容性
  • 遵循企业编码规范
  • 确保接口安全性
  • 考虑大数量权限数据的性能
  • 界面设计符合用户体验原则

Workflow:

  1. 分析现有PageResult使用场景和依赖关系
  2. 设计R对象的统一响应格式和异常处理机制
  3. 开发前端权限管理的基础框架和路由配置
  4. 实现权限的CRUD接口和前端交互逻辑
  5. 进行系统集成测试和性能优化

OutputFormat:

  • 提供完整的接口文档和前端组件说明
  • 输出系统改造的风险评估报告
  • 提交可执行的代码和单元测试用例

Suggestions:

  • 采用模块化开发方式,逐步替换原有组件
  • 使用Swagger等工具维护接口文档
  • 建立完善的权限数据校验机制
  • 采用前端路由守卫实现权限控制
  • 定期进行代码审查和性能分析

Initialization

作为Java全栈开发工程师,你必须遵守Constrains和project-rule.md,使用默认Language与用户交流。

分享一个提示词优化网站: https://prompt.always200.com/

  •  

Springboot 接收&返回 LocalDateTime 全自动时间戳互转

前言

从Java 8开始,LocalDateTime作为一种更高效的日期时间处理类被引入,用以替代旧版的Date。然而,在Spring Boot项目中,默认情况下前端传入和返回LocalDateTime的格式可能不符合期望(例如:期望为毫秒级时间戳)。因此,需要配置自定义的序列化器和反序列化器来满足需求。

注意事项

  • JavaScript中的Number类型整数取值范围是±2^53 - 1,而Java中的Long类型可以安全地表示更大的数值(64位),因此推荐在Java端使用LongString来接收和返回数据,以避免精度丢失问题。

解决方案

为了使Spring Boot应用能够正确地将LocalDateTime与毫秒级时间戳相互转换,可以通过自定义Jackson的序列化器和反序列化器来实现。以下是具体的实现代码:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Configuration
public class LocalDateTimeConfig {

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> {
            // 创建一个用于序列化和反序列化的DateTimeFormatter
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            // 添加自定义的LocalDateTime序列化器和反序列化器
            JavaTimeModule javaTimeModule = new JavaTimeModule();
            javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
            javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));

            // 将JavaTimeModule添加到ObjectMapper中
            builder.modules(javaTimeModule);
        };
    }
}
  •  

灵感时刻-2025-04-24 22:35:11

18岁时想拥有的东西,30岁的时候全都拥有了。那个时候真傻,总想着快点长大,去大城市。跟着流淌的车河,如云的大厦。仿佛这里才是每一个少年都应该去的地方,现在好了,我确实是和车河一起,流淌在了水泥丛林。24小时灯火通明的城市,像是一个庞大的机器,永远在高效冷静地转动。

  •  

SpringBoot中6种自定义starter开发方法

一、什么是SpringBoot Starter

在SpringBoot生态中,starter是一种特殊的依赖,它能够自动装配相关组件,简化项目配置。

官方提供了众多starter,如spring-boot-starter-web、spring-boot-starter-data-jpa等,但在实际业务中,我们常常需要开发自己的starter来封装通用功能,实现一次开发,多处复用。

自定义starter的核心价值在于:

• 封装复杂的配置逻辑,实现开箱即用 • 统一技术组件的使用规范,避免”轮子”泛滥 • 提高开发效率,减少重复代码 本文将详细介绍6种不同的自定义starter开发方法。

二、方法一:基础配置类方式

这是最简单的starter开发方法,通过创建一个包含@Configuration注解的配置类,使用@Bean方法定义需要注入的组件。

实现步骤 1. 创建Maven项目:命名遵循xxx-spring-boot-starter格式 2. 添加依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>
  1. 创建配置类:

    @Configuration
    public class SimpleServiceAutoConfiguration {
        
    @Bean
    public SimpleService simpleService() {
        return new SimpleServiceImpl();
    }
    }
    
  2. 创建自动配置文件:在resources/META-INF/spring.factories中添加:

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.example.SimpleServiceAutoConfiguration
    

使用方式

使用时只需要在项目中添加依赖:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>simple-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

优缺点分析

优点:

• 实现简单,上手容易 • 适合封装简单的功能组件

缺点:

• 不支持定制化配置 • 无法根据条件选择性装配 • 功能过于简单,适用场景有限

适用场景:适合封装简单的工具类或无需外部配置的功能组件。

三、方法二:条件装配方式

通过SpringBoot的条件装配机制,实现根据特定条件决定是否启用配置的starter。

实现步骤

  1. 创建Maven项目同上
  2. 创建配置类,添加条件注解:

    @Configuration
    @ConditionalOnClass(RedisTemplate.class)
    public class RedisServiceAutoConfiguration {
        
    @Bean
    @ConditionalOnMissingBean
    public RedisService redisService() {
        return new RedisServiceImpl();
    }
        
    @Bean
    @ConditionalOnProperty(prefix = "redis.cache", name = "enabled", havingValue = "true")
    public RedisCacheManager redisCacheManager() {
        return new RedisCacheManager();
    }
    }
    
  3. 配置自动装配文件同上

条件注解说明

SpringBoot提供了丰富的条件注解:

• @ConditionalOnClass:当类路径下有指定类时 • @ConditionalOnMissingBean:当容器中没有指定Bean时 • @ConditionalOnProperty:当配置文件中有指定属性时 • @ConditionalOnWebApplication:当应用是Web应用时 • @ConditionalOnExpression:基于SpEL表达式的条件

优缺点分析

优点:

• 智能装配,避免无用组件加载 • 可以根据环境条件决定是否启用功能 • 防止与已有Bean冲突

缺点:

• 配置逻辑较复杂 • 调试排错难度增加 • 需要考虑条件之间的优先级和冲突

适用场景:适合需要根据环境条件选择性启用的功能组件,如根据是否是Web环境决定是否启用Web相关功能。

四、方法三:属性绑定方式

通过@ConfigurationProperties实现自定义配置的starter,支持从配置文件中读取参数。

实现步骤

  1. 创建属性类:

    @ConfigurationProperties(prefix = "example.service")
    @Data
    public class ServiceProperties {
    /**
     * 是否启用服务
     */
    private boolean enabled = true;
        
    /**
     * 服务URL
     */
    private String url = "http://localhost:8080";
        
    /**
     * 连接超时时间
     */
    private int timeout = 3000;
    }
    
  2. 创建自动配置类:

    @Configuration
    @EnableConfigurationProperties(ServiceProperties.class)
    @ConditionalOnProperty(prefix = "example.service", name = "enabled", havingValue = "true", matchIfMissing = true)
    public class ExampleServiceAutoConfiguration {
        
    @Autowired
    private ServiceProperties properties;
        
    @Bean
    @ConditionalOnMissingBean
    public ExampleService exampleService() {
        return new ExampleServiceImpl(properties.getUrl(), properties.getTimeout());
    }
    }
    
  3. 配置元数据提示:创建META-INF/spring-configuration-metadata.json

    {
    "properties": [
    {
      "name": "example.service.enabled",
      "type": "java.lang.Boolean",
      "description": "Whether to enable example service.",
      "defaultValue": true
    },
    {
      "name": "example.service.url",
      "type": "java.lang.String",
      "description": "Service URL.",
      "defaultValue": "http://localhost:8080"
    },
    {
      "name": "example.service.timeout",
      "type": "java.lang.Integer",
      "description": "Connection timeout in milliseconds.",
      "defaultValue": 3000
    }
    ]
    }
    

优缺点分析

优点:

• 支持从配置文件读取参数,实现灵活配置 • 配置项有元数据提示,用户体验好 • 支持配置校验和默认值

缺点:

• 开发工作量增加 • 需要维护配置元数据 • 配置项过多时管理复杂

适用场景:适合需要通过外部配置定制化的功能组件,如各种客户端和连接池配置。

五、方法四:完全自动配置方式

结合前面方法,实现一个完整的自动配置starter,包含条件装配、属性绑定和多组件配置。

实现步骤

  1. 创建多个组件:

    // 核心服务接口
    public interface ComplexService {
    String process(String input);
    }
    
    // 实现类
    public class ComplexServiceImpl implements ComplexService {
    private final String endpoint;
    private final int timeout;
        
    public ComplexServiceImpl(String endpoint, int timeout) {
        this.endpoint = endpoint;
        this.timeout = timeout;
    }
        
    @Override
    public String process(String input) {
        // 实现逻辑
        return "Processed: " + input;
    }
    }
    // 辅助组件
    public class ServiceHelper {
    public void assist() {
        // 辅助功能实现
    }
    }
    
  2. 创建属性类:

    @ConfigurationProperties(prefix = "complex.service")
    @Data
    public class ComplexServiceProperties {
    private boolean enabled = true;
    private String endpoint = "http://api.example.com";
    private int timeout = 5000;
    private AdvancedConfig advanced = new AdvancedConfig();
        
    @Data
    public static class AdvancedConfig {
        private boolean cacheEnabled = false;
        private int cacheSize = 100;
    }
    }
    
  3. 创建自动配置类:

    @Configuration
    @EnableConfigurationProperties(ComplexServiceProperties.class)
    @ConditionalOnProperty(prefix = "complex.service", name = "enabled", havingValue = "true", matchIfMissing = true)
    public class ComplexServiceAutoConfiguration {
        
    @Autowired
    private ComplexServiceProperties properties;
        
    @Bean
    @ConditionalOnMissingBean
    public ComplexService complexService() {
        return new ComplexServiceImpl(
            properties.getEndpoint(), 
            properties.getTimeout()
        );
    }
        
    @Bean
    @ConditionalOnProperty(prefix = "complex.service.advanced", name = "cache-enabled", havingValue = "true")
    public CacheManager cacheManager() {
        return new SimpleCacheManager(properties.getAdvanced().getCacheSize());
    }
        
    @Bean
    public ServiceHelper serviceHelper() {
        return new ServiceHelper();
    }
    }
    
  4. 添加自动装配文件:在META-INF/spring.factories中添加配置 优缺点分析

优点:

• 功能完整,支持复杂场景 • 组件化设计,支持条件装配 • 灵活的配置选项

缺点:

• 实现复杂度高 • 需要考虑多组件间的依赖关系

适用场景:适合复杂的企业级功能组件,如分布式事务、安全认证等需要多组件协同工作的场景。

六、方法五:Enable模式方式

通过自定义@Enable注解,允许用户主动启用特定功能。

实现步骤

  1. 创建功能接口和实现类:

    public interface FeatureService {
    void execute();
    }
    
    public class FeatureServiceImpl implements FeatureService {
    @Override
    public void execute() {
        // 实现逻辑
    }
    }
    
  2. 创建@Enable注解:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Import(FeatureConfiguration.class)
    public @interface EnableFeature {
    /**
     * 模式设置
     */
    Mode mode() default Mode.SIMPLE;
        
    enum Mode {
        SIMPLE, ADVANCED
    }
    }
    
  3. 创建配置类:

    @Configuration
    public class FeatureConfiguration implements ImportAware {
        
    private EnableFeature.Mode mode;
        
    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        Map<String, Object> attributes = importMetadata.getAnnotationAttributes(
                EnableFeature.class.getName());
        this.mode = (EnableFeature.Mode) attributes.get("mode");
    }
        
    @Bean
    public FeatureService featureService() {
        if (mode == EnableFeature.Mode.SIMPLE) {
            return new SimpleFeatureServiceImpl();
        } else {
            return new AdvancedFeatureServiceImpl();
        }
    }
    }
    

使用方式

在应用主类中使用@Enable注解启用功能:

@SpringBootApplication
@EnableFeature(mode = EnableFeature.Mode.ADVANCED)
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

优缺点分析

优点:

• 显式启用功能,使用意图明确 • 支持通过注解参数定制功能 • 可以与自动配置结合使用

缺点:

• 需要用户主动添加注解 • 不完全符合SpringBoot开箱即用的理念 • 增加用户的使用负担

适用场景:适合可选功能或有多种使用模式的功能组件,如特定的集成方案或可选功能增强。

七、方法六:模块化与组合式starter

通过拆分功能模块,实现可组合的starter体系,用户可以按需引入所需功能。

实现步骤 1. 创建基础模块:

myproject-spring-boot-starter (父模块)
├── myproject-core-spring-boot-starter (核心功能)
├── myproject-web-spring-boot-starter (Web功能)
├── myproject-cache-spring-boot-starter (缓存功能)
└── myproject-security-spring-boot-starter (安全功能)
  1. 核心模块实现:

    // 在core模块中
    @Configuration
    @ConditionalOnClass(CoreService.class)
    public class CoreAutoConfiguration {
        
    @Bean
    @ConditionalOnMissingBean
    public CoreService coreService() {
        return new CoreServiceImpl();
    }
    }
    
  2. 功能模块实现:

    // 在web模块中
    @Configuration
    @ConditionalOnWebApplication
    @ConditionalOnClass(CoreService.class)
    public class WebAutoConfiguration {
        
    @Autowired
    private CoreService coreService;
        
    @Bean
    public WebService webService() {
        return new WebServiceImpl(coreService);
    }
    }
    
  3. 依赖管理:

    <dependency>
    <groupId>com.example</groupId>
    <artifactId>myproject-core-spring-boot-starter</artifactId>
    <version>${project.version}</version>
    </dependency>
    

优缺点分析

优点:

• 功能模块化,按需引入 • 减少不必要的依赖 • 便于团队协作开发 • 符合单一职责原则

缺点:

• 模块间依赖关系管理复杂 • 版本一致性维护困难 • 开发和测试工作量增加

适用场景:适合大型项目或平台型应用,需要根据不同业务场景选择不同功能组合的情况。

八、各种方法对比与选择建议

方法 实现难度 灵活性 可配置性 适用场景
基础配置类方式 ★☆☆☆☆ ★★☆☆☆ ★☆☆☆☆ 简单工具类封装
条件装配方式 ★★☆☆☆ ★★★☆☆ ★★☆☆☆ 环境敏感功能
属性绑定方式 ★★★☆☆ ★★★★☆ ★★★★★ 可配置组件
完全自动配置方式 ★★★★☆ ★★★★★ ★★★★★ 企业级复杂功能
Enable模式方式 ★★★☆☆ ★★★★☆ ★★★☆☆ 可选功能组件
模块化组合式方式 ★★★★★ ★★★★★ ★★★★★ 大型平台级应用

九、自定义starter开发最佳实践

  1. 命名规范 • 非官方starter命名:xxx-spring-boot-starter • 官方starter命名:spring-boot-starter-xxx
  2. 依赖管理 • 使用spring-boot-starter作为基础依赖 • 避免引入不必要的传递依赖 • 明确声明版本兼容性范围
  3. 配置设计 • 使用合理的配置前缀,避免冲突 • 提供合理的默认值 • 编写完整的配置元数据,提供IDE提示
  4. 条件装配 • 合理使用条件注解,避免不必要的组件加载 • 使用@ConditionalOnMissingBean避免覆盖用户自定义Bean • 考虑多种环境条件的组合场景
  5. 错误处理 • 提供清晰的错误提示 • 实现合理的降级策略 • 提供诊断和自检功能
  6. 文档化 • 编写详细的使用文档 • 提供配置示例 • 说明与其他组件的集成方式 十、总结 自定义starter是SpringBoot生态中重要的扩展机制,开发者可以根据不同的需求场景,选择合适的方式实现自己的starter。

从简单的基础配置类方式,到复杂的模块化组合式方式,每种方法都有其适用场景和优缺点。

开发自定义starter时,应遵循以下原则

  1. 遵循约定优于配置的理念
  2. 提供合理的默认值
  3. 允许用户定制化和覆盖默认行为
  4. 做好错误处理和降级策略
  •  

黑苹果睡眠间隔唤醒 AppleACPIPlatformPower Wake reason: RTC

通过终端命令查询最近1天内的唤醒情况log show --last 1d | grep "Wake reason"可以清晰的看到主要唤醒原因是kernel: (AppleACPIPlatform) AppleACPIPlatformPower Wake reason: RTC (Alarm) 这也是网上比较常见的异常唤醒原因,网上搜索之后得出解决方法,就是往引导配置里面添加一下补丁。

需要用到OpenCore Configurator根据对应的opencore版本下载对应的版本即可。

根据图片中的位置将以下补丁代码一一对应添加即可

Base: __ZN8AppleRTC18setupDateTimeAlarmEPK11RTCDateTime
Comment: Disable RTC wake scheduling
Count: 1
Enabled: True
Identifier: com.apple.driver.AppleRTC
Replace: C3

或者直接把下面的代码复制粘贴到config.plist文件中

<key>Patch</key>
<array>
	<dict>
		<key>Arch</key>
		<string>Any</string>
		<key>Base</key>
		<string>__ZN8AppleRTC18setupDateTimeAlarmEPK11RTCDateTime</string>
		<key>Comment</key>
		<string>Disable RTC wake scheduling</string>
		<key>Count</key>
		<integer>1</integer>
		<key>Enabled</key>
		<true/>
		<key>Find</key>
		<data></data>
		<key>Identifier</key>
		<string>com.apple.driver.AppleRTC</string>
		<key>Limit</key>
		<integer>0</integer>
		<key>Mask</key>
		<data></data>
		<key>MaxKernel</key>
		<string></string>
		<key>MinKernel</key>
		<string>19.0.0</string>
		<key>Replace</key>
		<data>ww==</data>
		<key>ReplaceMask</key>
		<data></data>
		<key>Skip</key>
		<integer>0</integer>
	</dict>
</array>

保存配置文件重启观察一天之后日志中的唤醒记录是否已经正常

  •  

Linux/Windows 系统 ollama 配置允许外网访问

如何在Linux和Windows系统中,分别通过停止服务、修改环境变量和设置OLLAMA_HOST来允许Ollama通过IP地址访问其接口。Linux使用systemd管理服务,而Windows需直接操作进程并设置环境变量。

Ollama在linux环境中如何支持外部或者宿主机通过IP访问其接口

1、首先停止ollama服务:systemctl stop ollama 2、修改ollama的service文件:/etc/systemd/system/ollama.service 在[Service]下边增加两行:

Environment="OLLAMA_HOST=0.0.0.0"
Environment="OLLAMA_ORIGINS=*"

或者如果要限制端口就加上软件

Environment="OLLAMA_HOST=0.0.0.0:11434" 
Environment="OLLAMA_ORIGINS=*"

端口根据实际情况修改

3、重载daemon文件 systemctl daemon-reload 4、启动ollama服务 systemctl start ollama

Ollama在windows环境中如何支持通过IP来访问接口

1、首先停止ollama服务的允许。由于windows下安装的ollama不是一个标准的windows service,所以只能直接杀掉两个ollama进程。

2、为当前windows系统添加环境变量:电脑-属性-高级系统设置-环境变量 变量:OLLAMA_HOST,值:0.0.0.0:11434

3、关掉已打开的命令行窗口,打开新命令行,用ollama serve或者ollama start来启动ollama服务,此时ollama服务在启动时将读取环境变量中的OLLAMA_HOST,支持IP端口访问

  •  

生日快乐🎂

叮叮叮🔔 按时长大啦😁 是个两岁的小朋友啦🤓IMG_2159.jpegIMG_2686.jpegIMG_3628.jpegIMG_3921.jpeg

  •  

灵感时刻-2024-12-09 23:10:43

有时候我也想和世界告别

这几年过得好快 失去了色彩

攒够了失望无奈

情绪调成静音 影子也会缺席

我快要沉入海底 已无可救药

  •  

Win10系统更新暂停期限突破:轻松延长至3650天教程

在使用Windows 10系统的过程中,许多用户都曾遇到过系统自动更新的烦恼。尤其是当系统提示即将进行更新,而我们又恰好处于工作或者娱乐的关键时刻,这时候暂停更新就显得尤为重要。然而,Windows 10系统默认的暂停更新期限只有35天,这对于许多用户来说显然是不够的。那么,当这35天的暂停期限到期后,我们是否还能继续暂停更新呢?答案是肯定的。本文将详细介绍如何突破Windows 10系统更新暂停的限制,将暂停期限轻松延长至3650天。

一、准备工作 在开始操作之前,我们需要确保已经关闭了Windows Update的自动更新功能,并且当前系统没有正在进行的更新任务。此外,由于我们将要修改注册表,因此请务必备份好注册表信息,以防操作失误导致系统出现问题。

二、修改注册表 打开注册表编辑器 首先,我们需要打开注册表编辑器。按下键盘上的【Win + R】组合键,打开运行窗口,输入【regedit】命令,然后按下【确定或回车】键,即可打开注册表编辑器。

允许应用更改设备 在弹出的用户账户控制窗口中,点击【是】以允许注册表编辑器对你的设备进行更改。

定位到目标路径 在注册表编辑器窗口中,依次展开到以下路径: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings

新建DWORD值 在右侧空白处,右键点击鼠标,选择【新建 - DWORD (32 位)值(D)】,然后将其命名为【FlightSettingsMaxPauseDays】。

设置暂停天数 双击打开【FlightSettingsMaxPauseDays】,在弹出的编辑DWORD(32位)值窗口中,将基数选择为【十进制】,然后在数值数据栏中输入你想暂停更新的天数。例如,我们可以输入【3650】,然后点击【确定】按钮。

三、验证结果 完成上述步骤后,我们可以返回到Windows Update的设置界面,查看暂停更新的天数是否已经被修改为我们设置的天数。如果一切正常,你会发现暂停更新的天数已经成功延长至3650天。

  •  

灵感时刻-2024-11-26 09:38:22

一些人涌向城市,却对人毫无兴趣;每天与人打交道,却对人充满倦意,这似乎成了一种生活的现实,却是现实的可悲。IMG_6463.jpeg

  •  

中年男人最大的悲哀是什么?

前些年花了1w给自己配了个电脑,配之前想着以后没事能在家打几盘游戏,已经好几年过去了、除了电脑买回来的那天下载了一些游戏之外、包括最近的黑猴玩了几把之后,就一把没打过,今年已经到了而立之年了,生活太累了。

  •  

灵感时刻-2024-07-26 14:05:35

一个人如果不看书,那么他的价值观就会由他身边的人决定。 因为他没有别的输入途径,只能模仿身边的人或者慢慢被环境所改变, 周围流行什么,就跟随什么。 永远找不到自己。

  •