JDK 17 + Spring Boot 3.5.8:企业级开发技术栈全景

飞鱼系统技术栈全景解析

💡 摘要: 本文深入剖析飞鱼管理系统的完整技术栈架构,涵盖 Spring Boot 3.5.8、Spring Security 6、MyBatis、Redis 等核心技术选型。通过 RuoYi-Vue、RuoYi-Vue3 和飞鱼系统三个版本的详细对比,揭示技术升级背后的决策逻辑。包含 5 个技术选型误区、3 套性能优化方案 (启动速度提升 73%、内存占用降低 75%),以及企业级架构设计经验。适合 Java 后端开发工程师、系统架构师阅读,助你构建高性能、可扩展的企业级应用。


📊 一、技术架构总览

1.1 整体架构图

后端架构
用户层
前端应用

Vue 2.6 + Element UI
网关层

Nginx 反向代理
应用层

Spring Boot 3.5.8
安全认证

Spring Security 6 + JWT
Controller 层

RESTful API
Service 层

业务逻辑处理
Mapper 层

MyBatis ORM
MySQL 8.2
Redis 7.x

缓存/会话存储
对象存储

本地/S3
监控运维

Actuator + Prometheus
任务调度

Quartz 2.5

1.2 技术栈分层说明

层级 技术选型 职责描述
表现层 Vue 2.6 + Element UI 用户界面交互、数据展示
网关层 Nginx 反向代理、负载均衡、静态资源服务
应用层 Spring Boot 3.5.8 核心业务逻辑处理
安全层 Spring Security 6 + JWT 认证授权、权限控制
持久层 MyBatis 3.0.5 + PageHelper ORM 映射、分页查询
数据层 MySQL 8.2 + Redis 7.x 关系型数据存储 + 分布式缓存
工具层 FastJSON2/Hutool/Apache Commons 通用工具类库
监控层 Spring Boot Actuator + Oshi 系统监控、健康检查

🔧 二、后端技术栈详解

2.1 Spring Boot 3.5.8 - 核心框架

🎯 为什么选择 Spring Boot 3.5.8?

作为 Spring Boot 3.x 系列的最新稳定版本,3.5.8 带来了众多优势:

✅ 全面拥抱 Jakarta EE 9

xml 复制代码
<!-- 传统 Java EE → Jakarta EE 迁移 -->
<dependency>
  <groupId>jakarta.servlet</groupId>
  <artifactId>jakarta.servlet-api</artifactId>
  <version>6.0.0</version>
</dependency>

✅ 改进的依赖注入机制

  • 强制使用构造器注入 (推荐方式)
  • 更好的循环依赖检测
  • 支持 Record 类作为 Bean

✅ 原生支持 GraalVM

bash 复制代码
# 编译为 Native Image
mvn -Pnative native:compile

# 启动时间:30 秒 → 0.1 秒
# 内存占用:512MB → 128MB

✅ 可观测性增强

  • Micrometer Tracing 集成
  • 分布式追踪支持
  • 改进的健康检查端点
📦 核心 Starter 依赖
xml 复制代码
<properties>
  <spring-boot.version>3.5.8</spring-boot.version>
</properties>

<dependencies>
<!-- Web 基础功能 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 安全认证 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- 数据验证 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<!-- 监控运维 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- AOP 支持 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>

2.2 Spring Security 6.3+ - 安全基石

🔐 重大变更

Spring Security 6.x 相比 5.x 有颠覆性变化:

❌ 废弃 WebSecurityConfigurerAdapter

java 复制代码
// ❌ Spring Security 5.x 写法
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/public/**").permitAll()
            .anyRequest().authenticated();
    }
}

// ✅ Spring Security 6.x 写法
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(auth -> auth
            .requestMatchers("/public/**").permitAll()
            .anyRequest().authenticated()
        );
        return http.build();
    }
}

✅ Lambda DSL 语法

java 复制代码
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .csrf(csrf -> csrf.disable())
        .sessionManagement(session -> session
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        )
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/api/login").permitAll()
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}
🛡️ 飞鱼系统的安全特性
安全功能 实现方式 说明
认证鉴权 JWT Token 无状态认证,支持多终端
密码加密 BCrypt 强哈希算法,自动加盐
权限控制 @PreAuthorize 方法级别细粒度权限
XSS 防护 XssFilter 请求参数过滤
CSRF 防护 Token 验证 防止跨站请求伪造
限流保护 RateLimiter 防止恶意刷接口

2.3 MyBatis 3.0.5 - 持久层框架

🎯 为什么选择 MyBatis 而不是 JPA?

❌ JPA 的局限性:

java 复制代码
// ❌ 复杂查询难以维护
@Query("SELECT u FROM User u WHERE u.department.id = :deptId AND u.status = :status " +
       "AND (u.role = :role1 OR u.role = :role2) " +
       "ORDER BY u.createTime DESC")
List<User> findComplexUsers(@Param("deptId") Long deptId, 
                           @Param("status") Integer status,
                           @Param("role1") String role1,
                           @Param("role2") String role2);

// ❌ 动态 SQL 困难
@Query(value = "SELECT * FROM user " +
       "WHERE 1=1 " +
       "#{#username != null ? 'AND username LIKE %' + #username + '%' : ''} " +
       "#{#email != null ? 'AND email = ' + #email : ''}",
       nativeQuery = true)
List<User> findDynamicUsers(String username, String email);
// SQL 注入风险,难以维护

✅ MyBatis 的优势:

xml 复制代码
<!-- ✅ 复杂查询清晰易读 -->
<mapper namespace="com.feiyu.user.UserMapper">
  <select id="selectComplexUsers" resultMap="UserResult">
    SELECT u.*, d.dept_name, r.role_name
    FROM sys_user u
    LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
    LEFT JOIN sys_user_role ur ON u.user_id = ur.user_id
    LEFT JOIN sys_role r ON ur.role_id = r.role_id
    <where>
      <if test="deptId != null">
        AND u.dept_id = #{deptId}
      </if>
      <if test="status != null">
        AND u.status = #{status}
      </if>
      <if test="username != null and username != ''">
        AND u.username LIKE CONCAT('%', #{username}, '%')
      </if>
      <if test="email != null">
        AND u.email = #{email}
      </if>
    </where>
    ORDER BY u.create_time DESC
  </select>
</mapper>

  <!-- ✅ 动态 SQL 安全灵活 -->
<select id="selectDynamicUsers" resultMap="UserResult">
SELECT * FROM sys_user
<where>
  <if test="username != null and username != ''">
    AND username LIKE CONCAT('%', #{username}, '%')
  </if>
  <if test="email != null">
    AND email = #{email}
  </if>
  <if test="status != null">
    AND status = #{status}
  </if>
</where>
</select>

性能对比:

场景 JPA MyBatis 胜出者
简单 CRUD ⭐⭐⭐⭐⭐ 自动生成 ⭐⭐⭐ 手动编写 🏆 JPA
复杂查询 ⭐⭐ 难以维护 ⭐⭐⭐⭐⭐ 灵活控制 🏆 MyBatis
动态 SQL ⭐⭐ 容易注入 ⭐⭐⭐⭐⭐ 安全可靠 🏆 MyBatis
SQL 优化 ⭐⭐⭐ 黑盒优化 ⭐⭐⭐⭐⭐ 完全可控 🏆 MyBatis
学习成本 ⭐⭐⭐ 需要理解概念 ⭐⭐⭐⭐ 简单易学 🏆 MyBatis
📦 MyBatis 核心配置
xml 复制代码
<!-- pom.xml -->
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>3.0.5</version>
</dependency>

<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
yaml 复制代码
# application.yml
mybatis:
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  type-aliases-package: com.ant.cluster.system.domain
  configuration:
    map-underscore-to-camel-case: true  # 下划线转驼峰
    cache-enabled: true  # 开启二级缓存
    lazy-loading-enabled: false  # 关闭延迟加载
✨ 飞鱼的 ORM封装创新
java 复制代码
// ✅ 所有 Mapper 继承 BaseMapper
public interface SysUserMapper extends BaseMapper<SysUser, Long> {
    // 只需定义自定义查询方法
    SysUser selectByUserName(String userName);
}

// ✅ 所有 Service 继承 BaseService
@Service
public class SysUserService extends BaseServiceImpl<SysUser, Long> 
    implements ISysUserService {
    
    // 自动拥有 CRUD 方法
    // findById(id)
    // findAll()
    // save(entity)
    // deleteById(id)
    // ...
}

2.4 Druid 1.2.27 - 数据库连接池

🎯 为什么选择 Druid?
连接池 性能 监控 扩展性 社区活跃度
Druid ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
HikariCP ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐
DBCP2 ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐

Druid 核心优势:

  • ✅ 强大的监控功能 (Web 控制台)
  • ✅ SQL 防火墙 (WallFilter)
  • ✅ 慢 SQL 统计
  • ✅ 连接泄漏检测
  • ✅ 阿里出品,久经考验
📦 Druid 生产环境配置
yaml 复制代码
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 初始连接数
      initial-size: 5
      # 最小空闲连接
      min-idle: 10
      # 最大活跃连接
      max-active: 50
      # 获取连接超时时间
      max-wait: 60000
      # 心跳检测
      keep-alive: true
      # 连接超时时间
      connect-timeout: 5000
      # Socket 超时时间
      socket-timeout: 60000

      # 监控配置
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        login-username: admin
        login-password: your_password
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"

      # Filter 配置
      filter:
        stat:
          enabled: true
          db-type: mysql
          log-slow-query: true
          slow-query-millis: 1000
        wall:
          enabled: true
          config:
            drop-table-allow: false  # 禁止删除表
            truncate-allow: false    # 禁止清空表
        slf4j:
          enabled: true
          statement-create-after-log-enabled: false
          statement-close-after-log-enabled: false
          result-set-open-after-log-enabled: false
          result-set-close-after-log-enabled: false

2.5 Redis 7.x - 分布式缓存

🎯 Redis 在飞鱼系统中的应用场景
应用场景 Key 命名规范 数据结构 过期策略
用户 Token login_tokens:{uuid} String 2 小时
验证码 captcha_codes:{uuid} String 5 分钟
用户信息缓存 sys:user:{userId} Hash 30 分钟
字典数据缓存 sys:dict:{dictType} Hash 永久
限流计数 rate_limit:{api}:{userId} String 1 分钟
幂等性 Token idempotent:{token} String 5 秒
在线用户 online_users:{token} Hash 实时刷新
📦 RedisUtil 统一封装
java 复制代码
// ✅ 飞鱼系统统一使用RedisUtil
@Autowired
private RedisUtil redisUtil;

// String 操作
redisUtil.set("key", "value", 30, TimeUnit.MINUTES);
String value = redisUtil.get("key");

// Hash 操作
redisUtil.hset("user:1001", "name", "张三");
Map<String, Object> userInfo = redisUtil.hgetAll("user:1001");

// List 操作
redisUtil.lpush("task:queue", "task1", "task2");
List<Object> tasks = redisUtil.lrange("task:queue", 0, -1);

// 批量操作
List<String> keys = Arrays.asList("key1", "key2", "key3");
redisUtil.delete(keys);

2.6 FastJSON2 2.0.60 - JSON 序列化

🎯 为什么选择 FastJSON2?
JSON 库 性能 安全性 易用性 生态
FastJSON2 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
Jackson ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Gson ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐

FastJSON2 核心优势:

  • ✅ 性能比 FastJSON 1.x 提升 50%+
  • ✅ 修复了已知安全漏洞
  • ✅ 更好的泛型支持
  • ✅ 更小的包体积
📦 FastJSON2 配置
xml 复制代码
<dependency>
  <groupId>com.alibaba.fastjson2</groupId>
  <artifactId>fastjson2</artifactId>
  <version>2.0.60</version>
</dependency>
java 复制代码
// ✅ 统一 JSON 配置
@Configuration
public class JsonConfig {
    @Bean
    public HttpMessageConverters fastJsonHttpMessageConverters() {
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        fastJsonConfig.setCharset(StandardCharsets.UTF_8);
        
        // 配置序列化选项
        fastJsonConfig.setSerializerFeatures(
            SerializerFeature.PrettyFormat,      // 格式化输出
            SerializerFeature.WriteNullStringAsEmpty,  // null 字符串转为""
            SerializerFeature.WriteNullListAsEmpty,    // null 集合转为[]
            SerializerFeature.WriteDateUseDateFormat,  // 使用日期格式
            SerializerFeature.DisableCircularReferenceDetect  // 禁用循环引用检测
        );
        
        fastConverter.setFastJsonConfig(fastJsonConfig);
        return new HttpMessageConverters(fastConverter);
    }
}

🎨 三、前端技术栈深度对比

3.1 技术选型决策过程

在飞鱼系统开发初期,我们面临一个艰难的抉择:

复制代码
选项 A: 继续使用 Vue 2.6 + Element UI (若依原版)
选项 B: 升级到 Vue 3 + Element Plus (RuoYi-Vue3)
选项 C: 使用 Vue 3 + TypeScript (RuoYi-Vue3-Plus)

3.2 三大版本全方位对比

📊 核心技术对比表
特性/版本 飞鱼系统 RuoYi-Vue3 RuoYi-Vue3-TypeScript
Vue 版本 2.6.12 3.4+ 3.4+
脚本语言 JavaScript ES6+ JavaScript ES6+ TypeScript 5+
构建工具 Vue CLI 4.4.6 Vite 5+ Vite 5+
UI 组件库 Element UI 2.15 Element Plus 2.7+ Element Plus 2.7+
状态管理 Vuex 3.6 Pinia 2.1+ Pinia 2.1+
路由管理 Vue Router 3.4 Vue Router 4.3+ Vue Router 4.3+
HTTP 客户端 Axios 0.21+ Axios 1.x Axios 1.x
🎯 选择 Vue 2.6 的理由

尽管 Vue 3 已经成熟,但我们仍选择 Vue 2.6,基于以下考量:

✅ 技术成熟度

  • Vue 2.6 历经多年打磨,稳定性极高
  • 社区资源丰富,问题容易找到解决方案
  • 团队成员技术储备充足

✅ 生态完善

  • Element UI 组件齐全,文档完善
  • 第三方插件丰富 (图表、编辑器等)
  • 兼容性好,少有 breaking changes

✅ 学习成本低

  • Options API 易于理解
  • 无需学习 Composition API
  • 不需要 TypeScript 基础

⚠️ Vue 3 的挑战

  • Composition API 学习曲线陡峭
  • TypeScript 增加开发复杂度
  • 部分插件生态不完善
  • 迁移成本较高
💡 我们的建议
团队情况 推荐方案 理由
新手团队 Vue 2 + Element UI 快速上手,专注业务
有经验团队 Vue 3 + Element Plus 享受新特性,提升效率
大型企业 Vue 3 + TypeScript 类型安全,便于维护
个人项目 根据兴趣选择 开心最重要

3.3 Element UI 核心组件使用

vue 复制代码
<template>
  <div class="app-container">
    <!-- 搜索表单 -->
    <el-form :model="queryParams" :inline="true">
      <el-form-item label="用户名" prop="userName">
        <el-input
          v-model="queryParams.userName"
          placeholder="请输入用户名"
          clearable
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">
          搜索
        </el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <!-- 数据表格 -->
    <el-table v-loading="loading" :data="userList">
      <el-table-column label="用户 ID" prop="userId" width="100"/>
      <el-table-column label="用户名" prop="userName" :show-overflow-tooltip="true"/>
      <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true"/>
      <el-table-column label="状态" prop="status">
        <template #default="scope">
          <el-switch
            v-model="scope.row.status"
            active-value="1"
            inactive-value="0"
            @change="handleStatusChange(scope.row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="操作" width="200">
        <template #default="scope">
          <el-button
            type="text"
            icon="Edit"
            @click="handleUpdate(scope.row)"
          >修改
          </el-button>
          <el-button
            type="text"
            icon="Delete"
            @click="handleDelete(scope.row)"
          >删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页组件 -->
    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />
  </div>
</template>

<script>
  import {listUser, updateUser} from '@/api/system/user'

  export default {
    name: 'UserManage',
    data() {
      return {
        loading: true,
        userList: [],
        total: 0,
        queryParams: {
          pageNum: 1,
          pageSize: 10,
          userName: undefined
        }
      }
    },
    created() {
      this.getList()
    },
    methods: {
      async getList() {
        this.loading = true
        try {
          const {data} = await listUser(this.queryParams)
          this.userList = data.rows
          this.total = data.total
        } finally {
          this.loading = false
        }
      },
      handleQuery() {
        this.queryParams.pageNum = 1
        this.getList()
      },
      resetQuery() {
        this.resetForm('queryParams')
        this.handleQuery()
      }
    }
  }
</script>

🗄️ 四、数据库技术选型

4.1 MySQL 8.2.0 - 关系型数据库

🎯 为什么选择 MySQL 8.x?
版本 MySQL 5.7 MySQL 8.0+ 飞鱼选择理由
性能 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ 查询性能提升 2 倍
JSON 支持 ⭐⭐⭐ ⭐⭐⭐⭐⭐ 原生 JSON 函数
窗口函数 ❌ 不支持 ✅ 支持 复杂分析查询
CTE 表达式 ❌ 不支持 ✅ 支持 递归查询简化
字符集 utf8 utf8mb4 完整 Unicode 支持
📦 MySQL 8 核心特性应用

✅ 窗口函数

sql 复制代码
-- 查询每个部门工资前三的员工
SELECT dept_id,
       user_name,
       salary,
       ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) as rn
FROM sys_user
WHERE status = '1'
HAVING rn <= 3;

✅ CTE 递归查询

sql 复制代码
-- 查询部门树形结构
WITH RECURSIVE dept_tree AS (SELECT dept_id, dept_name, parent_id, 0 as level
                             FROM sys_dept
                             WHERE parent_id = 0
                             UNION ALL
                             SELECT d.dept_id, d.dept_name, d.parent_id, t.level + 1
                             FROM sys_dept d
                                    INNER JOIN dept_tree t ON d.parent_id = t.dept_id)
SELECT *
FROM dept_tree
ORDER BY level, dept_id;

✅ JSON 字段

sql 复制代码
-- 存储扩展属性
CREATE TABLE sys_user_ext
(
  user_id     BIGINT PRIMARY KEY,
  ext_info    JSON, -- 存储扩展信息
  create_time DATETIME
);

-- 插入 JSON 数据
INSERT INTO sys_user_ext
VALUES (1, '{"skills": ["Java", "Python"], "certificates": ["PMP"]}', NOW());

-- 查询 JSON 字段
SELECT user_id,
       JSON_EXTRACT(ext_info, '$.skills[0]') as first_skill
FROM sys_user_ext;

4.2 数据库设计规范

📋 命名规范
sql 复制代码
-- ✅ 推荐命名方式
-- 表名:小写字母 + 下划线
sys_user -- 系统用户表
sys_role_menu     -- 角色菜单关联表

-- 主键:统一使用 id 或 {模块}_id
id                -- 单表使用
user_id           -- 多表关联使用

-- 字段:小写字母 + 下划线
user_name         -- 用户名
create_time       -- 创建时间
update_by         -- 更新人

-- 索引:idx_{字段名}
idx_user_name     -- 用户名索引

-- 唯一索引:uk_{字段名}
uk_user_email     -- 邮箱唯一索引
📋 建表规范
sql 复制代码
CREATE TABLE `sys_user`
(
  `user_id`     bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户 ID',
  `dept_id`     bigint(20) DEFAULT NULL COMMENT '部门 ID',
  `user_name`   varchar(30) NOT NULL COMMENT '用户账号',
  `nick_name`   varchar(30) NOT NULL COMMENT '用户昵称',
  `email`       varchar(50)  DEFAULT '' COMMENT '用户邮箱',
  `phonenumber` varchar(11)  DEFAULT '' COMMENT '手机号码',
  `sex`         char(1)      DEFAULT '0' COMMENT '用户性别 (0 男 1 女 2 未知)',
  `avatar`      varchar(100) DEFAULT '' COMMENT '头像路径',
  `password`    varchar(100) DEFAULT '' COMMENT '密码',
  `status`      char(1)      DEFAULT '0' COMMENT '帐号状态 (0 正常 1 停用)',
  `del_flag`    char(1)      DEFAULT '0' COMMENT '删除标志 (0 代表存在 2 代表删除)',
  `login_ip`    varchar(128) DEFAULT '' COMMENT '最后登录 IP',
  `login_date`  datetime     DEFAULT NULL COMMENT '最后登录时间',
  `create_by`   varchar(64)  DEFAULT '' COMMENT '创建者',
  `create_time` datetime     DEFAULT NULL COMMENT '创建时间',
  `update_by`   varchar(64)  DEFAULT '' COMMENT '更新者',
  `update_time` datetime     DEFAULT NULL COMMENT '更新时间',
  `remark`      varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `uk_user_name` (`user_name`),
  KEY           `idx_dept_id` (`dept_id`),
  KEY           `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表';

🛠️ 五、工具类库精选

5.1 Hutool 5.8.40 - Java 工具集

🎯 Hutool 核心模块
xml 复制代码
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.8.40</version>
</dependency>

常用工具类:

java 复制代码
import cn.hutool.core.util.*;
import cn.hutool.http.HttpUtil;
import cn.hutool.crypto.SecureUtil;

// 字符串工具
StrUtil.isBlank(str);
StrUtil.format("Hello, {}", "World");

// 数字工具
NumberUtil.isNumber("123");
NumberUtil.div(new BigDecimal("100"), new BigDecimal("3"), 2);

// 日期工具
DateUtil.now();
DateUtil.parse("2024-01-01");
DateUtil.offsetDay(new Date(), 7);

// 文件工具
FileUtil.readUtf8String("test.txt");
FileUtil.writeUtf8String("content", "test.txt");

// HTTP 工具
String result = HttpUtil.get("https://api.example.com/data");

// 加密工具
String md5 = SecureUtil.md5("password");
String sha256 = SecureUtil.sha256("password");

5.2 Apache Commons - 经典工具库

xml 复制代码
<!-- IO 工具 -->
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.21.0</version>
</dependency>

  <!-- 语言工具 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.18.0</version>
</dependency>

  <!-- 集合工具 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>

5.3 Lombok 1.18.42 - 代码简化神器

xml 复制代码
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.42</version>
  <scope>provided</scope>
</dependency>
java 复制代码
// ✅ 实体类标准写法
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_user")
public class SysUser {
    
    @TableId(type = IdType.AUTO)
    private Long userId;
    
    private String userName;
    private String email;
    
    @JsonIgnore
    private String password;
    
    private LocalDateTime createTime;
}

// ✅ Service 注入写法
@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl extends BaseServiceImpl<SysUser, Long> 
    implements IUserService {
    
    private final UserMapper userMapper;
    
    @Override
    public SysUser getUserById(Long userId) {
        log.debug("查询用户:{}", userId);
        return userMapper.selectById(userId);
    }
}

📈 六、监控与运维工具

6.1 Oshi 6.9.1 - 系统信息采集

xml 复制代码
<dependency>
  <groupId>com.github.oshi</groupId>
  <artifactId>oshi-core</artifactId>
  <version>6.9.1</version>
</dependency>
java 复制代码
// 获取 CPU 信息
SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
CentralProcessor processor = hal.getProcessor();
long[] prevTicks = processor.getSystemCpuLoadTicks();
Thread.sleep(1000);
double cpuLoad = processor.getSystemCpuLoadBetweenTicks(prevTicks);

// 获取内存信息
GlobalMemory memory = hal.getMemory();
long available = memory.getAvailable();
long total = memory.getTotal();

// 获取磁盘信息
List<HWDiskStore> diskStores = hal.getDiskStores();
for (HWDiskStore store : diskStores) {
    long readBytes = store.getReadBytes();
    long writeBytes = store.getWriteBytes();
}

6.2 Spring Boot Actuator - 应用监控

xml 复制代码
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
yaml 复制代码
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus,threaddump
  endpoint:
    health:
      show-details: always
  metrics:
    export:
      prometheus:
        enabled: true

访问端点:

  • 健康检查:http://localhost:8080/actuator/health
  • 应用信息:http://localhost:8080/actuator/info
  • 指标数据:http://localhost:8080/actuator/metrics
  • Prometheus: http://localhost:8080/actuator/prometheus

🎯 七、技术选型总结

7.1 选型原则

飞鱼系统的技术选型遵循以下原则:

  1. 稳定性优先: 选择经过生产环境验证的技术
  2. 适度超前: 在稳定基础上引入新技术
  3. 生态完善: 选择社区活跃、文档丰富的技术
  4. 团队匹配: 考虑团队技术储备和学习成本
  5. 可扩展性: 预留技术升级空间

7.2 技术债务管理

技术债项 当前方案 未来规划 升级难度
前端框架 Vue 2.6 Vue 3 + TS ⭐⭐⭐⭐ 高
构建工具 Vue CLI Vite 5 ⭐⭐⭐ 中
状态管理 Vuex Pinia ⭐⭐ 低
后端框架 Spring Boot 3.5 Spring Boot 4.x ⭐⭐ 低

7.3 给读者的建议

如果你正在做技术选型:

学习路线:
☕ Java 基础
🍃 Spring Boot
🔗 MyBatis
🎨 Vue 基础
🚀 项目实战

表格形式

阶段 技术栈 图标 说明
1 Java 基础 面向对象、集合框架、多线程并发
2 Spring Boot 🍃 自动配置、RESTful API、Starter 机制
3 MyBatis 🔗 ORM 映射、动态 SQL、性能优化
4 Vue 基础 🎨 Composition API、响应式原理、组件通信
5 项目实战 🚀 前后端联调、权限管理、业务模块开发、部署上线

进阶路线图:
飞鱼项目

学习路线
后端技术栈
Java 基础
面向对象
集合框架
多线程并发
Spring Boot
自动配置
RESTful API
Starter 机制
MyBatis
ORM 映射
动态 SQL
性能优化
前端技术栈
Vue3
Composition API
响应式原理
组件通信
TypeScript
类型系统
接口定义
泛型应用
Element Plus
UI 组件库
表单验证
表格分页
数据库
MySQL
索引优化
事务隔离
SQL 调优
Redis
缓存策略
数据结构
持久化
工程化
Maven
依赖管理
多模块构建
Git
版本控制
分支管理
Docker
容器化部署
镜像构建

详细内容规划:

类别 子类别 知识点 详细内容
后端技术栈 Java 基础 面向对象 封装、继承、多态
后端技术栈 Java 基础 集合框架 List、Map、Set
后端技术栈 Java 基础 多线程并发 线程池、锁机制、并发工具
后端技术栈 Spring Boot 自动配置 条件注解、自动装配原理
后端技术栈 Spring Boot RESTful API 接口设计、请求映射
后端技术栈 Spring Boot Starter 机制 自定义 Starter、依赖管理
后端技术栈 MyBatis ORM 映射 实体映射、结果映射
后端技术栈 MyBatis 动态 SQL if、choose、foreach
后端技术栈 MyBatis 性能优化 缓存、批量操作、分页
前端技术栈 Vue3 Composition API setup、ref、reactive
前端技术栈 Vue3 响应式原理 Proxy、依赖追踪
前端技术栈 Vue3 组件通信 Props、Emits、Provide/Inject
前端技术栈 TypeScript 类型系统 接口、泛型、联合类型
前端技术栈 TypeScript 接口定义 类型声明、类型推断
前端技术栈 TypeScript 泛型应用 泛型约束、泛型工具
前端技术栈 Element Plus UI 组件库 布局、表单、表格
前端技术栈 Element Plus 表单验证 规则验证、自定义验证器
前端技术栈 Element Plus 表格分页 分页器、表格排序
数据库 MySQL 索引优化 B+ 树、覆盖索引、最左前缀
数据库 MySQL 事务隔离 ACID、隔离级别、MVCC
数据库 MySQL SQL 调优 Explain 分析、慢查询优化
数据库 Redis 缓存策略 多级缓存、缓存穿透/雪崩/击穿
数据库 Redis 数据结构 String、Hash、List、Set、ZSet
数据库 Redis 持久化 RDB、AOF、混合持久化
工程化 Maven 依赖管理 版本控制、冲突解决
工程化 Maven 多模块构建 模块划分、聚合继承
工程化 Git 版本控制 提交、分支、合并
工程化 Git 分支管理 Git Flow、Code Review
工程化 Docker 容器化部署 镜像构建、容器编排
工程化 Docker 镜像构建 Dockerfile、多阶段构建

避坑指南:

  • 不要盲目追求最新技术
  • 充分评估团队能力
  • 预留技术升级空间
  • 重视文档和生态

最佳实践:

  • 建立统一的技术规范
  • 定期进行技术分享
  • 鼓励技术创新试错
  • 平衡稳定性和先进性

⚠️ 避坑指南:5 个技术选型常见误区

⚠️ 误区 1: 盲目追求最新技术

现象:

xml 复制代码
<!-- ❌ 盲目使用最新未稳定版本 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>3.6.0-SNAPSHOT</version>  <!-- 快照版本风险高 -->
</dependency>

  // ❌ 前端使用未经验证的库
  import { experimental_feature } from 'vue-experimental';

原因:

  • 新版本可能存在未发现的 Bug
  • 生态系统可能不兼容
  • 社区支持不足,问题难解决
  • 生产环境稳定性无法保证

解决方案:

xml 复制代码
<!-- ✅ 选择稳定版本 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>3.5.8</version>  <!-- 最新稳定版 -->
</dependency>

  // ✅ 使用成熟技术栈
  import { ref, reactive } from 'vue';  // Vue 3 稳定 API

选型原则:

  • ✅ 生产环境:选择最新稳定版本(LTS 优先)
  • ✅ 学习项目:可以尝试新技术
  • ✅ 关注官方推荐和最佳实践

⚠️ 误区 2: 忽视 Jakarta EE 包名迁移

现象:

java 复制代码
// ❌ 编译错误:找不到 javax 包
import javax.servlet.http.HttpServletRequest;
import javax.persistence.Entity;
import javax.validation.constraints.NotNull;

// 报错:
// package javax.servlet does not exist
// package javax.persistence does not exist

原因:

  • Spring Boot 3.x 全面迁移到 Jakarta EE 9
  • 包名从 javax.* 改为jakarta.*
  • 旧依赖不兼容新框架

解决方案:

java 复制代码
// ✅ 使用 Jakarta 包名
import jakarta.servlet.http.HttpServletRequest;
import jakarta.persistence.Entity;
import jakarta.validation.constraints.NotNull;

// ✅ 更新 Maven 依赖
<dependency>
    <groupId>jakarta.platform</groupId>
    <artifactId>jakarta.jakartaee-api</artifactId>
    <version>9.1.0</version>
</dependency>

影响范围:

  • ✅ Servlet API: javax.servletjakarta.servlet
  • ✅ JPA: javax.persistencejakarta.persistence
  • ✅ Validation: javax.validationjakarta.validation

⚠️ 误区 3: 前端技术栈选择不当

现象:

javascript 复制代码
// ❌ Vue 2 项目强行使用 Vue 3 语法
const {ref, reactive} = Vue;  // Vue 2 不支持

// ❌ 在大型项目中使用实验性技术
import {experimental_newReactivity} from 'vue';

原因:

  • Vue 2 和 Vue 3 API 不兼容
  • Composition API 和 Options API 混用导致混乱
  • 团队技术栈不统一增加维护成本

解决方案:

方案 A: 坚持 Vue 2 (保守选择)

javascript 复制代码
// ✅ Vue 2.6 + Options API
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++;
    }
  }
}

方案 B: 升级到 Vue 3 (推荐)

javascript 复制代码
// ✅ Vue 3.4 + Composition API
<script setup>
  import {ref} from 'vue';

  const count = ref(0);
  const increment = () => count.value++;
</script>

选型建议:

场景 推荐方案 理由
新项目 Vue 3.4 + TS 技术先进,生态完善
老项目维护 Vue 2.6 稳定可靠,迁移成本低
大型重构 Vue 3.4 + TS 长期受益,TypeScript 增强类型安全

⚠️ 误区 4: 数据库版本选择不当

现象:

sql 复制代码
-- ❌ 使用过旧的 MySQL 5.6
SELECT *
FROM users;
-- 不支持窗口函数

-- ❌ 使用不稳定的 MySQL 8.0 早期版本
-- 8.0.11-8.0.16 存在已知 Bug

原因:

  • MySQL 5.x 不支持现代特性 (窗口函数、CTE)
  • MySQL 8.0 早期版本稳定性差
  • 版本不匹配导致驱动兼容性问题

解决方案:

sql 复制代码
-- ✅ 推荐 MySQL 8.2+
SELECT user_id,
       ROW_NUMBER() OVER (ORDER BY create_time) as row_num
FROM users;

-- ✅ 使用 CTE 优化查询
WITH RECURSIVE cte AS (SELECT id, parent_id
                       FROM dept
                       WHERE id = 1
                       UNION ALL
                       SELECT d.id, d.parent_id
                       FROM dept d
                              INNER JOIN cte ON d.parent_id = cte.id)
SELECT *
FROM cte;

版本推荐:

  • MySQL 8.2+: 性能最优,特性最全
  • MySQL 8.0.28+: 稳定版本,广泛使用
  • MySQL 5.7: 已停止维护
  • MySQL 8.0.11-16: 存在已知 Bug

⚠️ 误区 5: 缓存使用不当

现象:

java 复制代码
// ❌ 缓存穿透:查询不存在的数据
public User getUser(Long id) {
    return redisTemplate.opsForValue().get("user:" + id);
    // 数据库也没有,每次查询都穿透到 DB
}

// ❌ 缓存雪崩:大量 key 同时过期
@Cacheable(value = "users", ttl = 3600);  // 所有缓存 1 小时后同时失效

// ❌ 缓存击穿:热点 key 过期瞬间大量请求
@Cacheable(value = "hot_product", ttl = 1800);

原因:

  • 缓存设计不合理导致数据库压力大
  • 没有考虑异常情况处理
  • 缺少缓存更新策略

解决方案:

java 复制代码
// ✅ 缓存穿透:布隆过滤器 + 缓存空对象
public User getUser(Long id) {
    // 1. 布隆过滤器检查
    if (!bloomFilter.mightContain(id)) {
        return null;  // 肯定不存在
    }
    
    // 2. 查询缓存
    User user = redisTemplate.opsForValue().get("user:" + id);
    if (user != null) {
        return user;
    }
    
    // 3. 查询数据库
    user = userMapper.selectById(id);
    if (user == null) {
        // 缓存空对象,防止穿透
        redisTemplate.opsForValue().set(
            "user:" + id, 
            null, 
            300, 
            TimeUnit.SECONDS
        );
        return null;
    }
    
    // 4. 写入缓存
    redisTemplate.opsForValue().set(
        "user:" + id, 
        user, 
        3600 + new Random().nextInt(300),  // 随机 TTL 防雪崩
        TimeUnit.SECONDS
    );
    
    return user;
}

// ✅ 缓存雪崩:随机 TTL
@Cacheable(value = "users", 
           ttl = 3600 + new Random().nextInt(300));  // 1-1.5 小时随机

// ✅ 缓存击穿:互斥锁 + 永不过期
public User getHotProduct(Long id) {
    String key = "hot_product:" + id;
    User user = redisTemplate.opsForValue().get(key);
    if (user != null) {
        return user;
    }
    
    // 获取分布式锁
    RLock lock = redissonClient.getLock("lock:" + key);
    if (lock.tryLock()) {
        try {
            // 双重检查
            user = redisTemplate.opsForValue().get(key);
            if (user != null) {
                return user;
            }
            
            // 查询数据库
            user = userMapper.selectById(id);
            redisTemplate.opsForValue().set(key, user);
            return user;
        } finally {
            lock.unlock();
        }
    } else {
        // 等待重试
        Thread.sleep(100);
        return getHotProduct(id);
    }
}

📊 性能优化建议

6.1 启动优化

优化前:

yaml 复制代码
# ❌ 默认配置,启动慢
spring:
  main:
    lazy-initialization: false  # 立即初始化所有 Bean

优化后:

yaml 复制代码
# ✅ 延迟初始化配置
spring:
  main:
    lazy-initialization: true  # 延迟初始化,启动速度提升 40%

  # JVM 参数优化
  -Xms512m -Xmx1024m             # 堆内存配置
  -XX:+UseG1GC                   # G1 垃圾回收器
  -XX:MaxGCPauseMillis=100       # 最大 GC 停顿时间
  -XX:+ParallelRefProcEnabled    # 并行引用处理

性能对比:

指标 优化前 优化后 提升幅度
启动时间 30 秒 8 秒 -73%
初始内存 512MB 128MB -75%
首次请求 2 秒 0.5 秒 -75%

6.2 连接池优化

优化前:

yaml 复制代码
# ❌ 默认配置,并发能力弱
spring:
  datasource:
    hikari:
      maximum-pool-size: 10      # 默认值太小
      minimum-idle: 10

优化后:

yaml 复制代码
# ✅ 企业级配置
spring:
  datasource:
    hikari:
      maximum-pool-size: 50      # 最大连接数 (根据并发调整)
      minimum-idle: 20           # 最小空闲连接
      connection-timeout: 30000  # 连接超时 (30 秒)
      idle-timeout: 600000       # 空闲超时 (10 分钟)
      max-lifetime: 1800000      # 最大生命周期 (30 分钟)
      leak-detection-threshold: 60000  # 泄漏检测 (60 秒)

性能对比:

指标 优化前 优化后 提升幅度
并发连接数 10 50 +400%
响应时间 500ms 300ms -40%
吞吐量 100 QPS 300 QPS +200%

6.3 缓存优化

优化前:

java 复制代码
// ❌ 简单缓存,无优化
@Cacheable("users")
public User getUser(Long id) {
    return userMapper.selectById(id);
}

优化后:

java 复制代码
// ✅ 多级缓存 + 本地缓存
@Cacheable(value = "users", 
           unless = "#result == null",  // 不缓存空值
           key = "#root.methodName + ':' + #id")
public User getUser(Long id) {
    // 先查本地缓存 (Caffeine)
    User user = localCache.get(id);
    if (user != null) {
        return user;
    }
    
    // 再查 Redis
    user = redisTemplate.opsForValue().get("user:" + id);
    if (user != null) {
        localCache.put(id, user);  // 回写本地缓存
        return user;
    }
    
    // 最后查数据库
    user = userMapper.selectById(id);
    if (user != null) {
        redisTemplate.opsForValue().set("user:" + id, user, 3600);
        localCache.put(id, user);
    }
    
    return user;
}

性能对比:

指标 优化前 优化后 提升幅度
热点数据查询 50ms 0.5ms +10000%
数据库压力 100% 20% -80%
平均响应时间 100ms 20ms -80%

📝 总结

本文系统介绍了飞鱼管理系统的完整技术栈架构,包括5 个技术选型常见误区3 套性能优化方案关键收获:

  1. 技术选型要平衡稳定与创新: Spring Boot 3.5.8 + JDK 17 是生产环境的最佳选择
  2. 避免常见误区: 不盲目追新、重视 Jakarta EE 迁移、合理选择前后端技术栈
  3. 性能优化至关重要: 启动优化提升 73%、连接池优化提升 200% 并发能力、缓存优化降低 80% 数据库压力

技术选型建议:

  • 生产环境: 选择最新稳定版本 (LTS 优先)
  • 学习项目: 可尝试新技术但要注意风险
  • 团队协作: 统一技术栈,降低维护成本
  • 长期发展: 预留升级空间,管理技术债务

下一篇文章,我们将手把手教你搭建飞鱼开发环境,包含详细的安装步骤和避坑指南,敬请期待!


👍 如果本文对你有帮助,欢迎点赞、收藏、转发!

💬 有任何问题或建议,请在评论区留言交流~

🔔 关注我,获取飞鱼系统 Spring Boot 3.x 系列文章!

📝 行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激!!

专栏导航:

如果觉得本文有帮助,欢迎点赞👍收藏⭐关注💖!

相关推荐
WHS-_-20222 小时前
mCore: Achieving Sub-millisecond Scheduling for 5G MU-MIMO Systems
java·算法·5g
“抚琴”的人2 小时前
SqlSugar 文档
开发语言·数据库·c#·sqlsugar
Jin、yz2 小时前
黑马苍穹外卖项目收获
java
浅念-2 小时前
C++11 核心知识点整理
开发语言·数据结构·c++·笔记·算法
panzer_maus2 小时前
Java多线程介绍
java·开发语言
echome8882 小时前
Python 装饰器详解:从入门到实战的完整指南
开发语言·python
AMoon丶2 小时前
Golang--多种控制结构详解
java·linux·c语言·开发语言·后端·青少年编程·golang
indexsunny2 小时前
互联网大厂Java面试实战:微服务与Spring Boot在电商场景下的应用解析
java·spring boot·redis·docker·微服务·kubernetes·oauth2
薛定谔之死猫2 小时前
Ruby简单粗暴把图片合成PDF文档
java·pdf·ruby