Files
rui-docs/backend/业务应用模块创建规则.md
vifo a7f3ee3565 refactor: 全局替换 spring-ai -> rui-framework
同步仓库名称变更,涉及 16 个文件 66 处引用:
- ai-skills: 菜单配置
- backend/guides: AI操作手册、环境配置、部署、gitnexus、opencode 工作流
- backend: 模块创建规则、通信规范、协作工作流、实施规范
- frontend: 收银设计、管理后台实施计划
- standards: 数据库设计规范
2026-06-08 12:56:39 +08:00

11 KiB
Raw Permalink Blame History

业务应用模块创建规则

app/ 目录下创建业务模块,按子模块模式拆分。 app/ 目录整体不提交到 git。

模块结构

app/
├── pom.xml                           # 聚合所有业务模块
└── rui-{领域}/
    ├── pom.xml                       # 领域聚合 POM
    ├── rui-{领域}-api/               # [可部署] REST API 服务(有 main Class
    ├── rui-{领域}-common/            # [库] DTO、枚举、配置、工具
    ├── rui-{领域}-core/              # [库] Mapper、Entity、Service(数据库层)
    ├── rui-{领域}-provider/          # [库] 第三方集成(可选)
    └── rui-{领域}-task/              # [库] MQ 监听器 + 定时任务(可选)

三模块(最小配置)

模块 类型 作用
-api 可部署 REST 控制器、启动类、application.yml
-common DTO、VO、枚举、常量、配置属性
-core Mapper、Entity、ServiceMyBatis Plus

五模块(含第三方集成和异步任务)

模块 类型 作用
-provider 库(可选) 第三方 SDK/API 封装(支付、短信、AI 等)
-task 库(可选) MQ 监听器、定时任务、异步处理

包命名

com.rui.{领域}.api          # api 模块
com.rui.{领域}              # common 模块
com.rui.{领域}.core         # core 模块
com.rui.{领域}.provider     # provider 模块
com.rui.{领域}.task         # task 模块

POM 层级

app/pom.xml                 → parent: rui-parent (不加 relativePath)
  └── rui-{领域}/pom.xml    → parent: rui-app
        ├── rui-{领域}-api/ → parent: rui-{领域}
        ├── rui-{领域}-common/
        ├── rui-{领域}-core/
        ├── rui-{领域}-provider/  (可选)
        └── rui-{领域}-task/      (可选)

<relativePath> 一律不加,Maven 自动从本地仓库查找父 POM。

依赖关系

common ——→ rui-common-core
core ———→ rui-common-mybatis, rui-common-security, common
api ———→ core, rui-common-security, rui-common-web
provider → common
task ———→ core, common
  • 框架依赖rui-common-*):版本由 rui-parent BOM 管理,不加 <version>
  • 内部模块依赖rui-{领域}-*):加 <version>${project.version}</version>

app/pom.xml 模板

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.rui</groupId>
        <artifactId>rui-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

    <artifactId>rui-app</artifactId>
    <packaging>pom</packaging>

    <name>rui-app</name>
    <description>睿核科技 — 业务应用模块聚合</description>

    <modules>
        <module>rui-payment</module>
        <!-- 新增模块在此添加 -->
    </modules>
</project>

api 模块 POM 模板

<dependencies>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webmvc</artifactId>
    </dependency>
    <dependency>
        <groupId>com.rui</groupId>
        <artifactId>rui-{领域}-core</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>com.rui</groupId>
        <artifactId>rui-common-security</artifactId>
    </dependency>
    <dependency>
        <groupId>com.rui</groupId>
        <artifactId>rui-common-web</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>repackage</id>
                    <goals><goal>repackage</goal></goals>
                    <configuration><attach>true</attach></configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

启动类模板

package com.rui.{领域}.api;

import com.rui.common.security.annotation.EnableResourceServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableResourceServer
public class {Domain}ApiApplication {
    public static void main(String[] args) {
        SpringApplication.run({Domain}ApiApplication.class, args);
    }
}

日志配置模板

api 模块需复制日志配置文件:

cp docs/logback-spring-template.xml \
   app/rui-{领域}/rui-{领域}-api/src/main/resources/logback-spring.xml
  • 无需修改,自动读取 spring.application.name 作为日志目录名
  • 按级别分文件(debug / info / warn / error
  • 控制台彩色输出,dev 环境显示 DEBUG

注意事项

  1. app/ 目录加入 .gitignore,业务模块不提交到框架仓库
  2. api 模块需配置 @EnableResourceServer(资源服务器模式)
  3. 各模块 Bean 通过 AutoConfiguration.imports 自动注入,不在启动类上使用 scanBasePackages(参见下方「模块 Bean 注入规范」)
  4. Mapper 扫描由 rui-common-mybatis 统一处理(@MapperScan("com.rui.**.mapper")),各模块无需重复配置
  5. 白名单 URL 通过 security.oauth2.ignore-urls 在 Nacos 配置
  6. 本地开发配置如 config/application-dev.yml 也需 gitignore

Git 规则

业务应用模块(app/ 目录下的模块)使用独立的 Git 仓库管理,与框架主仓库完全分离。

仓库初始化

cd app/rui-{领域}
git init
git add .
git commit -m "feat(init): 初始化{领域}模块"
git remote add origin git@gitee.com:pigeon/rui-{领域}.git
git push -u origin master

提交规范

与框架主仓库一致:

  • 格式type(scope): 中文描述
  • typefeat(新功能)、fix(修复)、docs(文档)、refactor(重构)、chore(构建)
  • 示例feat(payment): 添加支付宝下单接口

推送规则

  • 本地开发:修改后自动 git commit,但不自动推送
  • 推送时机:由开发者手动执行 git push,或在完成阶段性开发后统一推送
  • 自动推送阈值:当未推送提交数 超过 10 个 时,自动推送到远程
  • 禁止:将业务模块代码提交到框架主仓库(app/ 已加入 .gitignore

与框架主仓库的关系

rui-framework/                          # 框架主仓库(git
├── backend/                        # 提交到框架仓库
├── docs/                           # 提交到框架仓库
├── app/                            # 不提交到框架仓库(.gitignore
│   └── rui-payment/                # 独立 Git 仓库
│       ├── .git/                   # 独立的 git 历史
│       └── ...

模块 Bean 注入规范

@SpringBootApplication 禁止扩大扫描范围

API 启动类上的 @SpringBootApplication 不得使用 scanBasePackages 参数扩大包扫描范围。

  • 错误示例:@SpringBootApplication(scanBasePackages = {"com.rui.payment"})
  • 正确示例:@SpringBootApplication

启动类应仅扫描自身所在包(com.rui.{领域}.api)及其子包。

跨模块 Bean 通过 AutoConfiguration 注入

其他模块需要暴露给 Spring 容器的 Bean@Service@Component@Mapper 等),由各模块自行通过 AutoConfiguration.imports 注册

实现方式

  1. 在模块中创建自动配置类(通常在 config 包下):
package com.rui.{领域}.core.config;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

@AutoConfiguration
@ComponentScan("com.rui.{领域}.core")
public class PaymentCoreAutoConfiguration {
}
  1. 在模块的 src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中注册:
com.rui.{领域}.core.config.PaymentCoreAutoConfiguration

原则

  • 每个可复用模块(core、provider、task)必须有自己的 AutoConfiguration
  • 启动类只需引入依赖,无需关心其他模块的包路径
  • rui-common-mybatis 已通过 AutoConfiguration.imports 自动注入并包含 @MapperScan("com.rui.**.mapper"),各模块无需重复配置 Mapper 扫描

Controller 路径规范

URL 格式

/{模块}/{功能}/{方法}

例如:/payment/trade/create/order/refund/query

控制器分类

控制器命名 路径 认证 说明
XxxController /{模块}/{功能}/* 需认证 常规业务接口
XxxEntryController /{模块}/entry/** 免认证 对外入口(收银台、H5 等)
XxxNotifyController /{模块}/notify/** 免认证 第三方回调(支付、消息等)
XxxInnerController /{模块}/inner/** 通过 @Inner 注解控制 内部 Feign 调用

Nacos 白名单配置

# Spring Boot 4 使用 PathPattern,不支持 /**/ 中间通配
# 需按模块显式列出白名单路径
security:
  oauth2:
    ignore-urls:
      - /payment/entry/**
      - /payment/notify/**
      - /user/entry/**
      - /actuator/**

示例

// 常规接口 — 需认证
@RestController
@RequestMapping("/payment/trade")
public class PaymentTradeController {
    @PostMapping("/create")
    public R<Trade> create(@RequestBody TradeRequest req) { ... }
}

// 对外入口 — 免认证
@RestController
@RequestMapping("/payment/entry")
public class PaymentEntryController {
    @PostMapping("/alipay")
    public R<PayResult> alipay(@RequestBody PayRequest req) { ... }
}

// 第三方回调 — 免认证
@RestController
@RequestMapping("/payment/notify")
public class PaymentNotifyController {
    @PostMapping("/alipay")
    public String alipayNotify(HttpServletRequest request) { ... }
}

// 内部调用 — @Inner 保护
@RestController
@RequestMapping("/payment/inner")
public class PaymentInnerController {
    @Inner
    @GetMapping("/trade/{id}")
    public Trade getTrade(@PathVariable Long id) { ... }
}