Spring Boot中的自定义过滤器
今天我们来聊聊Spring Boot中的自定义过滤器。过滤器是Java Web开发中处理HTTP请求和响应的重要组件。Spring Boot提供了简单且强大的过滤器配置机制,使得创建和管理自定义过滤器变得非常方便。
一、过滤器概述
过滤器(Filter)是一种用于预处理请求和后处理响应的组件。它可以拦截请求和响应,对其进行修改或处理。常见的用途包括日志记录、身份验证、安全检查、数据压缩等。
二、创建自定义过滤器
在Spring Boot中创建自定义过滤器非常简单。我们需要实现javax.servlet.Filter
接口,并重写其中的doFilter
方法。接下来,我们将创建一个示例过滤器,记录请求的处理时间。
1. 创建过滤器类
首先,我们创建一个过滤器类,命名为RequestLoggingFilter
:
package cn.juwatech.filter;
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 java.io.IOException;
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 {
long startTime = System.currentTimeMillis();
chain.doFilter(request, response);
long endTime = System.currentTimeMillis();
System.out.println("Request processed in " + (endTime - startTime) + " ms");
}
@Override
public void destroy() {
// 销毁过滤器
}
}
2. 注册过滤器
接下来,我们需要将这个过滤器注册到Spring Boot应用中。我们可以通过配置类或注解来完成。
通过配置类注册过滤器:
package cn.juwatech.config;
import cn.juwatech.filter.RequestLoggingFilter;
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("/*");
return registrationBean;
}
}
通过注解注册过滤器:
如果使用Spring Boot 2.0及以上版本,可以直接在过滤器类上使用@Component
注解进行注册:
package cn.juwatech.filter;
import org.springframework.stereotype.Component;
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 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 {
long startTime = System.currentTimeMillis();
chain.doFilter(request, response);
long endTime = System.currentTimeMillis();
System.out.println("Request processed in " + (endTime - startTime) + " ms");
}
@Override
public void destroy() {
// 销毁过滤器
}
}
三、过滤器的应用场景
- 日志记录
日志记录是过滤器最常见的应用场景之一。通过自定义过滤器,可以记录每个请求的详细信息,包括处理时间、请求参数、响应状态等。
package cn.juwatech.filter;
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 java.io.IOException;
public class LoggingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("Request received at " + System.currentTimeMillis());
chain.doFilter(request, response);
System.out.println("Response sent at " + System.currentTimeMillis());
}
@Override
public void destroy() {
// 销毁
}
}
- 身份验证
过滤器还可以用于身份验证。在处理请求之前,可以检查请求头或Cookie中的身份信息,决定是否允许请求通过。
package cn.juwatech.filter;
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 java.io.IOException;
public class AuthenticationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 简单示例,实际应用中应使用更安全的方式
String token = request.getParameter("token");
if ("valid-token".equals(token)) {
chain.doFilter(request, response);
} else {
response.getWriter().write("Authentication failed");
}
}
@Override
public void destroy() {
// 销毁
}
}
- 数据压缩
过滤器还可以用于响应数据的压缩。通过在过滤器中对响应数据进行压缩,可以减少传输的数据量,提高传输效率。
package cn.juwatech.filter;
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.http.HttpServletResponse;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
public class CompressionFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
GZIPResponseWrapper gzipResponseWrapper = new GZIPResponseWrapper(httpServletResponse);
chain.doFilter(request, gzipResponseWrapper);
gzipResponseWrapper.finish();
}
@Override
public void destroy() {
// 销毁
}
}
class GZIPResponseWrapper extends HttpServletResponseWrapper {
private GZIPOutputStream gzipOutputStream = null;
private ServletOutputStream servletOutputStream = null;
public GZIPResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
this.servletOutputStream = response.getOutputStream();
this.gzipOutputStream = new GZIPOutputStream(servletOutputStream);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new ServletOutputStream() {
@Override
public boolean isReady() {
return servletOutputStream.isReady();
}
@Override
public void setWriteListener(WriteListener writeListener) {
servletOutputStream.setWriteListener(writeListener);
}
@Override
public void write(int b) throws IOException {
gzipOutputStream.write(b);
}
};
}
public void finish() throws IOException {
gzipOutputStream.finish();
}
}
四、总结
本文介绍了Spring Boot中的自定义过滤器,包括过滤器的基本概念、创建和注册方法以及常见的应用场景。通过自定义过滤器,我们可以在请求处理的各个阶段进行灵活的操作,从而实现日志记录、身份验证和数据压缩等功能。