项目规则文档分享

前言

各位好,这是近半年我在ai编程的使用过程中,不断调整后的project_rules,包含了个人项目的框架设计和编码规范,分享给大家,希望对你有帮助

目录

  1. 项目概述
  2. 项目架构
  3. 后端开发规范
  4. 前端开发规范
  5. 微服务架构规范
  6. 数据库设计规范
  7. 安全与测试规范

1. 项目概述

本项目基于微服务架构的企业级云平台系统,采用前后端分离的开发模式。项目包含多个模块,支持多租户、权限管理、部门管理等企业级功能。

1.1 技术栈概览

  • 后端: Spring Boot 3.x + Spring Cloud 2023.x + MyBatis Plus
  • 前端: React 18 + TypeScript + Vite
  • 数据库: MySQL + Redis
  • 认证: OAuth2 + JWT
  • 消息队列: RocketMQ + Spring Cloud Stream
  • 监控: OpenTelemetry + Jaeger

2. 项目架构

2.1 整体架构

  • 微服务架构: 基于Spring Cloud微服务生态
  • 前后端分离: React + TypeScript前端,Spring Boot后端
  • 多模块设计: 按业务领域划分模块
  • 多租户支持: 平台级和租户级权限隔离

2.2 模块结构

v3-cloud/
├── v3-pom/                 # 依赖管理模块
├── v3-frame/               # 框架核心模块
├── v3-starter/             # 自动配置启动器
├── v3-module/              # 业务模块
├── v3-portal/              # 门户服务
└── v3-web-ui/              # 前端应用

3. 后端开发规范

3.1 代码结构规范

3.1.1 包结构规范

com.wenx.v3system.modular.{domain}/
├── controller/             # 控制器层
├── service/               # 业务服务层
│   └── impl/              # 服务实现
├── domain/                # 领域模型
│   ├── po/                # 持久化对象
│   ├── dto/               # 数据传输对象
│   ├── maps/              # 对象映射转换(MapStruct)
│   └── query/             # 查询条件对象
├── mapper/                # 数据访问层
└── config/                # 配置类

3.1.2 实体类规范

@Data
@EqualsAndHashCode(callSuper = true)
@TableName("table_name")
public class EntityName extends BaseEntity {

  @Serial
  private static final long serialVersionUID = 1L;

  /**
   * 字段描述
   */
  @TableField("column_name")
  private String fieldName;
}

要求:

  • 继承 BaseEntityBaseDeptEntity
  • 使用 @Data@EqualsAndHashCode(callSuper = true)
  • 使用 @TableName 指定表名
  • 添加详细的字段注释
  • 包含 serialVersionUID

3.1.3 对象映射规范(MapStruct)

项目使用 MapStruct 进行 PO 与 DTO 之间的对象映射转换,统一放置在 maps 包下。

@Mapper(componentModel = "spring")
public interface EntityMap {

  EntityMap INSTANCE = Mappers.getMapper(EntityMap.class);

  /**
   * DTO转PO
   */
  Entity toPo(EntityDto dto);

  /**
   * PO转DTO
   */
  EntityDto toDto(Entity po);

  /**
   * DTO列表转PO列表
   */
  List<Entity> toPoList(List<EntityDto> dtoList);

  /**
   * PO列表转DTO列表
   */
  List<EntityDto> toDtoList(List<Entity> poList);
}

要求:

  • 使用 @Mapper(componentModel = "spring") 注解,集成Spring容器
  • 提供 INSTANCE 静态实例用于非Spring环境调用
  • 提供双向转换方法:toPo()toDto()
  • 提供批量转换方法:toPoList()toDtoList()
  • 映射接口命名规范:{Entity}Map

3.2 分层职责规范

3.2.1 Controller层职责

控制器层只允许执行以下操作(不超过10行代码):

  1. 参数接收和验证:接收HTTP请求参数,进行基础验证
  2. 服务调用:调用对应的Service层方法
  3. 响应返回:将Service层结果封装为HTTP响应
  4. 权限验证:使用注解进行权限检查
@RestController
@RequestMapping("/api/v1/resource")
@RequiredArgsConstructor
@Slf4j
@Api(tags = "资源管理")
public class ResourceController {

  private final ResourceService resourceService;

  @GetMapping("/list")
  @ApiOperation("查询资源列表")
  @RequiresPermissions(SystemPermission.SYSTEM_READ_CODE)
  public R<PageResponse<ResourceDto>> list(ResourceQuery query) {
    return R.success(resourceService.page(query));
  }

  @PostMapping("/add")
  @ApiOperation("创建资源")
  @RequiresPermissions(SystemPermission.SYSTEM_ALL_CODE)
  public R<Long> add(@RequestBody ResourceDto dto) {
    return R.success(resourceService.create(dto));
  }
}

3.2.2 Service层职责

Service层必须承担以下职责:

  1. 业务逻辑实现:所有复杂的业务判断、数据处理逻辑
  2. 数据验证:业务规则验证、数据一致性检查
  3. 事务管理:使用@Transactional管理事务边界
  4. 外部服务调用:调用其他微服务或第三方服务
  5. 数据转换:使用MapStruct进行PO与DTO之间的转换
@Service
@RequiredArgsConstructor
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class SysRoleRestServiceImpl implements SysRoleRestService {

  private final SysRoleMapper roleMapper;
  private final SysRoleMenuMapper roleMenuMapper;

  @Override
  public void assignPermissionsToRoleByData(Long roleId, Object permissionData) {
    log.info("开始处理角色权限分配,角色ID: {}", roleId);
    
    // 复杂业务逻辑在Service层实现
    if (permissionData instanceof List) {
      processPermissionList(roleId, (List<?>) permissionData);
    }
    
    log.info("角色权限分配完成,角色ID: {}", roleId);
  }
}

3.3 Base层抽象使用规范

3.3.1 BaseRestController 基础控制器

项目提供标准化的基础控制器,自动提供完整的CRUD操作接口。

@RestController
@RequestMapping("/api/v3/sys/users")
public class SysUserRestController extends BaseRestController<SysUserDto, SysUserQuery, SysUserRestService> {

  public SysUserRestController(SysUserRestService service) {
    super(service);
  }

  // 自动获得标准CRUD接口:分页查询、详情查询、新增、更新、删除
}

重要技术限制:

警告 泛型类型擦除问题: 使用BaseRestController的超类方法返回视图时,由于Java泛型类型擦除机制,会导致JSON序列化失败。

解决方案: 在Service层明确指定返回类型

// 正确:在Service层明确返回类型
@Service
public class SysUserRestServiceImpl implements SysUserRestService {

  @Override
  public PageResponse<SysUserDto> page(SysUserQuery query) {
    // 明确指定返回类型,避免泛型擦除
    Page<SysUser> page = this.page(
            new Page<>(query.getPageNum(), query.getPageSize()),
            buildQueryWrapper(query)
    );

    List<SysUserDto> dtoList = SysUserMap.INSTANCE.toDtoList(page.getRecords());

    return PageResponse.<SysUserDto>builder()
            .records(dtoList)
            .total(page.getTotal())
            .current(page.getCurrent())
            .size(page.getSize())
            .build();
  }
}

3.4 缓存使用规范

3.4.1 缓存命名规范

项目使用Redis分布式缓存,统一使用@Cacheable@CacheEvict注解进行声明式缓存管理。

缓存命名格式

  • 使用冒号分隔的层级结构:{domain}:{entity}:{type}
  • 缓存Key使用简单动态传递:key = "#parameter"key = "'prefix:' + #parameter"

标准缓存命名示例

// 用户相关缓存
@Cacheable(value = "sys:user:permissions", key = "#userId")
@Cacheable(value = "sys:user:auth", key = "'account:' + #account")

// 权限相关缓存
@Cacheable(value = "permission:conditions", key = "#permissionId")
@Cacheable(value = "permission:conditions:table", key = "#tableName")

// 角色相关缓存  
@Cacheable(value = "sys:role:permissions", key = "#roleId + ':codes'")

3.4.2 缓存使用最佳实践

@Service
@RequiredArgsConstructor
public class SysPermissionConditionCacheServiceImpl implements SysPermissionConditionCacheService {

    private final SysPermissionConditionMapper permissionConditionMapper;

    // 缓存查询 - 懒加载模式
    @Override
    @Cacheable(value = "permission:conditions:table", key = "#tableName", unless = "#result.isEmpty()")
    public List<SysPermissionCondition> getByTableName(String tableName) {
        if (tableName == null) {
            return Collections.emptyList();
        }
        log.debug("从数据库加载表 {} 的权限条件", tableName);
        return loadByTableName(tableName);
    }

    // 缓存清除
    @Override
    @CacheEvict(value = "permission:conditions:table", key = "#tableName")
    public void refreshTableCache(String tableName) {
        log.debug("清除表 {} 的权限条件缓存", tableName);
    }
}

3.4.3 缓存设计原则

  1. 懒加载策略:缓存未命中时才读库,不使用预加载
  2. 细粒度缓存:按业务维度设计缓存Key,便于精确清除
  3. 条件缓存:使用unless条件避免缓存无效数据
  4. 及时清理:数据更新时必须清除相关缓存
  5. 统一命名:缓存命名保持与项目其他Service一致

3.5 开发禁止项

3.5.1 架构设计禁止项

  • 禁止在Controller层实现业务逻辑,所有业务逻辑必须在Service层实现
  • 禁止Controller方法超过10行代码,复杂逻辑必须委托给Service层
  • 禁止跨层调用,严格按照Controller -> Service -> Mapper的调用链
  • 禁止重复编写CRUD代码,必须使用BaseRestControllerBaseRestService
  • 禁止直接使用@Autowired注解,使用@RequiredArgsConstructor进行依赖注入

3.5.2 技术栈禁止项

  • 禁止使用JPA,项目统一使用MyBatis Plus
  • 禁止使用Sleuth+Zipkin,项目使用OpenTelemetry+Jaeger
  • 禁止引入Spring Boot 2.x或更低版本依赖,项目使用Spring Boot 3.x
  • 禁止使用非标准的返回格式,统一使用R<T>

3.5.3 类型安全禁止项

  • 禁止直接使用父类的泛型方法返回视图,必须在Service层明确指定返回类型
  • 禁止返回Object或裸对象,必须使用具体的DTO类型
  • 禁止在分页查询中忽略泛型指定,必须使用PageResponse.<DTO>builder()
  • 禁止省略MapStruct转换,直接返回Entity对象到前端

3.5.4 缓存使用禁止项

  • 禁止使用本地内存缓存,统一使用Redis分布式缓存
  • 禁止手动管理缓存,必须使用@Cacheable@CacheEvict注解
  • 禁止缓存命名不规范,必须使用冒号分隔的层级结构
  • 禁止缓存更新操作不清除相关缓存,必须使用@CacheEvict及时清理

3.5.5 安全禁止项

  • 禁止在代码中硬编码敏感信息(密码、密钥、Token等)
  • 禁止绕过权限验证,所有接口必须使用@RequiresPermissions进行权限控制
  • 禁止在日志中输出敏感信息(密码、身份证号、银行卡号等)
  • 禁止在代码中拼接SQL语句,使用MyBatis Plus的条件构造器

4. 前端开发规范

4.1 技术栈

  • 框架: React 18 + TypeScript
  • 构建工具: Vite
  • 状态管理: Zustand
  • 路由: React Router v6
  • UI组件: Ant Design
  • HTTP客户端: Axios
  • 代码规范: ESLint + Prettier

4.2 项目结构

src/
├── components/           # 通用组件
├── pages/               # 页面组件
├── hooks/               # 自定义Hooks
│   └── business/        # 业务hooks(按功能模块组织)
├── stores/              # 状态管理
├── services/            # API服务
├── utils/               # 工具函数
├── types/               # TypeScript类型定义
├── constants/           # 常量定义
├── assets/              # 静态资源
└── routes/              # 路由配置

4.3 业务逻辑分层规范

4.3.1 Hooks层架构规范

前端组件中的业务逻辑必须迁移到专门的business hooks层实现,组件仅负责UI渲染和事件转发。

一个页面一个hooks原则

  • 每个页面原则上只使用一个主要的business hook
  • 将所有相关的业务逻辑整合到一个hooks文件中
  • 避免创建过多的小粒度hooks导致组件复杂化

正确示例(统一hooks):

// hooks/business/useRoles.ts - 角色管理统一hooks
export const useRoles = () => {
  // 基础数据管理
  const [roles, setRoles] = useState([]);
  const [loading, setLoading] = useState(false);

  // 角色详情管理
  const [viewingRole, setViewingRole] = useState(null);
  const [detailsVisible, setDetailsVisible] = useState(false);

  // 表单管理
  const [modalVisible, setModalVisible] = useState(false);
  const [editingRole, setEditingRole] = useState(null);

  // 权限分配管理
  const [permissionModalVisible, setPermissionModalVisible] = useState(false);
  const [selectedPermissions, setSelectedPermissions] = useState([]);

  // 所有相关的业务方法
  const openRoleDetails = useCallback(async (role) => {
    // 详情页面逻辑
  }, []);

  const submitForm = useCallback(async (values) => {
    // 表单提交逻辑
  }, []);

  return {
    // 返回所有状态和方法
    roles, loading, viewingRole, detailsVisible,
    modalVisible, editingRole, permissionModalVisible,
    openRoleDetails, submitForm,
    // ...其他状态和方法
  };
};

// 组件使用
const RolesPage = () => {
  const {
    roles, loading, viewingRole, detailsVisible,
    openRoleDetails, submitForm, // ...其他
  } = useRoles(); // 只使用一个hooks

  return (
    <div>
      {/* UI渲染 */}
    </div>
  );
};

4.3.2 组件职责分离规范

组件层只允许执行以下操作

  1. UI渲染:渲染组件的界面元素
  2. 事件绑定:绑定hooks中的事件处理函数
  3. 条件渲染:根据hooks状态进行条件渲染
  4. 样式处理:处理组件的样式和布局

禁止在组件中进行的操作

  • 禁止API调用(使用hooks中的方法)
  • 禁止复杂的数据处理逻辑(迁移到hooks)
  • 禁止直接管理状态(使用hooks的状态)
  • 禁止在组件中定义复杂的事件处理函数

4.4 前端开发禁止项

4.4.1 架构设计禁止项

  • 禁止创建过多的小粒度hooks文件(如useRoleDetails、useRoleForm等)
  • 禁止在组件中直接定义复杂的事件处理函数
  • 禁止在组件中直接进行API调用或复杂数据处理
  • 禁止生成重复的类型定义和接口
  • 禁止创建不必要的工具类和帮助函数

4.4.2 编码规范禁止项

  • 禁止不使用TypeScript严格模式
  • 禁止组件名不使用PascalCase
  • 禁止文件名不使用kebab-case
  • 禁止不使用ESLint和Prettier进行代码质量控制

5. 微服务架构规范

5.1 服务拆分原则

  • 业务边界: 按照业务领域进行服务拆分
  • 数据独立: 每个服务拥有独立的数据库
  • 团队自治: 一个团队负责一个或多个相关服务
  • 技术栈统一: 保持技术栈的一致性

5.2 同步通信规范

使用OpenFeign进行服务间调用:

@FeignClient(name = "user-service", path = "/api/v1/users")
public interface UserServiceClient {

  @GetMapping("/{userId}")
  R<UserDto> getUserById(@PathVariable("userId") Long userId);

  @PostMapping("/batch")
  R<List<UserDto>> getUsersByIds(@RequestBody List<Long> userIds);
}

5.3 异步通信规范

使用Spring Cloud Stream + RocketMQ:

@Component
public class MessageProcessor {

  // 消息处理函数
  @Bean
  public Consumer<UserCreatedEvent> handleUserCreated() {
    return event -> {
      log.info("处理用户创建事件: {}", event);
      // 处理业务逻辑
    };
  }

  // 消息转换函数
  @Bean
  public Function<OrderCreatedEvent, NotificationEvent> processOrder() {
    return orderEvent -> {
      // 转换逻辑
      return NotificationEvent.builder()
              .userId(orderEvent.getUserId())
              .message("订单创建成功")
              .build();
    };
  }
}

// 消息发送
@Component
@RequiredArgsConstructor
public class MessageSender {

  private final StreamBridge streamBridge;

  public void sendUserCreatedEvent(UserCreatedEvent event) {
    streamBridge.send("userCreated-out-0", event);
  }
}

6. 数据库设计规范

6.1 命名规范

  • 表名使用下划线命名法,如:sys_user
  • 字段名使用下划线命名法,如:user_name
  • 索引名格式:idx_表名_字段名
  • 外键名格式:fk_表名_字段名

6.2 基础字段

所有业务表必须包含以下基础字段:

CREATE TABLE example_table (
  id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  create_by BIGINT COMMENT '创建人ID',
  update_by BIGINT COMMENT '更新人ID',
  deleted TINYINT NOT NULL DEFAULT 0 COMMENT '删除标记(0:正常,1:删除)',
  -- 业务字段
  INDEX idx_create_time (create_time),
  INDEX idx_deleted (deleted)
);

6.3 多租户支持

支持多租户的表需要添加租户字段:

tenant_id BIGINT NOT NULL COMMENT '租户ID',
INDEX idx_tenant_id (tenant_id)

7. 安全与测试规范

7.1 安全规范

7.1.1 认证与授权

  • 统一使用 OAuth2 + JWT
  • 访问接口必须经过权限验证
  • 严禁在代码中硬编码密钥或凭证

7.1.2 数据安全

  • 所有敏感数据(密码、token、身份证号)必须加密存储
  • 日志中禁止打印敏感信息
  • 传输层必须使用 HTTPS/TLS

7.1.3 安全编码规范

  • 禁止 SQL 拼接,必须使用参数化查询
  • 防止 XSS:前端输出必须转义
  • 防止 CSRF:后端启用 CSRF Token 校验
  • 使用 SonarQube 或 Checkmarx 进行代码安全扫描

7.2 测试规范

7.2.1 单元测试

  • 所有业务逻辑必须编写单元测试,覆盖率不低于 80%
  • 使用 JUnit5 + Mockito,禁止使用 JUnit4
  • 单元测试命名规范:方法名_场景_预期结果

7.2.2 集成测试

  • 使用 Spring Boot Test 进行集成测试
  • 引入 Testcontainers 模拟数据库、MQ、Redis 等外部依赖
  • 集成测试必须在 CI 中自动运行

7.2.3 前端测试

  • 前端使用 Jest + React Testing Library
  • 所有 hooks 和组件必须有快照测试或行为测试
  • 关键交互逻辑必须有 E2E 测试(Cypress 或 Playwright)

附录

A. 常用工具类

  • R<T>: 统一返回结果封装
  • BaseEntity: 基础实体类
  • PageResponse<T>: 分页响应封装
  • TraceContextManager: 链路追踪上下文管理工具

B. 权限常量

  • SystemPermission: 系统权限常量
  • PlatformPermission: 平台权限常量

C. 架构质量检查清单

后端代码检查

  • Controller方法是否超过10行代码?
  • 是否存在业务逻辑在Controller层实现?
  • 是否使用了BaseRestController/BaseRestService?
  • 是否使用了MapStruct进行对象转换?
  • 是否统一使用R返回格式?
  • Service层是否明确指定了返回类型,避免泛型擦除?
  • 分页查询是否使用PageResponse.<DTO>builder()指定泛型?
  • 是否避免返回Object或裸对象类型?

前端代码检查

  • 是否创建了过多的小粒度hooks文件?
  • 组件是否包含复杂的业务逻辑?
  • 是否在组件中直接进行API调用?
  • hooks是否按功能模块合理组织?
  • 是否遵循"一个页面一个主要hooks"原则?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前端学习指引大纲 1. HTML 基础 掌握 HTML 是前端开发的第一步。对于有 Java 背景的开发者,HTM...
    _刘小c阅读 514评论 0 0
  • 目录结构保持一致,使得多人合作容易理解与管理,提高工作效率。Vue标准项目 #简要说明 main.js主入口,ro...
    Zxinli阅读 4,474评论 3 1
  • 返回目录[https://github.com/GrowingGit/GitHub-Chinese-Top-Cha...
    wgl0419阅读 2,707评论 0 0
  • 在线预览:戳我 😘 本地预览: 按顺序执行完命令后,即可在 localhost:3000 端口看到以下内容: 概览...
    始悔不悟阅读 7,898评论 3 4
  • 一、项目 1.1 结构 项目结构示例如下: 其中user包表示业务功能,通常有多个,如order、product,...
    chadLi阅读 48评论 0 0