news 2026/10/18 14:14:23

Java 项目实战: 交友项目 - 章节复盘:微服务骨架与手机号验证码登录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 项目实战: 交友项目 - 章节复盘:微服务骨架与手机号验证码登录

概述

交友项目第一章从零把一个散装的 Maven 空工程,搭成了一个能注册到 Nacos、能发短信、能用手机号 + 验证码登录的微服务骨架。本篇不复述每一步怎么点,而是把这一章的五个板块串成一条链,抽走那些"下次还会再写一遍"的套路,并给出一份能自己勾选的自检清单。

纲要

  • 本章一句话产出:可运行的微服务骨架 + 手机号验证码登录(含首次登录自动注册)
  • 本章知识地图:五个板块的依赖顺序(前一板块是后一板块的前提)
  • 工程终态:第一章结束时的真实模块清单与关键类
  • 可复用套路清单:第三方能力封装四件套 / Dubbo 三件套 / 验证码 + Redis / JWT / BasePojo
  • 关键坑回顾:spring.factories路径、Dubbo 注册协议、序列化、123456硬编码
  • 自检清单:八项可勾选验证
  • 练习建议:唯一索引 + 频控 + 密钥外置
  • 下一章预告:完善用户信息(头像、人脸识别、统一鉴权)

本章一句话产出

一句话概括:用 Dubbo + Nacos 搭起可注册的微服务骨架,跑通"手机号 + 验证码"登录,新用户在登录时自动注册,并把时间字段的填充收敛到公共基类。

这句话里有三个动作,缺一个链路就断:骨架要先注册得上去,短信才发得出去;验证码要能落进 Redis,登录时才有东西校验;用户表要能查、能写,自动注册才成立。

本章知识地图

五个板块不是并列的,是有严格先后依赖的。前一板块不成立,后一板块就没有落脚点。

决定模块怎么切

模块不定好,组件没地方放

依赖没治理好,组件引不进来

发不出验证码,登录无从谈起

created/updated 反复手写才想抽基类

项目认知
是什么 / 什么架构 / 有哪些模块

工程准备
工具环境 + 模块划分 + 依赖治理

第三方能力接入
阿里云短信 + 自动装配组件

用户登录
验证码 -> JWT -> 自动注册

代码优化
BasePojo + 自动填充

依赖关系说穿了就三句话:

  • 模块划分不定好,mf-autoconfig这个组件就没地方放,mf-dubbo-interface也不能被别的模块依赖。
  • 依赖没在父工程dependencyManagement里统一版本,组件引进来就是版本漂移,A 模块 3.4.1 的 MyBatis-Plus、B 模块 3.5.x,跑起来才报错。
  • 短信和 JWT 都是登录的前置条件:前者负责把验证码送到用户手里,后者负责把"登录成功"这个状态封成 stateless 的凭证。

工程终态:第一章结束时长什么样

实读第一章代码快照,模块清单与讲义 3.2.2 的模块表一致,八个模块全部就位(mf-dubbo-mongo在这一章还是空壳,只建了目录)。

mf/ # 父工程(聚合 + 统一版本管理) ├── pom.xml ├── mf-autoconfig/ # 自动装配组件(第三方能力封装) │ └── src/main/ │ ├── java/com/mf/autoconfig/ │ │ ├── mfAutoConfiguration.java │ │ ├── properties/SmsProperties.java │ │ └── template/SmsTemplate.java │ └── resources/META-INF/spring.factories ├── mf-model/ # 实体类模块 │ └── src/main/java/com/mf/model/domain/ │ ├── BasePojo.java # created / updated 自动填充基类 │ └── User.java # 继承 BasePojo ├── mf-commons/ # 工具类模块 │ └── src/main/java/com/mf/commons/utils/JwtUtils.java ├── mf-dubbo/ # Dubbo 模块的父级(仅作管理) │ ├── mf-dubbo-interface/ # Dubbo 接口(契约) │ │ └── com/mf/dubbo/api/UserApi.java │ ├── mf-dubbo-db/ # Dubbo 服务(数据库部分) │ │ └── com/mf/dubbo/ │ │ ├── DubboDBApplication.java │ │ ├── api/UserApiImpl.java │ │ ├── handler/MyMetaObjectHandler.java │ │ └── mappers/UserMapper.java │ └── mf-dubbo-mongo/ # Dubbo 服务(MongoDB 部分,暂空) └── mf-app-server/ # 与手机端交互的入口 └── com/mf/server/ ├── AppServerApplication.java ├── controller/LoginController.java └── service/UserService.java

两个关键产物在这一章定型:mf-autoconfig里的短信组件被mf-app-server直接@Autowired就能用,证明自动装配真的生效;mf-model的User继承BasePojo,把created/updated从业务代码里彻底摘掉。

可复用套路清单

这一章的价值不在"写了哪些类",而在于几个会反复出现的模式。后面每个业务域基本都是在套这几张模板。

套路本章用在哪后续哪里还会再用
第三方能力封装四件套:Properties+Template+AutoConfiguration+spring.factories阿里云短信OSS 上传、人脸识别、内容审核,凡是"接一个云厂商 SDK"都是同一套
Dubbo 服务三件套:interface契约 +Impl实现 + 消费者@DubboReferenceUserApi/UserApiImpl后续每个新业务域(动态、推荐、IM)都要新建一组
验证码 + Redis 组合登录验证码,5 分钟 TTL凡是短时效数据(临时凭证、一次性令牌、防重复提交标记)都能照此办理
JWT 签发与校验登录后签发 token,携带id+mobile后续所有需要身份识别的接口都靠它,配合统一鉴权拦截器
BasePojo+ 自动填充created/updated后续所有持久化实体都继承它,不再手写时间字段

四件套的骨架长这样,换个第三方 SDK 只需替换SmsTemplate里的实现。

# mf-autoconfig/src/main/resources/META-INF/spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.mf.autoconfig.mfAutoConfiguration
packagecom.mf.autoconfig;importcom.mf.autoconfig.properties.SmsProperties;importcom.mf.autoconfig.template.SmsTemplate;importorg.springframework.boot.context.properties.EnableConfigurationProperties;importorg.springframework.context.annotation.Bean;// 自动装配入口:被 spring.factories 声明后,其他工程引入本模块即自动生效@EnableConfigurationProperties({SmsProperties.class})publicclassmfAutoConfiguration{// 把配置类里的参数注入 Template,再以 Bean 的形式暴露给使用者@BeanpublicSmsTemplatesmsTemplate(SmsPropertiesproperties){returnnewSmsTemplate(properties);}}

Dubbo 三件套的分工值得记牢:mf-dubbo-interface只放UserApi接口,被提供者和消费者共同依赖;mf-dubbo-db里UserApiImpl用@DubboService暴露;mf-app-server里用@DubboReference(新版本注解,等价于旧的@Reference)引用。接口模块不依赖实现模块,这是解耦的关键。

消费者端的配置也是固定模板,注意registry.address用spring-cloud://localhost(走 Nacos 注册中心),不是nacos://。

# mf-app-server/src/main/resources/application.ymlserver:port:18080# Web 端口spring:application:name:mf-app-serverredis:# 验证码存这里host:192.168.136.160port:6379cloud:nacos:discovery:server-addr:192.168.136.160:8848dubbo:registry:address:spring-cloud://localhost# 由 Nacos 托管注册发现consumer:check:false# 启动时不强校验提供者是否存在

本章的关键坑回顾

坑都集中在"配置写对但装不上/发现不到",而且很多是静默失败——不报错,就是没效果。

坑症状解法
spring.factories路径写错短信组件@Autowired注入失败或注入为 null,启动无异常必须放在resources/META-INF/spring.factories,文件全名不能差一个字母;先确认模块已install
dubbo.scan.base-packages写错提供者启动正常,但注册中心里看不到服务路径要精确到com.mf.dubbo.api,与@DubboService所在包一致
spring-cloud://与nacos://混淆服务注册不上,或消费者发现不到提供者走 Nacos 注册中心时统一用spring-cloud://localhost
Web 端口与 Dubbo 协议端口混用两个服务抢占端口,或调用超时Web 用server.port(18080/18081),Dubbo 协议用dubbo.protocol.port(20881),两条线分开
实体没实现SerializableDubbo 调用时报序列化异常传输对象(如User)必须实现Serializable,BasePojo已实现,继承即可
JWT 密钥硬编码、payload 放敏感信息密钥泄露即全站伪造;claims 可被 base64 解码密钥外置到配置,payload 只放id、mobile这类非敏感标识
验证码开发态写死123456忘记改回上线后任意手机号都能用123456登录联调期临时写死可以,提交前必须换回随机 6 位并走短信通道
tb_user.mobile缺唯一索引并发首次登录时同一手机号插入两条给mobile加唯一索引,并捕获DuplicateKeyException兜底
多模块工程未先install公共模块依赖mf-model报找不到坐标先mvn install父工程与公共模块,再做子模块开发
Maven 依赖未统一版本管理运行期NoSuchMethodError、版本漂移版本统一写在父工程<dependencyManagement>,子模块只写坐标不写版本

自检清单

跑通本章的标准不是"代码能编译",而是下面八项逐条成立。每一项都给了验证方式。

检查项怎么验
环境已就绪Linux 里docker ps能看到 MySQL、Redis、Nacos;Maven 能拉到依赖
服务已注册到 Nacos打开 Nacos 控制台http://<ip>:8848,服务列表里有mf-app-server与mf-dubbo-db
短信能真正发出调用smsTemplate.sendSms("真实号码","1234"),手机收到短信(不是只打印日志)
验证码能落进 Redis调POST /user/login后redis-cli执行keys CHECK_CODE_*,能看到键且 TTL 约 300s
登录能拿到 token调POST /user/loginVerification,返回体里有token字段且是一串A.B.C
新用户自动注册且isNew=true用未注册手机号登录,DBtb_user新增一行,返回值isNew=true
老用户isNew=false用已注册手机号再登录一次,tb_user不新增,返回值isNew=false
created字段自动填充新注册用户那一行created不为空,且值约等于插入时刻

练习建议

不看讲义、把登录链路独立再实现一遍,是最有效的检验——建议改用不同的包名/类名,验证自己记住的是结构而不是代码位置。

补一道并发防线。tb_user.mobile加唯一索引,并处理DuplicateKeyException。

-- 改哪里:数据库执行ALTERTABLEtb_userADDUNIQUEINDEXuk_mobile(mobile);
// 怎么验证:并发调用登录,同一手机号插两次只成功一次,另一次被捕获而非抛 500try{LonguserId=userApi.save(user);user.setId(userId);isNew=true;}catch(DuplicateKeyExceptione){// 并发下已被别人抢先注册,回查即可user=userApi.findByMobile(phone);isNew=false;}

补一个频控。给发验证码接口加"同一手机号 60 秒一次 / 一天 10 条",用 Redis 计数 + TTL。

// 改哪里:UserService#sendMsg 开头StringlimitKey="SMS_LIMIT_"+phone;Longcount=redisTemplate.opsForValue().increment(limitKey);if(count!=null&&count==1){redisTemplate.expire(limitKey,Duration.ofDays(1));// 首次设置日上限 TTL}if(count!=null&&count>10){thrownewRuntimeException("今日验证码次数已达上限");}// 怎么验证:连续点 11 次发短信,第 11 次返回受限;把键删掉后恢复

把硬编码清掉。JWT 密钥mfxs123、默认密码123456、Redis key 前缀CHECK_CODE_都提到配置或常量类。

# 改哪里:application.yml 增加mf:jwt:secret:${MF_JWT_SECRET:change-me}expire-seconds:3600
// 怎么验证:全局搜索代码里不再出现 "mfxs123" 与 "123456" 字面量// 只保留常量类或配置读取

给验证码加一次性语义。校验成功后立即删除 Redis 里的验证码(现有代码已经做了delete),并确认删的是同一个 key,避免大小写或前缀不一致导致删了个寂寞。

常见误解澄清

  • 以为登录做完项目就过半了。其实只是把骨架打通了,业务功能(动态、推荐、IM)一个都还没开始。
  • 以为学到的是一次性代码。短信组件、Dubbo 三件套、JWT 工具类都是可迁移的套路,后面每个模块都在复用它。
  • 以为123456可以留在代码里。联调临时写死可以,交付前必须换回随机验证码并接通短信。
  • 以为流程跑通就算完成。还要补防线:唯一索引挡并发、频控挡刷短信、密钥外置挡泄露。

下一篇预告

后续将进入"完善用户信息":上传头像、人脸识别、个人资料管理,并引入统一鉴权与统一异常处理。它会直接吃掉本章的产物——短信组件那套自动装配套路会被复用来接 OSS 与人脸识别 SDK,JWT 会在统一鉴权拦截器里被解析出id,BasePojo会被新的用户资料实体继续继承。本章把骨架和凭证体系立住了,下一章才有地方往上长业务。

官方文档

  • 阿里云短信服务
  • JSON Web Token 官方测试站
  • Spring Boot 自动装配与 spring.factories
  • Apache Dubbo 注解驱动

总结

  • 本章的产出是一条可运行的登录链路:注册中心能发现服务,短信能发出,验证码能落 Redis,登录能拿 token,新用户能自动注册。
  • 真正沉淀下来的不是八个模块的目录,而是五套可复用套路:第三方封装四件套、Dubbo 三件套、验证码 + Redis、JWT、BasePojo。
  • 容易翻车的地方几乎都在配置静默失效(spring.factories路径、Dubbo 扫描包、注册协议),排查时先看"服务有没有注册上去",再往下查。
  • 流程跑通只是及格线,唯一索引、发短信频控、密钥外置这三条防线补上,才算把这一章的隐患真正修掉。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 14:10:39

医院信息管理系统HIS的Java Swing实战:报告模块开发与避坑指南

简介&#xff1a;医院信息管理系统Java Swing课程设计资源&#xff0c;面向高校数据库课设及桌面应用开发学习者。系统完整实现药品类型与药品信息管理、药品入库出库、科室医生病人管理、处方登记及挂号诊断收费等模块&#xff0c;数据库层包含十多个表、三个视图、七个触发器…

作者头像 李华
网站建设 2026/10/18 14:09:45

VTK 体绘制入门到排错:传递函数、采样距离与透明度的关系

同一组体数据&#xff0c;换一套透明度曲线就可能从“什么都看不到”变成“整块发白”。这不一定意味着数据出错&#xff0c;也不一定是显卡不够快。体绘制把空间采样、标量映射与沿光线合成连接在一起&#xff0c;任何一个环节的约定变化都可能影响最终画面。本文先建立可解释…

作者头像 李华
网站建设 2026/10/18 14:09:14

多动作并行异步DDPG:选矿浮选智能决策模型工程化实践

简介&#xff1a;本资源是一篇发表于《控制与决策》2022年第8期的学术论文PDF&#xff0c;面向自动化、智能优化与流程工业领域的研究生、科研人员及工程技术人员&#xff0c;聚焦选矿过程运行指标的动态决策难题。针对传统深度确定性策略梯度&#xff08;DDPG&#xff09;算法…

作者头像 李华