ARTICLE DETAIL

资讯详情

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

Spring Boot乡村养老服务管理系统开发实战:从源码到上线全解析

Spring Boot乡村养老服务管理系统开发实战:从源码到上线全解析 简介这是一套基于SpringBoot框架构建的乡村养老服务管理系统完整源码面向乡村养老场景覆盖管理员、老人、医疗人员与志愿者四类用户。系统模块包括账户管理、养老服务申请与记录、老人健康信息维护、志愿者陪伴照料等流程适合作为毕业设计、课程项目或乡村养老信息化改造的参考基线。压缩包共926个文件、33.73MB核心文件包括145个Java后端代码、71个Vue页面、161个JavaScript脚本、64个HTML页面、52个样式文件并附带SQL数据库脚本与项目启动脚本。服务申请、健康档案、志愿活动记录等业务流程完整前后端结构清晰便于按模块阅读和二次开发。目前已有43人在线学习浏览。借助这套源码可以直观理解SpringBoot的分层架构、前后端接口配合方式、健康数据管理流程以及乡村养老服务业务闭环对想落地JavaWeb项目或扩展养老管理功能的学习者具有明确参考价值。1. 乡村养老服务管理系统到底在做什么先想清楚业务模型再写代码“乡村养老服务管理系统”这个标题听起来很大但落到代码里核心就三件事老人档案建卡、上门服务留痕、补贴发放有据。Spring Boot 框架在其中管的是接口、事务和权限真正难的是业务模型能不能贴合村一级的真实操作习惯。如果你手里拿到的正是这样一个 zip 源码包最忌讳上手就改代码。先看 README、SQL 脚本和实体类把“乡–村–服务人员”三级角色和一张工单从创建到结算的状态流转挖出来再决定改哪里。这套逻辑顺了后面跑通、改造、交差都顺。这个方向适合三类人做毕业设计或课程项目的在校生、接乡镇零散信息化项目的独立开发者、以及想把 Excel 台账换成系统的基层信息员。我会按“解压源码 → 改配置 → 跑通业务 → 排查坑 → 准备上线”的顺序把常见做法和血泪经验说清楚。2. 用 Spring Boot 搭出可扩展的项目骨架从 zip 源码包到本地能跑2.1 解压源码后先认清目录结构Maven 工程与 SQL 脚本拿到 zip 后第一步不是急着点 IDE 运行而是先解压看结构。一个规范的 Spring Boot 后端工程通常长下面这样rural-eldercare/ ├── pom.xml ├── sql/ │ ├── 1_schema.sql # 建表脚本 │ └── 2_data.sql # 演示数据 ├── src/main/java/com/rural/eldercare/ │ ├── RuralElcareApplication.java │ ├── controller/ # 接口层 │ ├── service/ # 业务层 │ ├── mapper/ # MyBatis 数据访问接口 │ ├── entity/ # 实体类 │ ├── dto/ # 入参/出参对象 │ └── config/ # 安全、Web 配置 └── src/main/resources/ ├── application.yml ├── mapper/ # Mapper XML └── static/ # 静态资源/前端页面如果你拿到的包和我这里不完全一样命名不同很正常重点看三个入口pom.xml、application.yml、XXXApplication.java。pom.xml决定你用的 Spring Boot 版本和依赖application.yml决定连哪个库、端口号启动类里的main方法是整个 jar 的入口。这里有个识别技巧看pom.xml里parent中的版本。Spring Boot 2.7.x 和 3.x 的写法差别很大比如WebSecurityConfigurerAdapter在 3.x 被移除了javax.*包名也换成了jakarta.*。先确认版本再查资料能省下一晚上的折腾。如果发现是 2.3.x、2.6.x 这种老版本也别急着升级乡镇项目稳定优先只要没有严重安全漏洞保持原版跑得转就是胜利。sql目录是最容易忽略却最要命的部分。很多源码包单独提供 SQL 脚本而不是用 JPA 自动建表。这时你必须在跑应用前把库建好否则启动会报找不到表。拿到的 SQL 文件一般有两个一个建表、一个灌数据。我习惯先把2_data.sql导入看看到底有哪些演示数据这样后面调试接口时心里有数。2.2 改三个必改配置数据源、端口、MyBatis 映射路径要让项目在本地跑起来优先动application.yml里这三个位置。下面是一份常见配置骨架server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/rural_elder?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 换成你自己的密码 driver-class-name: com.mysql.cj.jdbc.Driver sql: init: platform: mysql mode: always mybatis: type-aliases-package: com.rural.eldercare.entity mapper-locations: classpath:mapper/*.xmlurl里的characterEncodingutf8保证中文不乱码serverTimezoneAsia/Shanghai保证日期计算不偏 8 小时这一点后面避坑章节还会专门说。password不要硬编码在 yml 里生产环境推荐用环境变量替换例如${DB_PASSWORD}。mybatis.mapper-locations告诉框架去哪找 XML 文件type-aliases-package让你在 XML 里可以直接写resultTypeElder而不是一长串全限定类名。如果启动时报Invalid bound statement (not found)八成就是这个路径和src/main/resources/mapper/实际目录对不上。先检查这两个路径比重新导入项目快得多。然后初始化数据库mysql -uroot -p -e create database rural_elder default charset utf8mb4; mysql -uroot -p rural_elder sql/1_schema.sql mysql -uroot -p rural_elder sql/2_data.sql这三行分别是建库、建表、灌演示数据。别小看第三步没有演示数据列表接口全是空的你根本没法判断 SQL 写得对不对。如果要换 MySQL 8.0driver-class-name用com.mysql.cj.jdbc.Driver如果是 5.7可能得回退到旧驱动类但新驱动向下兼容默认用新的即可。2.3 为什么选 MyBatis 而不是 JPA乡镇项目改表频繁的务实选择很多教程默认推 JPA但在这种有大量报表、多表联查、临时加筛选条件的场景里我一般选 MyBatis。原因很朴素SQL 可控。村信息员今天打电话说“能不能加一个只看五保户的选项”你直接进 XML 改一条 SQL 就能交付用 JPA 的 Specification 绕来绕去反而难调。如果你看到源码里既有Mapper接口又有 XML说明查询都放在 XML 里。去找src/main/resources/mapper/ElderMapper.xml大概率能看到类似这样的统计语句select idcountByHealthLevel resultTypeint SELECT COUNT(*) FROM elder WHERE village_id #{villageId} GROUP BY health_level /select#{villageId}是预编译参数框架会帮你转义而${villageId}是字符串拼接哪怕这个值来自后端常量也不要出现在接受用户输入的地方否则就是 SQL 注入。这个原则在民政系统的安全审计里是必查项如果你要交付给政府类客户这点不能含糊。如果整个工程还出现了“若依框架”的痕迹比如SysUser、RuoYiApplication这类命名说明它是在若依脚手架上改的业务。这种源码的权限和用户管理不用你费心但你的业务代码要放独立模块里别混进框架自带的system模块。否则后面若依升级你的改动全会被冲突淹没。2.4 第一次启动从 jar 包到接口冒出 JSON 的标准动作配置改完后有两种启动方式。在 IDE 里直接跑RuralElcareApplication.java最简单但想验证打包能不能用我更建议先跑一遍 Maven 打包mvn clean package -DskipTests java -jar target/rural-eldercare-0.0.1-SNAPSHOT.jar-DskipTests是跳过单元测试如果你拿到包的测试类里配了无法访问的数据库地址这一步能少踩一次坑。注意看启动日志里Tomcat started和Started RuralElcareApplication这两行出现它们才算没白跑。启动成功后用浏览器访问登录接口或者url里的某个页面。如果项目有 Spring Boot 自带的前端静态页打开http://localhost:8080应该能看到登录页面。如果是纯后端接口项目没有页面很正常用 curl 验证一下健康检查curl http://localhost:8080/actuator/health返回{status:UP}就说明应用活了。这条命令在接下来所有排错里都是第一道照妖镜先看应用本身活着没再谈接口逻辑。3. 核心模块落地老人档案、服务工单与补贴发放的代码实现3.1 老人档案建模容易漏掉的冗余字段与字典设计先看elder表的建表语句。这是整个系统的心脏字段设计直接决定后续有多少补丁。CREATE TABLE elder ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, id_card VARCHAR(18) NOT NULL UNIQUE, gender TINYINT COMMENT 0-女 1-男, birth_date DATE, village_id BIGINT NOT NULL COMMENT 所属行政村, health_level TINYINT COMMENT 1-自理 2-半失能 3-失能, poverty_flag TINYINT DEFAULT 0 COMMENT 1-低保/五保, contact_phone VARCHAR(20), address VARCHAR(255), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY idx_village (village_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;我把birth_date和gender从身份证号里“冗余”了一份。有人觉得多余但乡村录入场景里很多老人第一次建档时身份证号没带在身上信息员填的是出生年份和性别。等后来补录身份证号再回填。冗余字段不是白存它是给不完美的现实留的口子。health_level和poverty_flag这类状态字段建议专门建一张字典表或者在 Java 里用枚举兜底。不要散写在业务代码的数字魔数里否则别人接手时根本不知道health_level2到底是“半失能”还是“失能”。如果源码里已经有了dictionary表就优先用它。另外village_id不要只建普通索引建议建联合索引比如KEY idx_village_level (village_id, health_level)。因为后期报表全是“某个村有几个半失能老人”这种联合索引能让统计 SQL 走覆盖索引省很多时间。3.2 服务工单的状态机从派单到结单的流转与防篡改养老服务最怕“假服务”。护工没上门系统里却多了一条服务记录这不仅是管理问题还是资金问题。所以工单不能随便增删改必须走状态机。下面是核心的创建工单方法public ServiceOrder createOrder(OrderCreateDTO dto) { Elder elder elderMapper.findById(dto.getElderId()); if (elder null) { throw new ServiceException(老人档案不存在); } String today LocalDate.now().toString(); int done orderMapper.countTodayOrders(dto.getWorkerId(), today); if (done 8) { throw new ServiceException(该护工今日工单已达上限不能派单); } ServiceOrder order ServiceOrder.of(dto.getElderId(), dto.getWorkerId(), OrderState.CREATED); orderMapper.insert(order); return order; }先校验老人存在再校验护工当日负荷。countTodayOrders统计的是“已派 进行中”的工单防止把护工排到一天十几个单服务质量崩掉。我见过某些项目把限制写成 999等于没有限制最后被审计问得话都说不出来。真正要紧的是状态流转。我会把“结单”单独放在一个 service 方法里不交给 Controller 直接改字段public void completeOrder(Long orderId, Long workerId, CompleteOrderDTO dto) { ServiceOrder order orderMapper.findById(orderId); if (order null || order.getState() ! OrderState.IN_PROGRESS) { throw new ServiceException(当前状态不允许结单); } if (!order.getWorkerId().equals(workerId)) { throw new ServiceException(只能结自己的单); } order.setState(OrderState.COMPLETED); order.setEndTime(LocalDateTime.now()); order.setRemark(dto.getRemark()); orderMapper.updateState(order); }CREATED → IN_PROGRESS → COMPLETED → CONFIRMED每一步都校验“谁在操作、当前状态合法吗”。假如需要“取消”只能管理员取消护工自己不能撤销因为撤销和补单都是一条后门。审计时数据库里的state_change_log比任何解释都有说服力。为什么不在 Controller 里写这套逻辑因为层与层各管一件事。Controller 只收参数、返回 JSONService层承载业务规则。这样以后加一条“周六不能结单”的规则你只改 service 不碰接口定义前端字段也不用动。3.3 补贴计算金额用 BigDecimal单价从参数表来补贴是乡村养老系统的资金命脉算错一分钱都会被查。常见错误是用double存单价或者把单价硬编码在代码里。正确做法是public BigDecimal calcSubsidy(Long orderId) { ServiceOrder order orderMapper.findById(orderId); if (order.getState() ! OrderState.CONFIRMED) { throw new ServiceException(只有确认后的订单才能结算); } SubsidyRule rule subsidyRuleMapper.findByServiceTypeAndLevel( order.getServiceType(), order.getHealthLevel()); if (rule null) { throw new ServiceException(未配置该服务项目的补贴标准); } BigDecimal amount rule.getUnitPrice(); if (order.getServiceType() ServiceType.HOMECARE.getCode()) { amount amount.multiply(BigDecimal.valueOf(order.getWorkMinutes().doubleValue() / 60.0)) .setScale(2, RoundingMode.HALF_UP); } return amount; }金额运算必须用BigDecimal.multiply并指定舍入模式divide如果要除紧跟精度否则直接抛ArithmeticException。补贴单价放在subsidy_rule表里由乡镇管理员按季度调整别换一次政策就发一次包。我在实际项目里见过洗浴项目按 22 分钟计费double累计 20 条后差出两毛钱对账对到半夜。那之后我给自己定了条死规矩凡是金额、单价、补贴一律BigDecimal且精度统一两位舍入用HALF_UP。HELP这个词在这里不是求助而是“向上取一半”的舍入模式中文叫四舍五入。3.4 统计报表用一条 SQL 代替几十行 Java 循环乡镇系统逃不开月报、季报。别在 Java 里 for 循环每个村统计直接在 Mapper XML 里写聚合 SQL既清晰又省内存。常见的补贴汇总select idsumSubsidyByVillage resultTypejava.util.Map SELECT v.name AS village_name, COALESCE(SUM(s.amount), 0) AS subsidy_total, COUNT(DISTINCT s.elder_id) AS elder_count FROM village v LEFT JOIN service_order s ON s.village_id v.id WHERE s.state 4 AND s.confirm_time BETWEEN #{start} AND #{end} GROUP BY v.id, v.name ORDER BY subsidy_total DESC /selectCOALESCE(SUM(...), 0)处理没有服务记录的村避免返回null导致前端显示空白。COUNT(DISTINCT s.elder_id)算受益人次不是服务单数因为一个老人可能一月服务了 10 次口径要清楚。如果你拿到源码里的统计 SQL 没有加state 4即 CONFIRMED赶紧补上否则会把未确认的草稿单子算进补贴这是财务事故。4. 权限与监控Spring Security 和 Spring Boot Admin 的集成要点4.1 登录认证为什么选 JWT 而不是 Session乡村网络环境差服务人员可能上午在村西头下午去另一个村服务站点也常换机器。Session 存在内存里应用一重启全掉线。更现实的理由是现在很多项目接的是手机 H5前后端分离已经是主流。JWT 无状态、方便多端验证但要注意密钥管理和过期策略。常见做法是写一个过滤器解析请求头里的Authorization: Bearer xxxComponent public class JwtAuthenticationFilter extends OncePerRequestFilter { Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String auth request.getHeader(Authorization); if (auth ! null auth.startsWith(Bearer )) { String token auth.substring(7); try { Claims claims Jwts.parser() .setSigningKey(secretKey()) .parseClaimsJws(token).getBody(); request.setAttribute(uid, claims.get(uid)); request.setAttribute(role, claims.get(role)); } catch (JwtException | IllegalArgumentException e) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, 登录已过期); return; } } chain.doFilter(request, response); } }密钥别写死在代码里放到配置文件或者环境变量里每次启动从配置读取这样就算代码传到 git 上也不会泄露。JWT 的优势是“天然分布式”但secretKey()要让别人知道你是读的哪个配置不然新人接手时到处找密钥最后把写死的密钥翻出来了等于白设计。4.2 角色与数据权限乡、村、服务人员三种视角数据权限比角色更头疼。同是“管理员”乡级管理员能看全乡村级管理员只能看自己村。在表上加village_id还不够查询时要把当前用户的villageId强制注入进去而不是信任前端传的参数。PreAuthorize(hasAnyRole(TOWN_ADMIN,VILLAGE_ADMIN,WORKER)) public PageResultElderVO pageElders(ElderQueryDTO dto) { Long userId SecurityUtil.getUserId(); UserInfo user userMapper.findRole(userId); if (user.getRole().equals(VILLAGE_ADMIN)) { dto.setVillageId(user.getVillageId()); } return elderMapper.page(dto); }关键点是dto.setVillageId(user.getVillageId())它发生在你校验完角色之后。如果只靠前端传villageId别人调接口传villageId1就能看别的村。这是安全审计里最容易挨刀的地方。我在审查别人代码时第一件事就是搜Controller里有没有直接把参数透传给 Mapper 的接口十有八九能查出越权漏洞。在 Spring Boot 3.x 中WebSecurityConfigurerAdapter已被移除要改用SecurityFilterChain新版写法。如果你拿到的是 2.x 源码看到extends WebSecurityConfigurerAdapter会有“已弃用”的提示不用慌功能一样只是换了个写法。除非你有强制升级需求否则不要顺手把 Spring Boot 版本改了否则大量依赖都要跟着动。4.3 用 Spring Boot Admin 盯住运行健康度乡村项目通常没有专职运维出问题要能被提前发现。我习惯在服务里加spring-boot-admin-client连接一个内网跑的 admin server。配置只需要几行spring: boot: admin: client: url: http://192.168.10.10:9000 instance: prefer-ip: true service-url: http://192.168.10.20:8080 management: endpoints: web: exposure: include: health,info,metricsprefer-ip: true的意思是让 admin server 用内网 IP 去访问这个服务而不是机器名。management.endpoints.web.exposure.include只暴露health,info,metrics不要图方便放*尤其不能暴露shutdown和env。env会回显数据库密码相当于把保险柜钥匙挂在门口。admin server 本身最好也加server.address127.0.0.1或者白名单别绑0.0.0.0。监控面板这种东西只有运维和开发能看绑到公网等于把系统内部结构昭告天下。4.4 操作日志审计现场的第一手证据政务类项目最怕“死无对证”。谁在几点把某位老人的补贴从 200 改成了 300必须有记录。最省事的方案是用 AOP 切面统一记录写操作。在需要留痕的地方我给方法加一个自定义注解AuditLog(修改补贴)切面里统一记录入参、操作人、IP 和结果。下面是一个极简切入点Around(annotation(auditLog)) public Object log(ProceedingJoinPoint pjp, AuditLog auditLog) throws Throwable { String operator SecurityUtil.getUserId().toString(); String args Arrays.toString(pjp.getArgs()); Object result; try { result pjp.proceed(); saveLog(auditLog.value(), operator, args, SUCCESS); } catch (Exception e) { saveLog(auditLog.value(), operator, args, FAIL: e.getMessage()); throw e; } return result; }把日志写进数据库专门的一张表operate_log比翻文件日志高效得多。时间久了文件的日志会被滚动删除数据库表却能一直留着。审计时工作人员问你“为什么这条补贴取消了”你把operate_log里那行数据拍在桌上这是会计凭证级别的底气。5. 避坑指南乡村场景下最容易翻车的五个常见问题5.1 时区与日期补贴结算差一天等于差一路钱现象系统白天录入的服务工单凌晨查看时create_time比真实时间少了 8 小时日结报表把当天最后一批单算到了前一天补贴汇总对不上账。原因MySQL 连接串里没传serverTimezoneSpring Boot 默认用 JVM 时区而部署服务器可能是 UTC。字段类型用了DATETIME本来没问题但 JDBC 读取时发生了时区转换偏移。解决连接串统一加serverTimezoneAsia/Shanghai实体类时间字段用LocalDateTime不要用java.util.Date部署机器时执行timedatectl set-timezone Asia/Shanghai。这三件事缺一不可体检裤带系一道可能不够。5.2 身份证校验格式对不代表号码真现象能输入 18 位身份证号但随便改一个数字也能通过到民政核对名单时整批被退回。原因只写了正则\d{17}[\dXx]没有校验最后一位校验码。身份证第 18 位是根据前 17 位按 GB 11643 规则算出来的改一个数字校验码就对不上。解决写一个公共校验工具入库前调用。核心是加权求和后对 11 取模public static boolean isValidIdCard(String idCard) { if (idCard null || idCard.length() ! 18) return false; String regex ^\\d{17}[0-9Xx]$; if (!idCard.matches(regex)) return false; char[] chars idCard.toCharArray(); int[] w {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; String check 10X98765432; int sum 0; for (int i 0; i 17; i) { sum (chars[i] - 0) * w[i]; } return check.charAt(sum % 11) Character.toUpperCase(chars[17]); }注意一定要Character.toUpperCase(chars[17])否则用户输入小写x会误判。这套校验逻辑不复杂但很多人死活踩坑就是因为把自己写的正则当成了万能钥匙。5.3 MyBatis 批量插入一条巨大 SQL 拖垮数据库现象从 Excel 导入五百位老人档案时程序卡死或耗时十多分钟数据库 CPU 飙高。原因一个foreach拼了几千条 INSERT 组成的超大语句同时没调整 MySQL 的max_allowed_packet或者干脆用循环单条插入。解决用 MyBatis 的批量插入 SQL并且分批提交每批 200 条insert idbatchInsertElder INSERT INTO elder (name, id_card, gender, birth_date, village_id, health_level) VALUES foreach collectionlist iteme separator, (#{e.name}, #{e.idCard}, #{e.gender}, #{e.birthDate}, #{e.villageId}, #{e.healthLevel}) /foreach /insert调用时按 200 条一组循环并且不要和整个导入流程挤在同一个大事务里。正确姿势是“每批一个事务”中途失败只回滚这一批已提交的保留同时给导入接口一个断点续传的入口而不是让信息员从头再导一遍。5.4 文件上传图片存在数据库是最典型的灾难现象护工用手机拍照上传服务证明数据库.ibd文件几天涨了几个 GB备份越来越慢。原因有人图省事把图片转 Base64 字符串直接塞进TEXT字段。Base64 比原始字节多 33% 体积一张 1MB 照片变成 1.37MB 字符串存在库里再来一万张就是灾难。解决图片落在服务器或 OSS数据库只存 URL 和大小。本地存储就单独建/data/uploads目录通过路径访问不经过业务应用。上传接口加大小限制spring: servlet: multipart: max-file-size: 5MB还要在 Nginx 配置里对上传文件做后缀白名单只允许.jpg.jpeg.png否则有人传个.jsp上去就有被解析的风险。这个坑看似普通但几乎所有电子档案系统最后都栽在存储规划上。5.5 源码包跑不起来先怪环境还是先怪代码现象拿到 zip 解压后mvn spring-boot:run报一堆错第一反应是源码有问题。原因多半是 JDK 版本、Maven 镜像、MySQL 版本和代码不匹配。Spring Boot 2.x 用 JDK8/11Spring Boot 3.x 必须 JDK17MySQL 5.7 和 8.0 的驱动类名、认证方式都不一样。解决先看 README没有就自己查pom.xml和application.yml把 JDK 切到匹配版本Maven 换成国内镜像MySQL 建库用utf8mb4。如果连com.mysql.cj.jdbc.Driver都报找不到说明 pom 里没引驱动或驱动版本太低。最后看sql目录一般源码自带的 SQL 一定能跑通先别去动它。等应用起来了再根据你的业务需求去改表这样定位报错时你心里有明确的先后顺序。6. 从能跑到能用轻量压测、日志与上线前检查清单系统跑通只是第一步。要真敢让它在乡里部署得先过一遍弹量测试。乡镇系统不需要扛高并发一般几十个管理员同时用就撑死了但也不能几个请求就把线程池打满。先测登录接口和核心列表接口。用ab做简单压测ab -n 200 -c 20 -p login.json -T application/json http://localhost:8080/api/login-n 200是总请求数 200-c 20是并发数 20login.json是提前写好的请求体。如果错误率不是 0%先看接口返回的报错码。出现500打开应用日志看到SQLException就去查连接池配置看到OutOfMemoryError就把jvm的-Xmx调一下。压测不是为了好看是为了逼出那些只会在并发下现形的初始化 bug。日志配置要分层logging: file: name: logs/rural-elder.log level: com.rural.eldercare.mapper: debugmapper包用debug能打印 SQL 语句排查“查不到数据”很管用生产环境记得调回info否则一个高光时刻的村子能打出几个小时不重复的日志。日志文件建议按天滚动避免单文件越来越大找个日志文件时翻到怀疑人生。上线前检查清单整理成一张表存在项目根目录检查项正确姿势常见错误数据库连接串带serverTimezoneAsia/Shanghai使用 UTC 导致时间错 8 小时密码配置环境变量注入明文写在application.yml提交到仓库管理端端口内网隔离或白名单绑定公网0.0.0.0文件上传目录独立目录加 Nginx 映射图片 Base64 存库多环境配置至少dev和prod分离只有一份开发配置直接上线我自己在上一个乡村项目里吃过时区的亏后来每次交付前都会把“当前时间 数据库时间 业务时间”三处对一遍。代码能跑只是开始能经得起查才是能用。希望这个清单能帮你少熬几个夜也希望你交付的每个系统都不被“返工”二字追上。本文还有配套的精品资源点击获取
返回列表