JAVAWeb-Filter学习笔记
Filter
Filter
过滤器
Filter:过滤器,是 JavaWeb 三大组件之一,另外两个是 Servlet 和 Listener
工作流程:在程序访问服务器资源时,当一个请求到来,服务器首先判断是否有过滤器与去请求资源相关联,如果有过滤器可以将请求拦截下来,完成一些特定的功能,再由过滤器决定是否交给请求资源,如果没有就直接请求资源,响应同理
作用:过滤器一般用于完成通用的操作,例如:登录验证、统一编码处理、敏感字符过滤等
相关类
Filter
Filter是一个接口,如果想实现过滤器的功能,必须实现该接口
-
核心方法
方法 说明 void init(FilterConfig filterConfig) 初始化,开启过滤器 void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 对请求资源和响应资源过滤 void destroy() 销毁过滤器 -
配置方式
注解方式
1
2
()内填拦截路径,/*代表全部路径配置文件
1
2
3
4
5
6
7
8<filter>
<filter-name>filterDemo01</filter-name>
<filter-class>filter.FilterDemo01</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDemo01</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
FilterChain
-
FilterChain 是一个接口,代表过滤器对象。由Servlet容器提供实现类对象,直接使用即可。
-
过滤器可以定义多个,就会组成过滤器链
-
核心方法:
void doFilter(ServletRequest request, ServletResponse response)
用来放行方法如果有多个过滤器,在第一个过滤器中调用下一个过滤器,以此类推,直到到达最终访问资源。
如果只有一个过滤器,放行时就会直接到达最终访问资源。
FilterConfig
FilterConfig 是一个接口,代表过滤器的配置对象,可以加载一些初始化参数
方法 | 作用 |
---|---|
String getFilterName() | 获取过滤器对象名称 |
String getInitParameter(String name) | 获取指定名称的初始化参数的值,不存在返回null |
Enumeration |
获取所有参数的名称 |
ServletContext getServletContext() | 获取应用上下文对象 |
Filter使用
设置页面编码
请求先被过滤器拦截进行相关操作
过滤器放行之后执行完目标资源,仍会回到过滤器中
-
Filter 代码:
1
2
3
4
5
6
7
8
9
10
11
12
public class FilterDemo01 implements Filter{
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo01拦截到请求...");
//处理乱码
servletResponse.setContentType("text/html;charset=UTF-8");
//过滤器放行
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("filterDemo1放行之后,又回到了doFilter方法");
}
} -
Servlet 代码:
1
2
3
4
5
6
7
8
9
10
11
12
public class ServletDemo01 extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servletDemo01执行了...");
resp.getWriter().write("servletDemo01执行了...");
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
} -
控制台输出:
1
2
3filterDem 拦截到请求...
servletDem 执行了...
filterDem 放行之后,又回到了doFilter方法
多过滤器顺序
多个过滤器使用的顺序,取决于过滤器映射的顺序。
-
两个 Filter 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14public class FilterDemo01 implements Filter{
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo01执行了...");
filterChain.doFilter(servletRequest,servletResponse);
}
}
public class FilterDemo02 implements Filter{
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo02执行了...");
filterChain.doFilter(servletRequest,servletResponse);
}
} -
Servlet代码:
System.out.println("servletDemo02执行了...");
-
web.xml配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<filter>
<filter-name>filterDemo01</filter-name>
<filter-class>filter.FilterDemo01</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDemo01</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>filterDemo02</filter-name>
<filter-class>filter.FilterDemo02</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDemo02</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> -
控制台输出:
1
2
3filterDem 执行了
filterDem 执行了
servletDem 执行了...
在过滤器的配置中,有过滤器的声明和过滤器的映射两部分,到底是声明决定顺序,还是映射决定顺序呢?
答案是:<filter-mapping>
的配置前后顺序决定过滤器的调用顺序,也就是由映射配置顺序决定。
Filter生命周期
**创建:**当应用加载时实例化对象并执行init()初始化方法
**服务:**对象提供服务的过程,执行doFilter()方法
销毁:当应用卸载时或服务器停止时对象销毁,执行destroy()方法
-
Filter代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class FilterDemo03 implements Filter{
/*
初始化方法
*/
public void init(FilterConfig filterConfig) {
System.out.println("对象初始化成功了...");
}
/*
提供服务方法
*/
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo03执行了...");
//过滤器放行
filterChain.doFilter(servletRequest,servletResponse);
}
/*
对象销毁方法,关闭Tomcat服务器
*/
public void destroy() {
System.out.println("对象销毁了...");
}
} -
Servlet 代码:
System.out.println("servletDemo03执行了...");
-
控制台输出:
1
2
3
4对象初始化成功了...
filterDemo03执行了...
servletDemo03执行了...
对象销毁了
FilterConfig使用
Filter初始化函数init的参数是FilterConfig 对象
-
Filter代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public class FilterDemo04 implements Filter{
//初始化方法
public void init(FilterConfig filterConfig) {
System.out.println("对象初始化成功了...");
//获取过滤器名称
String filterName = filterConfig.getFilterName();
System.out.println(filterName);
//根据name获取value
String username = filterConfig.getInitParameter("username");
System.out.println(username);
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo04执行了...");
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() {}
} -
web.xml配置
1
2
3
4
5
6
7
8
9
10
11
12<filter>
<filter-name>filterDemo04</filter-name>
<filter-class>filter.FilterDemo04</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>zhangsan</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filterDemo04</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> -
控制台输出:
1
2
3对象初始化成功了...
filterDemo04
zhangsan
拦截行为
Filter过滤器默认拦截的是请求,但是在实际开发中,我们还有请求转发和请求包含,以及由服务器触发调用的全局错误页面。默认情况下过滤器是不参与过滤的,需要配置web.xml
开启功能后,当访问页面发生相关行为后,会执行过滤器的操作
五种拦截行为:
1 | <!--配置过滤器--> |
-
web.xml:
1
2
3
4
5
6
7
8
9
10
11<filter>
<filter-name>FilterDemo5</filter-name>
<filter-class>filter.FilterDemo5</filter-class>
<!--配置开启异步支持,当dispatcher配置ASYNC时,需要配置此行-->
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>FilterDemo5</filter-name>
<url-pattern>/error.jsp</url-pattern>
<dispatcher>ERROR</dispatcher>
<filter-mapping> -
ServletDemo03:
1
2
3
4protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servletDemo03执行了...");
int i = 1/ 0;
} -
FilterDemo05:
1
2
3
4
5
6
7
8public class FilterDemo05 implements Filter{
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo05执行了...");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
} -
控制台输出(注意输出顺序):
1
2servletDemo03执行了...
filterDemo05执行了...
对比Servlet
方法/类型 | Servlet | Filter | 备注 |
---|---|---|---|
初始化 方法 | void init(ServletConfig); | void init(FilterConfig); | 几乎一样,都是在web.xml中配置参数,用该对象的方法可以获取到。 |
提供服务方法 | void service(request,response); | void dofilter(request,response,FilterChain) | Filter比Servlet多了一个FilterChain,它不仅能完成Servlet的功能,而且还可以决定程序是否能继续执行。所以过滤器比Servlet更为强大。 在Struts2中,核心控制器就是一个过滤器。 |
销毁方法 | void destroy(); | void destroy(); | 方法/类型 |