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