1. 问题现象与初步分析
那天下午我正在开发黑马点评项目的博客模块,刚写完前端页面刷新就遇到了一个典型的空指针异常。前端页面上的探店笔记部分完全无法显示,控制台里清晰地抛出了NullPointerException。作为一名有经验的Java开发者,我立刻意识到这又是一个经典的"对象未判空"导致的运行时错误。
查看控制台堆栈信息,问题定位在BlogServiceImpl类的isBlogLiked方法。异常显示在尝试调用一个User对象的getId()方法时,这个User对象本身是null。有趣的是,这个bug只在用户未登录状态下才会出现——这立刻让我联想到用户认证流程可能存在问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 深入排查问题根源
2.1 异常堆栈分析
控制台的错误信息非常明确(虽然我在这里不能展示具体截图,但可以描述关键点):
- queryHotBlog方法调用了isBlogLiked方法
- isBlogLiked方法中通过UserHolder.getUser()获取用户信息
- 获取到的User对象为null
- 尝试调用null.getId()时抛出空指针异常
2.2 拦截器配置检查
既然问题与UserHolder相关,我自然想到检查拦截器配置。项目中使用的是Spring的HandlerInterceptor实现用户认证,采用了两层拦截设计:
- 第一层拦截器:处理所有请求,记录日志等基础操作
- 第二层拦截器:专门处理用户认证,将登录用户信息存入ThreadLocal
发现问题出在第二层拦截器的excludePathPatterns配置——它错误地将/blog/hot接口排除了。这意味着:
- 登录用户可以正常访问
- 未登录用户也能绕过认证
- 但ThreadLocal中存储的是null用户对象
- 这个null对象在后续流程中导致了NPE
3. 解决方案设计与实现
3.1 初步解决方案的缺陷
我的第一反应是:把/blog/hot从excludePathPatterns中移除,让拦截器正常拦截。这样确实能解决NPE问题,因为:
- 未登录用户访问会被重定向到登录页
- 只有登录用户才能获取到有效的User对象
但这样设计存在明显问题:
- 用户体验差:未登录用户连热门博客都无法浏览
- 业务不合理
