ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SpringBoot+Vue构建中药实验管理系统实战

SpringBoot+Vue构建中药实验管理系统实战 1. 项目概述这个中药实验管理系统是一个典型的现代化实验室信息管理平台采用目前主流的SpringBootVue前后端分离架构。作为一名长期从事医疗信息化系统开发的工程师我最近刚完成了一个类似项目的交付正好可以分享一些实战经验。系统核心功能覆盖中药实验全流程管理包括药材入库、实验记录、数据分析、报告生成等模块。采用MyBatis作为ORM框架MySQL作为数据库这种技术组合在当前企业级应用中非常普遍具有成熟稳定、开发效率高的特点。2025年最新版本特别优化了大数据量下的查询性能并增强了移动端适配能力。2. 技术架构解析2.1 后端技术栈SpringBoot 3.2作为后端框架相比传统SSM架构有显著优势自动配置减少了80%以上的XML配置内嵌Tomcat服务器简化部署Starter依赖机制让技术集成更便捷我们在项目中特别使用了这些关键配置// 数据源配置示例 spring.datasource.urljdbc:mysql://localhost:3306/tcm_lab?useSSLfalseserverTimezoneAsia/Shanghai spring.datasource.usernameroot spring.datasource.password123456 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver # MyBatis配置 mybatis.mapper-locationsclasspath:mapper/*.xml mybatis.type-aliases-packagecom.tcm.lab.entity2.2 前端技术栈Vue 3.2作为前端框架配合Element Plus组件库Composition API提升代码组织性Vite构建工具显著加快编译速度Pinia状态管理替代Vuex更轻量典型页面组件结构// 实验记录表单组件 template el-form :modelformData label-width120px el-form-item label药材名称 el-select v-modelformData.herbId filterable el-option v-foritem in herbList :keyitem.id :labelitem.name :valueitem.id /el-option /el-select /el-form-item !-- 更多表单字段 -- /el-form /template3. 核心功能实现3.1 药材库存管理采用三级分类体系根类别如根茎类、果实类子类别如补气药、清热药具体药材如人参、黄芪数据库设计关键表CREATE TABLE t_herb ( id int NOT NULL AUTO_INCREMENT, code varchar(20) NOT NULL COMMENT 药材编码, name varchar(50) NOT NULL, category_id int NOT NULL, specification varchar(100) DEFAULT NULL, stock decimal(10,3) DEFAULT 0.000, unit varchar(10) DEFAULT g, storage_condition varchar(50) DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY idx_code (code) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;3.2 实验过程跟踪实验流程状态机设计stateDiagram [*] -- 待开始 待开始 -- 进行中: 启动实验 进行中 -- 已暂停: 暂停操作 已暂停 -- 进行中: 继续实验 进行中 -- 已完成: 提交结果 已完成 -- 已审核: 质量检查 已审核 -- 已归档: 文档整理对应的状态变更API设计PostMapping(/experiment/{id}/status) public Result updateStatus( PathVariable Long id, RequestParam ExperimentStatus status) { Experiment experiment experimentService.getById(id); if (!experiment.canTransferTo(status)) { return Result.error(状态转换不合法); } experiment.setStatus(status); experimentService.updateById(experiment); return Result.success(); }4. 关键技术实现4.1 MyBatis动态SQL优化针对复杂查询场景我们采用select idselectExperimentByCondition resultMapExperimentResult SELECT * FROM t_experiment where if testherbId ! null AND herb_id #{herbId} /if if teststartDate ! null and endDate ! null AND create_time BETWEEN #{startDate} AND #{endDate} /if if teststatusList ! null and statusList.size() 0 AND status IN foreach collectionstatusList itemstatus open( separator, close) #{status} /foreach /if /where ORDER BY create_time DESC LIMIT #{offset}, #{pageSize} /select4.2 Vue表格性能优化大数据量渲染采用虚拟滚动el-table :datatableData stylewidth: 100% height500 row-keyid :row-height50 :virtual-scroll-options{ height: 500, rowHeight: 50 } el-table-column propname label实验名称 width180 / !-- 其他列 -- /el-table5. 系统部署方案5.1 开发环境配置推荐使用Docker Compose快速搭建version: 3 services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: tcm_lab ports: - 3306:3306 volumes: - ./mysql-data:/var/lib/mysql redis: image: redis:6 ports: - 6379:63795.2 生产环境部署采用NginxSpringBoot的部署架构前端部署 1. 执行 npm run build 生成dist目录 2. 配置Nginx指向dist目录 3. 设置反向代理到后端API 后端部署 1. 使用mvn package生成jar包 2. 编写systemd服务文件 3. 配置JVM参数 -Xms512m -Xmx2g -XX:MaxMetaspaceSize256m6. 常见问题解决方案6.1 MyBatis查询性能问题慢查询优化方案添加合适的索引ALTER TABLE t_experiment_data ADD INDEX idx_experiment_id (experiment_id);使用二级缓存cache evictionLRU flushInterval60000 size1024 readOnlytrue/复杂查询改用存储过程6.2 Vue组件通信问题推荐采用Pinia状态管理// stores/experiment.js export const useExperimentStore defineStore(experiment, { state: () ({ currentExperiment: null, history: [] }), actions: { setCurrentExperiment(exp) { this.currentExperiment exp this.history.push(exp) } } }) // 组件中使用 const store useExperimentStore() store.setCurrentExperiment(experimentData)7. 项目扩展方向7.1 微信小程序集成通过uni-app实现多端兼容// 获取实验列表 uni.request({ url: https://api.example.com/experiments, success: (res) { this.list res.data } })7.2 数据分析模块集成ECharts实现可视化template div refchart stylewidth:600px;height:400px;/div /template script setup import * as echarts from echarts import { onMounted, ref } from vue const chart ref(null) onMounted(() { const myChart echarts.init(chart.value) myChart.setOption({ xAxis: { type: category, data: [Mon, Tue, Wed] }, yAxis: { type: value }, series: [{ data: [120, 200, 150], type: bar }] }) }) /script8. 开发经验分享8.1 前后端联调技巧推荐使用Swagger UI YAPI后端集成Knife4jConfiguration EnableSwagger2 public class SwaggerConfig { Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(com.tcm.lab.controller)) .paths(PathSelectors.any()) .build(); } }前端使用Mock.js模拟数据8.2 数据库设计建议中药实验系统特有的设计考虑药材属性需要支持多种计量单位克、毫升、个实验步骤需要记录时间序列数据结果数据需要支持多种格式数值、文本、图片典型关联设计CREATE TABLE t_experiment_step ( id int NOT NULL AUTO_INCREMENT, experiment_id int NOT NULL, step_no int NOT NULL, action varchar(200) NOT NULL, duration int DEFAULT NULL COMMENT 分钟, operator_id int NOT NULL, start_time datetime DEFAULT NULL, end_time datetime DEFAULT NULL, PRIMARY KEY (id), KEY idx_experiment (experiment_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;9. 安全防护措施9.1 接口安全设计JWT认证实现public class JwtFilter extends OncePerRequestFilter { Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { String token request.getHeader(Authorization); if (StringUtils.hasText(token) token.startsWith(Bearer )) { token token.substring(7); try { Claims claims Jwts.parser() .setSigningKey(jwtSecret) .parseClaimsJws(token) .getBody(); String username claims.getSubject(); // 设置用户认证信息 } catch (Exception e) { logger.error(JWT解析失败, e); } } chain.doFilter(request, response); } }9.2 数据安全策略敏感字段加密Column(name patient_name) Convert(converter CryptoConverter.class) private String patientName; // 加密转换器 public class CryptoConverter implements AttributeConverterString, String { private static final String KEY your-secret-key; Override public String convertToDatabaseColumn(String attribute) { return AES.encrypt(attribute, KEY); } Override public String convertToEntityAttribute(String dbData) { return AES.decrypt(dbData, KEY); } }10. 性能优化实践10.1 缓存策略设计多级缓存实现方案本地Caffeine缓存Configuration EnableCaching public class CacheConfig { Bean public CaffeineCacheManager cacheManager() { CaffeineObject, Object caffeine Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(1000); return new CaffeineCacheManager(herbCache, expCache, caffeine); } }Redis分布式缓存数据库查询缓存10.2 SQL优化案例典型分页查询优化-- 反例大数据量性能差 SELECT * FROM t_experiment LIMIT 100000, 20; -- 正例使用索引覆盖 SELECT * FROM t_experiment WHERE id (SELECT id FROM t_experiment ORDER BY id LIMIT 100000, 1) ORDER BY id LIMIT 20;11. 项目文档规范11.1 API文档标准采用OpenAPI 3.0规范paths: /api/experiments: get: tags: [Experiment] summary: 获取实验列表 parameters: - name: status in: query schema: type: string enum: [DRAFT, IN_PROGRESS, COMPLETED] responses: 200: description: 成功获取 content: application/json: schema: $ref: #/components/schemas/ExperimentList11.2 数据库文档工具使用SchemaSpy生成ER图java -jar schemaspy-6.1.0.jar \ -t mysql \ -db tcm_lab \ -u root \ -p password \ -host localhost \ -port 3306 \ -o ./docs/db12. 测试方案设计12.1 单元测试实践SpringBoot测试示例SpringBootTest public class ExperimentServiceTest { Autowired private ExperimentService service; Test Transactional Rollback public void testCreateExperiment() { ExperimentDTO dto new ExperimentDTO(); dto.setName(黄芪含量测定); Experiment result service.createExperiment(dto); assertNotNull(result.getId()); assertEquals(黄芪含量测定, result.getName()); } }12.2 前端测试方案Vitest单元测试配置// vitest.config.js import { defineConfig } from vitest/config import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], test: { environment: happy-dom, coverage: { reporter: [text, json, html] } } })13. 持续集成部署13.1 GitHub Actions配置自动化构建流水线name: CI on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Set up JDK 17 uses: actions/setup-javav3 with: java-version: 17 - name: Build with Maven run: mvn -B package --file pom.xml - name: Upload Artifact uses: actions/upload-artifactv3 with: name: tcm-lab-backend path: target/*.jar13.2 前端自动化部署Vercel部署配置{ version: 2, builds: [ { src: dist/**, use: vercel/static } ], routes: [ { src: /(.*), dest: /dist/index.html } ] }14. 项目升级路径14.1 SpringBoot 3.x新特性虚拟线程支持Configuration public class ThreadConfig { Bean public TomcatProtocolHandlerCustomizer? protocolHandlerVirtualThreadExecutorCustomizer() { return protocolHandler - { protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor()); }; } }新的ProblemDetail错误处理改进的GraalVM原生镜像支持14.2 Vue 3组合式API最佳实践推荐使用script setup语法script setup import { ref, computed } from vue const count ref(0) const doubleCount computed(() count.value * 2) function increment() { count.value } /script template button clickincrement {{ count }} ({{ doubleCount }}) /button /template15. 项目经验总结在开发中药实验管理系统的过程中有几个关键点值得特别注意药材数据标准化是基础建立统一的药材编码体系维护完整的药材属性库实现单位自动换算功能实验流程可配置性很重要设计灵活的实验模板机制支持自定义审批流程允许步骤动态调整移动端适配需要考虑实验数据快速录入条码扫描功能集成离线操作支持性能优化要持续进行定期分析慢查询合理使用缓存大数据量分页处理这个技术栈组合(SpringBootVue)经过多个项目验证确实能够很好地满足中药实验室的信息化管理需求。特别是在处理复杂业务逻辑和需要快速迭代的场景下这种架构展现了良好的适应性和可维护性。
返回列表