过滤器
什么是过滤器
-
过滤器是JavaWeb三大组件之一,它与Servlet很相似!不它过滤器是用来拦截请求的,而不是处理请求的。当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,那么会继承执行用户请求的Servlet;如果Filter不“放行”,那么就不会执行用户请求的Servlet。
-
它会在一组资源(jsp、servlet、.css、.html等等)的前面执行!
它可以让请求得到目标资源,也可以不让请求达到! -
Filter是单例的!
Filter的生命周期
-
void init(FilterConfig)
创建之后,马上执行;Filter会在服务器启动时就创建!
-
void destory()
销毁之前执行!在服务器关闭时销毁
-
void doFilter(ServletRequest,ServletResponse,FilterChain)
每次过滤时都会执行
FilterConfig和FilterChain参数
-
FilterConfig的作用:
- 获取初始化参数:getInitParameter()
- 获取过滤器名称:getFilterName()
- 获取appliction:getServletContext()
-
FilterChain的作用:
- doFilter(ServletRequest, ServletResponse):放行!
- 放行,就相当于调用了目标Servlet的service()方法!
Filter中的doFilter()方法和FilterChain中的doFilter()方法有什么不同
-
Filter中的doFilter()方法是指每次过滤都会被调用
-
FilterChain中的doFilter()方法是放行
如何编写一个Filter
-
写一个类实现Filter接口
-
在web.xml中进行配置
<filter> <filter-name>xxx</filter-name> <filter-class>cn.itcast.web.filter.AFitler</fitler-class> </filter> <fitler-mapping> <filter-name>xxx</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
单个过滤器的执行流程
-
创建一个AFilter类,实现Filter接口
package cn.andios.test; import javax.servlet.*; import java.io.IOException; public class AFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("我在服务器启动时立即执行"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("拦截"); filterChain.doFilter(servletRequest,servletResponse);//放行,相当于调用了目标Servlet的service()方法! System.out.println("我又回来了"); } @Override public void destroy() { System.out.println("我在服务器关闭前执行"); } }
-
创建AServlet
package cn.andios.test; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class AServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("AServlet执行了"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } }
-
在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"> <!--配置servlet--> <servlet> <servlet-name>AServlet</servlet-name> <servlet-class>cn.andios.test.AServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AServlet</servlet-name> <url-pattern>/AServlet</url-pattern> </servlet-mapping> <!--配置过滤器--> <filter> <filter-name>AFilter</filter-name> <filter-class>cn.andios.test.AFilter</filter-class> </filter> <filter-mapping> <filter-name>AFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
-
测试结果
-
首先启动服务器,控制台输出了“我在服务器启动时立即执行”(说明执行了init方法)
-
然后请求AServlet,控制台又先后输出了:
-
“拦截”:说明执行了doFilter方法进行拦截
-
“AServlet执行了”:说明调用filterChain.doFilter(servletRequest,servletResponse);方法后,进行了放行
-
“我又回来了”:说明当放行后执行完被拦截的Servlet中的代码后,还会到过滤器中继续执行filterChain.doFilter(servletRequest,servletResponse);之后的代码。
-
-
多过滤器的执行流程
演示案例
-
创建一个AServlet
package cn.andios.test; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class AServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("AServlet执行了"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } }
-
创建一个AFilter
package cn.andios.test; import javax.servlet.*; import java.io.IOException; public class AFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("我在服务器启动时立即执行"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("AFilter####start"); filterChain.doFilter(servletRequest,servletResponse);//放行,相当于调用了目标Servlet的service()方法! System.out.println("AFilter####end"); } @Override public void destroy() { System.out.println("我在服务器关闭前执行"); } }
-
创建一个BFilter
package cn.andios.test; import javax.servlet.*; import java.io.IOException; public class BFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("我在服务器启动时立即执行"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("BFilter####start"); filterChain.doFilter(servletRequest,servletResponse);//放行,相当于调用了目标Servlet的service()方法! System.out.println("BFilter####end"); } @Override public void destroy() { System.out.println("我在服务器关闭前执行"); } }
-
在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"> <servlet> <servlet-name>AServlet</servlet-name> <servlet-class>cn.andios.test.AServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AServlet</servlet-name> <url-pattern>/AServlet</url-pattern> </servlet-mapping> <!--配置过滤器--> <filter> <filter-name>AFilter</filter-name> <filter-class>cn.andios.test.AFilter</filter-class> </filter> <filter-mapping> <filter-name>AFilter</filter-name> <url-pattern>/AServlet</url-pattern> </filter-mapping> <!--配置过滤器--> <filter> <filter-name>BFilter</filter-name> <filter-class>cn.andios.test.BFilter</filter-class> </filter> <filter-mapping> <filter-name>BFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
-
测试:启动服务器,并访问AServlet
控制台输出
AFilter####start
BFilter####start
AServlet执行了
BFilter####end
AFilter####end
- 先进入的过滤器返回时将会后执行
- FilterChain的doFilter()方法:
执行目标资源,或是执行下一个过滤器!如果没有下一个过滤器那么执行的是目标资源,如果有,那么就执行下一个过滤器!
多个Filter的执行顺序:
看web.xml中的配置顺序,哪个位置在前,哪个过滤器就先执行。
过滤器的四种拦截方式
在中进行配置!
- REQUEST默认的!
- FORWARD
- INCLUDE
- ERROR
FORWARD拦截方式的演示
-
创建AServlet
package cn.andios.test; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class AServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("AServlet执行了"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } }
-
创建BServlet
package cn.andios.test; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class BServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/AServlet").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } }
-
创建AFilter
package cn.andios.test; import javax.servlet.*; import java.io.IOException; public class AFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("我在服务器启动时立即执行"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("AFilter####start"); filterChain.doFilter(servletRequest,servletResponse);//放行,相当于调用了目标Servlet的service()方法! System.out.println("AFilter####end"); } @Override public void destroy() { System.out.println("我在服务器关闭前执行"); } }
-
创建BFilter
package cn.andios.test; import javax.servlet.*; import java.io.IOException; public class BFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("我在服务器启动时立即执行"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("BFilter####start"); filterChain.doFilter(servletRequest,servletResponse);//放行,相当于调用了目标Servlet的service()方法! System.out.println("BFilter####end"); } @Override public void destroy() { System.out.println("我在服务器关闭前执行"); } }
-
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"> <servlet> <servlet-name>AServlet</servlet-name> <servlet-class>cn.andios.test.AServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AServlet</servlet-name> <url-pattern>/AServlet</url-pattern> </servlet-mapping> <servlet> <servlet-name>BServlet</servlet-name> <servlet-class>cn.andios.test.BServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>BServlet</servlet-name> <url-pattern>/BServlet</url-pattern> </servlet-mapping> <!--配置过滤器--> <filter> <filter-name>AFilter</filter-name> <filter-class>cn.andios.test.AFilter</filter-class> </filter> <filter-mapping> <filter-name>AFilter</filter-name> <url-pattern>/AServlet</url-pattern> </filter-mapping> <!--配置过滤器--> <filter> <filter-name>BFilter</filter-name> <filter-class>cn.andios.test.BFilter</filter-class> </filter> <filter-mapping> <filter-name>BFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>FORWARD</dispatcher> </filter-mapping> </web-app>
-
演示:启动服务器
-
访问AServlet,控制台输出了
AFilter####start
AServlet执行了
AFilter####end说明BFilter配置的拦截方式是FORWARD,所以他只拦截FORWARD转发,不会拦截request请求。执行的也自然是AFilter了
-
然后访问BServlet,控制台输出了
BFilter####start
AServlet执行了
BFilter####end说明BServlet发起请求转发时,被BFilter拦截了,且它只拦截FORWARD
-