RuoYi全栈开发实战:从零构建业务模块的避坑指南
在微服务架构中新增一个完整业务模块,往往涉及前后端十余个环节的协同配置。许多开发者虽然熟悉单个技术点,却在模块化开发中频繁遭遇"接口404"、"路由失效"、"跨域报错"等典型问题。本文将基于RuoYi-Cloud与RuoYi-App的实战组合,演示如何系统性地完成从数据库设计到前端联调的全流程开发,特别聚焦那些官方文档未曾明说的配置细节和排错技巧。
1. 后端模块工程化构建
1.1 模块创建与依赖管理
新建ruoyi-app模块时,建议采用继承父pom而非简单复制依赖。在pom.xml中需要特别注意以下关键配置:
<parent> <groupId>com.ruoyi</groupId> <artifactId>ruoyi</artifactId> <version>3.8.0</version> </parent> <dependencies> <!-- 必须包含的starter --> <dependency> <groupId>com.ruoyi</groupId> <artifactId>ruoyi-common-core</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis Plus配置 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> </dependencies>常见问题排查表:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 启动报Bean冲突 | 依赖版本不一致 | 使用mvn dependency:tree检查冲突 |
| 无法注入Mapper | 未扫描到包 | 在启动类添加@MapperScan("com.ruoyi.app.mapper") |
| 事务失效 | 代理模式错误 | 确认@EnableTransactionManagement已启用 |
1.2 领域模型与数据持久化
实体类设计应遵循RuoYi规范,建议采用Lombok简化代码:
@Data @TableName("app_user") public class AppUser { @TableId(type = IdType.AUTO) private Long userId; @NotBlank(message = "用户名不能为空") @Size(min = 2, max = 20) private String userName; // 逻辑删除标记(需配合全局配置) @TableLogic private Integer delFlag; }Mapper接口需要特别注意动态SQL的编写规范:
<select id="selectUserList" resultType="AppUser"> SELECT * FROM app_user <where> <if test="userName != null and userName != ''"> AND user_name LIKE concat('%', #{userName}, '%') </if> AND del_flag = '0' </where> </select>提示:MyBatis Plus的
@TableField注解可解决字段名映射问题,如@TableField("user_name")
2. Nacos配置中心实战
2.1 服务注册关键参数
在bootstrap.yml中,以下配置项直接影响服务发现:
spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: dev # 多环境隔离 group: DEFAULT_GROUP ephemeral: true # 是否临时实例 metadata: version: 1.0 # 元数据可用于灰度发布2.2 网关路由配置陷阱
网关配置ruoyi-gateway-dev.yml常见问题:
- 路径匹配冲突:多个服务配置了相同Path前缀
- 过滤器顺序错误:
StripPrefix应在认证过滤器之前 - 负载均衡失效:服务名未正确注册到Nacos
推荐的路由配置模板:
- id: ruoyi-app uri: lb://ruoyi-app predicates: - Path=/app/v1/** filters: - StripPrefix=2 # 去除/app/v1前缀 - name: AuthFilter args: excludePaths: /app/v1/public/*3. 前端联调深度优化
3.1 请求封装最佳实践
在utils/request.js中需要统一处理:
const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 10000, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json;charset=UTF-8' } }) // 请求拦截器 service.interceptors.request.use(config => { // 自动添加Token if (store.getters.token) { config.headers['Authorization'] = 'Bearer ' + getToken() } // 微服务网关标识 config.headers['Gateway-Type'] = 'mobile-app' return config })3.2 跨域解决方案对比
| 方案 | 适用场景 | 优缺点 |
|---|---|---|
| 网关CORS配置 | 生产环境 | 安全但配置复杂 |
| 开发代理 | 本地开发 | 简单需重启 |
| Nginx反向代理 | 测试环境 | 灵活但需运维 |
推荐开发环境配置:
devServer: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, pathRewrite: { '^/api': '' } } } }4. 全链路调试技巧
4.1 日志追踪方案
- SkyWalking链路追踪:
# 启动参数添加 -javaagent:/path/to/skywalking-agent.jar -Dskywalking.agent.service_name=ruoyi-app- 日志关联ID:
@Slf4j @RestController public class AppUserController { @GetMapping("/list") public TableDataInfo list() { log.info("查询用户列表请求到达"); MDC.put("traceId", UUID.randomUUID().toString()); // ... } }4.2 接口文档自动化
Swagger集成配置:
@Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.ruoyi.app.controller")) .paths(PathSelectors.any()) .build() .globalOperationParameters(Collections.singletonList( new ParameterBuilder() .name("Authorization") .description("访问令牌") .modelRef(new ModelRef("string")) .parameterType("header") .required(false) .build())); }联调阶段建议开启Knife4j增强UI:
knife4j.enable=true knife4j.production=false在实际项目交付中,模块初始化时最容易忽略的是Nacos配置的版本控制。我们团队曾因未指定配置版本号导致测试环境读取了生产配置,后来通过建立严格的配置命名规范避免了此类问题,例如采用{应用名}-{环境}-{版本}.yml的格式管理所有配置文件。