25年10月智晟未来信息科技 Java开发实习生一面

写代码遇到bug时,你一般怎么排查?能举个最近解决的小例子吗?

“我遵循 ‘现象→定位→根因→修复→预防’ 五步法:
1️⃣ 复现与观察:明确触发条件(如‘仅iOS端提交订单失败’)
2️⃣ 日志追踪:查应用日志+链路ID(项目中集成SkyWalking)
3️⃣ 工具辅助:Arthas动态监控方法参数、Postman模拟请求
4️⃣ 最小化验证:写单元测试隔离问题模块
最近案例

  • 现象:测试反馈‘修改收货地址后,订单仍显示旧地址’
  • 排查
    • 日志发现addressService.update()返回成功,但订单查询仍为旧值
    • 用Arthas监控:watch com.service.AddressService update '{params, returnObj}' -x 3
    • 发现更新后未清除Redis缓存(缓存Key含用户ID,但更新逻辑漏了删除)
  • 解决:在更新方法末尾加redisTemplate.delete("address:"+userId)
  • 预防:推动团队在Code Review Checklist增加‘缓存操作完整性’检查项
    感悟:80%的Bug源于‘想当然’,严谨的日志埋点和缓存策略设计是防坑关键。”

项目里经常需要多表查询吗?比如查订单时要关联用户信息,你是怎么写的?

“高频场景(如订单列表需展示用户昵称、商品图片),我的策略:
🔹 简单关联(1-2表):MyBatis-Plus QueryWrapper + apply("LEFT JOIN user u ON o.user_id = u.id")
🔹 复杂关联(≥3表)

  • 写XML自定义SQL(明确JOIN条件,避免N+1)
  • 示例:
    <select id="selectOrderWithDetail" resultType="OrderVO">
      SELECT o.*, u.nickname, p.title 
      FROM orders o
      LEFT JOIN user u ON o.user_id = u.id
      LEFT JOIN product p ON o.product_id = p.id
      WHERE o.user_id = #{userId}
      ORDER BY o.create_time DESC
    </select>
    

🔹 性能优化
• 用EXPLAIN验证是否走索引(为user_id建联合索引)
• 大数据量时:先查订单ID列表 → 批量查用户/商品信息(MyBatis foreach
原则:宁可多查字段,避免多次数据库往返;所有JOIN均在测试环境压测验证。”

Redis哨兵机制听说过吗?简单说说它主要是解决什么问题的?

“哨兵(Sentinel)核心解决 Redis主从架构的高可用问题
监控:持续检测主/从节点健康状态
自动故障转移:主节点宕机时,选举从节点升主(基于Raft协议投票)
通知:通过API通知客户端新主节点地址
配置提供者:客户端连接哨兵获取当前主节点
项目认知

  • 当前二手平台用单机Redis(数据量小+有持久化),但设计时预留哨兵配置:
    spring.redis.sentinel.master=mymaster
    spring.redis.sentinel.nodes=192.168.1.10:26379,192.168.1.11:26379
    
  • 深知哨兵局限:脑裂风险(需配置min-replicas-to-write)、切换期间短暂不可用
  • 未来规划:学习Redis Cluster分片方案,应对亿级数据场景”

Linux平时用得多吗?开发或看日志时,顺手能说几个常用命令吗?

“深度依赖Linux:开发用WSL2,部署用CentOS,高频命令分场景:
🔹 日志排查
tail -n 100 app.log | grep "NullPointerException"(查最近100行错误)
journalctl -u myapp.service -f(systemd服务实时日志)
🔹 进程诊断
ps aux | grep javalsof -i :8080(查端口占用进程)
jstack <pid> > thread_dump.log(Java线程阻塞分析)
🔹 文件操作
grep -r "ERROR" /var/log/ --include="*.log"(递归搜日志)
du -sh /opt/* | sort -hr(查大文件目录)
🔹 网络检查
curl -I http://localhost:8080/health(HTTP头检测)
netstat -tunlp | awk '$4 ~ /:8080/'(精准查8080端口)
实战习惯:服务器部署后必配alias lg='tail -f /var/log/myapp/app.log | grep --color=auto',提升排查效率。”

简单聊聊你的项目吧~你主要负责哪块?过程中有啥印象深刻的小故事?

项目:校园二手交易平台(Spring Boot + Vue),覆盖2000+用户,日均订单50+
我的职责

  • 后端:订单/支付/消息模块开发 + Redis缓存设计 + RabbitMQ异步解耦
  • 前端:商品发布/订单管理页面 + 路由权限控制
  • 运维:Linux部署 + Nginx配置 + 监控脚本编写
    小故事
    上线前夜,测试发现‘同一商品被两人同时下单导致超卖’。
  • 行动
    1️⃣ 紧急回滚版本,用JMeter复现问题(200并发压测)
    2️⃣ 定位:库存扣减无锁,DB乐观锁版本号未生效(因MyBatis更新时漏传version)
    3️⃣ 修复:
    • Redis层:Lua脚本原子扣减
    • DB层:补全UPDATE ... WHERE version=#{version}
    • 前端:按钮防抖+提交后置灰
  • 结果:次日压测1000并发零超卖,团队复盘后将‘并发场景 checklist’纳入开发规范
    成长:深刻理解‘线上无小事’,技术方案必须经压测验证,也学会在压力下冷静协作。”

页面上的数据是怎么“变”出来的?前后端怎么配合把数据展示到用户眼前的?

“以‘查看我的订单’为例,完整链路:
1️⃣ 用户操作:点击‘我的订单’按钮(Vue前端)
2️⃣ 前端发起

  • Axios携带Token请求 GET /api/orders?pageNum=1&pageSize=10
  • Loading状态提示用户
    3️⃣ 后端处理
  • 拦截器校验JWT → ThreadLocal存用户ID
  • Service层:orderMapper.selectPage(page, wrapper.eq("user_id", currentUserId))
  • 组装VO(含商品缩略图URL、状态文案)
  • 返回JSON:{code:200, data:{records:[...], total:85}, msg:"success"}
    4️⃣ 前端渲染
  • Axios拦截器统一处理:
    • code≠200 → 弹窗提示
    • code=200 → 将data.records绑定到Element UI表格
  • 分页组件根据total动态生成页码
    协作关键点
    ✨ 接口文档先行(Swagger标注字段含义、示例值)
    ✨ 错误码共识(如1004=订单不存在)
    ✨ 联调前双方用Postman验证接口,避免‘我以为你懂’"

数据库里的“视图”(View)用过吗?你觉得它在项目里有啥实际用处?

“项目中未直接使用(因MyBatis-Plus动态查询更灵活),但深入理解其价值:
简化复杂查询:如‘用户活跃度报表’需关联5张表,建视图后业务代码只需SELECT * FROM user_activity_view
安全隔离:给运营同学开视图权限(仅含脱敏字段),避免直连核心表
逻辑封装:视图隐藏计算逻辑(如CONCAT(province, city) AS full_address),前端直接取用
兼容旧接口:表结构变更时,用视图保持API返回字段不变
反思与规划

  • 当前项目用Service层组装VO实现类似效果,但视图在跨团队数据共享场景优势明显
  • 已在本地测试库实践:为‘商品销售统计’建视图,对比直接SQL,查询代码行数减少60%
  • 未来若遇报表类需求,会主动评估视图方案,并与DBA讨论性能影响(如避免视图嵌套)”
#JAVA##面经##JAVA面经##Java面经#

本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏

全部评论

相关推荐

点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务