程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • 后端开发

    • Spring Boot多模块项目开发
    • Spring Boot图片资源返回
    • Spring Boot文件上传
    • Spring Boot文件下载
    • 对接第三方文件上传
    • Servlet 原生API
    • HttpServletResponse 和 ResponseEntity
    • 后端解决跨域问题
    • 后端拦截器
    • SpringBoot+Vue实现邮件发送与验证码验证
    • 谷歌验证码
    • 利用hutool工具类实现图片验证码
    • 统一返回格式
    • 通用 普通 登录模块
    • 通用 JWT 登录认证模块
    • 通用 普通 注册模块
    • 基于 MyBatis curd
    • 基于 MyBatis-Plus curd
    • Java 常见对象模型
    • 开发枚举的使用
    • MyBatis与MyBatis-Plus日期类型处理
    • 接口日志拦截基础版
      • AOP 和拦截器的执行顺序
      • 使用 Spring AOP 实现日志拦截
        • 1. 引入依赖
        • 2. 创建日志切面类
        • 3. 关键 API 和参数说明
      • 使用 Spring MVC 的 HandlerInterceptor 实现日志拦截
        • 1. 引入依赖
        • 2. 创建自定义拦截器
        • 3. 注册拦截器
        • 4. 关键 API 和参数说明
      • 使用 Logback + Slf4j 配合过滤器实现日志拦截
        • 1. 引入依赖
        • 2. 配置 Logback
        • 3. 自定义日志过滤器
        • 4. 关键 API 和参数说明
    • 接口日志拦截进阶版
    • 文件操作工具类
    • Spring Boot 数据校验
    • 幂等性
  • 前端开发

  • 开发笔记
  • 后端开发
scholar
2024-12-27
目录

接口日志拦截基础版

# 日志拦截基础版

在 Spring 框架中,AOP、拦截器和过滤器都是常见的技术,可以在不同层次进行请求的拦截和处理。它们的执行顺序和应用场景各不相同,因此理解它们的工作原理及最佳应用场景对开发高效、灵活的企业级应用非常重要。

# AOP 和拦截器的执行顺序

在处理一个 HTTP 请求时,Spring 会按照以下顺序执行:

  1. 过滤器(Filter):最早执行,用于全局请求处理,可以在请求到达 Spring 容器前进行拦截。这是处理请求的第一道关卡,适合做日志记录、跨域处理、认证等操作。
  2. 拦截器(HandlerInterceptor):在过滤器之后执行,它是在进入控制器方法之前和之后进行操作,适合处理权限校验、参数校验等业务逻辑。
  3. AOP 切面(Aspect):在拦截器之后执行,作用于方法层级,具体拦截的是目标方法的执行过程,适合进行业务逻辑层级的日志记录、性能监控和异常处理等操作。

为什么 AOP 无法拦截拦截器之前的请求内容

AOP 是基于 Spring 的代理机制(JDK 动态代理或 CGLIB)实现的,它只能拦截方法的执行。AOP 的本质是方法级别的切面编程,因此无法在拦截器之前获取请求内容。拦截器是在 Controller 方法执行之前就已经处理的,而 AOP 只能在方法实际调用时生效。

典型的使用场景

  • 全局日志记录(包括请求内容):使用过滤器,可以在请求进入 Spring 容器前记录详细日志信息。
  • 业务逻辑处理、权限校验:使用拦截器,可以在控制器方法调用前对请求进行处理。
  • 方法级别的日志或异常处理:使用 AOP,适合在业务逻辑层面或数据访问层面进行日志和异常处理。

# 使用 Spring AOP 实现日志拦截

在企业开发中,日志拦截是常见的需求,使用 Spring AOP 可以方便地实现方法级别的日志记录。Spring AOP 提供了强大的切面编程能力,可以在方法执行的前后进行日志记录,捕捉方法的执行过程和异常情况。下面将详细介绍如何通过 Spring AOP 实现日志拦截。

# 1. 引入依赖

首先,我们需要在 pom.xml 中引入 AOP 相关的依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
1
2
3
4

# 2. 创建日志切面类

在日志切面类中,我们可以定义切入点、前置通知、后置通知和异常通知。以下是详细代码示例:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 日志切面类,用于拦截 Controller 层的请求并记录日志
 */
@Aspect
@Component
public class LogAspect {

    // 使用 SLF4J 记录日志
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    /**
     * 定义切入点,拦截所有 com.yourpackage.controller 包及子包下的方法
     * execution 语法详解:
     * - 第一个 * 表示任意返回类型
     * - 包名路径表示需要拦截的类(可以使用 .. 表示包及其子包)
     * - 第二个 * 表示方法名称(* 表示任意方法)
     * - (..) 表示任意参数
     */
    @Pointcut("execution(* com.yourpackage.controller..*(..))")
    public void logPointcut() {}

    /**
     * 在目标方法执行前执行,记录方法名称和请求参数
     * @param joinPoint 包含了方法的签名、参数等信息
     */
    @Before("logPointcut()")
    public void logBefore(JoinPoint joinPoint) {
        // 获取请求的方法名称
        String methodName = joinPoint.getSignature().getName();
        // 获取请求的参数
        Object[] args = joinPoint.getArgs();
        // 记录日志
        logger.info("请求方法: {}", methodName);
        logger.info("请求参数: {}", args);
    }

    /**
     * 在目标方法成功执行后执行,记录返回值
     * @param joinPoint 依旧可以获取方法签名和参数
     * @param result 方法的返回值
     */
    @AfterReturning(value = "logPointcut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        // 记录返回值
        logger.info("响应结果: {}", result);
    }

    /**
     * 在目标方法抛出异常时执行,记录异常信息
     * @param joinPoint 同样可以获取方法签名、参数等信息
     * @param exception 捕获到的异常
     */
    @AfterThrowing(value = "logPointcut()", throwing = "exception")
    public void logAfterThrowing(JoinPoint joinPoint, Exception exception) {
        // 记录异常信息
        logger.error("请求方法: {} 发生异常: {}", joinPoint.getSignature().getName(), exception.getMessage());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

# 3. 关键 API 和参数说明

  • @Pointcut: 用于定义切入点表达式,控制需要拦截的方法范围。

    • execution(* com.yourpackage.controller..*(..)): 表示拦截 com.yourpackage.controller 包及其子包下的所有方法。
  • @Before: 在目标方法执行前执行,适合记录请求信息。

    • JoinPoint joinPoint: 传递了当前被拦截方法的签名和参数。
  • @AfterReturning: 在目标方法正常执行后执行,适合记录返回值。

    • @AfterReturning(value = "logPointcut()", returning = "result"): returning 表示接收方法的返回值。
  • @AfterThrowing: 在目标方法抛出异常时执行,适合记录异常信息。

    • @AfterThrowing(value = "logPointcut()", throwing = "exception"): throwing 表示捕获异常对象。

# 使用 Spring MVC 的 HandlerInterceptor 实现日志拦截

使用 Spring MVC 的 HandlerInterceptor 可以直接对 HTTP 请求进行拦截,记录请求和响应的详细信息,拦截器更适合对整个控制器层面的请求进行统一日志管理。

# 1. 引入依赖

Spring Boot Web 模块已经默认引入了相关依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
1
2
3
4

# 2. 创建自定义拦截器

以下是通过自定义拦截器实现日志记录的完整代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义日志拦截器,用于拦截 HTTP 请求并记录日志
 */
@Component
public class LogInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

    /**
     * 在请求处理前执行,记录请求的基本信息
     * @param request HTTP 请求对象
     * @param response HTTP 响应对象
     * @param handler 处理器对象(通常是控制器方法)
     * @return 返回 true 表示继续执行后续操作
     * @throws Exception 异常处理
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 记录请求的 URL
        logger.info("请求 URL: {}", request.getRequestURL().toString());
        // 记录请求的 HTTP 方法(GET、POST 等)
        logger.info("请求方法: {}", request.getMethod());
        // 记录请求的 IP 地址
        logger.info("请求 IP: {}", request.getRemoteAddr());
        return true; // 返回 true 继续执行请求
    }

    /**
     * 在请求处理完成后执行(包括异常情况),记录响应状态和异常信息
     * @param request HTTP 请求对象
     * @param response HTTP 响应对象
     * @param handler 处理器对象
     * @param ex 异常对象(如果存在)
     * @throws Exception 异常处理
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 记录响应的状态码
        logger.info("响应状态码: {}", response.getStatus());
        // 如果有异常,记录异常信息
        if (ex != null) {
            logger.error("请求异常: {}", ex.getMessage());
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

# 3. 注册拦截器

拦截器需要在 Spring MVC 的配置中进行注册:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 拦截器配置类,用于注册自定义拦截器
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LogInterceptor logInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器,拦截所有请求路径
        registry.addInterceptor(logInterceptor).addPathPatterns("/**");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 4. 关键 API 和参数说明

  • preHandle: 在请求处理前执行,用于记录请求的基本信息。

    • HttpServletRequest request: 请求对象,包含了请求的 URL、HTTP 方法、IP 地址等信息。
  • afterCompletion: 在请求完成后执行(包括异常情况),用于记录响应状态和异常信息。

    • HttpServletResponse response: 响应对象,包含了响应状态码。

# 使用 Logback + Slf4j 配合过滤器实现日志拦截

在一些情况下,可能需要更细粒度的日志控制,可以通过自定义过滤器配合 Logback 进行日志记录。

# 1. 引入依赖

如果项目中尚未使用 Logback 作为日志框架,需要引入以下依赖:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>
1
2
3
4
5

# 2. 配置 Logback

Logback 的配置文件通常位于 src/main/resources/logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 日志级别配置 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3. 自定义日志过滤器

通过过滤器实现日志拦截,拦截所有的 HTTP 请求:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * 自定义日志过滤器,拦截所有 HTTP 请求并记录日志
 */
@WebFilter(urlPatterns = "/*")
public class LogFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(LogFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 过滤器初始化操作(可选)
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 记录请求信息
        logger.info("请求协议: {}", request.getProtocol());
        logger.info("请求 IP: {}", request.getRemoteAddr());
        // 继续处理请求
        chain.doFilter(request, response);
        // 记录响应信息
        logger.info("响应类型: {}", response.getContentType());
    }

    @Override
    public void destroy() {
        // 过滤器销毁操作(可选)
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 4. 关键 API 和参数说明

  • doFilter: 过滤器的核心方法,所有的请求和响应都会通过此方法进行拦截。
    • ServletRequest request: 请求对象,包含了请求协议、IP 地址等信息。
    • ServletResponse response: 响应对象,包含了响应类型等信息。

结论

  • Spring AOP 适合方法级别的日志拦截,可以灵活控制日志输出的内容。
  • HandlerInterceptor 适合在控制器层面统一管理日志,使用简单,配置灵活。
  • Logback + Filter 适合需要全局日志控制和更细粒度定制的场景。
编辑此页 (opens new window)
上次更新: 2025/03/16, 22:19:39
MyBatis与MyBatis-Plus日期类型处理
接口日志拦截进阶版

← MyBatis与MyBatis-Plus日期类型处理 接口日志拦截进阶版→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式