2025-09-10 17:13:56 +08:00
|
|
|
|
### 问题1(考察多线程)
|
|
|
|
|
|
|
|
|
|
|
|
假设你现在需要写1个电商APP的用户订单详情接口,这个详情页包含:
|
|
|
|
|
|
|
|
|
|
|
|
- 关联的商品信息,比如商品名称、尺码、图片、文字介绍等等
|
|
|
|
|
|
- 订单的基础信息,比如创建时间、支付金额
|
|
|
|
|
|
- 订单的快递信息,比如从上海运往杭州,目前运输车辆的位置
|
|
|
|
|
|
|
2025-09-11 09:45:43 +08:00
|
|
|
|
<p style="color: red">
|
2025-09-11 09:50:47 +08:00
|
|
|
|
提问:这三种数据,彼此之间不耦合,假定每一个查询耗时1秒,单线程的情况下,同步执行三次查询,则需要3秒,如何加速这个查询?
|
2025-09-11 09:45:19 +08:00
|
|
|
|
</p>
|
2025-09-10 17:13:56 +08:00
|
|
|
|
|
2025-09-11 09:45:19 +08:00
|
|
|
|
<p style="color: green">
|
2025-09-11 09:33:40 +08:00
|
|
|
|
答案:多线程并行查询
|
2025-09-11 09:45:19 +08:00
|
|
|
|
</p>
|
2025-09-11 09:33:40 +08:00
|
|
|
|
|
2025-09-11 09:45:19 +08:00
|
|
|
|
<p style="color: red">
|
2025-09-11 09:51:28 +08:00
|
|
|
|
追问:假定有3个Runnable对象,分别是task1、task2、task3作为查询函数对象,如何调度或者编排这3个task?
|
2025-09-11 09:45:19 +08:00
|
|
|
|
</p>
|
2025-09-11 09:33:40 +08:00
|
|
|
|
|
2025-09-11 09:48:33 +08:00
|
|
|
|
> 如果没反应过来,引导一下:比如说用 CompletableFuture、Future 或者 FutureTask 说一下关键,要调用哪几个函数。
|
2025-09-11 09:48:11 +08:00
|
|
|
|
|
2025-09-11 09:45:19 +08:00
|
|
|
|
<p style="color: green">
|
2025-09-11 09:50:05 +08:00
|
|
|
|
方案一、使用 CompletableFuture 的 runAsync 函数包装3个task。再通过 allOf 函数添加3个task,调用 get 函数阻塞等待3个任务执行完毕。
|
2025-09-11 09:45:19 +08:00
|
|
|
|
</p>
|
2025-09-11 09:38:21 +08:00
|
|
|
|
|
2025-09-11 09:45:19 +08:00
|
|
|
|
<p style="color: green">
|
2025-09-11 09:50:05 +08:00
|
|
|
|
方案二、使用Future,把3个task提交给1个自定义线程池并接收Future对象,再使用get函数等待3个任务执行完毕
|
2025-09-11 09:45:19 +08:00
|
|
|
|
</p>
|
|
|
|
|
|
|
2025-09-11 09:33:40 +08:00
|
|
|
|
**如果回答的是CompletableFuture,继续延伸以下问题:**
|
2025-09-10 17:13:56 +08:00
|
|
|
|
|
2025-09-11 09:45:19 +08:00
|
|
|
|
<p style="color: red">CompletableFuture的默认线程池是什么?</p>
|
|
|
|
|
|
<p style="color: green">答案:ForkJoinPool</p>
|
|
|
|
|
|
<p style="color: red">ForkJoinPool适合CPU密集型还是IO密集型任务?</p>
|
|
|
|
|
|
<p style="color: green">答案:CPU密集型</p>
|
|
|
|
|
|
<p style="color: red">用CompletableFuture处理IO密集型的任务,应该怎么做?</p>
|
|
|
|
|
|
<p style="color: green">答案:自定义一个IO密集型的线程池</p>
|
2025-09-10 17:13:56 +08:00
|
|
|
|
|
2025-09-11 10:32:02 +08:00
|
|
|
|
### 问题2(考察对 Mybatis-Plus 或者 Mybatis 框架的掌握程度)
|
2025-09-11 10:10:26 +08:00
|
|
|
|
|
|
|
|
|
|
假设现在需要针对用户表里的**手机号、身份证号码**加密存储,业务上还需要根据*手机号后4位*和*身份证号后6位*的筛选。
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: red">
|
|
|
|
|
|
提问:请基于 Spring Boot 和 Mybatis 或 Mybatis Plus,说一下*手机号*和*身份证号*写入时加密,查询时解密,并且支持*手机号后4位*和*身份证号后6位*的筛选的实现思路。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: green">
|
2025-09-11 10:14:14 +08:00
|
|
|
|
详细答案:声明一个自定义注解,修饰实体类里的手机号和身份证号码。实现 Mybatis Plus 的 MetaObjectHandler 接口,覆写 insertFill 和 updateFill 处理数据的加密。实现 Mybatis 的 Interceptor 接口,拦截 ResultSetHandler 的 handleResultSets 函数,处理数据的解密。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: green">
|
|
|
|
|
|
简略答案:用自定义注解结合 Mybatis Plus 的自动填充功能实现数据加密,通过 Mybatis 的拦截器,实现数据的解密过程。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
2025-09-11 10:42:07 +08:00
|
|
|
|
> 大多数会倒在数据解密的实现,没答出来也不要紧,答出来说明能力还可以。
|
2025-09-11 10:32:02 +08:00
|
|
|
|
|
2025-09-11 10:42:07 +08:00
|
|
|
|
### 问题3
|
2025-09-11 10:32:02 +08:00
|
|
|
|
|
|
|
|
|
|
<p style="color: red">如何监控系统里的慢SQL?</p>
|
|
|
|
|
|
|
2025-09-11 10:42:07 +08:00
|
|
|
|
> 这道题可能会难倒一大片菜鸟,答出来说明能力还可以。
|
2025-09-11 10:32:02 +08:00
|
|
|
|
|
|
|
|
|
|
<p style="color: green">
|
2025-09-11 10:33:20 +08:00
|
|
|
|
通过数据库连接池进行监测,比如Druid连接池。Druid 内建了监控系统,收集了大量的查询相关的指标。通过 Druid Console 直接在网页端查看,或者使用 Druid 的导出器将数据同步到 Prometheus 和 Grafana。定义好慢SQL的特征,比如超过5s。在 Druid Console 或者 Grafana 查看这样的数据即可。
|
2025-09-11 10:42:07 +08:00
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
### 问题4
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: red">你们的项目token存在哪里?</p>
|
|
|
|
|
|
|
|
|
|
|
|
> 可能是 Redis、MySQL、JWT 都无所谓,主要是为了引导下面的问题
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: red">用户信息是从线程上下文获取的吗?</p>
|
|
|
|
|
|
|
2025-09-11 11:11:07 +08:00
|
|
|
|
> 回答不知道,说明他菜。只要不是很另类,99.99%都是线程上下文获取。
|
2025-09-11 10:42:07 +08:00
|
|
|
|
|
|
|
|
|
|
<p style="color: red">用过线程池处理过异步任务吗?</p>
|
|
|
|
|
|
|
|
|
|
|
|
> 如果回答没用过,那说明他之前任职的公司,整个开发团队都挺菜的,但不影响下面的提问。
|
|
|
|
|
|
|
2025-09-11 11:07:45 +08:00
|
|
|
|
<p style="color: red">如何让线程池里的线程,获取提交任务线程的上下文?比如提交任务线程上下文里的用户ID</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: green">
|
2025-09-11 11:09:38 +08:00
|
|
|
|
阿里巴巴开源中间件 TTL 进行拷贝线程上下文。如果是 Spring 的 ThreadPoolTaskExecutor 线程池,还可以利用 TaskDecorator(任务包装器)进行处理。
|
2025-09-11 11:07:45 +08:00
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: red">
|
|
|
|
|
|
假设微服务网关进行token鉴权,并提取用户信息,比如用户ID。如何在微服务之间透传用户ID,假设微服务中使用HTTP进行通信。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: green">
|
2025-09-11 11:09:38 +08:00
|
|
|
|
网关调用服务的时候,在请求头中设置用户ID。被调用服务通过请求头提取用户ID。
|
2025-09-11 11:07:45 +08:00
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: red">
|
2025-09-11 11:09:38 +08:00
|
|
|
|
如何在消息队列中透传?
|
2025-09-11 11:07:45 +08:00
|
|
|
|
</p>
|
|
|
|
|
|
|
2025-09-11 11:09:38 +08:00
|
|
|
|
> 这个追问主要看他脑子灵不灵光,笨一点的可能反应不过来。
|
|
|
|
|
|
|
2025-09-11 11:07:45 +08:00
|
|
|
|
<p style="color: green">
|
|
|
|
|
|
一样的思路,定义一个固定的消息体,消息体包含用户ID,在服务之间透传。
|
2025-09-11 11:26:08 +08:00
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
### 问题5
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: red"> 如何在多线程之间实现事务同步?不涉及跨数据源和服务,不需要借助分布式事务。</p>
|
|
|
|
|
|
|
|
|
|
|
|
> 引导:假设一个请求中,有大量的写入sql,互相不耦合。将其拆成多个小事务,使用多线程执行为其提速,但是其中1个发生异常,则全部回滚。
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: green">
|
2025-09-18 13:21:50 +08:00
|
|
|
|
使用 TransactionTemplate 手动创建事务,并在线程上下文中记录事务状态。Spring 的事务是绑定到 ThreadLocal 中的,如果某个线程的任务发生异常回滚,回滚所有线程的事务即可。
|
2025-09-18 13:21:11 +08:00
|
|
|
|
</p>
|
|
|
|
|
|
|
2025-09-18 13:36:23 +08:00
|
|
|
|
### 问题6(没人记这个,纯八股文)
|
2025-09-18 13:21:11 +08:00
|
|
|
|
|
|
|
|
|
|
<p style="color: red">已经存在的表添加联合系引的sql</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: green">
|
2025-09-18 13:36:05 +08:00
|
|
|
|
CREATE INDEX 索引名称 ON 表名称 (字段1,字段2...); 创建联合索引,需要结合查询字段的顺序,遵循最左前缀原则。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
### 问题7(没人记这个,纯八股文)
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: red">根据时间或者年龄这样的字段,使用 Mybatis Plus 的条件构造器怎么拼查询条件</p>
|
|
|
|
|
|
<p style="color: green">使用 between 函数,或者结合 le 和 ge 函数</p>
|
|
|
|
|
|
|
|
|
|
|
|
### 问题8(没人记这个,纯八股文)
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: red">自定义一个 JSR 303 参数校验注解,比如校验手机号是否合法要怎么做</p>
|
|
|
|
|
|
<p style="color: green">
|
|
|
|
|
|
自定义一个注解,继承 Constraint 注解,通过 validatedBy 属性指定校验的类和函数,在这个类里实现实际校验方法。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
### 问题9(没人记这个,纯八股文)
|
|
|
|
|
|
|
|
|
|
|
|
<p style="color: red">拦截器和过滤器哪个在前,哪个在后</p>
|
|
|
|
|
|
<p style="color: green">
|
|
|
|
|
|
过滤器是 Servlet 层面的,拦截器是 Spring 框架层面的,一个 Request 请求先抵达 Servlet 容器(比如Tomcat)所以先执行 Servlet 的过滤器,再执行拦截器。
|
2025-09-11 11:07:45 +08:00
|
|
|
|
</p>
|