Web基础之遇见Filter

Web基础之遇见Filter

一、Filter所为何物

Filter也称之为过滤器,它是Servlet技术中实用技术之一Web开发人员通过Filter技术,对web服务器管理的所有web资源进行拦截(例如Jsp, Servlet, 静态图片或html等),从而实现一些特殊的功能。

     例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

     它主要用于对请求进行预处理,也可以对响应进行后处理。 

     Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,

最后Filter再对服务器响应进行后处理。

二、Filter的功能:

1、ServletRequest到达Servlet之前,拦截客户的ServletRequest。根据需要检查ServletRequest,也可以修改ServletRequest头和数据。

2 、ServletResponse到达客户端之前,拦截ServletResponse。根据需要检查ServletResponse,也可以修改ServletResponse头和数据。


三、Filter的生命周期
在当前 WEB 应用被服务器加载时,由服务器通过反射机制创建Filter的实例(注意跟Servlet的区别),
init(FilterConfig)
服务器创建Filter实例后,紧接着调用 其 init(FilterConfig) 方法对该对象进行初始化
doFilter(ServletRequest, ServletResponse, FilterChain)
后续服务器将根据该Filter的配置,调用该方法对资源请求进行拦截
destory()
当该Filter被服务器卸载的时候,被服务器调用

注意:Filter跟Servlet一样,也是单例的ilter

四、Filter的执行流程(FilterChain过滤器链):



五、过滤器链是如何形成的?先后顺序是怎样的?
服务器在加载当前WEB应用的时候,会读取web.xml文件,根据各Filter在web.xml
文档中定义的先后顺序,初始化各个Filter,并按定义顺序形成一个链。

六、Filter的生命周期代码演示

Filter的编写:实现Filter接口即可
package com.usc.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 FilterLifeCycle implements Filter {
	
	public FilterLifeCycle(){
		System.out.println("Do my Constructer......");
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("Do my init......");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println("Do my doFilter......");
		System.out.println("请求向后面传递.....");
		chain.doFilter(request, response);
		System.out.println("请求传递回来了......");
		System.out.println("Do my doFilter end......");
	}

	@Override
	public void destroy() {
		System.out.println("Do my destroy......");
	}
}

在web.xml文件中配置拦截路径:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Filter</display-name>
 
  
  <filter>
  <filter-name>filterTest</filter-name>
  <filter-class>com.usc.filter.FilterLifeCycle</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>filterTest</filter-name>
  <url-pattern>/login.jsp</url-pattern>
  </filter-mapping>
  
  <filter>
  <filter-name>loginfilter</filter-name>
  <filter-class>com.usc.filter.LoginCheckFilter</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>loginfilter</filter-name>
  <url-pattern>/login</url-pattern>
  </filter-mapping>
 
</web-app>


login.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>登录界面</title>
</head>
<body>
	<form action="/Filter/login" method="POST">
		<table
			style="margin-top: 100px; margin-left: auto; margin-right: auto; text-align: center;">
			<tr>
				<td colspan="2">用户登录</td>
			</tr>
			<tr>
				<td>用户名:</td>
				<td><input type="text" name="userName" >
				<td>
			</tr>
			<tr>
				<td> 密  码:</td>
				<td><input type="password" name="pssWord" ></td>
			</tr>
			<tr>
				<td><input type="submit" value="登录"></td>
			</tr>
			<%
			String msg=(String)request.getAttribute("ErrorMsg");
			if(msg!=null){
				%>
				<tr>
				<td></td><td style="color: red"><%=msg%></td>
				</tr>
				<%
			}
			%>
		</table>
	</form>
</body>
</html>


运行结果:


七、Filter链执行顺序模拟
整体框架:

package com.usc.simulate;

/**
 * 自定义MyFilter接口
 */
public interface MyFilter{
	
	public void doFilter(MyRequest req,MyResponse resp,MyFilterChain chain);
}

package com.usc.simulate;

public class MyFilter1 implements MyFilter{

//	子类Filter1
	public void doFilter(MyRequest req, MyResponse resp, MyFilterChain chain) {
		System.out.println("MyFilter 1 start ......");
		chain.doFilter(req, resp, chain);
		System.out.println("MyFilter 1 finish ......");
	}

}

package com.usc.simulate;

public class MyFilter2 implements MyFilter{

	public void doFilter(MyRequest req, MyResponse resp, MyFilterChain chain) {
		System.out.println("MyFilter 2 start ......");
		chain.doFilter(req, resp, chain);
		System.out.println("MyFilter 2 finish ......");
	}

}

package com.usc.simulate;

public class MyFilter3 implements MyFilter{

	public void doFilter(MyRequest req, MyResponse resp, MyFilterChain chain) {
		System.out.println("MyFilter 3 start ......");
		chain.doFilter(req, resp, chain);
		System.out.println("MyFilter 3 finish ......");
	}

}

package com.usc.simulate;
/**
 * 自定义过滤器链
 *
 */
public class MyFilterChain {
	
	//过滤器数组,用来保存注册的Filter
	private MyFilter[] filters;
	//Servlet数组,保存注册的servlet
	private MyServlet server;
	//下标,用来表示链的顺序
	private int index=0;
	//构造方法,初始化数组
	public MyFilterChain(MyFilter[] filters, MyServlet server){
		this.filters=filters;
		this.server=server;
	}
	//doFilter方法,循环处理
	public void doFilter(MyRequest req,MyResponse resp,MyFilterChain chain){
		if(index<filters.length){
			filters[index++].doFilter(req, resp, this);
		}else{
			server.doService(req, resp);
		}
	}
}

package com.usc.simulate;

public class MyRequest {

}

package com.usc.simulate;

public class MyResponse {

}

package com.usc.simulate;

public class MyServlet {
	public void doService(MyRequest req,MyResponse resp){
		System.out.println("doService......");
	}
}

package com.usc.simulate;

public class Test {
	
	public static void main(String[] args) {
		
		//构造过滤器数组
		MyFilter[] filters ={new MyFilter1(),new MyFilter2(),new MyFilter3()};
		//创建链对象
		MyFilterChain chain = new MyFilterChain(filters, new MyServlet());
		//点方法,模拟执行Filter链
		chain.doFilter(new MyRequest(), new MyResponse(), chain);
	}

}

模拟运行结果:



八、Filter实际应用:利用Filter设置所有请求编码以及登录检查

login.jsp代码同上
welcome.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>首页</title>
</head>
<body>
	欢迎您<%=request.getAttribute("user") %>
</body>
</html>

LoginCheckFilter.java
package com.usc.filter;

import java.io.IOException;
import java.net.URLEncoder;

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 LoginCheckFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		 
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println("LoginCheckFilter.......");
		//设置所有请求编码
		request.setCharacterEncoding("UTF-8");
		//登录检查
		String userName=request.getParameter("userName");
		String passWord =request.getParameter("pssWord");
		//如果校验不通过,则请求将不再往下传递
		if(userName==null || "".equals(userName.trim()) || 
				passWord==null || "".equals(passWord.trim())){
			request.setAttribute("ErrorMsg", "用户名或密码填写不完整");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
			return;
		}else{
			//校验通过,请求往下传递
//			URLEncoder.encode(userName, "UTF-8");
			request.setAttribute("user", userName);
			chain.doFilter(request, response);	
		}
		System.out.println("LoginCheckFilter end.......");
	}
	@Override
	public void destroy() {
		
	}
}


LoginServlet.java
package com.usc.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class LoginServlet extends HttpServlet{

	private static final long serialVersionUID = 1L;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		//获取参数
//		String userName=req.getParameter("userName");
//		String passWord =req.getParameter("pssWord");
//		if(userName!=null){
//			req.setAttribute("user", userName);
//		}else{
//			req.setAttribute("user", "UNKNOW");
//		}
		req.getRequestDispatcher("/welcome.jsp").forward(req, resp);
	}
}


web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Filter</display-name>
  
  <filter>
  <filter-name>filterTest</filter-name>
  <filter-class>com.usc.filter.FilterLifeCycle</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>filterTest</filter-name>
  <url-pattern>/login.jsp</url-pattern>
  </filter-mapping>
  
  <filter>
  <filter-name>loginfilter</filter-name>
  <filter-class>com.usc.filter.LoginCheckFilter</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>loginfilter</filter-name>
  <url-pattern>/login</url-pattern>
  </filter-mapping>
  
  <servlet>
  <servlet-name>login</servlet-name>
  <servlet-class>com.usc.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>login</servlet-name>
  <url-pattern>/login</url-pattern>
  </servlet-mapping>
</web-app>

运行结果:





九、总结:
Filter是web三大组件之一(Servlet、Filter、Listener),Filter的主要功能是在请求到达Servlet处理前进行相关的预处理,比如设置编码格式,登录校验等;
Filter中,需要明白Filter链的形成过程,以及处理流程;我们做了一个模拟程序,来模拟这一过程是怎么发生的;另外,还需要注意的是,在web.xml配置的Filter前后顺序以及处理路径;这三大组件都是需要在web.xml文件进行配置的;
学无止境,共勉!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值