尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SpringBoot+Vue3全栈开发中医药数字化服务平台实践

SpringBoot+Vue3全栈开发中医药数字化服务平台实践 1. 项目概述中医药数字化服务的全栈实践作为一名长期从事Java全栈开发的工程师最近完成了一个中医药领域的数字化服务平台项目。这个系统采用SpringBootVue3MyBatis技术栈实现了经方药食两用服务的线上化解决方案。在实际开发过程中我发现中医药领域的信息化建设存在诸多特殊需求比如体质辨识的算法实现、药膳配方的结构化存储等这些都是传统CRUD系统不会遇到的挑战。这个平台的核心价值在于通过数字化手段解决中医药服务中的三个痛点经典药方与食疗方案分散在不同典籍中普通用户难以系统获取传统问诊模式效率低下无法满足现代人的快节奏需求药食同源理念缺乏科学化的呈现方式2. 技术架构设计与选型2.1 为什么选择SpringBootVue3全栈方案在技术选型阶段我们对比了多种方案后最终确定现在的技术栈。SpringBoot作为后端框架具有以下优势自动配置特性大幅减少XML配置内嵌Tomcat简化部署流程丰富的Starter依赖可快速集成MyBatis、Redis等组件完善的健康检查和管理端点前端选择Vue3而非React或Angular的考虑组合式API更适合复杂业务逻辑的封装更小的包体积和更好的性能与Element Plus的完美兼容性团队现有技术栈的延续性2.2 数据库设计中的中医药特色MySQL的表结构设计充分考虑了中医药领域的特殊性。以药膳食谱表为例CREATE TABLE herbal_recipe ( recipe_id bigint NOT NULL AUTO_INCREMENT, recipe_name varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, ingredients text COLLATE utf8mb4_unicode_ci, cooking_method text COLLATE utf8mb4_unicode_ci, suitable_for varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, nutritional_info text COLLATE utf8mb4_unicode_ci, creator_id bigint DEFAULT NULL, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (recipe_id), FULLTEXT KEY ft_ingredients (ingredients) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci;几个关键设计点使用utf8mb4_unicode_ci字符集以支持完整的中文和特殊符号对ingredients字段建立全文索引以便复杂搜索将适用体质(suitable_for)单独作为字段方便筛选营养分析(nutritional_info)采用TEXT类型存储结构化JSON3. 核心功能实现细节3.1 体质辨识与智能推荐算法系统最复杂的业务逻辑在于体质辨识算法。我们参考《中医体质分类与判定》标准将体质分为9类通过用户填写的问卷计算各体质得分public class ConstitutionCalculator { private static final MapString, Double WEIGHTS Map.of( A1, 1.0, A2, 0.8 /* 其他题目权重... */); public ConstitutionResult calculate(ListAnswer answers) { MapString, Double scores new EnumMap(ConstitutionType.class); // 计算原始分 answers.forEach(a - { String type a.getQuestion().getConstitutionType(); scores.merge(type, a.getScore() * WEIGHTS.get(a.getQuestionId()), Double::sum); }); // 转化分计算 MapString, Double convertedScores scores.entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, e - (e.getValue() - 10) / 20 * 100)); // 判断体质类型 String primaryType Collections.max( convertedScores.entrySet(), Comparator.comparingDouble(Map.Entry::getValue)).getKey(); return new ConstitutionResult(primaryType, convertedScores); } }3.2 药膳配方的结构化处理传统药膳配方包含药材、食材、剂量、炮制方法等信息我们设计了一套结构化存储方案{ recipe_id: 1024, recipe_name: 当归生姜羊肉汤, ingredients: [ { name: 当归, type: herb, amount: 10g, processing: 切片 }, { name: 生姜, type: spice, amount: 30g, processing: 切片 } ], steps: [ { order: 1, action: 焯水, target: 羊肉, duration: 3分钟 } ] }这种结构化的存储方式使得前端可以更灵活地展示配方便于实现剂量换算功能支持按药材/食材进行检索方便后续的数据分析4. 前后端交互的关键实现4.1 基于JWT的认证方案系统采用JWT进行身份认证考虑到中医药数据的敏感性我们做了以下安全增强Configuration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())) .addFilter(new JwtAuthorizationFilter(authenticationManager())) .authorizeRequests() .antMatchers(/api/public/**).permitAll() .antMatchers(/api/recipes/search).permitAll() .antMatchers(/api/**).authenticated(); } Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); } }安全要点使用BCryptPasswordEncoder且cost factor设为12JWT设置15分钟短有效期实现refresh token机制敏感接口增加二次认证4.2 文件上传与富文本处理药膳制作常需要上传图片和视频我们使用阿里云OSS进行文件存储public class OssService { private final OSS ossClient; private final String bucketName; public String uploadRecipeImage(MultipartFile file, Long recipeId) { String objectName recipes/ recipeId / UUID.randomUUID() FilenameUtils.getExtension(file.getOriginalFilename()); try (InputStream inputStream file.getInputStream()) { ossClient.putObject(bucketName, objectName, inputStream); return generateUrl(objectName); } catch (IOException e) { throw new StorageException(文件上传失败, e); } } private String generateUrl(String objectName) { // 生成带签名的URL有效期1小时 Date expiration new Date(System.currentTimeMillis() 3600 * 1000); return ossClient.generatePresignedUrl(bucketName, objectName, expiration).toString(); } }5. 开发中的经验与教训5.1 中医药术语的标准化处理在开发初期我们遇到了中医药术语不统一的问题。例如当归在不同典籍中可能有干归秦归等别名。解决方案是建立药材别名表CREATE TABLE herb_alias ( herb_id bigint NOT NULL, alias varchar(50) NOT NULL, PRIMARY KEY (herb_id,alias), INDEX idx_alias (alias) );在搜索时进行术语归一化public class HerbNormalizer { private final MapString, String aliasMap; public String normalize(String herbName) { return aliasMap.getOrDefault(herbName.toLowerCase(), herbName); } }5.2 性能优化实践在用户量测试时发现的性能问题及解决方案体质计算结果缓存Cacheable(value constitution, key #userId) public ConstitutionResult calculateConstitution(Long userId) { // 计算逻辑 }药膳列表分页优化-- 避免使用COUNT(*) OVER() SELECT * FROM herbal_recipe WHERE suitable_for LIKE %阳虚% ORDER BY create_time DESC LIMIT 10 OFFSET 0;前端虚拟滚动优化长列表template el-table-v2 :columnscolumns :datarecipes :height600 :width1000 :estimated-row-height60 :buffer-size20 / /template6. 部署与运维方案6.1 基于Docker的部署整个系统采用容器化部署docker-compose.yml配置示例version: 3.8 services: backend: build: ./backend ports: - 8080:8080 environment: - SPRING_PROFILES_ACTIVEprod - DB_URLjdbc:mysql://db:3306/tcm depends_on: - db - redis frontend: build: ./frontend ports: - 80:80 db: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORDsecurepassword - MYSQL_DATABASEtcm volumes: - db_data:/var/lib/mysql redis: image: redis:6-alpine volumes: db_data:6.2 监控与日志方案为了保证系统稳定运行我们实施了以下监控措施Spring Boot Actuator健康检查management.endpoints.web.exposure.includehealth,info,metrics management.endpoint.health.show-detailswhen_authorizedELK日志收集方案Configuration public class LogbackConfig { Bean public LoggerContext loggerContext() { LoggerContext context (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator new JoranConfigurator(); configurator.setContext(context); context.reset(); try { configurator.doConfigure( getClass().getResourceAsStream(/logback-spring.xml)); } catch (Exception e) { // 处理异常 } return context; } }在开发这个中医药服务平台的过程中我深刻体会到传统行业数字化转型的特殊性。技术实现上虽然使用的是通用技术栈但业务逻辑必须深入理解行业知识。比如体质辨识算法的实现就需要研读中医理论文献与专业医师反复沟通确认。这种跨界项目的开发经验让我认识到好的技术方案应该是技术与业务的完美融合而不是单纯的技术堆砌。
返回列表