Spring过滤器
Spring Filter
工作原理
- 过滤器依赖于 Servlet容器, 基于函数回调来实现
工作流程
- 用户请求时在 HttpServletRequest到 Servlet之前预处理相关事务 比如 修改或判断 HttpServletRequest头信息和数据. 然后 Servlet之后返回给用户 HttpServletResponse之前又处理相关事务并返回
使用场景
- 比较常见的有拦截过滤图片地址, URL地址, 敏感词汇, 检查头信息, 压缩响应信息, 权限验证, 设置字符编码
Spring过滤器的基本结构
- Spring Web包的过滤器核心接口及抽象类基本结构
javax.servlet.Filter -> org.springframework.web.filter -> GenericFilterBean -> OncePerRequestFilter -> AbstractRequestLoggingFilter
- 抽象类 GenericFilterBean继承了一系列接口, 主要实现了可以从 web.xml中取已定义的
init-param
的值或 application.properties等环境文件中取值, 然后初始化 Filter - 抽象类 OncePerRequestFilter继承了 GenericFilterBean, 继承 OncePerRequestFilter的自定义类, 主要实现每次接收请求时确保每个 Filter只执行一次, 以及实现抽象方法 doFilterInternal, 在此方法中决定过滤之前和之后执行的事件
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Configuration
public class CustomOncePerRequestFilter1 extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
System.out.println("CustomOncePerRequestFilter1 Environment custom-key: " + getEnvironment().getProperty("custom-key"));
try {
filterChain.doFilter(request, response);
} finally {
System.out.println("CustomOncePerRequestFilter1 Finally");
}
}
}
- 抽象类 AbstractRequestLoggingFilter继承了 OncePerRequestFilter, 继承 AbstractRequestLoggingFilter的自定义类, 主要遗传了父类的过滤之前和之后执行的事件, 实现抽象方法 beforeRequest和 afterRequest
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.AbstractRequestLoggingFilter;
import javax.servlet.http.HttpServletRequest;
@Configuration
public class CustomAbstractRequestLoggingFilter extends AbstractRequestLoggingFilter {
@Override
protected void beforeRequest(HttpServletRequest request, String message) {
String ipAddress = request.getHeader("X-FORWARDED-FOR");
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}
System.out.println("CustomAbstractRequestLoggingFilter > beforeRequest -> ipAddress: " + ipAddress);
System.out.println("CustomAbstractRequestLoggingFilter > beforeRequest -> url: " + request.getRequestURI());
System.out.println("CustomAbstractRequestLoggingFilter > beforeRequest -> name: " + request.getParameter("name"));
}
@Override
protected void afterRequest(HttpServletRequest request, String message) {
System.out.println("CustomAbstractRequestLoggingFilter > afterRequest -> name: " + request.getParameter("name"));
}
}
- 测试控制器 http://127.0.0.1:8080/test.do?name=林爷
@RestController
public class TestController {
@GetMapping(value = "/test.do")
public Map<String, String> test(@RequestParam(value="name", required=false, defaultValue="全爷") String name) {
System.out.println("TestController -> name: " + name);
return new HashMap<>();
}
}
输出:
CustomAbstractRequestLoggingFilter > beforeRequest -> ipAddress: 127.0.0.1
CustomAbstractRequestLoggingFilter > beforeRequest -> url: /test.do
CustomAbstractRequestLoggingFilter > beforeRequest -> name: 林爷
CustomOncePerRequestFilter1 Environment custom-key: abc123
TestController -> name: 林爷
CustomOncePerRequestFilter1 Finally
CustomAbstractRequestLoggingFilter > afterRequest -> name: 林爷
- 配置多个过滤器并排执行顺序
import com.example.demo.controller.CustomAbstractRequestLoggingFilter;
import com.example.demo.controller.CustomOncePerRequestFilter1;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import javax.servlet.Filter;
@Configuration
public class FilterConfig {
@Bean
public Filter customOncePerRequestFilter1() {
return new CustomOncePerRequestFilter1();
}
@Bean
public FilterRegistrationBean _customOncePerRequestFilter1() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new DelegatingFilterProxy("customOncePerRequestFilter1"));
registration.addUrlPatterns("/*"); // 拦截路径
registration.setOrder(0); // 顺序
return registration;
}
@Bean
public Filter customAbstractRequestLoggingFilter() {
return new CustomAbstractRequestLoggingFilter();
}
@Bean
public FilterRegistrationBean _customAbstractRequestLoggingFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new DelegatingFilterProxy("customAbstractRequestLoggingFilter"));
registration.addUrlPatterns("/*"); // 拦截路径
registration.setOrder(1); // 顺序
return registration;
}
}
输出:
CustomOncePerRequestFilter1 Environment custom-key: abc123
CustomAbstractRequestLoggingFilter > beforeRequest -> ipAddress: 127.0.0.1
CustomAbstractRequestLoggingFilter > beforeRequest -> url: /test.do
CustomAbstractRequestLoggingFilter > beforeRequest -> name: 林爷
TestController -> name: 林爷
CustomAbstractRequestLoggingFilter > afterRequest -> name: 林爷
CustomOncePerRequestFilter1 Finally
如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!