目录
- 过滤器和拦截器的区别
- 过滤器的使用
- 1.使用spring boot提供的FilterRegistrationBean
- 2.使用原生servlet注解定义Filter
- 拦截器的使用
在前面我们讲过拦截器怎么使用,参考:拦截器
和拦截器有个差不多的叫过滤器。
过滤器和拦截器的区别
首先看一下下面的流程图:
如上图,其中prehandel、posthandel、afterCompletion是拦截器的方法,filter pre和filter after是过滤器的方法。
两者区别主要有以下几点:
- 触发时机:过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。拦截器是进入servlet之后才触发。
- 生命周期:Filter的生命周期由Servlet容器管理,而拦截器由spring提供,并可以使用IoC容器来管理,因此拦截器可以获取IOC容器中的各个bean,而过滤器就不行。
- 实现方式:过滤器实现基于回调函数,拦截器(代理模式)的实现基于反射。
- 执行方式:过滤器的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。
- 影响范围:过滤器可以修改request和response,而拦截器不能。但是过滤器只能在请求的前后使用,而拦截器可以详细到每个方法。
基于以上区别,过滤器和拦截器的使用场景通常不同。
拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现。
拦截器主要应用场景:
- 登录验证,判断用户是否登录。
- 权限验证,判断用户是否有权限访问资源,如校验token。
- 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。
- 处理cookie、本地化、国际化、主题等。
- 性能监控,监控请求处理时长等。
过滤器主要应用场景:
- 过滤敏感词汇(防止sql注入)
- 设置字符编码
- URL级别的权限访问控制
- 压缩响应信息
过滤器的使用
有以下两种方式使用过滤器。
1.使用spring boot提供的FilterRegistrationBean
先定义Filter:只要实现接口import javax.servlet.Filter
,并实现是哪个方法即可,其中最重要的是doFilter方法,在里面写我们的过滤逻辑。代码如下:
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// doFilter()方法中的servletRequest参数的类型是ServletRequest,需要转换为HttpServletRequest类型方便调用某些方法
System.out.println("filter1");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String ip = request.getRemoteAddr();
String url = request.getRequestURL().toString();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = new Date();
String date = sdf.format(d);
System.out.printf("%s %s 访问了 %s%n", date, ip, url);
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
然后注册我们的Filter:
import com.example.server.common.MyFilter;
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 registrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter());
// 设置过滤的url
filterRegistrationBean.addUrlPatterns("/*");
// 设置优先级
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
}
2.使用原生servlet注解定义Filter
用@WebFilter就可以进行配置。代码如下:
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@Component
// 定义filterName 和过滤的url
@WebFilter(filterName = "myFilter2" ,urlPatterns = "/*")
@Order(2)
public class MyFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("my filter2");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
这里需要注意一点的是@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们还需在启动类中加另外一个注解:@ServletComponetScan,指定扫描的包。
@SpringBootApplication
@ServletComponentScan
public class FilterTestApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(FilterTestApplication.class, args);
}
}
拦截器的使用
参考文章:拦截器
参考文章:
https://blog.csdn.net/qq_49313444/article/details/107504196
https://blog.csdn.net/qq_42076204/article/details/125215984