本文介绍Web三大组件:Servlet、Filter、Listener中的Filter组件,并附上两个学习案例。
本文目录
Filter:过滤器
1.概念
生活中的过滤器:净水器,空气净化器,土匪…
web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
过滤器的作用:
- 一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤…
2.Filter快速入门
实现一个过滤器的步骤:
- 1.定义一个类,实现接口Filter;
- 2.复写接口里的方法;
- 3.配置过滤器拦截路径,有两种方式:web.xml配置或注解配置;
代码实现:
FilterDemo1.java
/**
* 过滤器快速入门程序
*/
@WebFilter(urlPatterns = "/*") //访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo1被执行了....");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
ServletDemo1.java
@WebServlet(name = "ServletDemo1", urlPatterns = "/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("访问到了ServletDemo1...");
}
}
访问ServletDemo1,
控制台打印:
3.过滤器细节
3.1 web.xml配置
可以在web.xml中配置过滤器:
例如,FilterDemo1在web.xml中配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置过滤器-->
<filter>
<!--过滤器名称-->
<filter-name>demo1</filter-name>
<!--过滤器所在类-->
<filter-class>com.dong.web.filter.FilterDemo1</filter-class>
</filter>
<!--映射-->
<filter-mapping>
<filter-name>demo1</filter-name>
<!-- 拦截路径 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3.2 过滤器执行流程
在访问有过滤器拦截的资源时,程序流程是:
- 1.执行过滤器
- 2.访问放行后的资源
- 3.访问资源回来(进行响应时),执行过滤器放行代码下边的代码
例子:
FilterDemo2.java
@WebFilter(filterName = "FilterDemo2", urlPatterns = "/*")
public class FilterDemo2 implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//对request对象请求消息增强
System.out.println("FilterDemo2执行了...");
//放行
chain.doFilter(req, resp);
//对response对象的响应消息增强
System.out.println("FilterDemo2回来了");
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
将过滤器换成FilterDemo2,再次访问ServletDemo1:
控制台打印:
3.3 过滤器生命周期方法
过滤器生命周期方法即Filter
接口中三个的方法:
- 1.
init
方法:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。多用于加载资源 - 2.
doFilter
方法:每一次请求被拦截资源时,会执行。可以执行多次 - 3.
destroy
方法:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。多用于释放资源
例子:
FilterDemo3.java
@WebFilter(filterName = "FilterDemo3", urlPatterns = "/*")
public class FilterDemo3 implements Filter {
/**
* 每一次请求资源被拦截时,会执行doFilter方法。可以执行多次
* @param req
* @param resp
* @param chain
* @throws ServletException
* @throws IOException
*/
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("doFilter...");
//放行
chain.doFilter(req, resp);
}
/**
* 在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次,用于加载资源。
* @param config
* @throws ServletException
*/
public void init(FilterConfig config) throws ServletException {
System.out.println("init...");
}
/**
* 在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。
* 只执行一次,一般用于释放资源。
*/
public void destroy() {
System.out.println("destroy...");
}
}
将过滤器换成FilterDemo3,再次访问ServletDemo1,然后关闭服务器:
控制台打印:
3.4 过滤器配置详解
使用@WebFilter
注解
1.拦截路径urlPatterns
配置:
- 拦截具体资源路径:
/index.jsp
只有访问index.jsp
资源时,过滤器才会被执行; - 拦截目录:
/user/*
访问/user
下的所有资源时,过滤器都会被执行; - 后缀名拦截:
*.jsp
访问所有后缀名为jsp资源时,过滤器都会被执行; - 拦截所有资源:
/*
访问任何资源时,过滤器都会被执行;
例子:
仅演示配置拦截目录。
FilterDemo4.java
@WebFilter("/user/*") //拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
public class FilterDemo4 implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemo4...");
//放行
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
/user
路径下的两个Servlet资源:
ServletDemo1.java
@WebServlet(name = "ServletDemo1", urlPatterns = "/user/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("访问到了ServletDemo1...");
}
}
ServletDemo2.java
@WebServlet(name = "ServletDemo2", urlPatterns = "/user/ServletDemo2")
public class ServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("访问到了ServletDemo2...");
}
}
浏览器分别访问ServletDemo1、ServletDemo2,
控制台打印:
2.拦截方式配置:资源被访问的方式
注解配置:
在@WebFilter
注解中设置dispatcherTypes
属性
属性值有:
- REQUEST:默认值。浏览器直接请求资源
- FORWARD:以请求转发访问资源的方式
- INCLUDE:请求包含访问资源方式
- ERROR:错误跳转资源
- ASYNC:异步访问资源
例子:
FilterDemo5.java
//浏览器直接请求index.jsp资源时,该过滤器会被执行
//@WebFilter(urlPatterns="/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
//只有转发访问index.jsp时,该过滤器才会被执行
//@WebFilter(urlPatterns="/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
//浏览器直接请求index.jsp或者转发访问index.jsp。该过滤器才会被执行
@WebFilter(urlPatterns="/index.jsp",dispatcherTypes ={ DispatcherType.FORWARD,DispatcherType.REQUEST})
public class FilterDemo5 implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemo5...");
//放行
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
index.jsp....
<%
System.out.println("index.jsp....");
%>
</body>
</html>
ServletDemo2.java
@WebServlet(name = "ServletDemo2", urlPatterns = "/ServletDemo2")
public class ServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("访问到了ServletDemo2...");
//转发到index.jsp
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
}
浏览器直接请求或者转发访问index.jsp资源
直接请求:
控制台打印:
转发访问index.jsp:
控制台打印:
web.xml配置:
在web.xml文件配置过滤器标签内,设置标签即可。
<!--配置过滤器-->
<filter>
<!--过滤器名称-->
<filter-name>demo5</filter-name>
<!--过滤器所在类-->
<filter-class>com.dong.web.filter.FilterDemo5</filter-class>
</filter>
<!--映射-->
<filter-mapping>
<filter-name>demo5</filter-name>
<!-- 拦截路径 -->
<url-pattern>/index.jsp</url-pattern>
<!--配置资源被访问的方式-->
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
3.5 过滤器链(配置多个过滤器)
多个过滤器,如果有两个过滤器,过滤器1和过滤器2,执行方式为:
- 执行过滤器1
- 过滤器2
- 执行访问资源
- 过滤器2
- 过滤器1
过滤器执行先后顺序问题
1.注解配置方式:按照过滤器类名的字符串比较规则比较,值小的先执行;
如:AFilter 和 BFilter,AFilter就先执行了 ,因为A的码值小于B的码值。
2.web.xml配置: 标签谁定义在上边,谁先执行;
例子:
有两个过滤器,FilterDemoA和FilterDemoB
FilterDemoA.java
@WebFilter(filterName = "FilterDemoA", urlPatterns = "/*")
public class FilterDemoA implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemoA执行了...");
//放行
chain.doFilter(req, resp);
System.out.println("FilterDemoA回来了...");
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
FilterDemoB.java
@WebFilter(filterName = "FilterDemoB", urlPatterns = "/*")
public class FilterDemoB implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemoB执行了...");
//放行
chain.doFilter(req, resp);
System.out.println("FilterDemoB回来了...");
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
浏览器访问index.jsp资源:
控制台打印:
过滤器执行先后顺序:因为类名FilterDemoA和FilterDemoB字符串比较,FilterDemoA值小。
以上就是Filter细节了,基本全面。下一篇,Filter的应用场景下的练习。
推荐阅读:
Filter案例:登录验证、敏感词汇过滤.
欢迎点赞评论,指出不足,笔者由衷感谢哦!~