J2EE进阶之过滤器Filter 二十一

xiaoxiao2021-02-28  91

过滤器Filter

一、过滤器是什么?有什么用?

过滤器是什么?

  过滤器是一个可以对请求相应进行拦截的程序。

作用:

  拦截一些信息,比如请求参数有相关不符合请求的。。。

二、过滤器的编码步骤

新建类,实现filter接口,会有三个为实现的方法,destroy,init,doFilter。在doFilter中编写逻辑。之后利用chain.doFilter(request,response)方法放行。 在xml中配置过滤器。

写个demo测试下:

Filter

public class FilterDemo1 implements Filter { public void init(FilterConfig filterConfig) throws ServletException { System.out.println("初始化了"); } //针对过滤范围内的资源的每次访问都会执行该方法,由服务器调用 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("FilterDemo1执行前"); chain.doFilter(request, response);//放行。让下一个执行 System.out.println("FilterDemo1执行后"); } public void destroy() { System.out.println("销毁了"); } }

再写一个Servlet

public class ServletDemo1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("ServletDemo1执行了"); }

配置xml文件

<filter> <filter-name>FilterDemo1</filter-name> <filter-class>wsj.filter1.FilterDemo1</filter-class> </filter> <filter-mapping> <!-- 过滤器过滤资源 --> <filter-name>FilterDemo1</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

打印输出:

总结: 你会发现在运行Servlet之前走了一遍过滤器,然后Servlet之后再次走了一遍过滤器。。注意:再次走过滤器是走了chain.doFilter(request, response);之后的代码。

三、过滤器的执行过程(生命周期)

生命周期

诞生:应用加载时(服务器开启时)就完成实例化,并由服务器调用init初始化方法。

走的Filter的init方法

活着:应用活着他就活着 死亡:应用被卸载时,就死亡,并由服务器调用destory方法。 走Destory方法:

在控制台输入指令:

然后代码就会走销毁方法:

四、串联过滤器

串联过滤器是指多个过滤器多个过滤器多某些资源进行过滤。编写多个过滤器,在xml文件中配置多个过滤器。执行顺序是先配置的过滤器先执行

写个demo2

public class FilterDemo2 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("FilterDemo2执行前"); chain.doFilter(request, response);//放行。让下一个执行 System.out.println("FilterDemo2执行后"); }

整个过程:

五、过滤器的简单案例:

1解决全站中文乱码问题。除了GET请求方式

public class SetCharacterEncodingFilter implements Filter { private FilterConfig filterConfig;//代表者过滤器的参数配置 public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //参数不存在,返回null String encoding = filterConfig.getInitParameter("encoding"); //给出默认编码 if(encoding == null){ encoding = "UTF-8"; } request.setCharacterEncoding(encoding);//解决POST请求参数的中文编码 response.setCharacterEncoding(encoding);//更改输出字符流的编码 response.setContentType("text/html;charset="+encoding);//告知客户端使用字符编码 chain.doFilter(request, response); } public void destroy() { } }

xml配置

<filter> <!-- POST请求和响应的编码过滤器 --> <filter-name>SetCharacterEncodingFilter</filter-name> <filter-class>com.itheima.filter.SetCharacterEncodingFilter</filter-class> <!-- 过滤器参数配置 --> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>SetCharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

分别控制html、css、js的静态资源的缓存时间

public class StaticResourcesNeedCacheFilter implements Filter { private FilterConfig filterConfig; public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request; HttpServletResponse response; try{ request = (HttpServletRequest)req; response = (HttpServletResponse)resp; }catch(Exception e){ throw new RuntimeException("non-http request or response"); } long time = 0;//缓存时间的偏移量 //根据用户访问的资源,获取参数的值,从而设置缓存的时间 String uri = request.getRequestURI();// String resourceType = uri.substring(uri.lastIndexOf(".")+1);// html // if("html".equals(resourceType)){ // String value = filterConfig.getInitParameter("html");//得到配置的html的缓存时间,单位是小时 // time = Long.parseLong(value)*60*60*1000; // } // // if("css".equals(resourceType)){ // String value = filterConfig.getInitParameter("css");//得到配置的html的缓存时间,单位是小时 // time = Long.parseLong(value)*60*60*1000; // } // if("js".equals(resourceType)){ // String value = filterConfig.getInitParameter("js");//得到配置的html的缓存时间,单位是小时 // time = Long.parseLong(value)*60*60*1000; // } String value = filterConfig.getInitParameter(resourceType); if(value!=null){ time = Long.parseLong(value)*60*60*1000; } response.setDateHeader("Expires", System.currentTimeMillis()+time); chain.doFilter(request, response); } public void destroy() { } }

xml配置

<!-- 控制静态资源的缓存时间 --> <filter> <filter-name>StaticResourcesNeedCacheFilter</filter-name> <filter-class>com.itheima.filter.StaticResourcesNeedCacheFilter</filter-class> <init-param> <param-name>html</param-name> <param-value>1</param-value><!-- 单位是小时 --> </init-param> <init-param> <param-name>css</param-name> <param-value>2</param-value><!-- 单位是小时 --> </init-param> <init-param> <param-name>js</param-name> <param-value>3</param-value><!-- 单位是小时 --> </init-param> </filter> <filter-mapping> <filter-name>StaticResourcesNeedCacheFilter</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> <filter-mapping> <filter-name>StaticResourcesNeedCacheFilter</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping> <filter-mapping> <filter-name>StaticResourcesNeedCacheFilter</filter-name> <url-pattern>*.css</url-pattern> </filter-mapping>

不缓存

public class DynamicResourcesNoCacheFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request; HttpServletResponse response; try{ request = (HttpServletRequest)req; response = (HttpServletResponse)resp; }catch(Exception e){ throw new RuntimeException("non-http request or response"); } response.setHeader("Expires", "-1"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); chain.doFilter(request, response); } public void destroy() { } }

xml配置

<!-- 控制动态资源不要缓存 --> <filter> <filter-name>DynamicResourcesNoCacheFilter</filter-name> <filter-class>com.itheima.filter.DynamicResourcesNoCacheFilter</filter-class> </filter> <filter-mapping> <filter-name>DynamicResourcesNoCacheFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>DynamicResourcesNoCacheFilter</filter-name> <url-pattern>/servlet/*</url-pattern> </filter-mapping>

六、过滤器的高级配置

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

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

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

ERROR:

以上都会出现不会过滤的情况

设置方式:

<filter-mapping> <filter-name>FilterDemo1</filter-name> <url-pattern>/*</url-pattern> <!-- 如果一个dispatcher都不写:默认是REQUEST --> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>

Gzip压缩

1 import java.io.ByteArrayOutputStream; 2 import java.io.IOException; 3 import java.io.OutputStreamWriter; 4 import java.io.PrintWriter; 5 import java.util.zip.GZIPOutputStream; 6 7 import javax.servlet.Filter; 8 import javax.servlet.FilterChain; 9 import javax.servlet.FilterConfig; 10 import javax.servlet.ServletException; 11 import javax.servlet.ServletOutputStream; 12 import javax.servlet.ServletRequest; 13 import javax.servlet.ServletResponse; 14 import javax.servlet.http.HttpServletRequest; 15 import javax.servlet.http.HttpServletResponse; 16 import javax.servlet.http.HttpServletResponseWrapper; 17 18 public class GzipFilter implements Filter { 19 20 public void init(FilterConfig filterConfig) throws ServletException { 21 22 } 23 24 public void doFilter(ServletRequest req, ServletResponse resp, 25 FilterChain chain) throws IOException, ServletException { 26 HttpServletRequest request; 27 HttpServletResponse response; 28 29 try { 30 request = (HttpServletRequest) req; 31 response = (HttpServletResponse) resp; 32 } catch (ClassCastException e) { 33 throw new ServletException("non-HTTP request or response"); 34 } 35 36 GzipHttpServletResponse mresponse = new GzipHttpServletResponse(response); 37 chain.doFilter(request, mresponse); 38 //在此处完成压缩 39 byte b[] =mresponse.getBytes();//得到原来要输出的数据是关键 40 System.out.println("数据原来大小:"+b.length); 41 42 ByteArrayOutputStream baos = new ByteArrayOutputStream();// 带有缓存的字节内存输出流 43 GZIPOutputStream gout = new GZIPOutputStream(baos); 44 gout.write(b); 45 gout.close();//数据用gzip压缩到了baos中 46 47 b = baos.toByteArray();//取出的压缩后的字节 48 System.out.println("数据压缩后的大小:"+b.length); 49 50 //告知客户端编码方式 51 response.setHeader("Content-Encoding", "gzip"); 52 response.setContentLength(b.length);//告知正文的长度 53 54 ServletOutputStream sos = response.getOutputStream(); 55 sos.write(b); 56 57 } 58 59 public void destroy() { 60 61 } 62 63 } 64 class GzipHttpServletResponse extends HttpServletResponseWrapper{ 65 private ByteArrayOutputStream baos = new ByteArrayOutputStream();//临时仓库,存放截获的原始数据 66 private PrintWriter pw; 67 public GzipHttpServletResponse(HttpServletResponse response){ 68 super(response); 69 } 70 //截获原来的数据:字节流 71 public ServletOutputStream getOutputStream() throws IOException { 72 return new MyServletOutputStream(baos); 73 } 74 //截获原来的数据:字符流 75 public PrintWriter getWriter() throws IOException { 76 pw = new PrintWriter(new OutputStreamWriter(baos, super.getCharacterEncoding()));//字符流--->字节流:查码表。 77 return pw; 78 } 79 //返回原始的数据 80 public byte[] getBytes(){ 81 try { 82 if(pw!=null){ 83 pw.close(); 84 } 85 baos.flush(); 86 } catch (IOException e) { 87 e.printStackTrace(); 88 } 89 return baos.toByteArray(); 90 } 91 } 92 class MyServletOutputStream extends ServletOutputStream{ 93 private ByteArrayOutputStream baos; 94 public MyServletOutputStream(ByteArrayOutputStream baos){ 95 this.baos = baos; 96 } 97 public void write(int b) throws IOException { 98 baos.write(b); 99 } 100 101 }

压缩结果:

转载请注明原文地址: https://www.6miu.com/read-59120.html

最新回复(0)