Spring filter的用法

Springfilter的用法

1.Filter技术是servlet2.3新增加的功能。它能够对Servlet容器的请求和响应对象进行检查和修改。

2.过滤器是JavaEE标准,采用函数回调的方式进行。是在请求进入容器之后,还未进入Servlet之前进行预处理,并且在请求结束返回给前端这之间进行后期处理。

3.Filter本身并不生成请求和响应对象,只是提供过滤功能。

4.Filter能够在Servlet被调用之前检查Request对象,并修改RequestHeader和Request内容;在Servlet被调用之后检查Response对象,修改ResponseHeader和Response的内容。

5.所有的过滤器都必须实现Filter接口

6.web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter

Filter的执行流程:

1.执行第一个过滤器的chain.doFilter()之前的代码-->

2.第二个过滤器的chain.doFilter()之前的代码-->……-->第n个过滤器的chain.doFilter()之前的代码-->

3.所请求servlet的service()方法中的代码-->所请求servlet的doGet()或doPost()方法中的代码-->

4.第n个过滤器的chain.doFilter()之后的代码-->……-->

5.第二个过滤器的chain.doFilter()之后的代码-->第一个过滤器的chain.doFilter()之后的代码。

Filter生命周期的四个阶段

(1)实例化:Web容器在部署Web应用程序时对所有过滤器进行实例化。Web容器回调它的无参构造方法。

(2)初始化:实例化完成之后,马上进行初始化工作。Web容器回调init()方法。

(3)过滤:请求路径匹配过滤器的URL映射时。Web容器回调doFilter()方法--主要的工作方法。

(4)销毁:Web容器在卸载Web应用程序前,Web容器回调destroy()方法。

例子:

1.编写java类实现Filter接口,并实现其doFilter方法。

public class FilterTest implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		String username = filterConfig.getInitParameter("username");
		System.out.println("init username == " + username);

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 转换成实例的请求和响应对象
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;

		System.out.println("doFilter before");
		chain.doFilter(req, resp);
		System.out.println("doFilter after");
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		System.out.println("FilterTest destroy == ");
	}
}

2.在web.xml中配置过滤器(多个filter就是多个复制)

<filter>
	<filter-name>filterTest</filter-name>
	<filter-class>com.proserver.common.controller.Test.filter.FilterTest</filter-class>
	<init-param>
		<param-name>userName</param-name>
		<param-value>HelloWorld</param-value>
	</init-param>
</filter>

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

<filter>
	<filter-name>filterTest3</filter-name>
	<filter-class>com.proserver.common.controller.Test.filter.FilterTest3</filter-class>
	<init-param>
		<param-name>userName</param-name>
		<param-value>HelloWorld</param-value>
	</init-param>
</filter>

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

<filter>
	<filter-name>filterTest2</filter-name>
	<filter-class>com.proserver.common.controller.Test.filter.FilterTest2</filter-class>
	<init-param>
		<param-name>userName</param-name>
		<param-value>HelloWorld</param-value>
	</init-param>
</filter>

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

1.filter定义过滤器的类

2.filter-mapping定义过滤器的的匹配规则(url-pattern匹配规则)

3.init-param为配置参数,可从FilterConfig中得到

4.servlet-name指定过滤器所拦截的Servlet名称。(过滤器规则),<servlet-name>元素给出的Servlet名字必须是在<servlet>元素中声明过的Servlet的名字。

5.url-pattern指定过滤器规则,正则表达式。加了/表示绝对路径http://localhost:8080/,没有加/表示的是相对路径

6.dispatcher指定过滤器所拦截的资源被Servlet容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。(就是请求的来源)

(1)REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。

(2)INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。

(3)FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。

(4)ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

HttpServletRequestWrapper、HttpServletResponseWrapper,HttpSessionWrapper用法

1.用于filter操作请求和回应包信息的

例子:

package com.proserver.common.controller.Test.filter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class WrapperedResponse extends HttpServletResponseWrapper {

	private ByteArrayOutputStream buffer = null;
	private ServletOutputStream out = null;
	private PrintWriter writer = null;

	public WrapperedResponse(HttpServletResponse resp) throws IOException {
		super(resp);
		buffer = new ByteArrayOutputStream();// 真正存储数据的流
		out = new WapperedOutputStream(buffer);
		writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
	}

	/** 重载父类获取outputstream的方法 */
	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		return out;
	}

	/** 重载父类获取writer的方法 */
	@Override
	public PrintWriter getWriter() throws UnsupportedEncodingException {
		return writer;
	}

	/** 重载父类获取flushBuffer的方法 */
	@Override
	public void flushBuffer() throws IOException {
		if (out != null) {
			out.flush();
		}
		if (writer != null) {
			writer.flush();
		}
	}

	@Override
	public void reset() {
		buffer.reset();
	}

	/** 将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据 */
	public byte[] getResponseData() throws IOException {
		flushBuffer();
		return buffer.toByteArray();
	}

	/** 内部类,对ServletOutputStream进行包装 */
	private class WapperedOutputStream extends ServletOutputStream {
		private ByteArrayOutputStream bos = null;

		public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException {
			bos = stream;
		}

		@Override
		public void write(int b) throws IOException {
			bos.write(b);
		}

		@Override
		public void write(byte[] b) throws IOException {
			bos.write(b, 0, b.length);
		}
	}
}
package com.proserver.common.controller.Test.filter;

import java.io.CharArrayWriter;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class ResponseWrapper extends HttpServletResponseWrapper{
	private PrintWriter cachedWriter;
	private CharArrayWriter bufferedWriter;

	public ResponseWrapper(HttpServletResponse response) {
		super(response);
		// 这个是我们保存返回结果的地方
		bufferedWriter = new CharArrayWriter();
		// 这个是包装PrintWriter的,让所有结果通过这个PrintWriter写入到bufferedWriter中
		cachedWriter = new PrintWriter(bufferedWriter);
	}

	@Override
	public PrintWriter getWriter() {
		return cachedWriter;
	}

	/**
	 * 获取原始的HTML页面内容。
	 * @return
	 */
	public String getResult() {
		return bufferedWriter.toString();
	}
}
package com.proserver.common.controller.Test.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FilterTest2 implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		String username = filterConfig.getInitParameter("username");
		System.out.println("FilterTest2 init username == " + username);

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 转换成实例的请求和响应对象
		 HttpServletRequest req = (HttpServletRequest) request;
		 HttpServletResponse resp = (HttpServletResponse) response;

		 System.out.println("begin filter invoke!");
		 WrapperedResponse wrapResponse = new WrapperedResponse((HttpServletResponse)response);

		 chain.doFilter(req, wrapResponse);
		 byte[] data = wrapResponse.getResponseData();
		 System.out.println("原始数据: " + new String(data));

		 String tempData = new String("jack xing xing");
		 ServletOutputStream out = resp.getOutputStream();
		 resp.setContentLength(tempData.getBytes().length);//一定要更改长度
		 out.write(tempData.getBytes());
		 out.flush();
		 System.out.println("end filter invoke!");
	}

	@Override
	public void destroy() {
		System.out.println("FilterTest2 FilterTest destroy == ");
	}
}

http://zhangzhaoaaa.iteye.com/blog/1853787