软考小程序开发实战:SpringBoot+Vue3 全栈搭建 AI 智能备考题库系统
# 软考学习系统全栈架构解析:从零到一打造智能化考试备考平台  > 本文将深入剖析一个完整的软考刷题小程序项目,涵盖后端 Spring Boot 架构设计、Vue 3 前端实现、AI 智能辅助、微信生态集成等核心技术点,为开发者提供全栈架构参考。 --- ## 目录 1. [项目概述](#1-项目概述) 2. [技术选型与架构设计](#2-技术选型与架构设计) 3. [后端架构深度解析](#3-后端架构深度解析) 4. [前端架构与实现](#4-前端架构与实现) 5. [AI 智能辅助系统](#5-ai-智能辅助系统) 6. [微信生态集成](#6-微信生态集成) 7. [数据库设计与优化](#7-数据库设计与优化) 8. [安全架构设计](#8-安全架构设计) 9. [部署与运维](#9-部署与运维) 10. [项目亮点与最佳实践](#10-项目亮点与最佳实践) --- ## 1. 项目概述 ### 1.1 项目背景 软考(计算机技术与软件专业技术资格考试)是中国 IT 从业人员的重要职业资格认证。传统的备考方式存在以下痛点: - 题库分散,缺乏系统化管理 - 学习进度难以追踪 - 缺乏个性化学习建议 - 备考效率低下 本项目旨在打造一个**智能化、系统化**的软考备考平台,通过 AI 技术赋能学习过程,提升备考效率。 ### 1.2 核心功能 | 功能模块 | 描述 | |---------|------| | 题库管理 | 分类、科目、章节、小节、题目的多层级管理 | | 练习系统 | 模拟练习、错题本、收藏夹、练习历史 | | AI 智能辅助 | 学习诊断、个性化路径、智能刷题、双师伴学 | | 打卡系统 | 每日打卡、连续打卡统计、打卡日历 | | VIP 会员 | 会员等级、支付系统、权限控制 | | 管理后台 | 数据统计、内容管理、用户管理 | --- ## 2. 技术选型与架构设计 ### 2.1 技术栈总览 ``` ┌─────────────────────────────────────────────────────────────┐ │ 前端层 │ │ Vue 3 + Vite + Ant Design Vue + ECharts + Vuex │ ├─────────────────────────────────────────────────────────────┤ │ 网关层 │ │ Nginx (反向代理、负载均衡、静态资源) │ ├─────────────────────────────────────────────────────────────┤ │ 后端层 │ │ Spring Boot 2.7 + Spring Security + JWT + MyBatis │ ├─────────────────────────────────────────────────────────────┤ │ 服务层 │ │ 微信登录/支付 | AI 能力 | 文件存储 | 消息推送 │ ├─────────────────────────────────────────────────────────────┤ │ 数据层 │ │ MySQL + MinIO + Redis (可选) │ └─────────────────────────────────────────────────────────────┘ ``` ### 2.2 后端技术栈 | 技术 | 版本 | 用途 | |-----|------|------| | Spring Boot | 2.7.0 | 基础框架 | | Spring Security | - | 安全认证 | | MyBatis | 2.2.2 | ORM 框架 | | MySQL | 5.7+ | 关系型数据库 | | JWT | 0.9.1 | 令牌认证 | | Knife4j | 4.4.0 | API 文档 | | LangChain4j | 0.35.0 | AI 能力集成 | | MinIO | 8.5.7 | 对象存储 | | 微信支付 SDK | 0.2.17 | 支付集成 | ### 2.3 前端技术栈 | 技术 | 版本 | 用途 | |-----|------|------| | Vue | 3.3.4 | 前端框架 | | Vite | 4.5.1 | 构建工具 | | Ant Design Vue | 3.2.20 | UI 组件库 | | ECharts | 5.4.3 | 数据可视化 | | Vuex | 4.0.2 | 状态管理 | | Vue Router | 4.5.1 | 路由管理 | | Axios | 1.9.0 | HTTP 客户端 | --- ## 3. 后端架构深度解析 ### 3.1 项目结构 ``` src/main/java/com/ruankao/tk/ ├── ai/ # AI 能力模块 │ ├── AiChatClient.java # AI 聊天客户端 │ ├── PromptTemplateService.java # Prompt 模板服务 │ └── dto/ # AI 相关 DTO ├── annotation/ # 自定义注解 │ ├── NoAuth.java # 免认证注解 │ └── RequireRole.java # 角色权限注解 ├── common/ # 公共模块 │ ├── CommonResult.java # 统一响应封装 │ └── RoleEnum.java # 角色枚举 ├── config/ # 配置类 │ ├── SecurityConfig.java # 安全配置 │ ├── MybatisConfig.java # MyBatis 配置 │ └── WxMiniAppConfig.java # 微信小程序配置 ├── controller/ # 控制器层 │ ├── admin/ # 后台管理接口 │ └── ... # 前台业务接口 ├── dto/ # 数据传输对象 ├── entity/ # 实体类 ├── mapper/ # MyBatis Mapper ├── repository/ # JPA Repository ├── service/ # 业务逻辑层 └── util/ # 工具类 ``` ### 3.2 分层架构设计 项目采用经典的**四层架构**: ```java // Controller 层 - 负责接收请求和返回响应 @RestController @RequestMapping("/api/exam/questions") @Api(tags = "考试题目管理") public class QuestionController { @Autowired private QuestionService questionService; @GetMapping("/{id}") @ApiOperation("根据ID获取题目") public CommonResult findById(@PathVariable Integer id) { return CommonResult.success(questionService.findById(id)); } } // Service 层 - 负责业务逻辑 @Service public class QuestionService { @Autowired private QuestionMapper questionMapper; public Question findById(Integer id) { return questionMapper.findById(id); } } // Mapper 层 - 负责数据访问 @Mapper public interface QuestionMapper { @Select("SELECT * FROM questions WHERE id = #{id}") Question findById(Integer id); } ``` ### 3.3 统一响应封装 ```java @Data public class CommonResult { private Integer code; private String message; private T data; public static CommonResult success(T data) { CommonResult result = new CommonResult<>(); result.setCode(200); result.setMessage("success"); result.setData(data); return result; } public static CommonResult error(String message) { CommonResult result = new CommonResult<>(); result.setCode(500); result.setMessage(message); return result; } } ``` ### 3.4 MyBatis 动态 SQL 项目使用 MyBatis XML 映射文件实现复杂的动态 SQL: ```xml SELECT * FROM questions AND (title LIKE CONCAT('%', #{keyword}, '%') OR content LIKE CONCAT('%', #{keyword}, '%')) AND subject_id = #{subjectId} AND status = #{status} ORDER BY created_at DESC LIMIT #{offset}, #{limit} ``` --- ## 4. 前端架构与实现 ### 4.1 项目结构 ``` webadmin/src/ ├── api/ # API 接口封装 │ ├── auth.js # 认证相关 │ ├── questions.js # 题目管理 │ └── ... ├── assets/ # 静态资源 ├── components/ # 公共组件 ├── config/ # 配置文件 │ ├── menuConfig.js # 菜单配置 │ └── env.js # 环境配置 ├── layout/ # 布局组件 ├── router/ # 路由配置 ├── store/ # Vuex 状态管理 │ └── modules/ # 模块化 store ├── styles/ # 样式文件 ├── utils/ # 工具函数 │ ├── auth.js # 认证工具 │ ├── request.js # 请求封装 │ └── pagination.js # 分页工具 └── views/ # 页面组件 ├── dashboard/ # 仪表盘 ├── questions/ # 题目管理 ├── category/ # 分类管理 └── ... ``` ### 4.2 Axios 请求封装 ```javascript // utils/request.js import axios from 'axios' import { getToken } from './auth' const service = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 30000 }) // 请求拦截器 service.interceptors.request.use( config => { const token = getToken() if (token) { config.headers['Authorization'] = `Bearer ${token}` } return config }, error => { return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response => { const res = response.data if (res.code !== 200) { // 错误处理 return Promise.reject(new Error(res.message || 'Error')) } return res }, error => { return Promise.reject(error) } ) export default service ``` ### 4.3 Vuex 模块化状态管理 ```javascript // store/modules/user.js import { login, logout, getUserInfo } from '@/api/auth' const state = { token: localStorage.getItem('token'), userInfo: null, roles: [] } const mutations = { SET_TOKEN: (state, token) => { state.token = token }, SET_USER_INFO: (state, userInfo) => { state.userInfo = userInfo } } const actions = { // 登录 async login({ commit }, loginForm) { const res = await login(loginForm) commit('SET_TOKEN', res.data.token) localStorage.setItem('token', res.data.token) return res }, // 获取用户信息 async getUserInfo({ commit }) { const res = await getUserInfo() commit('SET_USER_INFO', res.data) return res } } export default { namespaced: true, state, mutations, actions } ``` ### 4.4 路由权限控制 ```javascript // router/index.js import Vue from 'vue' import Router from 'vue-router' import { getToken } from '@/utils/auth' Vue.use(Router) const router = new Router({ routes: [ { path: '/login', component: () => import('@/views/login/index.vue'), meta: { title: '登录', noAuth: true } }, { path: '/', component: Layout, redirect: '/dashboard', children: [ { path: 'dashboard', component: () => import('@/views/dashboard/index.vue'), meta: { title: '仪表盘', icon: 'dashboard' } } ] } ] }) // 路由守卫 router.beforeEach(async (to, from, next) => { const token = getToken() if (token) { if (to.path === '/login') { next({ path: '/' }) } else { next() } } else { if (to.meta.noAuth) { next() } else { next(`/login?redirect=${to.path}`) } } }) export default router ``` --- ## 5. AI 智能辅助系统 ### 5.1 AI 能力架构 项目集成了 LangChain4j 框架,实现了多项 AI 能力:    ``` ┌─────────────────────────────────────────────────────────────┐ │ AI 能力层 │ ├─────────────┬─────────────┬─────────────┬───────────────────┤ │ 学习诊断 │ 智能刷题 │ 双师伴学 │ 智能组卷 │ ├─────────────┴─────────────┴─────────────┴───────────────────┤ │ Prompt 模板层 │ ├─────────────────────────────────────────────────────────────┤ │ AI 模型层 │ │ DeepSeek-v3.1 (OpenAI 兼容 API) │ └─────────────────────────────────────────────────────────────┘ ``` ### 5.3 AI 服务实现 ```java @Service public class AiDiagnosisService { @Autowired private AiChatClient aiChatClient; @Autowired private PromptTemplateService promptTemplateService; public AiDiagnosisResponseDTO diagnose(Integer userId, AiDiagnosisRequestDTO request) { // 1. 获取用户练习数据 UserPracticeData practiceData = getPracticeData(userId, request.getSubjectId()); // 2. 构建 Prompt String prompt = promptTemplateService.buildDiagnosisPrompt(practiceData); // 3. 调用 AI 模型 AiChatResult result = aiChatClient.chat(prompt); // 4. 解析响应 return parseDiagnosisResult(result.getContent()); } } ``` ### 5.4 流式响应支持 ```java @PostMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter chatStream(@Valid @RequestBody AiChatRequestDTO request) { SseEmitter emitter = new SseEmitter(120000L); // 2分钟超时 CompletableFuture.runAsync(() -> { try { // 流式调用 AI 模型 aiChatClient.chatStream(request.getMessage(), chunk -> { emitter.send(SseEmitter.event() .data(chunk, MediaType.TEXT_PLAIN)); }); emitter.complete(); } catch (Exception e) { emitter.completeWithError(e); } }); return emitter; } ``` --- ## 6. 微信生态集成 ### 6.1 微信小程序登录 ``` ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 用户 │ ──> │ 小程序 │ ──> │ 后端 │ ──> │ 微信API │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ │ 点击登录 │ │ │ │ ────────────> │ │ │ │ │ wx.login() │ │ │ │ ───────────────────────────> │ │ │ │ 返回 code │ │ │ │ │ │ │ │ code2Session │ │ │ │ ────────────> │ │ │ │ 返回 openid │ │ │ │ login(@RequestParam String code) { // 1. 获取微信登录信息 WxLoginResponse wxLoginResponse = wxLoginService.login(code); // 2. 执行登录或注册 LoginResponse loginResponse = authService.wxLogin(wxLoginResponse); return CommonResult.success(loginResponse); } } ``` ### 6.2 微信支付集成 ```java @Service public class WxPayService { @Autowired private WechatPayConfig wechatPayConfig; public PrepayResponse createOrder(CreateOrderDTO request) { // 1. 创建订单 Orders order = createOrder(request); // 2. 调用微信支付 API WechatPayService service = new WechatPayService.Builder() .merchantId(wechatPayConfig.getMerchantId()) .privateKeyPath(wechatPayConfig.getCertPath()) .merchantSerialNumber(wechatPayConfig.getMerchantSerialNumber()) .apiV3Key(wechatPayConfig.getApiV3Key()) .build(); PrepayRequest prepayRequest = new PrepayRequest(); prepayRequest.setAppid(wechatPayConfig.getAppid()); prepayRequest.setMchid(wechatPayConfig.getMerchantId()); prepayRequest.setDescription("软考VIP会员"); prepayRequest.setOutTradeNo(order.getOrderNo()); prepayRequest.setNotifyUrl(wechatPayConfig.getNotifyUrl()); Amount amount = new Amount(); amount.setTotal(order.getAmount()); amount.setCurrency("CNY"); prepayRequest.setAmount(amount); return service.prepay(prepayRequest); } } ``` --- ## 7. 数据库设计与优化 ### 7.1 核心表结构 ```sql -- 用户表 CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255), nickname VARCHAR(100), avatar VARCHAR(500), phone VARCHAR(20), status TINYINT DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); -- 题目表 CREATE TABLE questions ( id INT PRIMARY KEY AUTO_INCREMENT, sub_chapter_id INT NOT NULL, title TEXT NOT NULL, content TEXT, type TINYINT DEFAULT 1, -- 1:单选 2:多选 3:判断 difficulty TINYINT DEFAULT 1, -- 1:简单 2:中等 3:困难 explanation TEXT, status TINYINT DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (sub_chapter_id) REFERENCES exam_sub_chapters(id) ); -- 练习记录表 CREATE TABLE user_practice_history ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, subject_id INT NOT NULL, practice_type VARCHAR(20), -- practice/paper total_count INT, correct_count INT, score DECIMAL(5,2), duration INT, -- 耗时(秒) status TINYINT DEFAULT 0, -- 0:进行中 1:已完成 created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); ``` ### 7.2 索引优化 ```sql -- 题目表索引 CREATE INDEX idx_questions_sub_chapter ON questions(sub_chapter_id); CREATE INDEX idx_questions_status ON questions(status); CREATE INDEX idx_questions_type ON questions(type); -- 练习记录索引 CREATE INDEX idx_practice_history_user ON user_practice_history(user_id); CREATE INDEX idx_practice_history_subject ON user_practice_history(subject_id); CREATE INDEX idx_practice_history_created ON user_practice_history(created_at); ``` ### 7.3 MyBatis 配置优化 ```yaml # application.yml mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.ruankao.tk.entity configuration: map-underscore-to-camel-case: true cache-enabled: true lazy-loading-enabled: true multiple-result-sets-enabled: true ``` --- ## 8. 安全架构设计 ### 8.1 认证授权流程 ``` ┌─────────────────────────────────────────────────────────────┐ │ 请求流程 │ ├─────────────────────────────────────────────────────────────┤ │ 客户端 ──> JWT 过滤器 ──> 角色拦截器 ──> Controller │ │ │ │ │ │ │ 验证 Token │ 检查权限 │ │ ▼ ▼ │ │ 无效: 401 无权限: 403 │ └─────────────────────────────────────────────────────────────┘ ``` ### 8.2 JWT 认证实现 ```java @Component public class JwtUtil { @Value("${jwt.secret}") private String secret; @Value("${jwt.expiration}") private Long expiration; // 生成 Token public String generateToken(Integer userId, String username) { return Jwts.builder() .setSubject(username) .claim("userId", userId) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + expiration)) .signWith(SignatureAlgorithm.HS512, secret) .compact(); } // 解析 Token public Claims parseToken(String token) { return Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); } } ``` ### 8.3 API 加密传输 项目实现了 RSA 加密传输,保护敏感数据: ```java @Component public class ApiEncryptFilter implements Filter { @Autowired private ApiEncryptProperties properties; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (properties.isDevMode()) { // 开发环境:明文传输 chain.doFilter(request, response); } else { // 生产环境:解密请求,加密响应 EncryptedRequest encryptedRequest = parseEncryptedRequest(request); String decryptedBody = rsaDecrypt(encryptedRequest.getData()); // ... 处理请求 } } } ``` --- ## 9. 部署与运维 ### 9.1 环境配置 ```yaml # application.yml server: port: 66666 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/xxxxxx?useUnicode=true&characterEncoding=utf-8 username: ******************************************** password: ******************** # Knife4j 配置 knife4j: enable: true # 生产环境关闭 ``` ### 9.2 日志配置 ```xml %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n logs/ruankao.log logs/ruankao.%d{yyyy-MM-dd}.log 30 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ``` ### 9.3 Webhook 消息推送 ```yaml # Webhook 配置 webhook: platforms: dingtalk: url: https://oapi.dingtalk.com/robot/send?access_token=xxx secret: SECxxx enabled: true timeout: 5000 retry-count: 3 ``` --- ## 10. 项目亮点与最佳实践 ### 10.1 技术亮点 1. **AI 深度集成** - 基于 LangChain4j 的 AI 能力封装 - Prompt 模板化管理,便于迭代 - 流式响应支持,提升用户体验 2. **微信生态闭环** - 小程序登录无缝集成 - 微信支付完整流程 - 公众号消息推送 3. **安全设计** - JWT + RBAC 权限模型 - API 加密传输 - 敏感数据脱敏 4. **性能优化** - MyBatis 二级缓存 - 数据库索引优化 - 分页查询优化 ### 10.2 代码规范 - 统一的响应格式封装 - 完善的异常处理机制 - 规范的日志记录 - 详细的 API 文档(Knife4j) ### 10.3 可扩展性 - 模块化设计,便于功能扩展 - 配置外部化,环境隔离 - 接口标准化,便于对接第三方 --- ## 总结 本项目是一个完整的全栈应用,涵盖了: - **后端**:Spring Boot + MyBatis + Spring Security - **前端**:Vue 3 + Vite + Ant Design Vue - **AI**:LangChain4j + DeepSeek - **微信**:小程序登录 + 微信支付 - **运维**:日志、监控、Webhook 通过这个项目,可以学习到: 1. 企业级 Java 应用架构设计 2. 前后端分离开发模式 3. AI 能力集成实践 4. 微信生态开发经验 5. 安全与性能优化技巧