Spring MVC 拦截器 (Interceptor) 课程笔记
1. 什么是拦截器 (Interceptor)
- 拦截器 (Interceptor) 类似于我们之前学习过的 J2EE 过滤器 (Filter)。
- 作用:对请求进行前置和后置的过滤处理。
- 与 Filter 的区别:
- Interceptor 是 Spring MVC 的标准组件,由 Spring IOC 容器管理。
- Filter 是 J2EE 的标准组件,由第三方容器厂商实现。
- 实现逻辑:Interceptor 依赖于 Spring AOP 编程的理念,而 Filter 属于底层 Servlet API。
2. Interceptor 和 Spring AOP 的关系
- Interceptor 的实现依赖于 Spring AOP 面向切面编程的理念。
- 其行为与 AOP 中的环绕通知 (Around Advice) 类似。
3. 开发 Interceptor 的流程
Interceptor 的开发包含以下三个步骤:
- 引入依赖:在
pom.xml
中引入javax.servlet
依赖,并设置scope
为provided
,防止与 Tomcat 中的版本冲突。 - 创建 Interceptor 类:实现
HandlerInterceptor
接口。 - 配置 Application Context:在
applicationContext.xml
中注册拦截器。
步骤1:引入依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
步骤2:创建拦截器类
在项目中创建拦截器类,并实现 HandlerInterceptor
接口:
import org.springframework.web.servlet.HandlerInterceptor;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("Request URL: " + request.getRequestURL() + " - 准备执行");
return true; // 返回 true 表示继续执行,false 表示中断请求
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
System.out.println("目标处理成功");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("响应内容已产生");
}
}
方法说明:
preHandle
:在请求进入 Controller 之前执行,返回值决定是否继续执行请求。postHandle
:在目标资源处理完毕但未产生响应文本之前执行。afterCompletion
:在响应文本产生后执行。
步骤3:配置 Application Context
在 applicationContext.xml
中配置拦截器:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.imock.rest.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
配置说明:
<mvc:mapping>
:配置拦截的 URL 路径,例如/**
表示拦截所有路径。<bean>
:指定处理拦截的类。
4. 拦截器的执行顺序
preHandle
→Controller
→postHandle
→afterCompletion
- 时机:
preHandle
:在请求处理前执行,可用于权限验证、参数检查等。postHandle
:在请求处理完毕但未产生响应文本时执行,可用于对数据进行后置处理。afterCompletion
:在响应文本产生后执行,可用于清理资源或记录日志。
5. 拦截器与 Filter 的对比
特性 | Interceptor | Filter |
---|---|---|
管理方式 | 由 Spring IOC 容器管理 | 由 Servlet 容器管理 |
实现机制 | 基于 Spring AOP | 基于 Servlet API |
拦截对象 | 处理 Spring MVC Controller 的请求 | 拦截所有请求,包括静态资源 |
执行顺序控制 | preHandle , postHandle , afterCompletion | doFilter 方法处理整个请求链 |
6. 实例演示
- 访问
localhost/restful/persons
查看 JSON 响应内容。 - 控制台输出:
Request URL: /restful/persons - 准备执行 findPersons 返回 List 目标处理成功 响应内容已产生
注意:配置 <mvc:mapping path="/**"/>
表示拦截所有 URL,如果只想拦截特定的 URL,可以精确匹配路径。
7. 小结
- 拦截器的开发步骤:
- 在
pom.xml
中引入javax.servlet
依赖。 - 实现
HandlerInterceptor
接口的三个方法。 - 在
applicationContext.xml
中配置拦截器。
- 在
- 三个关键方法:
preHandle
:请求前拦截postHandle
:请求处理后拦截,但在响应前afterCompletion
:响应后拦截
- 拦截路径配置:可以使用通配符
/**
拦截所有 URL,也可以指定具体路径。
课程笔记:用户流量拦截器开发
课程目标
本节课程将开发一个 用户流量拦截器。主要目的是通过拦截器自动收集用户的访问信息,如访问时间、访问网址、浏览器信息、系统信息、IP 地址等,并将这些信息记录到日志文件中。通过这些数据分析,可以获得用户访问行为的有用信息。
核心内容
1. 用户流量拦截器的作用
- 自动收集用户的访问信息,如访问的时间、网址、使用的浏览器和系统、IP 地址等。
- 通过分析这些数据,可以了解用户的访问行为,如受欢迎的商品、访问的时间段、用户设备的类型等。
- 为不同时间段推荐商品,基于用户设备进行用户体验优化。
2. 实现拦截器
- 拦截器名称:
AccessHistoryInterceptor
,用于记录所有用户请求的访问数据。 - 继承接口:实现
HandlerInterceptor
接口,并重写preHandle
方法以捕捉用户访问的相关数据。
3. 使用 Logback 记录日志
- Logback 依赖引入:在
pom.xml
中添加logback
的 Maven 依赖。<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency>
- 启动项目:Spring MVC 默认支持 Logback,可以直接在控制台输出日志。
4. Logback 日志配置
- 配置文件:创建
logback.xml
配置文件。- 文件路径:
src/main/resources/logback.xml
- 文件路径:
- 日志格式:定义日志的输出格式,包括线程名、时间、日志级别、类名和日志信息。
日志配置示例:
<configuration>
<!-- 控制台日志输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%thread] %d %level %logger{10} - %msg%n</pattern>
</encoder>
</appender>
<!-- 文件日志输出:按天滚动 -->
<appender name="accessHistoryLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>D:/logs/history.%d.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>[%thread] %d %level %logger{10} - %msg%n</pattern>
</encoder>
</appender>
<!-- 日志输出级别及应用范围 -->
<root level="INFO">
<appender-ref ref="console"/>
</root>
<logger name="com.example.interceptor.AccessHistoryInterceptor" level="INFO" additivity="false">
<appender-ref ref="accessHistoryLog"/>
</logger>
</configuration>
5. 配置解释
- 控制台日志:使用
ConsoleAppender
将日志输出到控制台,方便调试。 - 文件日志:使用
RollingFileAppender
生成按天滚动的日志文件,存储用户访问日志到D:/logs
目录。 additivity
参数:设置为false
以避免重复输出到控制台。
6. 编写 AccessHistoryInterceptor 拦截器
- 实现
preHandle
方法,收集用户访问的信息,如 IP 地址、访问时间、用户设备等。 - 使用 Logback 记录收集到的信息到日志文件中。
拦截器代码示例:
public class AccessHistoryInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(AccessHistoryInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String userIp = request.getRemoteAddr();
String url = request.getRequestURL().toString();
String browserInfo = request.getHeader("User-Agent");
logger.info("IP: {}, URL: {}, Browser: {}", userIp, url, browserInfo);
return true;
}
}
7. Logback 使用总结
- 通过在
logback.xml
中配置不同的Appender
,可以将日志输出到多个地方,例如控制台和文件。 - 日志文件按天滚动:每一天生成一个新的日志文件,便于管理和分析。
- 灵活性:可以根据日志级别和具体的拦截器配置不同的日志输出方式。
总结
- 用户流量拦截器:通过 Spring MVC 的拦截器机制可以方便地收集用户请求数据。
- Logback 日志组件:提供了强大的日志管理功能,可以将用户访问日志按天记录到文件中,方便后期分析。
- 应用场景:日志信息的收集有助于电商网站的用户行为分析,有助于制定更加精准的营销策略。
课程笔记:用户流量拦截器开发(续)
课程目标
继续开发用户流量拦截器,完善拦截器功能,实现对用户访问数据的收集,并将这些数据按固定格式记录到日志文件中。最终生成的日志可以被进一步解析和分析,以挖掘用户行为信息。
核心内容
1. AccessHistoryInterceptor 拦截器开发
- 创建日志对象:使用
Logger
记录日志。private static final Logger logger = LoggerFactory.getLogger(AccessHistoryInterceptor.class);
- 收集用户信息:通过
request
对象获取用户的 IP 地址、访问的 URL 以及用户的客户端环境信息(User-Agent)。 - 使用 StringBuilder 构建日志信息:
StringBuilder log = new StringBuilder(); log.append(request.getRemoteAddr()) // 用户IP .append("|") .append(request.getRequestURL()) // 访问URL .append("|") .append(request.getHeader("User-Agent")); // 用户环境 logger.info(log.toString());
- 拦截器配置:在
mvc:interceptors
中配置新的拦截器,对所有请求进行拦截,同时排除静态资源。
2. 日志配置调整
- 配置
logback.xml
:在logback.xml
中定义新的日志输出配置,确保AccessHistoryInterceptor
产生的日志能按天记录到文件中。 - 示例日志配置:
<logger name="com.example.interceptor.AccessHistoryInterceptor" level="INFO" additivity="false"> <appender-ref ref="accessHistoryLog"/> </logger>
- 拦截所有请求:配置路径为
/*
,确保对所有用户访问的请求进行记录,同时排除静态资源:<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/resources/**"/> <bean class="com.example.interceptor.AccessHistoryInterceptor"/> </mvc:interceptor> </mvc:interceptors>
3. 测试拦截器
- 打开浏览器测试:访问不同的 URL,查看拦截器是否能够准确记录用户请求日志。
- 日志文件验证:检查
D:/logs/history.<date>.log
文件,确认日志条目是否符合预期格式。 - 日志内容示例:
[main] 2023-10-22 INFO AccessHistoryInterceptor - 127.0.0.1|http://localhost/client.html|Mozilla/5.0 (Windows NT 10.0; Win64; x64)
4. 用户行为分析
- 日志内容解读:通过分析日志信息,可以得出以下有用数据:
- 用户 IP:判断用户的地理位置。
- 访问 URL:了解用户访问了哪些页面或商品。
- 用户环境:了解用户使用了什么设备、操作系统和浏览器。
- 应用场景:可以通过日志分析来优化产品推荐,如根据用户访问的商品类型,在首页展示相关商品的推荐信息。
5. 提取关键数据
- 任务挑战:利用之前学到的字符串和 IO 相关的知识,从日志文件中提取关键信息(如时间、IP 地址、用户环境等)。
- 数据解析思路:每行日志都是一个固定格式的字符串,可以使用分隔符(如
|
)和正则表达式来提取具体数据。
示例代码
public static void parseLogFile(String logFilePath) {
try (BufferedReader br = new BufferedReader(new FileReader(logFilePath))) {
String line;
while ((line = br.readLine()) != null) {
String[] parts = line.split("\|");
String ip = parts[0];
String url = parts[1];
String userAgent = parts[2];
System.out.println("IP: " + ip + ", URL: " + url + ", User-Agent: " + userAgent);
}
} catch (IOException e) {
e.printStackTrace();
}
}
6. 拦截器与过滤器的对比
- 拦截器:专注于拦截 HTTP 请求,对请求进行预处理和后处理,适用于 Spring MVC 项目。
- 过滤器:适用于 Servlet,主要在请求进入 Servlet 之前或者响应返回客户端之前执行,具有更广泛的应用场景。
总结
- 用户流量拦截器:通过 Spring MVC 的拦截器机制,收集用户访问数据,并使用日志进行记录。
- 日志文件解析:将日志记录按天分割存储,便于后续分析。可以从日志中提取用户访问的时间、IP、使用设备等信息,从而挖掘用户行为,优化用户体验。
- 场景应用:通过对用户流量数据的分析,可以精准地提供个性化推荐和营销策略,提高电商网站的用户黏性和转化率。
课程笔记:Spring MVC 执行原理与数据处理流程
课程目标
本节课程介绍了 Spring MVC 的底层执行原理和数据处理流程,让大家了解请求从发出到最终返回的全过程。在整个流程中,Spring MVC 涉及五大核心组件,它们共同协作,完成用户请求的处理和响应。
核心内容
1. Dispatcher Servlet
- 功能:作为 Spring MVC 的核心,它会拦截所有请求,并交由 Spring MVC 框架处理。
- 流程:外部应用服务器发送请求,首先被
DispatcherServlet
拦截,然后转交给 Spring MVC 进行处理。
2. Handler Mapper
- Handler 的定义:在计算机中称为“处理器”,它是
Interceptor
(拦截器)和Controller
(控制器)的统称。 - Handler Mapper 的作用:通过访问的 URL 获取对应的 执行链。
- 执行链:表示请求在被
Controller
处理前,依次会被哪些Interceptor
拦截。例如:- 请求 -> 拦截器1 -> 拦截器2 -> Controller
- Handler Mapper:只负责获取执行链,不进行真正的请求处理。
- 执行链:表示请求在被
3. Handler Adapter
- 功能:负责执行具体的 Handler 方法。
- 根据不同的 Handler 类型(
Interceptor
或Controller
),决定调用对应的方法。 - Interceptor:执行前置处理方法。
- Controller:调用与 URL 对应的方法,返回结果。
- 根据不同的 Handler 类型(
- 工作原理:
- 请求到达时,
Handler Adapter
先按执行链依次调用每个Interceptor
的前置方法。 - 最后调用
Controller
对应的处理方法。 - 数据处理完毕后,返回的数据会逆向通过
Interceptor
依次返回到DispatcherServlet
。
- 请求到达时,
4. ModelAndView 对象
- 作用:
Controller
方法通常返回一个ModelAndView
对象,包含模型数据和视图信息。 - 流程:
Handler Adapter
获取ModelAndView
对象,并将其返回给DispatcherServlet
。DispatcherServlet
根据View
信息选择对应的模板引擎。
5. View Resolver
- 功能:视图解析器,根据
ModelAndView
中的视图名称,选择相应的模板引擎(如 FreeMarker、Thymeleaf)。 - 工作原理:
- 选择正确的模板引擎,生成视图对象。
DispatcherServlet
拿到视图对象后,会结合Model
中的数据进行渲染,生成最终的 HTML。
6. 整个处理流程总结
- 请求发送:外部应用发送请求,
DispatcherServlet
拦截请求。 - 查找执行链:
Handler Mapper
查找对应的 Handler 执行链。 - 执行 Handler:
Handler Adapter
依次调用执行链中的Interceptor
,最终调用Controller
方法。 - 返回数据:
Controller
方法返回ModelAndView
对象。 - 选择模板引擎:
DispatcherServlet
通过View Resolver
选择对应的视图模板引擎。 - 渲染视图:结合
Model
数据生成最终的 HTML。 - 响应返回:HTML 随着响应返回给客户端浏览器,显示最终结果。
7. 主要组件回顾
- Dispatcher Servlet:核心控制器,处理请求和响应。
- Handler Mapper:根据请求 URL 获取执行链。
- Handler Adapter:根据 Handler 类型,选择执行 Interceptor 或 Controller。
- ModelAndView:封装返回的数据和视图信息。
- View Resolver:解析视图信息,选择对应模板引擎。
总结
整个 Spring MVC 的处理流程是一个完整的链条,从请求被 DispatcherServlet
拦截开始,依次通过 Handler Mapper
查找执行链、Handler Adapter
执行相应的 Handler,再返回 ModelAndView
,最后通过 View Resolver
渲染视图并返回给用户。理解这个流程,可以帮助我们在开发中更好地使用和调试 Spring MVC 应用。
Java 拦截器和过滤器的区别
在 Java 中,拦截器(Interceptor)和过滤器(Filter)都是用于在请求处理之前或之后执行某些逻辑的机制,但它们在实现和使用方面有一些重要的区别:
1. 定义与应用层面
-
拦截器(Interceptor)
- 拦截器是一种面向切面编程(AOP)的实现,主要用于处理方法调用前后的行为。
- 通常在框架层(如 Spring 或 Hibernate)中使用,拦截器会在某个方法执行前、执行后或者抛出异常时执行一些逻辑。
- 拦截器可以作用于方法调用的全过程,包括控制器方法、服务方法等,能够深入到方法级别。
-
过滤器(Filter)
- 过滤器是一种基于 Servlet 的机制,用于在 Servlet 请求和响应的处理过程中进行预处理和后处理。
- 通常在 Web 应用中使用,主要用于处理请求和响应,例如:对请求进行身份验证、日志记录、编码转换等。
- 过滤器可以作用于整个请求/响应链,包括静态资源(如 CSS 和 JS 文件)。
2. 工作原理与生命周期
-
拦截器
- 拦截器基于方法调用,在方法执行的生命周期内执行(例如方法执行前、方法执行后)。
- 可以控制方法的执行(如阻止方法执行),适合进行权限控制、事务管理、日志等操作。
- 生命周期由框架控制,比如在 Spring 中,拦截器是在 Handler 方法执行的前后执行。
-
过滤器
- 过滤器基于请求/响应的生命周期,在请求到达 Servlet 之前和响应离开 Servlet 之后执行。
- 不能直接控制方法的执行,只能过滤请求和响应,常用于跨切面逻辑,如请求参数验证、统一编码等。
- 生命周期由容器控制(如 Tomcat),当应用启动时过滤器被初始化,并在应用关闭时销毁。
3. 实现方式
-
拦截器
- 在 Spring 中,实现
HandlerInterceptor
接口(或者使用@Aspect
注解实现 AOP)。 - 可以通过配置类或者注解进行注册和控制。
- 常用方法:
preHandle
、postHandle
、afterCompletion
。
- 在 Spring 中,实现
-
过滤器
- 在 Java EE 中,实现
javax.servlet.Filter
接口。 - 需要在
web.xml
中配置,或者使用@WebFilter
注解。 - 常用方法:
doFilter
。
- 在 Java EE 中,实现
4. 使用场景
-
拦截器
- 权限控制:在方法调用前检查用户权限。
- 日志记录:记录方法的调用时间和执行情况。
- 事务管理:在方法执行前后开启和提交事务。
-
过滤器
- 请求和响应的预处理与后处理:统一编码、CORS 处理、数据压缩等。
- 过滤无效请求:比如过滤掉非法 IP 或者用户。
- 认证与授权:检查请求的合法性,执行安全检查。
总结
特性 | 拦截器 (Interceptor) | 过滤器 (Filter) |
---|---|---|
作用范围 | 方法级别 | 请求和响应级别 |
控制方式 | 基于 AOP 的方法调用拦截 | 基于 Servlet 请求/响应链的过滤 |
使用场景 | 权限控制、日志记录、事务管理 | 编码转换、CORS、认证与授权 |
生命周期 | 由框架控制,如 Spring | 由容器控制,如 Tomcat |
实现接口 | HandlerInterceptor 或 AOP 注解 | javax.servlet.Filter |
拦截器和过滤器在实际开发中各有用途,选择时需要根据需求的不同层次和作用域来决定使用哪一种。