springboot实现过滤器
过滤器的英文名称为 Filter, 是 Servlet 技术中最实用的技术。如同它的名字一样,过滤器是处于客户端和服务器资源文件之间的一道过滤网,帮助我们过滤掉一些不符合要求的请求,通常用作 Session 校验,判断用户权限,如果不符合设定条件,则会被拦截到特殊的地址或者基于特殊的响应。
一 过滤器简介
过滤器是对数据进行过滤,预处理过程,当我们访问网站时,有时候会发布一些敏感信息,发完以后有的会用*替代,还有就是登陆权限控制等,一个资源,没有经过授权,肯定是不能让用户随便访问的,这个时候,也可以用到过滤器。
过滤器的功能还有很多,例如实现URL级别的权限控制、压缩响应信息、编码格式等等。拦截掉我们不需要的接口请求,修改请求(request)和响应(response)内容,完成CORS跨域请求等等。
- 过滤器依赖Servlet容器,属于Servlet规范的一部分。
- 在实现上基于Servlet容器的函数回调,可以对几乎所有请求进行过滤。
- Filter的生命周期由Servlet容器管理。
过滤器执行流程
-
SpringBoot启动默认加载的Filter
characterEncodingFilter
hiddenHttpMethodFilter
httpPutFormContentFilter
requestContextFilter
-
Filter优先级
@Order(1):表示过滤器的顺序,假设我们有多个过滤器,你如何确定过滤器的执行顺序?这个注解就是规定过滤器的顺序。
Ordered.HIGHEST_PRECEDENCE
Ordered.LOWEST_PRECEDENCE
低位值意味着更高的优先级 Higher values are interpreted as lower priority
自定义Filter,避免和默认的Filter优先级一样,不然会冲突
注册Filter的bean FilterRegistrationBean
同模块里面有相关默认Filter
web->servlet->filter
二 过滤器配置使用方式 自定义Filter
过滤器里面的三个方法
init : filter对象只会创建一次,init方法也只会执行一次。
doFilter : 主要的业务代码编写方法,可以多次重复调用
destroy : 在销毁Filter时自动调用(程序关闭或者主动销毁Filter)。
过滤器配置使用方式一:通过注解方式注入过滤器
在pom.xml 中引入spring-boot-starter-web包。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
//@Component
@Order(1) // 指定过滤器的执行顺序@Order(1)
@WebFilter(filterName = "loginFilter", urlPatterns = "/*" , initParams = {
@WebInitParam(name = "URL", value = "http://localhost:8081")})
public class LoginFilter implements Filter {
/**
* 容器加载的时候调用
*
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化 init loginFilter");
}
/**
* 请求被拦截的时候进行调用
*
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(" doFilter loginFilter");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String username = request.getParameter("username");
if ("admin".equals(username)) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
System.out.println("非admin,返回主页");
response.sendRedirect("/index.html");
return;
}
}
/**
* 容器被销毁的时候调用
*/
@Override
public void destroy() {
System.out.println("销毁 destroy loginFilter");
}
}
1) 注解:
-
@Component就是把这个类注入到IOC容器中 可以不用在SpringBootApplication上使用@ServletComponentScan
-
@WebFilter:标记一个类为filter,被spring进行扫描,表示这个class是过滤器。@WebFilter是spring3.0的一个注解。
2)参数:
- filterName 为过滤器名字,
- urlPatterns 为过滤器的范围,拦截规则,支持正则
- initParams 为过滤器初始化参数。
3)例如:
@WebFilter(urlPatterns = “/api”,filterName = “myFilter”)说明这是一个web过滤器,它拦截的url为/api,过滤器名字为myFilter
4)官网地址:https://docs.spring.io/spring-boot/docs/2.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#boot-features-embedded-container-servlets-filters-listeners
@RequestMapping("/api/testFilter")
public Object testFilter() {
Map map = new HashMap();
map.put("test","我的过滤器");
return map;
}
在SpringBootApplication上使用@ServletComponentScan注解后,Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码。
@SpringBootApplication
@MapperScan({"com.beiluo.demo.dao","com.beiluo.demo.mapper"})
@ServletComponentScan // 扫描 Servlet 相关的组件
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
过滤器配置使用方式二 : 通过代码方式注入过滤器
public class TestFilter implements Filter {
private String url;
/**
* filter对象只会创建一次,init方法也只会执行一次。
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.url = filterConfig.getInitParameter("URL");
System.out.println("Filter init...");
}
/**
* 主要的业务代码编写方法
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
long start = System.currentTimeMillis();
System.out.println(start + " Filter doFilter before...");
filterChain.doFilter(servletRequest, servletResponse);
long end = System.currentTimeMillis();
System.out.println(end + "Filter doFilter after...");
}
/**
* 在销毁Filter时自动调用。
*/
@Override
public void destroy() {
System.out.println("Filter destroy...");
}
}
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new TestFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setName("testFilter");
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
}
三 过滤器和拦截器的区别
AOP不是一种具体的技术,而是一种编程思想。在面向对象编程的过程中,我们很容易通过继承、多态来解决纵向扩展。 但是对于横向的功能,比如,在所有的service方法中开启事务,或者统一记录日志等功能,面向对象的是无法解决的。所以AOP——面向切面编程其实是面向对象编程思想的一个补充。而我们今天讲的过滤器和拦截器都属于面向切面编程的具体实现
Filter | Interceptor | |
---|---|---|
实现方式 | 过滤器是基于函数回调 | 基于Java的反射机制的,通常通过动态代理的方式来执行 |
规范 | 依赖于Servlet容器,属于Servlet规范的一部分,生命周期由Servlet容器管理 | Spring规范 ,独立存在的,通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。 |
作用范围 | 对几乎所有的请求起作用 | 只对action请求起作用 |