Filter

来源:互联网 发布:淘宝手机号解除绑定 编辑:程序博客网 时间:2024/05/18 00:28
Filter的总结:
今天终于可以进入最后的一个阶段的学习了,就是来学习Filter接口。
①Filter是什么呢?
(1)Filter是JavaWeb的一个重要组件,称之为筛选器或者过滤器。可以对Servlet请求进行拦截,同样也可以对Servlet响应进行拦截,从而在Servlet进行响应处理的前后做一些特殊的处理。
(2)Filter是一个实现Filter接口的java类,和Servlet类相似。但是Filter是在web应用加载时(服务器启动时)创建的,并且执行init()方法,在请求请求拦截时执行doFilter()方法,当请求再次被拦截时也只会执行doFilter()方法,而不会再创建Filter对象,也就是说Filter对象也是一个单例。
(3)Filter和Servlet一样也是需要在web.xml中进行注册和映射的,这样服务器才能在调用时准确的找到对应的Filter.Filter既然作为拦截器,他可以拦截jsp,Serlvet,静态图片文件和静态html文件。在web.xml中注册了一个Filter对某个web资源进行拦截处理时,这个

Filter就成了服务器与该web应用资源通信道路上的一道关卡。该Filter可以对服务器对web资源的请求和web资源给服务器响应进行拦截,可以在过滤器中决定是否继续请求web资源或者是做其他处理。当然一个web应用中可以配置多个Filter,一个Filter可以拦截一个或者一组web资源的请求。

配置Filter的截图如下:


其中url-pattern中配置的就是当请求/响应的url为url-pattern的匹配模式时需要进行拦截。
在filter-mapping中还可以配置一个子元素为<dispatcher>,是用来指定服务器通过哪些方式调用web资源会被Filter拦截。其主要有有以下几个
值:REQUEST,FORWARD,INCLUDE,ERROR。可以设置多个<dispatcher>来指定哪些方式服务器调用web资源Filter进行拦截。
具体的解释如下图:


这里主要了解的就是REQUEST和FORWAED方式。REQUEST说简单点就是通过浏览器发出的get和post请求或者是通过response.sendRedirect()方法进行重定向的。FORWARD就是通过request.getRequestDispatcher('/web资源').forward(request,response)方法在服务器端进行转发的方式。

Filter的配置如下:


java代码的实现如下:

HttpFilter类接下来的所有Filter实现类都是继承该类下面就不做过多的复制了。

package com.yd.filter;import java.io.IOException;import javax.security.auth.Destroyable;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public abstract class HttpFilter implements Filter{private FilterConfig config;//默认调用改销毁方法@Overridepublic void destroy() {}//默认调用改过滤方法@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest request2=(HttpServletRequest) request;HttpServletResponse response2=(HttpServletResponse) response;doFilter(request2, response2, chain);}public abstract void doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain)throws IOException, ServletException;//默认调用初始化方法@Overridepublic void init(FilterConfig config) throws ServletException {this.config=config;init();}public abstract void init();public FilterConfig getConfig(){return this.config;}}
ForwardFilter类:

package com.yd.filter;import java.io.IOException;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class ForwardFilter extends HttpFilter {@Overridepublic void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws IOException, ServletException {System.out.println("Before forward dispatcher");//转向下一个过滤器chain.doFilter(request, response);System.out.println("After forward dispatcher");}@Overridepublic void init() {// TODO Auto-generated method stub}}
RequestFilter类:

package com.yd.filter;import java.io.IOException;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;//用于过滤request方式派发的web资源的过滤器public class RequestFilter extends HttpFilter {//实现父类的过滤方法@Overridepublic void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("Before request dispatcher");//转向下一个过滤器chain.doFilter(request, response);System.out.println("After request dispatcher");}@Overridepublic void init() {}}
登陆页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><!-- <form action="/FilterTest/ServletTest" method="post">用户名<input type="text" name="username"/>密码<input type="password" name="password"/><input type="submit" value="提交"/></form> --><%-- <%String err=(String)request.getAttribute("err");if(err!=null){out.println("<span style='color=red'>"+err+"<span>");}%> --%><jsp:forward page="/ServletTest"></jsp:forward></body></html>
测试页面:

package com.yd.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * Servlet implementation class ServletTest */@WebServlet("/ServletTest")public class ServletTest extends HttpServlet {private static final long serialVersionUID = 1L;           /**     * @see HttpServlet#HttpServlet()     */    public ServletTest() {        super();        // TODO Auto-generated constructor stub    }/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubresponse.setContentType("text/html;charset=utf-8");PrintWriter out=response.getWriter();out.println("欢迎光临!");System.out.println("Servlet执行");}/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubdoGet(request, response);}}

(1)通过request方式请求ServletTest的index.jsp和结果截图


(2)通过forward方式请求ServletTest的index.jsp和结果截图


②Filter接口中有三个未实现的方法:
(1)init(FilterConfig filterConfig)方法,。当web应用启动时,服务器会根据web.xml中配置的Filter进行创建,并且存储在服务器内存中。服务器在创建好该Filter对象实例后立即执行该init()方法。init()方法在Filter的生命周期中只执行一次。服务器在调用init()方法时会传进一个filerConfig的参数,filterConfig和servletConfig一样可以获得servletContext对象,以及部署描述符中该Filter的配置参数。
(2)doFilter(ServletRequest request, ServletResponse response, FilterChain chain)方法。当客户端请求目标资源时,服务器就会调用与之相关联的过滤器并且进行拦截执行该方法。其中参数request,response为web容器或者是Filter链的上一个Filter传递过来的请求和响应对象。其中一个很重要的参数就是FilterChain称之为Filter链。
什么是Filter链呢?
其实Filter链很简单的理解就是当客户端请求一个web资源时与之相关联的所有Filter会被服务器调用并且排列成一条链。其排列的顺序和Filter在web.xml中配置的filter-mapping的顺序有关,filter-mapping的配置在前面,其在链中的位置就靠前,也就先进行过滤。参数Filterchain代表拦截当前web资源的Filter链的对象,在特定的操作完成之后,可以在当前Filter对象的doFilter方法中调用Filterchain.doFilter(request,response)方法才能将请求交付给Filter链中的下一个Filter或者是目标web资源。也可以在Filter中直接向客户端返回响应信息,利用转发或者重定向方式转到其他资源。doFilter方法的请求和响应参数的类型是ServletRequest和ServletResponse,也就是说,过滤器的使用不依赖于具体的协议。
(3)destroy()方法,当服务器关闭要卸载Filter之前执行该方法,在Filter生命周期中该方法也只执行一次,在这个方法中可以释放
Filter使用的资源。节省服务器内存空间。
③那么我们Filter链的执行顺序如何呢?

首先看一个简单的例子,java代码如下:
index.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><form action="/FilterTest/ServletTest" method="post">用户名<input type="text" name="username"/>密码<input type="password" name="password"/><input type="submit" value="提交"/></form> <%-- <%String err=(String)request.getAttribute("err");if(err!=null){out.println("<span style='color=red'>"+err+"<span>");}%> --%><%-- <jsp:forward page="/ServletTest"></jsp:forward> --%></body></html>

UsernameFilter:

package com.yd.filter;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class UsernameFilter implements Filter{private String username=null;@Overridepublic void destroy() {// TODO Auto-generated method stub}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {/*request.setCharacterEncoding("utf-8");//首先获得请求参数里的usernameString name=request.getParameter("username");if (username.equals(name)) {//如果用户名相同那么就跳转到下一个过滤器chain.doFilter(request, response);}else{request.setAttribute("err", "用名民错误");//进行转发request.getRequestDispatcher("/index.jsp").forward(request, response);}*/System.out.println("Before Username");chain.doFilter(request, response);System.out.println("After Username");}@Overridepublic void init(FilterConfig config) throws ServletException {username=config.getInitParameter("username");}}

PasswordFilter:

package com.yd.filter;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import jdk.nashorn.internal.ir.RuntimeNode.Request;public class PasswordFilter implements Filter{private String password=null;@Overridepublic void destroy() {// TODO Auto-generated method stub}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {//获得请求参数/*String pwd=request.getParameter("password");if (password.equals(pwd)) {chain.doFilter(request, response);}else{request.setAttribute("err", "密码错误");request.getRequestDispatcher("/index.jsp").forward(request, response);}*/System.out.println("Before Password");chain.doFilter(request, response);System.out.println("After Password");}@Overridepublic void init(FilterConfig config) throws ServletException {password=config.getServletContext().getInitParameter("password");}}

ServletTest:

package com.yd.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * Servlet implementation class ServletTest */@WebServlet("/ServletTest")public class ServletTest extends HttpServlet {private static final long serialVersionUID = 1L;           /**     * @see HttpServlet#HttpServlet()     */    public ServletTest() {        super();        // TODO Auto-generated constructor stub    }/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubresponse.setContentType("text/html;charset=utf-8");PrintWriter out=response.getWriter();out.println("欢迎光临!");System.out.println("Servlet执行");}/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubdoGet(request, response);}}
显示结果如下:

Before Username

Before Password

Servlet执行

After Password

After Username

所以Filter链的执行顺序如下图所示:


这里有一点要注意的是,servlet在执行完service方法后首先先把响应返回给浏览器,然后在依次执行没有执行完的Filter链中的内容。

0 0