Filter

4 篇文章 0 订阅
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;
	//默认调用改销毁方法
	@Override
	public void destroy() {
	}
	//默认调用改过滤方法
	@Override
	public 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;
	//默认调用初始化方法
	@Override
	public 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 {

	@Override
	public 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");
	}

	@Override
	public 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 {
	//实现父类的过滤方法
	@Override
	public 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");
	}

	@Override
	public 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 stub
		response.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 stub
		doGet(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;
	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		/*request.setCharacterEncoding("utf-8");
		//首先获得请求参数里的username
		String 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");
	}

	@Override
	public 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;
	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public 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");
	}

	@Override
	public 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 stub
		response.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 stub
		doGet(request, response);
	}

}
显示结果如下:

Before Username

Before Password

Servlet执行

After Password

After Username

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


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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值