1. 项目导入前,先把黑马点评当“产品”而不是“代码库”看
我在带过好几个新手跑这个项目之后发现一个普遍问题:很多人拿到黑马点评源码后的第一反应,是解压、打开IDEA、直接点运行,结果看到一个又一个红色报错就开始慌了。其实黑马点评不是一个“打开就能跑”的玩具工程,它是一个由前端页面、后端接口、MySQL数据库、Redis缓存组合而成的完整系统。你只有先搞清楚每个组件在项目里扮演什么角色,导入时才不会瞎猜。
从Java基础学完到真正上手实战项目,中间最大的坎不是语法,而是“环境协作”。黑马点评这个项目正好把这个坎完整暴露给你:它用Maven管理依赖,用SpringBoot提供接口,用MyBatis-Plus操作MySQL里的用户、商铺、优惠券等数据,用Redis处理验证码、缓存、分布式锁。项目导入这件事,本质上是把你本机的Java环境、数据库环境、缓存环境跟项目里的配置对齐。
很多人在这一步被劝退,不是因为智商问题,而是因为不知道项目启动到底需要哪些“外部条件”。我自己第一次导入时也犯过蠢:先运行了后端,结果控制台一直报连不上数据库;好不容易把MySQL启动了,又发现Redis没装;搞定了Redis,前端页面又打不开。每个环节单独看都不难,但串在一起就会让人手忙脚乱。
你手里这份黑马点评源码,通常是后端工程为主,前端页面有的版本放在resources/static目录下,有的版本是独立的Vue工程。如果你的版本是前者,那SpringBoot启动后浏览器访问localhost:8080就能看到页面;如果是后者,你得先把前端工程单独跑起来,用Vite或Webpack把页面代理到后端接口。这一步一定要在导入前确认清楚,因为它决定了你后面排查问题的方向。
我整理了一份导入前检查清单,你可以照着过一遍:
- JDK版本:项目基于Java 8还是Java 17写的,必须在pom.xml或README里确认,IDEA里配置的Project SDK要和它一致。
- Maven版本:IDEA自带的Maven可能版本过新或过旧,建议用3.6以上版本,并配置国内镜像,不然依赖能下载半小时。
- MySQL版本:5.7或8.0都可以,但要注意数据库连接串里的时区参数,
serverTimezone=Asia/Shanghai不能省略。 - Redis版本:Windows版可以用5.x,Linux或Docker环境用6.x都没问题,关键是确认Redis服务真的在运行。
- Node环境:只有当前端是独立工程时才需要,
node -v能看到版本号就行。
黑马点评这类教学项目的价值就在于,它逼着你把这些工程化常识提前过一遍。你在学校或自学时可能只写单文件代码,根本不需要考虑“Redis没启动”这种事,但只要开始做真实项目,这些全是基本功。
1.1 解读项目的核心业务流程:先跑通一个完整闭环
导入前,我还建议你先花十几分钟把源码里的核心业务模块过一眼。黑马点评表面上是一个类似大众点评的商户搜索项目,核心业务是查看商铺、点赞、关注、发笔记、抢优惠券,而“短信登录”是所有业务的前置条件——你连登录都没搞定,后面所有功能都试不了。
看源码时不要一个文件一个文件读,先看controller层的路由映射。你会发现在比较早期的课程版本里,用户相关的接口有这几个重点:
POST /user/code:接收手机号,生成验证码并发送。POST /user/login:接收手机号和验证码,校验成功后返回登录凭证。GET /user/me:获取当前登录用户信息,用来验证登录态是否生效。
这三个接口就构成了短信登录的最小闭环。你把项目导入并跑通之后,至少应该能在页面上看到验证码发送成功的提示,登录后右上角出现用户头像。这个过程不需要你去改任何业务代码,但它能证明你的环境没问题,后面调功能时才有底气。
1.2 导入工程时的格式选择:别在第一步选错打开方式
IDEA导入项目有很多入口,有人用Open直接选文件夹,有人用Open选pom.xml,有人用New -> Project from Existing Sources。对于黑马点评这种Maven工程,最省事的方式是直接选择项目根目录里的pom.xml文件打开,IDEA会把它识别为Maven Project并自动开始下载依赖。
如果你选了整个文件夹,IDEA有时会把它当成普通Java工程,不触发Maven的依赖解析,这时候你的类里全是Cannot resolve symbol 'SpringBootApplication'之类的红线。遇到这种情况不要急着重装IDEA,右键点击pom.xml,选择Add as Maven Project,IDEA就会开始引入Maven结构和所有依赖。
导入完成后第一件事,不是运行,而是确认Maven的依赖真的下载完了。看IDEA右侧的Maven窗口,如果Dependencies列表里还有红线的包,说明没下载成功。换镜像源或者删掉本地仓库里损坏的.lastUpdated文件再重新下载,都是常用手段。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 导入整个项目时,最容易卡住你的4个环节
2.1 MySQL数据初始化:不是把所有sql文件都执行一遍就行
黑马点评的SQL文件通常在sql目录下,我记得的版本里有一个类似hmdp.sql的脚本,里面把表结构和一些基础数据都打包好了。你只需要在MySQL里手动创建一个数据库,再把整个sql文件导入这个空数据库即可。
这里要特别注意:表结构初始化脚本不要拆开执行。有些同学习惯用Navicat打开sql文件,然后只选择部分语句执行,结果执行到一半因为外键关联报错,后面再导就再也回不到干净状态了。正确做法是新建一个名为hmdp(或者你自己命名的库),字符集选utf8mb4,排序规则选utf8mb4_general_ci或utf8mb4_unicode_ci,然后把整个sql文件直接运行。
运行完之后,重点检查几张核心表的数据数量。tb_user里应该有测试用户,tb_shop里应该有商铺数据,如果这些表是空的,大概率是脚本只建了表没有插入数据,或者你选的库不对。导入SQL后去application.yml里核对数据库连接串,url里的库名必须和你新建的库名完全一致,否则启动后一调用数据库接口就报Table doesn't exist。
2.2 Redis环境:启动前先看端口,启动后别忘了ping一下
黑马点评对Redis的依赖非常重,从短信验证码、商铺缓存到后面的秒杀库存,几乎每个核心功能都离不开Redis。所以你在导入项目时如果没装Redis,那后面的每一步都会走得很痛苦。
不同操作系统下的Redis安装方式不一样。Windows用户可以去GitHub找微软维护的Redis发行包,解压后直接运行redis-server.exe;Linux和Mac用户最方便的是用Docker拉取redis:6.2镜像,一行命令搞定。但在项目导入阶段,你不需要关心Redis的高可用和持久化,只需要保证本地能启动、能连上就行。
怎么验证Redis没问题?开一个命令行窗口运行redis-cli ping,如果返回PONG,说明服务活着。然后检查一下项目中配置的Redis端口,默认是6379,如果你本机的Redis跑在别的端口上,记得改配置文件。
我在实际带项目时发现一个很隐蔽的坑:项目配置里Redis的password不是空的,但本机Redis没设置密码,连接时会被拒绝。每次遇到这种问题,第一反应先看配置,第二反应看控制台最底层的异常信息,它一般会明确告诉你“DENIED Redis is running in protected mode”还是“Connection refused”。
2.3 Maven依赖下载:全局镜像和仓库配置要一次到位
Java初学者第一次接触Maven时,最容易卡死的就是依赖下载。黑马点评的依赖数量不算夸张,但因为国内网络环境的问题,直接从中央仓库拉依赖会很慢,经常卡在某个jar包上半天不动。
这里建议你直接修改Maven的settings.xml文件,加一个阿里云公共镜像。网上教程很多,但我要提醒一个细节:修改完镜像配置后,之前下载失败留下的lastUpdated缓存不会自动清理。最稳妥的办法是打开本地仓库目录,搜索所有.lastUpdated后缀文件并删除,再回到IDEA里点击Reload All Maven Projects。
另一个常见问题是pom.xml里的依赖版本和本地JDK版本不兼容。黑马点评不同时期的版本基础依赖差异很大,老版本如果用了Java 8的特性和库,而你的IDEA运行环境是Java 17,编译时会报一些奇怪的错。最直接的办法是在pom.xml的properties标签里把java.version改成你自己的JDK版本,然后让Project Structure里的SDK版本也保持一致。
2.4 启动项目后,先定一个小目标:把前端首页调出来
后端工程启动成功后,控制台会出现SpringBoot的Logo和端口号,默认是8080。如果你的版本把前端静态页面打包进了resources/static,浏览器访问localhost:8080就能看到首页。这里有一个很容易被忽略的点:首页能打开,不代表静态资源加载正常。
我遇到过的情况是:页面文字和框架出来了,但图片全部裂开,登录按钮点击后没有任何反应,打开浏览器开发者工具一看,一堆静态资源请求返回404。出现这个问题的原因大多数是静态资源目录结构不对,比如你的文件放在了resources根目录而不是resources/static里,SpringBoot默认不会把它们作为静态资源暴露。
如果你拿到的版本是独立前端工程,还需要先执行npm install安装依赖,再执行npm run dev启动Vite服务。此时前端跑在5173端口,后端跑在8080端口,前端页面访问后端接口会产生跨域问题,通常项目里已经配置了CORS或代理,如果没有,你需要检查前端工程里的vite.config.js的代理配置是否正确。
3. 短信登录不只是验验证码,它是一整套“登录态管理”方案
3.1 为什么不用Session,而要用Redis存验证码?
很多Java初学者第一次接触黑马点评的短信登录时,都会有一个困惑:之前学的登录都是用HttpSession保存用户状态的,为什么这个项目要用Redis?
这个问题的答案要分成两层。第一层是分布式场景,真实互联网项目通常有多个后端实例负载均衡,用户的请求可能被分发到不同机器上,而Session默认存在单台服务器内存里,一旦请求到了另一台机器就找不到会话了。Redis是独立部署的公共存储,所有实例都往同一个Redis读写数据,天然解决了Session共享问题。
第二层是验证码本身的场景约束。验证码有很强的时效性,5分钟或者2分钟后必须失效;同一个手机号可能被恶意刷接口;发送频率需要限制。如果用Session存验证码,你要自己维护定时清理的逻辑,而Redis天然支持SET key value EX seconds这种带过期时间的指令,过期后key自动删除,非常适合描述“临时数据”的语义。
黑马点评里的验证码逻辑,大致可以这样理解:
- 用户输入手机号,点击“获取验证码”。
- 后端校验手机号格式,生成一个6位随机数字。
- 将验证码以
手机号为key一部分,存入Redis,设置过期时间(通常是5分钟或2分钟)。 - 通过短信服务商把验证码发给用户,但开发阶段一般会把验证码打印到控制台。
- 用户输入手机号和验证码后,后端从Redis取出验证码,与用户输入的比对。
这套设计最聪明的地方,是把验证码的“临时性”交给Redis的过期机制去管理,而不是自己在代码里开定时任务去扫描清理。你用Session的时候,Session也不会主动清数据,过期Session要等容器统一清理,但Redis单key过期显然更可控、更精确。
3.2 发送验证码接口的关键逻辑:手机号校验和频率控制
短信登录的第一步是“发送验证码”,很多同学觉得这个接口特别简单,生成一个随机数存Redis就完事了。但它其实藏着两个容易忽略的细节:手机号是否合法,以及发送频率是否过快。
手机号校验,正规做法是用正则表达式,比如^1[3-9]\d{9}$这样的规则简单判断。如果手机号不合法,直接返回参数错误,不要继续往下执行。这块没什么技术难点,但面试时很容易被问到“你怎么校验手机号”。
频率控制是黑马点评课程里讲得比较细的一个点。你在正常逻辑里加上一个判断:以手机号为key,如果Redis里已经存在验证码,就直接提示“发送过于频繁”。但这里有个问题:验证码过期时间是5分钟,用户一分钟内点击了两次,第一次的验证码可能还没过期,第二次如果直接拒绝,体验很不好。
更合理的思路是单独维护一个发送频率标记。比如以手机号为key存储一个短TTL的标记,TTL设为60秒,发送前先查这个key是否存在,存在就抛出“请勿频繁发送”。这样你就能把验证码本身的5分钟过期和发送频率的1分钟限制完全分开管理,互不干扰。
我在自己做这个功能时,还会在服务端加一层通用校验:无论用户怎么操作,同一个手机号的验证码,在Redis里永远只保留最新一个。新验证码生成后覆盖旧的,过期时间重新计算。这样就算用户真的连续发送了两次,旧验证码也立即失效,避免了“验证码使用旧码也能通过”的安全漏洞。
3.3 手机号+验证码登录:自动注册逻辑才是这个项目的精髓
输入手机号和验证码,点击登录按钮,接下来发生的事情比很多人想象中多一点。如果这个手机号从来没有注册过,黑马点评的策略不是让你先跳转去注册,而是直接为你创建一个新用户,然后再登录。
这个“自动注册”逻辑是实际项目中非常常见的做法,叫“一键登录”或“无密码登录”。短信验证码本身就证明了你是手机号的主人,所以不需要额外设置密码,不需要确认“用户名是否被占用”,直接往用户表里插一条数据,用户再回来时自然就是老用户了。
后端的处理链路大概是:
- 根据前端传来的手机号,从Redis取出验证码。
- 校验验证码是否存在、是否过期、是否与输入值一致。
- 校验通过后,根据手机号查询用户表。
- 如果用户不存在,则创建新用户,默认头像和昵称可以按手机号规则生成。
- 将用户信息写入Redis,key用随机token,value是用户对象序列化后的JSON或用户ID。
- 给Redis中的用户登录态设置过期时间,比如30分钟。
- 把token返回给前端,前端以后每次请求都在请求头带上它。
这里有几个容易写错的细节。验证码校验失败时,要不要把Redis里的验证码删掉?我建议不要立即删,防止恶意用户通过多次失败把正常用户的验证码消耗掉,但如果你担心暴力猜测,可以加一个连续失败次数限制,超过一定次数强制删除。验证码比对时,最好先判断存在再判断相等,因为Redis里查不到key时会返回null,直接对null调用equals会空指针。
3.4 登录成功后,前端怎么保存并用上token?
短信登录接口返回token后,前端不能只是把token存到变量里,因为用户一刷新页面变量就没了。常见的做法是把token保存在localStorage或sessionStorage里,然后每次发请求时,从存储中取出token,添加到请求头。
黑马点评的前端工程默认用了axios,所以通常会做一层请求拦截器,在发送请求前自动读取token并加到Authorization头里。这里我告诉你一个实用的验证方法:登录成功后打开浏览器开发者工具,切到Application面板,看Local Storage里是否有token;再看Network面板里的某个请求,请求头里是否带上了token。
如果你发现登录成功了但访问/user/me还是401,九成是前端请求没带上token,或者后端的拦截器放行规则写错把整个/user/**都拦截了。排查时先确认前端存储有没有值,再确认请求头有没有值,最后打开后端日志看拦截器到底拦截了哪个URL。
4. 短信登录里的拦截器与用户态传递:容易写成一团浆糊
4.1 为什么需要两个拦截器,而不是一个?
黑马点评的登录态校验,很多版本里用了双层拦截器的设计。第一层叫刷新拦截器,负责处理所有请求,只要请求头里带token,就尝试刷新用户登录态的有效期;第二层才是真正的登录校验拦截器,拦截需要登录才能访问的接口。
为什么要分两层?因为“刷新token过期时间”和“校验是否登录”是两个不同的关注点。如果只用一个拦截器,为了刷新登录态,你就必须把所有请求都拦截进来;但像首页浏览、商铺查询这类公开接口,并不需要用户登录。如果拦截器里对公开接口做了放行,又会出现“登录用户访问公开接口时token不被续期”的问题。
正确的分工是:第一个拦截器对所有请求生效,如果发现有token,就从Redis里查用户并刷新过期时间,就算token无效也不拦截,只是不设置用户;第二个拦截器只对需要登录的接口生效,如果发现用户没有登录态,直接返回401。
这种分层的直接好处是:公开接口不影响游客访问,但已登录用户的token只要还在有效期,每访问一次都会被续期。登录接口的token就不会出现“用户一直在浏览首页,结果30分钟后下单时突然掉线”的尴尬。
4.2 ThreadLocal在用户态传递中的角色
当你从Redis中查到了用户信息,怎么把这个用户对象传给后面的Controller使用呢?最简单粗暴的方式是每次在Controller方法上声明一个参数,让框架去注入,但这样会让代码很啰嗦。黑马点评或者其他教学项目更常见的做法,是用ThreadLocal。
ThreadLocal可以简单理解成“每个线程自己专属的存储箱”。一次HTTP请求从进入到结束,后端处理代码往往跑在同一个线程里,所以你可以在这个线程的某个环节把用户对象放进去,后面任何一个方法需要时再取出来。
在拦截器里大概是这样用的:
- 登录校验成功后,在ThreadLocal里保存当前用户ID。
- 在Controller里,用一个自定义工具类提供获取当前用户ID的方法。
- 在请求结束后的拦截器afterCompletion方法里,调用ThreadLocal的remove方法清理数据,防止线程池复用导致数据串号。
新手容易犯的错是只往ThreadLocal放数据,忘了remove。如果容器线程是复用的,上一个请求留下的用户信息会被下一个请求读到,造成用户A的数据展示给用户B,这是很严重的越权问题。所以一定要记住:存了就取,取了就清,凡是ThreadLocal操作要配套成对。
4.3 Token续期时的几个隐藏问题
在双层拦截器的设计里,每次请求只要带着有效token,就会重新设置Redis的过期时间。看起来很简单,但实际写的时候有几个容易被忽略的点。
第一个点:Redis里key的过期时间是以秒为单位的,续期时是重新执行expire命令,还是删除重建?建议用expire命令,简单高效,不要先去查再删除再新增,白白增加一次网络开销。
第二个点:当前端请求头里token已经过期时,你的刷新拦截器该怎么办?这时候Redis里查不到用户,不应该再去尝试续期,而是直接放行,让后面的登录拦截器去判断是否需要401。如果你在刷新拦截器里把过期的请求拦下来返回错误,那登录接口自己也会被误伤,因为登录前压根没有token。
第三个点:token续期和Redis里用户信息更新的边界。如果用户修改了头像,Redis里的用户信息要同步更新,而不仅仅是延长过期时间。不然会出现页面显示新头像,刷新后又变回旧头像的诡异情况。常规做法是更新数据库成功后更新Redis,或者直接删除Redis里的用户key,让下次请求时重新从数据库加载。
5. 从验证码到登录态,我把所有踩过的坑汇总成了一张排查表
5.1 常见现象、可能原因、排查思路对照
我带过很多同学调黑马点评的短信登录,几乎每天都能看到相似的报错。这里我把自己和学员踩过的坑整理成表格,你以后遇到类似问题可以直接按图索骥。
| 现象 | 可能原因 | 排查手段 |
|---|---|---|
| 点击获取验证码后页面无提示 | 前端请求没发出去,或后端接口地址配置错误 | 打开浏览器Network面板看请求是否发出,看状态码 |
| 后端日志里没有出现验证码 | 手机号校验未通过,接口提前return了 | 在手机号正则校验处打断点,逐步确认参数 |
| 验证码登录时报“验证码错误” | Redis里存的key和查询key不一致 | 在Redis-cli里手动执行keys *code*查看实际key |
| 登录接口偶尔能成功偶尔失败 | Redis过期时间太短,刚好碰到key过期 | 检查自己设置的TTL,连续失败时查看Redis存活时间 |
| 已经登录,但访问需要登录的接口返回401 | 前端请求头没带token,或拦截器放行规则错误 | 查看Network请求头,查看后端拦截器addPathPatterns配置 |
| 登录状态下用户头像不更新 | 更新数据库后没有同步更新Redis | 登录后调用更新接口,检查Redis中的用户信息 |
这张表的核心思路是先看数据有没有,再看数据对不对,最后看代码哪一步把数据弄丢了。
5.2 调试短信登录的实操技巧:Redis命令和日志一起用
短信登录用Redis之后,最大的好处是调试变得特别直观。以前用Session时,你看不到服务器内存里到底存了什么,只能靠代码猜;现在Redis是独立服务,你可以直接开一个命令行窗口,用redis-cli交互式检查所有数据。
下面几条命令是我排查黑马点评问题时最高频用到的:
bash复制redis-cli
# 查看所有验证码相关的key
keys *code*
# 查看某个key的剩余存活时间
ttl login:code:13800138000
# 查看token对应的用户信息
get login:token:abcd1234
这些命令能帮你快速确认三件事:验证码到底存进去没有、设置过期时间后有没有被自动清掉、登录成功后的token里到底放了什么数据。比在IDEA里一行行断点调试效率高得多。
另外,建议你在短信验证码生成后,用SLF4J的logger打一行日志,把验证码打印出来。教学项目没有真实短信通道时,控制台日志就是你唯一的“接收短信”渠道。很多人忘了打印,登录时完全不知道验证码是什么,还以为自己写错了。
5.3 为什么验证码存Redis以后,还是有人会空指针?
一个非常经典的报错出现在校验验证码环节,代码写成redisTemplate.opsForValue().get(key).equals(inputCode),结果Redis里没有这个key,get返回null,直接空指针。
这个问题的根子在于你把“Redis中查不到key”和“业务上验证码错误”混为一谈。Redis查询结果为空,可能只是key过期了,也可能你压根没存进去。所以判断时应先把查询结果取出来,判断是否为null,再跟用户输入比较。
正确做法是先让整个流程健壮起来。Redis查不到key,至少说明验证码过期或不存在,这时候应该给用户提示“验证码已过期,请重新获取”,而不是让后端抛异常。我通常还会把手机号一起放进日志里,方便以后用日志追踪整个登录链路。
还有一个小细节:存入Redis之前,先想一想你要存的是“验证码”还是“用户信息”。验证码可以直接存纯数字字符串,但用户信息通常是一个对象,不能直接塞进去,需要序列化成JSON字符串再存。用Jackson或Fastjson都可以,项目里用什么看你手里的pom.xml依赖,不要自己随手引入一个版本不对的库。
6. 学完短信登录后,先别急着往下做,试着回答这几个“为什么”
6.1 同一个手机号短时间重复发送验证码要怎么办?
黑马点评在真实业务里面对的逻辑,比课堂Demo复杂的地方在于:短信是按条计费的,如果用户恶意点击,服务端会在短时间内向同一个手机号发出大量短信,平台既损失了钱,用户也可能被短信轰炸。
最简单的限流方案是在Redis里额外维护一个短TTL的标记。发送验证码前先尝试设置一个key,设置为send:limit:手机号,有效期60秒。如果setIfAbsent返回false,说明这个手机号在60秒内已经发过一次,直接拒绝发送请求。
到了面试阶段,如果面试官问你“短信验证码功能怎么防刷”,这只是一个起步方案。往上扩展还有单IP限制、单个设备限制、图形验证码风控、黑名单拦截等,但那个属于业务安全范畴,做项目阶段先把频率限制写明白就比较能打了。
6.2 为什么登录后不直接返回用户信息,而是返回一个token?
这个功能的本质是你把“用户身份凭证”做成了一张短期有效的临时票据,交给前端保管。前端以后每次请求时带着票据出场,后端只需要校验票据真假,不需要每次重新输入手机号验证码。
不用Session的原因是服务端会产生大量状态数据,而且在多实例部署时存储不一致;不用JWT这类无状态token是因为黑马点评要考虑主动失效和续期,Redis的过期机制让token随时可以在服务端被撤销。所以你可以把黑马点评的token理解为“服务端会话ID”,只不过存储介质从JVM内存换成了Redis。
面试时,这套设计的回答框架可以归纳为四个字:存储前置。把会话数据从服务器内存中搬出来,放到统一缓存中间件里,应用服务器因此可以随意横向扩容。
6.3 用户长时间不操作,token应该什么时候失效?
黑马点评设定的过期时间一般是30分钟,但这里有一个面试常问的边界问题:用户在第29分钟操作了一次,要不要给token续期?
如果完全不给续期,用户在第35分钟再次操作时就会被强制踢下线,哪怕他之前一直在浏览,只是中间偶尔有几个请求间隔比较长。所以项目中才做了双拦截器:访问任何页面时只要token有效,就自动续期30分钟,用户只要一直在用,登录态就不会断。
这里要注意,如果你在刷新拦截器里同时把“公开接口”和“受保护接口”都刷了token,那部分公开接口也能维持登录态。这样做的坏处是用户关闭浏览器后很久再打开,token可能还在有效期内,如果串到公共电脑上就有安全隐患。有的实现会用滑动过期时间加绝对过期时间双重限制,比如单次会话超过24小时强制重新登录,不过教学项目里能用好“30分钟滑动过期”已经很不错了。
6.4 在这个功能里,你写的哪些代码以后会变成面试资本?
很多人做完短信登录后,简历上只会写一句“实现了手机号验证码登录”,这种描述在面试官眼里跟没写差不多。做项目不是跑通就结束,你需要把项目里的难点和取舍讲清楚。
我自己做技术分享时的建议是:翻看你写的代码,找出至少三个可以讲的设计点。比如ShiroFilter或SpringMVC拦截器怎么组织放行规则、ThreadLocal如何解决同一线程内用户信息共享和内存泄漏问题、Redis验证码的TTL和续期策略怎么设计。你把每一个“为什么”都能用一两句话说清楚,面试官才会相信这个项目是你亲手做的。
如果你自己写的代码没有这些复杂度也没关系,黑马点评的短信登录模块本身就是让你去模仿真实项目中常见做法的。你先把它提供的版本跑通,再按我的建议去扩展频率限制、失败次数限制、线程池清理这些细节,最后把实现思路记下来。做项目最怕的不是不会,而是什么都没想清楚就往下赶进度。
