JavaWeb学习笔记- Filter
什么是Filter
过滤器是 Servlet 容器中的一个组件,主要负责处理请求和响应,具体来说是负责对请求(HttpServletRequest)进行预处理, 以及对响应(HttpServletResponse)进行后处理,在实现上,基于函数回调,它可以对几乎所有请求进行过滤,所以它是依赖 Servlet 容器的。
执行流程
个Tomcat,如果Tomcat配置了拦截器,则由先拦截器该请求,拦截器可以选择拦截请求或者放行请求,也可以加强请求。(对用户发送的request对象进行加强)
Tomcat调用对应的Servlet处理完请求,返回响应结果时,也要走一遍过滤器,但这次不能拦截了。(你服务器要么不接受请求,既然接受了肯定是因为请求合法啊)
入门案例
创建一个类,实现Filter接口。注意!Filter的重名接口有很多,我们要选择javax.servlet包下的。
重写Filter接口的三个方法,其中doFilter是过滤器的核心方法,init()是过滤器初始化时执行,destroy()过滤器销毁时执行。
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filterDemo1 被创建了");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo1 被执行了!");
}
@Override
public void destroy() {
System.out.println("filterDemo1 被销毁了");
}
}
web.xml配置拦截路径。/*
表示拦截所有请求
注意,在比较早的版本中,web.xml
中filter要写在所有的servlet配置的前面,否则会爆红。
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.kaikeba.course06.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
书写一个简单的Servlet,方便查看结果
@WebServlet("/hello")
public class URLDemo1 extends HttpServlet {}
结果:
我们无论发出什么请求,servlet不会执行,输出不存在的界面,也是空白界面。
控制台:
我们每次请求,我们的拦截器都进了拦截因为URL是/*
,但是我们缺少放行逻辑。
放行:
拦截器有个重要的步骤是放行,当我们拦截请求是,可以在doFilter()内加一些逻辑判读或者增强操作,然后放行。
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo1 被执行了!");
filterChain.doFilter(servletRequest, servletResponse);
}
控制台:
控制台打印了filterDemo1执行了,然后是servlet执行。
注意以下程序执行结果:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo1 放行!");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("filterDemo1 慢走不送!");
}
结果:
我们看到程序的执行顺序是先放行,然后执行Servlet,最后再执行doFilter()下面的代码逻辑。所以doFilter()上面的代码逻辑是用户发送请求,doFilter()下面的代码逻辑是服务器发送响应结果给用户。
生命周期
初始化init
Filter在Tomcat启动时就创建了
放行doFilter
每一次请求拦截请求时执行,每次都是同一个Filter对象,可以多次执行。
销毁destroy
Filter随着Tomcat服务器的关闭而销毁。
注解配置
和Servlet一样,Filter也支持注解配置。
如果只有一个元数据,urlPatterns可以不写。
urlPatterns可以传入多个,是个String[]数组对象。
@WebFilter(urlPatterns = "/*")
public class FilterDemo1 implements Filter {}
URL路径
- 普通方式
-
/hello
:访问/hello的资源时,拦截器才执行 -
``/user/hello`:访问/user/hello的资源时,拦截器才执行
-
/index.jsp
:访问index.jsp的资源时,拦截器才执行很好理解,我们的URL和请求一一对应,不区分大小写。
- 添加通配符
/*
:拦截所有请求/user/*
:拦截/hello下的所有请求*.jsp
:拦截任何以.jsp结尾的请求
注意事项:
通配符的优先级是非常低的,所以默认情况下。用户发来一个请求,如果我们不是使用通配符的URL也能处理请求,则通配符是不生效的,但是如果没有一个Servlet可以处理一个请求,则通配符*
才会生效的。
特殊情况演示:
- 错误方式
/*.jsp
-
/*/*
这种方式会失去匹配功能,也根据浏览器而异,一般情况下,该URL什么都无法接收。
-
/he*
:
拦截方式的配置
filter 有一个重要的属性叫dispatcherTypes,用来设置拦截资源的方式。
- **REQUEST:**默认值,表示拦截浏览器的直接请求资源
- **FORWARD:**表示拦截转发访问的资源
- **INCLUED:**表示拦截包含访问资源
- **ERROR:**表示拦截错误资源跳转
- **ASYNC:**表示拦截异步访问资源
可以在@WebFilter中配置也可以在web.xml配置。
注解配置,拦截转发
@WebFilter(urlPatterns = "/*",dispatcherTypes = DispatcherType.FORWARD)
public class FilterDemo1 implements Filter {
xml配置
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.kaikeba.course06.FilterDemo1</filter-class>
<init-param>
<param-name>dispatcherTypes</param-name>
<param-value>FORWARD</param-value>
</init-param>
</filter>
过滤器链
指配置了多个过滤器,并且过滤器之前有一定的包含关系,比如两个过滤器都是拦截/*
请求。
过滤器的先后顺序:
- 注解配置
比较类名的字符串ASCII
@WebFilter("/*")
public void Filter1() implements Filter{
...
}
@WebFilterr("/*")
public void Filter2() implements Filter{
...
}
- web.xml配置
按照配置的先后顺序
filter2先执行,然后执行filter1
<filter>
<filter-name>filter2</filter-name>
<filter-class>com.kaikeba.course06.FilterDemo2</filter-class>
</filter>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.kaikeba.course06.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器链的执行顺序:
如果有两个过滤器,过滤器1,过滤器2。执行顺序: