首页 新闻中心 技术资料备存中心 详情

Spring Boot 中的过滤器的用法及示例代码另有异常处理方案

2024-09-03

Spring Boot 中的过滤器是一种用于处理 HTTP 请求和响应的重要组件。以下是对 Spring Boot 过滤器的简要介绍:

1. 概念:

   过滤器是 Java Servlet 规范中的一部分,用于在请求到达 Servlet(在 Spring MVC 中通常是 DispatcherServlet)之前和响应发送回客户端之前执行预处理和后处理操作。

2. 我司项目中主要用途:

   - 请求/响应编码转换

   - 请求内容的修改或包装

   - 身份验证和授权

   - 日志记录和审计

   - 数据压缩

   - 不想让用户访问的数据我们也会放到过滤器里以防止用户能访问到

3. 实现方式:

   通过实现 javax.servlet.Filter 接口来创建过滤器。

4. 关键方法:

   - init(): 过滤器初始化时调用

   - doFilter(): 处理请求和响应的主要方法

   - destroy(): 过滤器销毁时调用

5. 配置:

   可以通过 @Component 注解和 @WebFilter 注解,或者通过 FilterRegistrationBean 在 Java 配置类中注册过滤器。

6. 执行顺序:

   多个过滤器组成过滤器链,按照配置的顺序依次执行。

7. 与拦截器的区别:

   过滤器是 Servlet 规范的一部分,作用于所有请求;拦截器是 Spring MVC 的一部分,只作用于 Spring MVC 的请求。


以下是我司技术人员写的一个简单的示例:这个过滤器会记录所有请求的处理时间和一些基本信息。首先,让我们创建过滤器:

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class RequestLoggingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 过滤器初始化时的操作(如果需要)
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        long startTime = System.currentTimeMillis();
        // 记录请求信息
        System.out.println("开始处理请求: " + httpRequest.getMethod() + " " + httpRequest.getRequestURI());
        // 继续处理请求
        chain.doFilter(request, response);
        // 记录响应信息
        long endTime = System.currentTimeMillis();
        System.out.println("请求处理完成: " + httpRequest.getRequestURI() +
                ", 状态码: " + httpResponse.getStatus() +
                ", 耗时: " + (endTime - startTime) + "ms");
    }
    @Override
    public void destroy() {
        // 过滤器销毁时的操作(如果需要)
    }
}

这个过滤器已经使用 `@Component` 注解,Spring Boot 会自动检测并注册它。但是,如果你想更精确地控制过滤器的顺序或者应用于特定的 URL 模式,你可以创建一个配置类:

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<RequestLoggingFilter> loggingFilter() {
        FilterRegistrationBean<RequestLoggingFilter> registrationBean = new FilterRegistrationBean<>();
        
        registrationBean.setFilter(new RequestLoggingFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(1);  // 设置过滤器的优先级
        
        return registrationBean;
    }
}

这个示例中的过滤器做了以下几件事:

1. 在 `doFilter` 方法开始时,记录请求的开始时间和基本信息。

2. 调用 `chain.doFilter(request, response)` 继续处理请求。

3. 在请求处理完成后,记录响应状态码和处理时间。

我司技术在使用这个过滤器后,每次处理请求时,控制台会输出类似以下的信息:

开始处理请求: GET /api/example
请求处理完成: /api/example, 状态码: 200, 耗时: 50ms

这个简单的示例展示了如何创建和配置一个基本的过滤器。你可以根据具体需求修改或扩展这个过滤器,例如添加更详细的日志记录、请求参数检查、响应内容修改等功能。以下我们再看看异常如何处理:


处理异常如下:

我司经常会处理这些问题

以下是一些在 Spring Boot 过滤器中处理异常的方法和最佳实践:

在 doFilter 方法中使用 try-catch 块。这是最直接的方法,可以捕获并处理在过滤器链中发生的异常。

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class ExceptionHandlingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (Exception e) {
            // 记录异常
            System.err.println("过滤器捕获到异常: " + e.getMessage());
            e.printStackTrace();
            // 设置响应
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            httpResponse.getWriter().write("发生了一个错误: " + e.getMessage());
        }
    }
}

第二步,你可以创建一个专门的异常处理过滤器。你可以创建一个专门的过滤器来处理异常,并将其放置在过滤器链的最前面。

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@Order(Integer.MIN_VALUE) // 确保这个过滤器是第一个执行的
public class GlobalExceptionFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (Exception e) {
            System.err.println("全局异常过滤器捕获到异常: " + e.getMessage());
            e.printStackTrace();
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            httpResponse.getWriter().write("服务器遇到了一个问题");
        }
    }
}

第三步:使用 ErrorController 处理过滤器中的异常。如果你想让 Spring Boot 的错误处理机制来处理过滤器中的异常,你可以将异常传播到 ErrorController。

import jakarta.servlet.*;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class ExceptionPropagatingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (Exception e) {
            // 记录异常
            System.err.println("过滤器捕获到异常: " + e.getMessage());
            
            // 将异常重新抛出,让 ErrorController 处理
            throw new ServletException(e);
        }
    }
}

最后,你可以创建一个自定义的 ErrorController 来处理这些异常:

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.servlet.http.HttpServletRequest;
@RestController
public class CustomErrorController implements ErrorController {
    @RequestMapping("/error")
    public ResponseEntity<String> handleError(HttpServletRequest request) {
        Exception exception = (Exception) request.getAttribute("jakarta.servlet.error.exception");
        
        if (exception != null) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("发生错误: " + exception.getMessage());
        }
        
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("发生未知错误");
    }
}

第四步,最佳实践。总是记录异常,这对于调试和监控非常重要。考虑不同类型的异常,可能需要不同的处理方式。不要在响应中暴露敏感的错误信息。使用统一的错误响应格式。在处理异常时,确保正确设置响应的状态码。通过这些方法,你可以在过滤器中有效地处理异常,提高应用的稳定性和用户体验。选择哪种方法取决于你的具体需求和应用架构。


contact us

服务热线:0632-52721230632-5271123

业务咨询:1396946888218006320170

营销中心:山东省 枣庄市 市中区 中坚1878 A406室

邮箱:kf@zzint.com

微信客服
在线联系
13969468882
返回顶部