在 Java 快速开发领域,若依(RuoYi) 毫无疑问是很多企业的首选脚手架。它就像一把瑞士军刀,开箱即用。

但很多开发者在使用时,往往陷入了“舒适区陷阱”:

❌ 只会点“下一步”生成单表 CRUD,遇到**“主子表(一对多)”**这种稍微复杂的业务就卡壳;

❌ 需求一变,不知道改 Controller 还是 Service,甚至搞不清 ruoyi-common 和 ruoyi-system 的区别;

❌ 面试被问到“若依如何保证主子表数据一致性”,支支吾吾答不上来。

只会用工具,你永远只是“API 调用工程师”;只有拆解工具,你才能进阶为架构师。

今天,我将结合多年的 Java 实战经验与 AI 辅助编程心得,带你通过一次“外科手术式”的拆解,彻底搞懂若依的前后端架构。本文包括以下几个章节,将详细介绍若依框架架构。每个章节分别讲述以下内容:

  • 项目概览

  • 后端6大模块详解:每个模块的职责、功能、依赖关系

  • 前端结构分析:目录结构、前后端对应关系、核心组件

  • CRUD完整流程:包含主子表操作实战案例

  • 技术架构深度解析 AI 提示词(Prompt)

核心技术栈

二、后端模块详解

项目采用Maven多模块结构,共6个核心模块:

2.1 模块结构树状图

ruoyi (父工程)
├── ruoyi-admin        [应用入口层]
├── ruoyi-framework    [框架核心层]
├── ruoyi-system       [业务实现层]
├── ruoyi-common       [通用工具层]
├── ruoyi-generator    [代码生成层]
├── ruoyi-quartz       [定时任务层]
└── ruoyi-vue          [前端vue页面层]

2.2 各模块详细职责

① ruoyi-admin - 应用入口层

职责:整个应用的启动入口和Web接口暴露

核心内容:

RuoYiApplication.java:Spring Boot启动类

controller目录:存放各种业务Controller

system:系统管理相关接口(用户、角色、菜单等)

monitor:系统监控接口(在线用户、日志等)

tool:工具接口(代码生成、Swagger等)

依赖关系:

依赖 ruoyi-framework(获取安全配置)

依赖 ruoyi-quartz(定时任务)

依赖 ruoyi-generator(代码生成)

新手小贴士:这是你启动项目运行的模块,相当于"总指挥"。所有HTTP请求的入口都在这里的Controller中。

② ruoyi-framework - 框架核心层

职责:提供安全认证、拦截器、配置等框架级功能核心内容:

framework/
├── config/           [配置类]
│   ├── SecurityConfig.java        // Spring Security配置
│   ├── RedisConfig.java           // Redis配置
│   ├── DruidConfig.java           // 数据库连接池配置
│   └── MyBatisConfig.java         // MyBatis配置
├── security/         [安全模块]
│   ├── filter/
│   │   └── JwtAuthenticationTokenFilter.java  // JWT过滤器
│   ├── handle/       // 认证失败、退出处理器
│   └── service/      // 用户详情、权限服务
├── aspectj/          [切面]
│   ├── LogAspect.java             // 日志切面
│   ├── DataScopeAspect.java       // 数据权限切面
│   └── RateLimiterAspect.java     // 限流切面
└── web/service/
    └── TokenService.java          // Token管理服务

关键设计思想:

JWT无状态认证:不使用Session,通过Token实现分布式会话

过滤器链:

   请求 
   → CorsFilter(跨域) 
   → JwtAuthenticationTokenFilter(Token验证) 
   → SecurityFilterChain(权限校验) 
   → Controller

AOP切面编程:通过注解实现日志、权限、限流等功能

依赖关系:

依赖 ruoyi-common(工具类)

依赖 ruoyi-system(用户、菜单等业务)

③ ruoyi-system - 业务实现层

职责:系统核心业务逻辑实现

标准分层结构(以用户管理为例):

system/
├── controller/
│   └── SysUserController.java      [接口层] 接收HTTP请求
├── service/
│   ├── ISysUserService.java        [接口定义]
│   └── impl/
│       └── SysUserServiceImpl.java [业务逻辑]
├── mapper/
│   └── SysUserMapper.java          [数据访问接口]
├── domain/
│   └── SysUser.java                [实体类]
└── resources/mapper/
    └── SysUserMapper.xml           [SQL映射文件]

内置功能模块:

用户管理(sys_user)

角色管理(sys_role)

菜单管理(sys_menu)

部门管理(sys_dept)

岗位管理(sys_post)

字典管理(sys_dict)

参数配置(sys_config)

操作日志(sys_oper_log)

登录日志(sys_logininfor)

依赖关系:依赖 ruoyi-common(工具类、基类)

④ ruoyi-common - 通用工具层

职责:提供项目通用组件、工具类、常量、异常等

核心内容:

common/
├── annotation/       [自定义注解]
│   ├── Log.java                    // 操作日志注解
│   ├── DataScope.java              // 数据权限注解
│   ├── RepeatSubmit.java           // 防重复提交注解
│   ├── RateLimiter.java            // 限流注解
│   └── Excel.java                  // Excel导出注解
├── core/             [核心类]
│   ├── controller/BaseController.java  // Controller基类
│   ├── domain/
│   │   ├── AjaxResult.java         // 统一返回结果
│   │   ├── BaseEntity.java         // 实体基类
│   │   └── model/LoginUser.java    // 登录用户信息
│   ├── page/
│   │   └── TableDataInfo.java      // 分页数据
│   └── redis/RedisCache.java       // Redis操作类
├── constant/         [常量类]
│   ├── Constants.java
│   └── HttpStatus.java
├── enums/            [枚举类]
├── exception/        [异常类]
├── utils/            [工具类]
│   ├── StringUtils.java
│   ├── DateUtils.java
│   ├── SecurityUtils.java          // 安全工具类
│   ├── poi/ExcelUtil.java          // Excel工具
│   └── file/FileUtils.java         // 文件工具
└── filter/           [过滤器]
    ├── XssFilter.java              // XSS过滤
    └── RepeatableFilter.java       // 可重复读取请求体

设计亮点:

统一返回格式:所有接口返回 AjaxResult

通用基类:BaseEntity 提供 createTime、updateTime 等公共字段

注解驱动:通过注解实现日志、Excel导出、数据权限等功能

⑤ ruoyi-generator - 代码生成层

职责:根据数据库表结构自动生成代码

生成内容:

Domain实体类

Mapper接口 + XML

Service接口 + 实现类

Controller接口

前端Vue页面(index.vue)

前端API(api.js)

菜单SQL

模板文件位置:

resources/vm/
├── java/
│   ├── domain.java.vm
│   ├── mapper.java.vm
│   ├── service.java.vm
│   ├── serviceImpl.java.vm
│   └── controller.java.vm
├── xml/mapper.xml.vm
├── vue/index.vue.vm
└── js/api.js.vm

新手小贴士:这是若依的"黑科技"!只需在页面上选择数据库表,点击生成,就能自动创建完整的CRUD代码,大大提高开发效率。

⑥ ruoyi-quartz - 定时任务层

职责:实现定时任务的调度管理

核心功能:

动态添加/修改/删除定时任务

任务执行日志记录

任务并发控制

Cron表达式配置

🎨 三、前端模块详解

3.1 目录结构

ruoyi-ui/
├── src/
│   ├── api/              [API接口]
│   │   ├── login.js              // 登录接口
│   │   ├── menu.js               // 菜单接口
│   │   └── system/               // 系统管理接口
│   ├── assets/           [静态资源]
│   │   ├── images/
│   │   └── styles/
│   ├── components/       [公共组件]
│   │   ├── Editor/               // 富文本编辑器
│   │   ├── FileUpload/           // 文件上传
│   │   ├── ImageUpload/          // 图片上传
│   │   └── RightToolbar/         // 表格工具栏
│   ├── directive/        [自定义指令]
│   │   ├── permission/           // 权限指令 v-hasPermi
│   │   └── dialog/               // 弹窗拖拽
│   ├── layout/           [布局组件]
│   │   ├── components/           // 头部、侧边栏、标签页
│   │   └── index.vue
│   ├── router/           [路由配置]
│   │   └── index.js
│   ├── store/            [Vuex状态管理]
│   │   ├── modules/
│   │   │   ├── user.js           // 用户信息
│   │   │   ├── permission.js     // 权限路由
│   │   │   └── settings.js       // 系统设置
│   │   └── index.js
│   ├── utils/            [工具类]
│   │   ├── request.js            // axios封装
│   │   ├── auth.js               // Token管理
│   │   └── dict.js               // 字典工具
│   ├── views/            [页面组件]
│   │   ├── login.vue             // 登录页
│   │   ├── index.vue             // 首页
│   │   └── system/               // 系统管理页面
│   │       ├── user/
│   │       ├── role/
│   │       └── menu/
│   ├── App.vue
│   ├── main.js           [入口文件]
│   └── permission.js     [路由守卫]
├── public/
│   └── index.html
├── .env.development      [开发环境配置]
├── .env.production       [生产环境配置]
└── vue.config.js         [Vue配置]

3.2 前后端对应关系

四、CRUD 完整流程

4.1 后端数据流

以用户列表查询为例:

① 前端发起请求
   GET /system/user/list?pageNum=1&pageSize=10

② 请求到达后端过滤器链
   CorsFilter → JwtAuthenticationTokenFilter → SecurityFilterChain

③ 进入Controller层
   @GetMapping("/list")
   public TableDataInfo list(SysUser user) {
       startPage();  // 开启分页
       List<SysUser> list = userService.selectUserList(user);
       return getDataTable(list);  // 封装分页数据
   }

④ Service层业务处理
   @Override
   public List<SysUser> selectUserList(SysUser user) {
       return userMapper.selectUserList(user);
   }

⑤ Mapper层数据库查询
   接口:SysUserMapper.selectUserList(SysUser user)
   XML:<select id="selectUserList" ...>
         SELECT * FROM sys_user WHERE ...
        </select>

⑥ 返回数据
   {
     "code": 200,
     "msg": "查询成功",
     "rows": [...],
     "total": 100
   }

4.2 前端调用流程

// ① API定义 (src/api/system/user.js)
export function listUser(query) {  
  return request({    
    url: '/system/user/list',
    method: 'get',
    params: query
  })
}

// ② 页面调用 (src/views/system/user/index.vue)
methods: {  getList() {
    this.loading = true;
    listUser(this.queryParams).then(response => {
      this.userList = response.rows;
      this.total = response.total;
      this.loading = false;
    });
  }
}

// ③ request.js统一拦截// 请求拦截:自动添加Token
request.interceptors.request.use(config => {
  const token = getToken();
  if (token) {
    config.headers['Authorization'] = 'Bearer ' + token;
  }
  return config;
})

// 响应拦截:统一处理错误
request.interceptors.response.use(response => {
  const code = response.data.code;
  if (code === 401) {
    // Token过期,跳转登录
  }
  return response.data;
})

4.3 主子表操作流程

以【合同管理(主表)+ 合同明细(子表)】为例:

数据库设计:

-- 主表
CREATE TABLE sys_contract (
  contract_id BIGINT PRIMARY KEY,
  contract_no VARCHAR(50),
  contract_amount DECIMAL(10,2),
  ...
);

-- 子表
CREATE TABLE sys_contract_detail (
  detail_id BIGINT PRIMARY KEY,
  contract_id BIGINT,  -- 外键关联主表
  product_name VARCHAR(100),
  quantity INT,
  unit_price DECIMAL(10,2),
  ...
);

​​​​​后端处理:

@Service
public class SysContractServiceImpl implements ISysContractService {

    @Autowired
    private SysContractMapper contractMapper;

    @Autowired
    private SysContractDetailMapper detailMapper;

    @Transactional  // 事务控制
    @Override
    public int insertContract(SysContract contract) {
        // 1. 插入主表
        int rows = contractMapper.insertContract(contract);

        // 2. 插入子表
        List<SysContractDetail> detailList = contract.getDetailList();
        if (detailList != null && !detailList.isEmpty()) {
            for (SysContractDetail detail : detailList) {
                detail.setContractId(contract.getContractId());
                detailMapper.insertContractDetail(detail);
            }
        }

        return rows;
    }
}

前端处理:

<template>
  <!-- 主表表单 -->
  <el-form :model="form">
    <el-form-item label="合同编号">
      <el-input v-model="form.contractNo"></el-input>
    </el-form-item>

    <!-- 子表表格 -->
    <el-table :data="form.detailList">
      <el-table-column label="产品名称" prop="productName"></el-table-column>
      <el-table-column label="数量" prop="quantity"></el-table-column>
      <el-table-column label="单价" prop="unitPrice"></el-table-column>
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button @click="handleDeleteDetail(scope.$index)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-button @click="handleAddDetail">添加明细</el-button>
  </el-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        contractNo: '',
        contractAmount: 0,
        detailList: []  // 子表数据
      }
    }
  },
  methods: {
    // 添加明细行
    handleAddDetail() {
      this.form.detailList.push({
        productName: '',
        quantity: 0,
        unitPrice: 0
      });
    },

    // 计算合同总额
    calculateTotal() {
      let total = 0;
      this.form.detailList.forEach(item => {
        total += item.quantity * item.unitPrice;
      });
      this.form.contractAmount = total;
    },

    // 提交表单
    submitForm() {
      this.calculateTotal();  // 计算总额
      addContract(this.form).then(response => {
        this.$message.success('新增成功');
      });
    }
  }
}
</script>

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐