0%

Spring MVC 拦截器详解:从原理到实践

拦截器(Interceptor)是 Spring MVC 提供的核心功能之一,用于在请求处理的不同阶段进行拦截并执行自定义逻辑(如权限校验、日志记录、性能监控等)。它与 Servlet 过滤器(Filter)类似,但更贴合 Spring MVC 的生命周期,使用更灵活。从 “拦截器与过滤器的区别→拦截器的使用→执行原理→实战场景” 全面解析 Spring MVC 拦截器。

拦截器与过滤器的核心区别

虽然拦截器和过滤器都能实现请求拦截,但两者在技术归属、执行时机、拦截范围等方面有本质区别:

特性 拦截器(Interceptor) 过滤器(Filter)
技术归属 Spring MVC 框架提供 Servlet 规范提供(Java EE 原生)
执行时机 在 DispatcherServlet 内部执行 在 DispatcherServlet 之前执行
拦截范围 仅拦截 Spring MVC 管理的请求(如 @RequestMapping 标注的方法) 拦截所有进入 Web 容器的请求(包括静态资源、JSP 等)
底层实现 基于 Java 反射机制 基于函数回调
生命周期管理 由 Spring 容器管理,可注入 Spring Bean 由 Web 容器管理,无法直接使用 Spring 资源
方法粒度 可精确到 Controller 方法级别 仅能到 URL 级别

拦截器的核心接口与方法

Spring MVC 拦截器通过 HandlerInterceptor 接口定义核心行为,包含三个关键方法,分别对应请求处理的不同阶段:

阅读全文 »

Spring MVC 返回 JSON 详解:从原理到自定义配置

在前后端分离架构中,Spring MVC 需频繁返回 JSON 格式数据(而非传统视图),核心依赖 @ResponseBody 注解与 HttpMessageConverter 机制。从 “快速实现→底层原理→自定义消息转换” 三个维度,彻底讲透 Spring MVC 如何处理 JSON 数据交互。

快速实现:返回 JSON 数据的 2 个核心步骤

Spring MVC 返回 JSON 只需 “添加依赖 + 标注注解”,无需复杂配置,适用于 90% 以上的常规场景。

步骤 1:添加 JSON 解析依赖(Jackson)

Spring MVC 默认使用 Jackson 作为 JSON 解析工具,需添加 jackson-databind 依赖(包含 jackson-corejackson-annotations):

1
2
3
4
5
6
<!-- Maven 依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version> <!-- 推荐使用最新稳定版 -->
</dependency>
  • 依赖作用:提供 JSON 与 Java 对象的互转能力,Spring MVC 会自动检测该依赖,并注册 MappingJackson2HttpMessageConverter(JSON 消息转换器)。

步骤 2:使用 @ResponseBody 标注方法

在 Controller 方法上添加 @ResponseBody 注解,Spring MVC 会自动将方法返回的 Java 对象(如 UserList<User>)转换为 JSON 字符串,并设置响应头 Content-Type: application/json

实战示例:返回单个对象与集合
阅读全文 »

MySQL 查询深度解析:执行顺序、高级排序与 NULL 值处理

MySQL 查询是数据库操作的核心,理解其执行机制、掌握高级排序技巧及正确处理 NULL 值,能显著提升查询效率和准确性。本文基于查询执行顺序,详解高级用法及常见陷阱。

MySQL 查询的执行顺序

MySQL 执行 SELECT 语句时,并非按语句书写顺序执行,而是遵循固定的内部逻辑流程。正确理解执行顺序,是优化查询和排查问题的基础。

执行顺序详解(从先到后)

  1. FROM 子句:确定查询的数据来源(表、视图或子查询),是查询的起点。
    例:FROM employees 表示数据来自 employees 表。
  2. WHERE 子句:对 FROM 获取的原始数据进行行级筛选,排除不满足条件的记录(在分组前执行)。
    例:WHERE department = 'Sales' 筛选出销售部门的记录。
  3. GROUP BY 子句:将 WHERE 筛选后的结果按指定字段分组(相同值的记录归为一组)。
    例:GROUP BY department 按部门分组。
  4. 聚集函数计算:对每个分组应用聚集函数(SUMMAXCOUNT 等),生成分组的统计结果。
    例:COUNT(employee_id) 计算每个部门的员工数。
  5. HAVING 子句:对分组后的结果进行筛选(在分组后执行,可使用聚集函数)。
    例:HAVING COUNT(employee_id) > 10 筛选出员工数超过 10 人的部门。
  6. 计算表达式:处理查询中的算术运算或函数(如 salary * 1.1UPPER(name))。
  7. SELECT 子句:提取需要返回的字段(或表达式结果),此时才确定最终输出的列。
  8. ORDER BY 子句:对 SELECT 提取的结果按指定字段排序(ASC 升序,DESC 降序)。

示例:执行顺序验证

1
2
3
4
5
6
7
8
SELECT 
department,
COUNT(employee_id) AS emp_count -- 步骤7:提取字段
FROM employees -- 步骤1:数据来源
WHERE hire_year >= 2020 -- 步骤2:筛选2020年后入职的员工
GROUP BY department -- 步骤3:按部门分组
HAVING emp_count > 5 -- 步骤5:筛选员工数>5的部门
ORDER BY emp_count DESC; -- 步骤8:按员工数降序

执行流程:

  1. employees 表获取所有记录;
  2. 筛选出 2020 年及以后入职的员工;
  3. department 分组;
  4. 计算每个部门的员工数(emp_count);
  5. 保留 emp_count > 5 的分组;
  6. 无额外表达式计算;
  7. 提取 departmentemp_count
  8. emp_count 降序排序。

高级排序:ORDER BYCASE 表达式

ORDER BY 支持静态字段排序,结合 CASE 表达式可实现动态排序逻辑,根据条件调整排序依据。

语法:ORDER BY CASE ... END

阅读全文 »

1
2
startID=>start: 开始
startID->

graph TD
0((0)) --- 1((1)) --- 3((3))
1((1)) --- 4((4))
0((0)) --- 2((2))