30、过滤器

学习目标:

1、了解Filter的概念

2、掌握Filter的定义和使用

3、根据业务需要灵活定义Filter

学习过程:

一、什么是过滤器filter

与Servlet相似,可以绑定到一个Web应用程序中。但是与其他Web应用程序组件不同的是,过滤器是“链”在容器的处理过程中的。这就意味着它们会在servlet处理器之前访问一个进入的请求,并且在外发的响应信息返回到客户前访问这些响应信息。这种访问使得过滤器可以检查并修改请求和响应的内容。 通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截。

过滤器放在Web资源之前,可以在请求抵达它所应用的Web资源(可以是一个servlet、一个JSP页面)之前截获进入的请求,并且在它返回到客户之前也会截获输出请求。也就说过滤器会在请求前后都会经过这个过滤器。

在Servlet作为过滤器使用时,它可以对客户的请求进行处理。 处理完成后,它会交给下一个过滤器处理,这样,客户的请求在过滤链里逐个处理,直到请求发送到目标为止.

filter在很多地方都可以使用,你可以把servlet中的一些共用代码抽象到filter中,比如对提交的数据进行统一编码,也可以把登录拦截放到filter中进行,也可以把发送给客户端的静态页面先进行压缩后再发送,还可以实现过滤敏感词汇、等等等功能。

二、定义过滤器filter

Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter

1、实现过滤器。

新建一个普通类FirstFilter,然后实现Filter接口。并实现其三个方法

public class FirstFilter implements Filter {
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("FirstFilter初始化了。");

	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		//进入过滤器
		//System.out.println("FirstFilter进入下一步之前  前  前");
		//进入下一步
		chain.doFilter(request, response);

		//System.out.println("FirstFilter进入下一步之后  后  后");
	}

	public void destroy() {
		System.out.println("FirstFilter销毁了。");

	}

}

2、过滤器的配置。

上面我们定义了一个过滤器,因为过滤器的生命周期有web容器管理,和servlet一样,我们需要在web.xml中配置这个过滤器,这样web容器启动的时候就会初始化这个过滤器。打开web.xml,添加一下代码:

	<filter>
		<filter-name>firstFilter</filter-name>
		<filter-class>com.filter.FirstFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>firstFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

和servlet差不多的一个配置,其中url-pattern是需要过滤的路径,我们可以直接写一个url路径,同时它也支持通配符(*)的使用,比如“/*”就表示过滤所有的信息,“/admin/*”就表示过滤所有的在admin访问路径下的所有的信息,这里我们先拦截的是“/userServlet”这个路径。

3、过滤器的生命周期

这个时候你就可以启动tomcat服务器了,注意filter是在服务器启动的时候就会初始化了,并且在服务器关闭的时候才会销毁,所以filter整个生命周期由服务器维护。

重点是doFilter方法,这个方法在每一次拦截的时候都会执行。在这个方法里面有三个参数其中有两个我们非常属性的request和response对象,还有就是FilterChain对象,这个对象一般会调用doFilter方法,表示把交给下一个链操作,可能是servlet,也可能是下一个过滤器。

现在你可以打开浏览器输入访问/userServlet这个网址。

http://localhost:8080/userdemo/userServlet。

查看控制台的输入,会先输出:

FirstFilter访问业务核心前执行

执行了核心的逻辑servlet

FirstFilter访问业务核心后执行

4、过滤器的先后顺序

注意过滤器在web.xml的定义顺序是会影响其拦截的先后顺序的,如果两个过滤器都会拦截同一个路径,那么先定义的就会先拦截。比如我们再定义一个过滤器:

public class SecondFilter implements Filter {

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		//System.out.println("SecondFilter进入下一步之前  前  前");
		chain.doFilter(request, response);
		//System.out.println("SecondFilter进入下一步之后  后  后");
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub

	}

	public void destroy() {
		// TODO Auto-generated method stub

	}

}

在web.xml中配置时,是在第一个过滤器的后面定义的,也是一样拦截同一个路径;

	<filter>
		<filter-name>firstFilter</filter-name>
		<filter-class>com.filter.FirstFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>firstFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<filter>
		<filter-name>secondFiter</filter-name>
		<filter-class>com.filter.SecondFilter</filter-class>
	</filter>
	
	<filter-mapping>
	   <filter-name>secondFiter</filter-name>
	   <url-pattern>/*</url-pattern>
	</filter-mapping>

这是时候我们在访问/userServlet这个网址。

http://localhost:8080/userdemo/userServlet。

结果输出如下:

FirstFilter访问业务核心前执行

SecondFilter访问业务核心前执行

执行了核心的逻辑servlet

SecondFilter访问业务核心后执行

FirstFilter访问业务核心后执行

先拦截的过滤器,与返回给客户端的顺序相反,也就是和栈的结构是一样的,先进后出。当然这个也是很容易理解的。

三、过滤器的应用

1、编码过滤器

下面我们可以讲两个简单的应用,因为每一个servlet都需要设置编码,代码如下:

request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");

所以我们放到filter中配置,先进一个编码过滤器:

//编码拦截器
public class ChaFilter implements Filter {

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");

		chain.doFilter(request, response);
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub

	}

	public void destroy() {
		// TODO Auto-generated method stub

	}

}

我们可以把这个拦截器放到最前面。在web.xml配置如下;

	<filter>
		<filter-name>chaFilter</filter-name>
		<filter-class>com.filter.ChaFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>chaFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

好,这样就不要在每个servlet都写上编码的代码了。

2、登录拦截器

要做这个登录拦截器,我们必须先做好规划,比如需要登录才能访问的路径,我们一律都是放在admin的访问路径之下的。这样我们就只需要拦截这个路径就可以了,凡是没有登录的就去登录页面,登录就去下一个操作就行了。实现代码如下:

public class LoginFilter implements Filter {

	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest request=(HttpServletRequest)req;
		HttpServletResponse response=(HttpServletResponse)res;
		
		// 先判断用户是否已经登录了。
		HttpSession session = request.getSession();
		User userss = (User) session.getAttribute("user");
		if (userss == null) {
			response.sendRedirect("/userdem/index.jsp");
			return;
		}
		
		chain.doFilter(request, response);

	}

	public void destroy() {
		// TODO Auto-generated method stub

	}

	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub

	}

}

web.xml配置文件如下;

	<filter>
		<filter-name>loginFilter</filter-name>
		<filter-class>com.filter.LoginFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>loginFilter</filter-name>
		<url-pattern>/admin/*</url-pattern>
	</filter-mapping>

猜你喜欢

转载自blog.csdn.net/liubao616311/article/details/84072050