面试 总结(1)
面试总结
一、spring相关
1. Spring Security角色管理实现
在智慧种植虫害识别系统中,我实现了农户端和企业端的双角色权限控制,这一部分是这样实现的:
MySQL 表时设计区分农户和企业的角色表与权限表。登录时,JWT 令牌包含用户 ID、角色表和权限表字段。通过配置 Spring Security 的 Security Config 拦截请求,获取角色权限字段,判断能否访问当前接口
2. Spring MVC工作流程
- 用户发送HTTP请求至前端控制器
DispatcherServlet
。 DispatcherServlet
通过HandlerMapping
(处理器映射器)查找对应的Controller
(处理器)。Controller
执行业务逻辑后,返回ModelAndView
(包含数据模型和视图信息)。DispatcherServlet
通过视图解析器对ModelAndView
进行渲染,生成最终视图并响应给客户端。
3. AOP原理及代理类型
AOP(面向切面编程)是Spring的核心特性之一,用于解决代码冗余问题,实现日志、事务等功能的复用:
- 原理:通过代理模式,在不修改目标代码的情况下,为目标方法添加额外功能(如前置通知、后置通知、异常通知等)。
- 代理类型:
- JDK动态代理:基于接口生成代理类,要求目标类必须实现接口。
- CGLIB动态代理:基于目标类生成代理子类,无需目标类实现接口,通过继承实现代理。
- 应用场景:日志记录、事务管理、权限校验等。
二、消息队列(RabbitMQ)
1. 点餐系统中的异步处理
在点餐系统中,我用RabbitMQ实现了下单流程的异步化,提升系统吞吐量:
- 下单流程:
- 后端接收下单请求,先校验菜品在售状态和用户余额。
- 校验通过后,生成订单号,将订单状态设为“待支付”并存入MySQL,同时向用户发送“下单成功”消息。
- 生产者向RabbitMQ发送订单信息,消费者监听队列,负责执行扣减菜品库存、记录下单日志等非核心流程。
- 用户支付后,系统更新订单状态,触发后续配送等流程。
2. 订单超时未支付处理方案
(下单超过一定时间之后提醒用户)
针对订单超时未支付场景,使用RabbitMQ延迟队列实现自动处理:
- 实现逻辑:
- 下单成功后,系统向RabbitMQ发送延迟消息(设置消息过期时间,如30分钟)。
- 消息过期后,消费者监听并接收消息,根据订单号查询数据库中订单状态。
- 若订单仍为“未支付”状态,执行以下操作:向用户发送“订单超时”短信、回滚菜品库存、更新订单状态为“已取消”。
3. 延迟队列实现方式
延迟队列可通过RabbitMQ的“死信队列+消息存活时间(TTL)”实现:
- 消息设置过期时间(TTL),并指定死信交换机和死信队列。
- 消息过期后,自动从原队列转发到死信队列。
- 消费者监听死信队列,处理超时任务(如订单超时、优惠券过期等)。
三、数据结构与集合
HashMap核心机制
HashMap是Java中常用的键值对集合,其底层实现与扩容机制如下:
- 默认初始化容量:16(必须是2的幂次方,便于哈希计算)。
- 负载因子:0.75,当元素数量达到“容量×负载因子”时触发扩容。
- 扩容机制:扩容至原容量的2倍,重新计算所有元素的哈希值并迁移至新数组。
- 结构转换:
- 当链表长度>8且数组长度>64时,链表转为红黑树(提升查询效率)。
- 当红黑树节点数<6时,转回链表(减少红黑树维护成本)。
四、数据库操作
SQL分组统计查询思路
以“按产品和月份统计销售额并取前三”为例,查询思路如下:
- 使用
MONTH()
或DATE_FORMAT()
函数从订单时间中提取月份。 - 按“产品ID+月份”分组(
GROUP BY
)。 - 用
SUM()
函数计算每组的销售额(SUM(金额字段)
)。 - 按销售额降序排序(
ORDER BY 销售额 DESC
)。 - 取前三条结果(
LIMIT 3
)。
示例SQL:
SELECT product_id, DATE_FORMAT(order_time, '%Y-%m') AS month, SUM(amount) AS sales
FROM orders
GROUP BY product_id, month
ORDER BY sales DESC
LIMIT 3;
补充:也可以用窗口函数实现
WITH MonthlySales AS (SELECT product_id,DATE_TRUNC('month', order_time) AS month,SUM(order_amount) AS total_salesFROM ordersGROUP BY product_id, DATE_TRUNC('month', order_time)
),
RankedSales AS (SELECT product_id,month,total_sales,ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY total_sales DESC) AS sales_rankFROM MonthlySales
)
SELECT product_id,month,total_sales
FROM RankedSales
WHERE sales_rank <= 3
ORDER BY product_id, sales_rank; -- 可选:按产品、排名排序,结果更清晰
分组聚合 :先按产品 + 月份汇总销售额,得到基础统计;
窗口函数 :通过 ROW_NUMBER() 给每个产品的月份销售额 “内部排序”,生成排名;
筛选结果 :保留排名前 3 的记录,实现 “每个产品最高三个月份” 的需求。
SQL窗口函数:数据分析的"透视窗"
在SQL数据分析中,窗口函数是绕不开的关键工具。它像给数据开了"透视窗",能在保留明细的同时做分组计算,高效解决排名、累计、对比类需求。整理了核心知识点,速记备用👇
窗口函数:对数据集的"特定子集(窗口)"计算,保留原始行结构,不合并数据。
语法模板:
函数名(参数) OVER ([PARTITION BY 列名] -- 分组窗口(可选)[ORDER BY 列名] -- 窗口内排序(可选)[ROWS/RANGE 范围] -- 行范围(进阶,可选)
)
常用:
1. 排名函数
ROW_NUMBER()
:同分组内生成唯一序号(值相同也跳号)RANK()
:值相同则排名相同,后续排名跳号(如 1,1,3…)DENSE_RANK()
:值相同则排名相同,后续排名不跳号(如 1,1,2…)
2. 聚合函数
SUM()
/AVG()
/MAX()
/MIN()
结合窗口,实现累计计算或移动统计(如累计销售额、近3月平均值)。
3. 偏移函数
LAG(列名, n)
:取当前行前n行数据(用于环比对比,如本月 vs 上月)LEAD(列名, n)
:取当前行后n行数据(反向环比)
典型场景
- TopN 需求:按产品分组,取销售额最高的3个月份
- 趋势分析:计算用户消费的累计金额、月均消费
- 波动对比:用
LAG/LEAD
分析销售额环比变化
与 GROUP BY 区别
特性 | GROUP BY 聚合 | 窗口函数 |
---|---|---|
结果行数 | 每组1行(合并数据) | 保留原始行数(明细+计算) |
数据视角 | 仅看分组汇总 | 能透视分组内所有行数据 |
五、开发工具与流程
1. Git常用命令(提交与推送代码)
git pull
:拉取远程仓库最新代码,避免冲突。git add <文件名>
或git add .
:将文件添加到暂存区。git commit -m "提交说明"
:将暂存区文件提交到本地仓库。git push
:将本地仓库代码推送到远程仓库。
2. Maven模块依赖处理
当多模块项目中模块A被模块B依赖,修改A后需处理依赖更新:
- 模块A修改后,执行
mvn install
:将A打包并安装到本地仓库。 - 模块B执行
mvn clean
(清理旧文件)→mvn compile
(编译)→mvn package
(打包),确保依赖更新。 - 分布式环境中,可通过
mvn deploy
将A推送到私服,供其他模块拉取。
六、Redis数据结构
Redis是高性能的键值对数据库,支持多种数据结构,适用于不同场景:
- String(字符串):存储文本、数字等,如用户token、计数器。
- List(列表):有序可重复,支持头插(
lpush
)、尾插(rpush
),可用于消息队列、任务队列。 - Hash(哈希):键值对集合,适用于存储对象(如用户信息:
user:{id} -> {name: "xxx", age: 20}
)。 - Set(集合):无序不可重复,支持交集、并集运算,适用于标签、好友关系。
- Sorted Set(有序集合):带分数的Set,按分数排序,适用于排行榜、延时任务。