Filter学习

java web filter 之一 基础实现

本文主要对filter的基本使用进行了讲解,其中涉及到了

filter是什么

一个filter处理一个jsp

多个filter处理一个jsp

filter是什么

Filter 是java下的一种过滤器 ,能实现对java web程序 客户端和服务器端消息的过滤,也就是在服务器段接受request之前,可以预先对request进行处理,或在客户端接受response之前,对response进行处理。

Filter的使用非常灵活,是在“链”到客户端和服务器之间的,在需要时可以配置到客户端与服务器之间,在不需要时可以去掉。filter还可以设置其对发送到哪些页面或从哪些页面发出的消息进行过滤,即是一中横切性的编程,可插拔。Filter执行的大致过程如下图

实现filter相关的功能,需要实现javax.servlet.jar包下的filter接口,该接口有三个方法,分别是init doFilter,destory方法,把需要执行某些功能的代码放到doFilter方法中

一个Filter处理一个jsp:

实现filter要实现javax.servlet包下的filter接口,本例子实现的是设置所有jsp也的字符编码

package com.tgb.drp.util.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;

/**
 * 采用filter统一处理字符集
 *
 */
public class CharsetEncodingFilter implements Filter {

	private String encodeString;
        //Filter注销方法
	@Override
	public void destroy() {

	}
        //filter要实现的功能
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println("begin");
		// 设置字符集
		request.setCharacterEncoding(encodeString);

		//继续向下执行,如果还有其他filter继续调用其他filter,没有的话将消息发送给服务器或客户端
		chain.doFilter(request, response);
		System.out.println("end");
	}
        //初始化方法
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		//
		encodeString=filterConfig.getInitParameter("encoding");
	}

}

//写好filter类后,需要在配置文件中设置对哪些request和response进行过滤处理,本例子设置对所有的jsp页进行处理,在web.xml的web-app节点下,配置好后,可以写一个jsp页进行测试了。

    <filter>
    	<filter-name>CharsetEncodingFilter</filter-name>
    	<filter-class>com.tgb.drp.util.filter.CharsetEncodingFilter</filter-class>
    	<init-param>
    		<param-name>encoding</param-name>
    		<param-value>GBK</param-value>
    	</init-param>
    </filter>
    <filter-mapping>
    	<filter-name>CharsetEncodingFilter</filter-name>
    	<url-pattern>*.jsp</url-pattern>
    </filter-mapping>

  

多个filter处理一个jsp页

如果想实现多个filter对同一个jsp页进行处理,例如既需要设置字符编码,又需要验证身份,只需要在在写好响应的filter后继续配置在web.xml里。我们继续上面的例子,再写一个验证身份的Filter,命名为AuthenticationFilter,代码如下

package com.tgb.drp.util.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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class AuthenticationFilter implements Filter {

	@Override
	public void destroy() {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		//控制用户访问权限
		HttpServletRequest req=(HttpServletRequest)request;
		HttpServletResponse res=(HttpServletResponse)response;
		HttpSession session=req.getSession();

		if(session.getAttribute("user_info")!=null){
			chain.doFilter(request, response);
		}else{
			res.sendRedirect(req.getContextPath()+"/error.html");
		}
	}

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

	}

}

然后在配置文件里继续进行下配置,代码如下

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  	<welcome-file-list>
        <welcome-file>index.html</welcome-file>

    </welcome-file-list>
    <filter>
    	<filter-name>CharsetEncodingFilter</filter-name>
    	<filter-class>com.tgb.drp.util.filter.CharsetEncodingFilter</filter-class>
    	<init-param>
    		<param-name>encoding</param-name>
    		<param-value>GBK</param-value>
    	</init-param>
    </filter>
    <filter-mapping>
    	<filter-name>CharsetEncodingFilter</filter-name>
    	<url-pattern>*.jsp</url-pattern>
    </filter-mapping>

    <filter>
    	<filter-name>AuthenticationFilter</filter-name>
    	<filter-class>com.tgb.drp.util.filter.AuthenticationFilter</filter-class>
    </filter>
    <filter-mapping>
    	<filter-name>AuthenticationFilter</filter-name>
    	<url-pattern>*.jsp</url-pattern>
    </filter-mapping>

	<session-config>
		<session-timeout>60</session-timeout>
	</session-config>
</web-app>

  好了到此就可以设置两个filter对一个jsp页进行处理了,当启动tomcat,访问响应的jsp页时,设置的filter就会起作用。

6.1. Filter

6.1.1. Filter的用途

Filter这种机制常被用来实现下面的功能:

页面授权 根据登录用户的权限,阻止或许可用户访问特定的页面。
日志和审计 记录和检查用户访问WEB应用的情况。
图片转换 改变图片的格式、精度、尺寸等。
页面压缩 压缩页面内容,加快下载速度。
本地化 显示本地语言和风格的页面。
XSLT转换 对XML内容进行XSLT转换,使之适用于多种客户端。
高速缓存 高速缓存页面,提高响应速度。

当然还有更多种的应用,我们不可能一一列举。

Filter的通用性很好。任何filter均独立于其它filter和servlet,因此它可以和任意其它filter和servlet组合搭配。下面是一段配置示例 ── 通过SetLoggingContextFilter,日志系统可以记录当前请求的信息,例如:URL、referrer URL、query string等。

例 6.1. Filter配置示例(/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/xml/ns/j2ee  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd
    ">
    <filter>
        <filter-name>mdc</filter-name>
        <filter-class>com.alibaba.citrus.webx.servlet.SetLoggingContextFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>mdc</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...
</web-app>

6.1.2. Filter工作原理

图 6.1. Filter Chain

如图所示。多个filter和至多一个servlet被串联成一个链,被称为Filter Chain。执行的时候,引擎将控制权交给链条中的头一个filter(如果有的话)。然后,就像击鼓传花一样,控制权被依次传递给filter chain中的下一个filter或servlet。每一个得到控制权的filter可以做下面的事:

  • 继续传递控制权或立即终止filter chain。

    • Filter可将控制权传递给链条中的下一个filter或者最终的servlet。
    • Filter也可以不将控制权传递给下一个filter或servlet,这样便中止了整个filter chain的执行。
  • 预处理。在传递控制权给下一个filter或servlet之前,filter可以预先做一些事情:
    • 设置request、response中的参数,例如:character encoding、content type等。
    • HttpServletRequestWrapper传递给链条中的下一位,filter可以通过wrapper改变request中的任意值。
    • HttpServletResponseWrapper传递给链条中的下一位,filter可以通过wrapper来拦截后续filter或servlet对response的修改。
  • 提交。在控制权从filter chain中返回以后,filter还可以做一些后续提交的操作。
    • 例如,将response中拦截而来的数据,压缩或转换格式,并发送给客户端或filter chain的上一级。
    • 通过trycatch还可以捕获filter chain下一级所有的异常,并做处理。

6.1.3. Filter的限制

Filter是很有用的。作为servlet的补充,filter也是很成功的。但是filter并没有被设计用来完成一切事情。事实上,filter的设计限制了filter的用途。每个filter具有下面的限制:

  • Filter可以访问和修改数据。但它只能访问和修改HttpServletRequestHttpServletResponseServletContext等容器级的对象,而不能(或很难)访问应用程序中的状态。所以filter无法实现和应用逻辑密切相关的功能。
  • Filter可以影响执行流程。但它不能改变filter chain的结构和顺序。Filter chain的结构和顺序是由web.xml中定义的。当filter得到控制权以后,它只能选择继续下去,或者立即结束,而没法进行循环、分支、条件判断等更复杂的控制。因此,filter只能用来实现粗粒度的流程控制功能(例如,当用户未获授权时,停止执行filter chain),难以应付更细致的应用程序内的控制需求。
  • Filter与其它filter和servlet之间,除了request和response对象以外,无法共享其它的状态。这既是优点又是缺点。优点是使filter更独立、更通用;缺点是filter与其它filter、servlet之间难以协作,有时甚至会引起无谓的性能损失。

6.1.4. Webx对filter功能的补充

综上所述,一个filter常常做的两件事是:

  • 改变request/response对象(通过HttpServletRequestWrapperHttpServletResponseWrapper);
  • 改变应用执行的流程。

其实,大部分filter只做其中一件事。例如:

  • 页面压缩filter仅仅改变response,并不改变应用的流程。
  • 页面授权filter根据当前请求用户的身份,判定他是否有权限访问当前页面。这个filter会影响应用流程,却不会去改变request和response。

当然也有例外。有一些filter不做上面两件事中任何一件。例如,日志filter仅仅读取request对象并记录日志而已,既不改变request/response,也不影响应用的流程。还有一些filter同时做上面两件事。比如高速缓存页面的filter不仅要修改response,而且当cache被命中时,不再执行下一步的流程,而是直接返回cache中的内容,以提高性能。

Webx框架提供了两个服务,正好吻合了上述两个最常用的filter的功能。

Request Contexts服务 该服务负责访问和修改request和response,但不负责改变应用执行的流程。
Pipeline服务 提供应用执行的流程,但不关心request和response。

虽然这两个服务看起来和filter的功能类似,但是它们远比filter要强大和方便 ── 它们克服了上述filter的几个限制:

  • 和Filter不同,Request Contexts和Pipeline服务可以访问应用内部的状态和资源,效率更高,功能更强。
  • 和Filter不同,Pipeline服务可以定义灵活(但仍然简单)地控制应用的流程 。Pipeline不仅可以控制流程的中断或继续,还可以实现子流程、循环、条件转移、异常处理等更精细的流程控制。Pipeline服务甚至可以运用在非WEB的环境中。
  • 和Filter不同,Request Contexts服务中的每一个环节(Request Context)之间并非完全独立、互不干涉的。每个request context可以访问它所依赖的其它request context中的状态。
时间: 2024-10-06 15:27:04

Filter学习的相关文章

Angular之filter学习

过滤器(filter)正如其名,作用就是接收一个输入,通过某个规则进行处理,然后返回处理后的结果.主要用在数据的格式化上,例如获取一个数组中的子集,对数组中的元素进行排序等.ng内置了一些过滤器,它们是:currency(货币).date(日期).filter(子串匹配).json(格式化json对象).limitTo(限制个数).lowercase(小写).uppercase(大写).number(数字).orderBy(排序).总共九种.除此之外还可以自定义过滤器,这个就强大了,可以满足任何

Java Web学习(35):Filter学习(二)

与Filter相关的接口 FilterConfig接口 getInitParamter():获取初始化参数, getFilterName():获取过滤器名称, getServletContext():获取application, FilterChain接口 doFilter(ServletRequest,ServletResponse):放行,相当于调用了目标Servlet的service()方法. 过滤器的四种拦截方式 1拦截请求REQUEST(默认) 2拦截转发FOWARD 3拦截包含INC

Java Web学习(34):Filter学习(一)

什么是过滤器 生活中的过滤器场景: 什么是Web过滤器 Web过滤器过滤用户请求,但是不处理结果. 过滤器包括:过滤源,过滤规则和过滤结果. 过滤器的概念 过滤器是一个服务器端的组件,它可以截取客户端的请求与响应信息,并对这些信息过滤. 过滤器的工作原理 假设我们访问Web资源时: 1)没有过滤器的情况下: 2)存在过滤器的情况下: 过滤器的工作原理: 过滤器拦截请求和响应,以便查看.提取或以某种方式操作正在客户机和服务器之间交换的数据. 过滤器只能针对用户的请求进行服务器端跳转,不直接返回数据

java web filter 学习(2)

本文主要对filter的基本使用进行了讲解,其中涉及到了 filter是什么 一个filter处理一个jsp 多个filter处理一个jsp filter是什么 Filter 是java下的一种过滤器 ,能实现对java web程序 客户端和服务器端消息的过滤,也就是在服务器段接受request之前,可以预先对request进行处理,或在客户端接受response之前,对response进行处理. Filter的使用非常灵活,是在"链"到客户端和服务器之间的,在需要时可以配置到客户端与

Java Web学习(35):Filter学习(三)

解决项目字符乱码 乱码问题说明:基本上在每个Servlet中都要处理乱码问题,所以应该把这个工作放到过滤器中来完成. 获取请求参数中的乱码问题: POST请求:request.setCharacterEncoding("UTF-8"); GET请求:new String(request.getParamter("xxx").getBytes("ISO-8859-1","UTF-8"); 响应的乱码问题: response.se

JavaWeb-过滤器Filter学习(四)敏感词过滤实例

通过Filter来实现留言板的敏感词过滤- 思路很简单,我们这里的敏感词是直接先放进去的,实际项目中,肯定是存在数据库中.在Filter 过滤器中,我们先拿到用户提交的留言,如果出现了敏感词,我们就用*号来替换. 代码演示: index.jsp: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="htt

JavaWeb-过滤器Filter学习(三)实现用户的自动登录与IP黑名单过滤

实现用户的自动登录: 解决方案: 设置一个全站拦截的过虑器. 在此过虑器中,读取用户带过来的Cookie信息,然后从中读取用户的用户名和密码,自动帮助用户登录. 即可实现自动登录功能. 用Filter验证用户是否已经登录过.已经登录过了,我们就根据他选择的自动登录来选择让他在多久内能自动登录. IP黑名单过滤就很简单了,只要在Filter过滤器防范一下就OK. 在init方法中,我们先把黑名单的IP加载进Set<String> set集合, Set集合有如下特点: Java.util.Hash

JavaWeb-过滤器Filter学习(一)Filter知识点

Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息.自动登录等一些高级功能. Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter.

JavaWeb-过滤器Filter学习(二)设置全站编码与设置页面缓存

以前我们设置servlet的request和response的编码需要在每个servlet都设置,如果Servlet很多,显得很麻烦,现在我们可以用过滤器很简单的实现这个功能. 还有页面缓存,如果我们的网页是静态的,图片和内容基本上很少变化或者不变化的,我们就可以告诉客户端这个页面你缓存多久~以达到节省流量的目的. 设置全站编码: 先写好Filter:CharacterFilter.java: package cn.hncu.pubs; import java.io.IOException; i