过滤器详解

一、简介

(一)概述

1、Filter,过滤器,用于在servlet之外对request 和response 进行修改。Filter 有一个 FilterChain 的概念,一个FilterChain 包括多个 Filter。客户端请求 request在抵达servlet 之前会经过 FilterChain 里面所有的 Filter,服务器响应 response 从servlet 抵达客户端浏览器之前也会经过 FilterChain 里面所有的 Filter 。过程如图所示:

(二) Filter 的实现

1、实现自定义的 Filter 需要满足一下条件:

1)实现 javax.servlet.Filter 接口,实现其 init、doFilter、destroy 三个方法。

2)实现在web.xml中的配置。

2、javax.servlet.Filter 接口

1) Filter 接口有三个方法:这三个方法反应了  Filter 的生命周期。

①、init:只会在 web 程序加载的时候调用,即启动如tomcat等服务器时调用。一般负责加载配置的参数。

②、destroy :web程序卸载的时候调用。一般负责关闭某些容器等。

③、doFilter:每次客户端请求都会调用一次。Filter 的所有工作基本都集中在该方法中进行。 

[java] view plain copy
 
  1. package servlet.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11. import javax.servlet.http.HttpServletRequest;  
  12.   
  13. import org.apache.log4j.Logger;  
  14. /** 
  15.  *  
  16.  * MyFilter.java 
  17.  * 
  18.  * @title 过滤器 
  19.  * @description 
  20.  * @author SAM-SHO  
  21.  * @Date 2014-9-25 
  22.  */  
  23. public class MyFilter implements Filter {  
  24.   
  25.     private Logger logger = Logger.getLogger(this.getClass());  
  26.       
  27.     public void destroy() {  
  28.   
  29.     }  
  30.   
  31.     public void doFilter(ServletRequest req, ServletResponse resp,  
  32.             FilterChain chain) throws IOException, ServletException {  
  33.           
  34.         HttpServletRequest request = (HttpServletRequest) req;  
  35.           
  36.         String contextPath = request.getContextPath();//上下文路径  
  37.         String servletPath = request.getServletPath();//得到访问的servlet或者jsp的路径  
  38.           
  39.         logger.debug("上下文路径:"+contextPath);  
  40.         logger.debug("访问的servlet或者jsp的路径 : "+servletPath);  
  41.                   
  42.         chain.doFilter(req, resp);  
  43.   
  44.     }  
  45.   
  46.     public void init(FilterConfig filterConfig) throws ServletException {  
  47.   
  48.         String name =  filterConfig.getInitParameter("name");  
  49.         logger.debug("获取过滤器的初始化参数: " + name);  
  50.     }  
  51.   
  52. }  


3、 配置 Filter:每个过滤器需要配置在web.xml中才能生效,一个Filter需要配置<filter> 和 <filter-mapping>标签。

1)<filter>  :配置 Filter 名称,实现类以及初始化参数。可以同时配置多个初始化参数。

2)<filter-mapping> :配置什么规则下使用这个Filter 。

①、<url-pattern> :配置url的规则,可以配置多个,也可以使用通配符(*)。例如 /jsp/* 适用于本ContextPath下以“/jsp/ ”开头的所有servlet路径, *.do 适用于所有以“ .do”结尾的servlet路径。

②、<dispatcher> :配置到达servlet的方式,可以同时配置多个。有四种取值:REQUEST、FORWARD、ERROR、INCLUDE。如果没有配置,则默认为REQUEST。它们的区别是:

# REQUEST :表示仅当直接请求servlet时才生效。

# FORWARD :表示仅当某servlet通过forward转发到该servlet时才生效。

# INCLUDE :Jsp中可以通过<jsp:include/>请求某servlet, 只有这种情况才有效。

# ERROR :Jsp中可以通过<%@page errorPage="error.jsp" %>指定错误处理页面,仅在这种情况下才生效。

③、<url-pattern>和<dispatcher> 是且的关系,只有满足<url-pattern>的条件,且满足<dispatcher>的条件,该Filter 才能生效。

[html] view plain copy
 
  1. <!-- 过滤器配置 -->  
  2.     <filter>  
  3.         <filter-name>MyFilter</filter-name>  
  4.         <filter-class>servlet.filter.MyFilter</filter-class>  
  5.         <init-param>  
  6.             <param-name>name</param-name>  
  7.             <param-value>Sam-Sho</param-value>  
  8.         </init-param>  
  9.     </filter>  
  10.     <filter-mapping>  
  11.         <filter-name>MyFilter</filter-name>  
  12.         <url-pattern>/jsp/*</url-pattern>  
  13.         <url-pattern>*.do</url-pattern>  
  14.   
  15.         <dispatcher>REQUEST</dispatcher>  
  16.         <dispatcher>FORWARD</dispatcher>  
  17.     </filter-mapping>  


3)总结:一个Web程序可以配置多个Filter ,访问有先后顺序,<filter-mapping> 配置在前面的Filter 执行要早于配置在后面的Filter 。

二、常用 Filter 

(一)字符编码的 Filter 

1、字符编码的 Filter 几乎每个项目都会用到。代码如下:

[java] view plain copy
 
  1. package servlet.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11.   
  12. /** 
  13.  *  
  14.  * CharacterEncodingFilter.java 
  15.  *  
  16.  * @title 编码过滤器 
  17.  * @description 
  18.  * @author SAM-SHO 
  19.  * @Date 2014-10-12 
  20.  */  
  21. public class CharacterEncodingFilter implements Filter {  
  22.   
  23.     private String characterEncoding;  
  24.     private boolean enabled;//是否启用  
  25.   
  26.     public void init(FilterConfig config) throws ServletException {  
  27.   
  28.         // 获取配置好的参数,  
  29.         characterEncoding = config.getInitParameter("characterEncoding");//配置好的字符编码  
  30.         enabled = "true".equalsIgnoreCase(config.getInitParameter("enabled"));//是否启用  
  31.     }  
  32.   
  33.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {  
  34.   
  35.         //设置字符编码  
  36.         if (enabled && characterEncoding != null) {  
  37.             request.setCharacterEncoding(characterEncoding);  
  38.             response.setCharacterEncoding(characterEncoding);  
  39.         }  
  40.   
  41.         chain.doFilter(request, response);//调用下一个过滤器  
  42.     }  
  43.   
  44.     public void destroy() {  
  45.         characterEncoding = null;//注销的时候,设为空  
  46.     }  
  47. }  


2、web.xml 配置如下:

[java] view plain copy
 
  1. <!-- 编码过滤器 -->  
  2. <filter>  
  3.     <filter-name>CharacterEncodingFilter</filter-name>  
  4.     <filter-class>servlet.filter.CharacterEncodingFilter</filter-class>  
  5.     <init-param>  
  6.         <param-name>characterEncoding</param-name>  
  7.         <param-value>UTF-8</param-value>  
  8.     </init-param>  
  9.     <init-param>  
  10.         <param-name>enabled</param-name>  
  11.         <param-value>true</param-value>  
  12.     </init-param>  
  13. </filter>  
  14. <filter-mapping>  
  15.     <filter-name>CharacterEncodingFilter</filter-name>  
  16.     <url-pattern>/*</url-pattern>  
  17. </filter-mapping>  



(二)防盗链 Filter 

1、防盗链需要使用到请求头 Referer ,该 Filter  的配置仅对 /images/ 和 /upload/images/ 下面的所有资源有效。代码如下:

[java] view plain copy
 
  1. package servlet.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13.   
  14. /** 
  15.  *  
  16.  * RefererFilter.java 
  17.  *  
  18.  * @title 责任链过滤器 
  19.  * @description 
  20.  * @author SAM-SHO 
  21.  * @Date 2014-12-9 
  22.  */  
  23. public class RefererFilter implements Filter {  
  24.   
  25.     public void init(FilterConfig config) throws ServletException {  
  26.     }  
  27.   
  28.     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {  
  29.   
  30.         // 必须的  
  31.         HttpServletRequest request = (HttpServletRequest) req;  
  32.         HttpServletResponse response = (HttpServletResponse) res;  
  33.   
  34.         // 禁止缓存  
  35.         response.setHeader("Cache-Control", "no-store");  
  36.         response.setHeader("Pragrma", "no-cache");  
  37.         response.setDateHeader("Expires", 0);  
  38.   
  39.         // 链接来源地址,通过获取请求头 referer 得到  
  40.         String referer = request.getHeader("referer");  
  41.         System.out.println("获取的来源--->: " + referer);  
  42.   
  43.         if (referer == null || !referer.contains(request.getServerName())) {//本站点访问,则有效  
  44.   
  45.             /** 
  46.              * 如果 链接地址来自其他网站,则返回错误图片 
  47.              */  
  48.             request.getRequestDispatcher("/error.gif").forward(request, response);  
  49.   
  50.         } else {  
  51.   
  52.             /** 
  53.              * 图片正常显示 
  54.              */  
  55.             chain.doFilter(request, response);  
  56.         }  
  57.   
  58.     }  
  59.   
  60.     public void destroy() {  
  61.     }  
  62. }  



2、配置如下:

[java] view plain copy
 
  1. <!--责任链过滤器  -->  
  2. <filter>  
  3.     <filter-name>RefererFilter</filter-name>  
  4.     <filter-class>servlet.filter.RefererFilter</filter-class>  
  5. </filter>  
  6. <filter-mapping>  
  7.     <filter-name>RefererFilter</filter-name>  
  8.     <url-pattern>/images/*</url-pattern>  
  9.     <url-pattern>/upload/images/*</url-pattern>  
  10. </filter-mapping>  



(三)权限校验 Filter 

1、为了方便,权限配置在文件中:

[java] view plain copy
 
  1. package servlet.filter;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.io.IOException;  
  5. import java.util.Properties;  
  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.ServletRequest;  
  12. import javax.servlet.ServletResponse;  
  13. import javax.servlet.http.HttpServletRequest;  
  14.   
  15.   
  16. public class PrivilegeFilter implements Filter {  
  17.   
  18.     private Properties pp = new Properties();//读取配置文件  
  19.   
  20.     public void init(FilterConfig config) throws ServletException {  
  21.   
  22.         // 从 初始化参数 中获取权 限配置文件 的位置  
  23.         String file = config.getInitParameter("file");  
  24.         String realPath = config.getServletContext().getRealPath(file);  
  25.         try {  
  26.             pp.load(new FileInputStream(realPath));  
  27.         } catch (Exception e) {  
  28.             config.getServletContext().log("读取权限控制文件失败。", e);  
  29.         }  
  30.     }  
  31.   
  32.     public void doFilter(ServletRequest req, ServletResponse res,  
  33.             FilterChain chain) throws IOException, ServletException {  
  34.   
  35.         HttpServletRequest request = (HttpServletRequest) req;  
  36.   
  37.         // 获取访问的路径,例如:admin.jsp  
  38.         String requestURI = request.getRequestURI().replace(  
  39.                 request.getContextPath() + "/", "");  
  40.   
  41.         // 获取 action 参数,例如:add  
  42.         String action = req.getParameter("action");  
  43.         action = action == null ? "" : action;  
  44.   
  45.         // 拼接成 URI。例如:log.do?action=list  
  46.         String uri = requestURI + "?action=" + action;  
  47.   
  48.         // 从 session 中获取用户权限角色。  
  49.         String role = (String) request.getSession(true).getAttribute("role");  
  50.         role = role == null ? "guest" : role;  
  51.   
  52.         boolean authentificated = false;  
  53.         // 开始检查该用户角色是否有权限访问 uri  
  54.         for (Object obj : pp.keySet()) {  
  55.             String key = ((String) obj);  
  56.             // 使用正则表达式验证 需要将 ? . 替换一下,并将通配符 * 处理一下  
  57.             if (uri.matches(key.replace("?", "\?").replace(".", "\.")  
  58.                     .replace("*", ".*"))) {  
  59.                 // 如果 role 匹配  
  60.                 if (role.equals(pp.get(key))) {  
  61.                     authentificated = true;  
  62.                     break;  
  63.                 }  
  64.             }  
  65.         }  
  66.         if (!authentificated) {  
  67.             System.out.println("您无权访问该页面。请以合适的身份登陆后查看。");  
  68.         }  
  69.         // 继续运行  
  70.         chain.doFilter(req, res);  
  71.     }  
  72.   
  73.     public void destroy() {  
  74.         pp = null;  
  75.     }  
  76. }  


2、web.xml配置如下:

[html] view plain copy
 
  1. <!-- 权限过滤器 -->  
  2. <filter>  
  3.     <filter-name>privilegeFilter</filter-name>  
  4.     <filter-class>  
  5.         servlet.filter.PrivilegeFilter  
  6.     </filter-class>  
  7.     <init-param>  
  8.         <param-name>file</param-name>  
  9.         <param-value>/WEB-INF/classes/privilege.properties</param-value>  
  10.     </init-param>  
  11. </filter>  
  12. <filter-mapping>  
  13.     <filter-name>privilegeFilter</filter-name>  
  14.     <url-pattern>*.do</url-pattern>  
  15. </filter-mapping>  

3、权限配置如下:

[html] view plain copy
 
  1. # Privilege Settings  
  2.   
  3. admin.do?action=*      =   administrator  
  4. log.do?action=*        =   administrator  
  5.   
  6. list.do?action=add     =   member  
  7. list.do?action=delete  =   member  
  8. list.do?action=save    =   member  
  9.   
  10. list.do?action=view    =   guest  
  11. list.do?action=list    =   guest  

(四)GZIP 压缩 Filter 

1、使用servlet 的对响应内容进行压缩:

[java] view plain copy
 
  1. private void GZipTest(HttpServletResponse response) throws IOException {  
  2.     //实现压缩  
  3.     String tDate = "准备被压缩的数据";  
  4.     System.out.println("压缩前的数据大小:  "+tDate.getBytes().length);  
  5.       
  6.     ByteArrayOutputStream bout = new ByteArrayOutputStream();  
  7.     GZIPOutputStream gout = new GZIPOutputStream(bout);  
  8.     gout.write(tDate.getBytes());  
  9.     gout.flush();  
  10.     gout.finish();  
  11.     gout.close();//写到字节数组流中  
  12.       
  13.     byte[] gzip = bout.toByteArray();//得到压缩后的数据  
  14.     System.out.println("压缩后的数据大小:  "+gzip.length);  
  15.       
  16.     // 通知浏览器数据采用压缩格式  
  17.     response.setHeader("Content-Encoding", "gzip");//压缩格式  
  18.     response.setHeader("Content-Length",gzip.length+"" );//压缩数据的长度  
  19.     response.getOutputStream().write(gzip);  
  20. }  



2、使用过滤器代码:

1)GZIP 压缩的核心是 JDK 自带的压缩数据的类,GZIPOutputStream 。

2)响应头:Content-Encoding 和 Content-Length 。

3)GZipResponseWrapper 类为自定义的 Response 类,内部对输出的内容进行 GZIP 的压缩。

3、代码如下:

[java] view plain copy
 
  1. package servlet.filter.gzip;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13.   
  14. /** 
  15.  *  
  16.  * GZipFilter.java 
  17.  *  
  18.  * @title 压缩过滤器 
  19.  * @description 
  20.  * @author SAM-SHO 
  21.  * @Date 2014-12-9 
  22.  */  
  23. public class GZipFilter implements Filter {  
  24.   
  25.     public void destroy() {  
  26.     }  
  27.   
  28.     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {  
  29.   
  30.         HttpServletRequest request = (HttpServletRequest) req;  
  31.         HttpServletResponse response = (HttpServletResponse) res;  
  32.   
  33.         //获取浏览器支持的压缩格式  
  34.         String acceptEncoding = request.getHeader("Accept-Encoding");  
  35.         System.out.println("Accept-Encoding: " + acceptEncoding);  
  36.   
  37.         if (acceptEncoding != null && acceptEncoding.toLowerCase().indexOf("gzip") != -1) {  
  38.   
  39.             // 如果客户浏览器支持 GZIP 格式, 则使用 GZIP 压缩数据  
  40.             GZipResponseWrapper gzipResponse = new GZipResponseWrapper(response);  
  41.             chain.doFilter(request, gzipResponse);  
  42.   
  43.             // 输出压缩数据  
  44.             gzipResponse.getOutputStream();  
  45.             gzipResponse.finishResponse();  
  46.   
  47.         } else {  
  48.             // 否则, 不压缩  
  49.             chain.doFilter(request, response);  
  50.         }  
  51.     }  
  52.   
  53.     public void init(FilterConfig arg0) throws ServletException {  
  54.     }  
  55. }  
[java] view plain copy
 
  1. package servlet.filter.gzip;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.OutputStreamWriter;  
  5. import java.io.PrintWriter;  
  6.   
  7. import javax.servlet.ServletOutputStream;  
  8. import javax.servlet.http.HttpServletResponse;  
  9. import javax.servlet.http.HttpServletResponseWrapper;  
  10.   
  11. /** 
  12.  *  
  13.  * GZipResponseWrapper.java 
  14.  * 
  15.  * @title 封装的Response ,不会真正输出到客户端 
  16.  * 继承 HttpServletResponseWrapper,其实现了 HttpServletResponse 接口 
  17.  * @description 
  18.  * @author SAM-SHO  
  19.  * @Date 2014-12-9 
  20.  */  
  21. public class GZipResponseWrapper extends HttpServletResponseWrapper {  
  22.   
  23.     // 默认的 response  
  24.     private HttpServletResponse response;  
  25.   
  26.     // 自定义的 outputStream, 执行close()的时候对数据压缩,并输出  
  27.     private GZipOutputStream gzipOutputStream;  
  28.   
  29.     // 自定义 printWriter,将内容输出到 GZipOutputStream 中  
  30.     private PrintWriter writer;  
  31.   
  32.     public GZipResponseWrapper(HttpServletResponse response) throws IOException {  
  33.         super(response);  
  34.         this.response = response;  
  35.     }  
  36.     @Override  
  37.     public ServletOutputStream getOutputStream() throws IOException {  
  38.         if (gzipOutputStream == null)  
  39.             gzipOutputStream = new GZipOutputStream(response);  
  40.         return gzipOutputStream;  
  41.     }  
  42.     @Override  
  43.     public PrintWriter getWriter() throws IOException {  
  44.         if (writer == null)  
  45.             writer = new PrintWriter(new OutputStreamWriter(  
  46.                     new GZipOutputStream(response), "UTF-8"));  
  47.         return writer;  
  48.     }  
  49.   
  50.     // 压缩后数据长度会发生变化 因此将该方法内容置空  
  51.     @Override  
  52.     public void setContentLength(int contentLength) {  
  53.     }  
  54.     @Override  
  55.     public void flushBuffer() throws IOException {  
  56.         gzipOutputStream.flush();  
  57.     }  
  58.   
  59.     public void finishResponse() throws IOException {  
  60.         if (gzipOutputStream != null)  
  61.             gzipOutputStream.close();  
  62.         if (writer != null)  
  63.             writer.close();  
  64.     }  
  65. }  
[java] view plain copy
 
  1. package servlet.filter.gzip;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.IOException;  
  5. import java.util.zip.GZIPOutputStream;  
  6.   
  7. import javax.servlet.ServletOutputStream;  
  8. import javax.servlet.http.HttpServletResponse;  
  9.   
  10. /** 
  11.  *  
  12.  * GZipOutputStream.java 
  13.  * 
  14.  * @title 自定义的压缩流,内部调用JDK自带的压缩流 
  15.  * @description 
  16.  * @author SAM-SHO  
  17.  * @Date 2014-12-9 
  18.  */  
  19. public class GZipOutputStream extends ServletOutputStream {  
  20.   
  21.     private HttpServletResponse response;  
  22.   
  23.     // JDK 自带的压缩数据的类  
  24.     private GZIPOutputStream gzipOutputStream;  
  25.   
  26.     // 将压缩后的数据存放到 ByteArrayOutputStream 对象中  
  27.     private ByteArrayOutputStream byteArrayOutputStream;  
  28.   
  29.     public GZipOutputStream(HttpServletResponse response) throws IOException {  
  30.         this.response = response;  
  31.         byteArrayOutputStream = new ByteArrayOutputStream();  
  32.         gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);  
  33.     }  
  34.     @Override  
  35.     public void write(int b) throws IOException {  
  36.         gzipOutputStream.write(b);  
  37.     }  
  38.     @Override  
  39.     public void close() throws IOException {  
  40.   
  41.         // 压缩完毕 一定要调用该方法  
  42.         gzipOutputStream.finish();  
  43.   
  44.         // 将压缩后的数据输出到客户端  
  45.         byte[] content = byteArrayOutputStream.toByteArray();  
  46.   
  47.         // 设定压缩方式为 GZIP, 客户端浏览器会自动将数据解压  
  48.         response.addHeader("Content-Encoding", "gzip");  
  49.         response.addHeader("Content-Length", Integer.toString(content.length));  
  50.   
  51.         // 输出  
  52.         ServletOutputStream out = response.getOutputStream();  
  53.         out.write(content);  
  54.         out.close();  
  55.     }  
  56.   
  57.     @Override  
  58.     public void flush() throws IOException {  
  59.         gzipOutputStream.flush();  
  60.     }  
  61.     @Override  
  62.     public void write(byte[] b, int off, int len) throws IOException {  
  63.         gzipOutputStream.write(b, off, len);  
  64.     }  
  65.     @Override  
  66.     public void write(byte[] b) throws IOException {  
  67.         gzipOutputStream.write(b);  
  68.     }  
  69. }  
[html] view plain copy
 
  1. <!-- 压缩过滤器 -->  
  2. <filter>  
  3.     <filter-name>gzipFilter</filter-name>  
  4.     <filter-class>servlet.filter.gzip.GZipFilter</filter-class>  
  5. </filter>  
  6. <filter-mapping>  
  7.     <filter-name>gzipFilter</filter-name>  
  8.     <url-pattern>/*</url-pattern>  
  9. </filter-mapping>  



(四)文件上传 Filter 

1、上传文件,修改<form> 标签的 enctype 设置为 “multipart/form-data” 。这样就可以通过获取请求头 Content-type 判断是否为文件上传。

2、使用 commons-fileupload-1.2.1.jar 实现上传。

[java] view plain copy
 
  1. package servlet.filter.upload;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11. import javax.servlet.http.HttpServletRequest;  
  12.   
  13. /** 
  14.  *  
  15.  * UploadFilter.java 
  16.  * 
  17.  * @title 文件上传 Filter  
  18.  * @description 
  19.  * @author SAM-SHO  
  20.  * @Date 2014-12-9 
  21.  */  
  22. public class UploadFilter implements Filter {  
  23.   
  24.     public void destroy() {  
  25.   
  26.     }  
  27.   
  28.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {  
  29.   
  30.         UploadRequestWrapper uploadRequest = new UploadRequestWrapper((HttpServletRequest) request);  
  31.   
  32.         chain.doFilter(uploadRequest, response);  
  33.   
  34.     }  
  35.   
  36.     public void init(FilterConfig filterConfig) throws ServletException {  
  37.   
  38.     }  
  39.   
  40. }  
[java] view plain copy
 
  1. package servlet.filter.upload;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.OutputStream;  
  6. import java.util.HashMap;  
  7. import java.util.Iterator;  
  8. import java.util.List;  
  9. import java.util.Map;  
  10.   
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletRequestWrapper;  
  13.   
  14. import org.apache.commons.fileupload.DiskFileUpload;  
  15. import org.apache.commons.fileupload.FileItem;  
  16.   
  17. /** 
  18.  *  
  19.  * UploadRequestWrapper.java 
  20.  *  
  21.  * @title 文件上传自定义Request 
  22.  * @description 
  23.  * @author SAM-SHO 
  24.  * @Date 2014-12-9 
  25.  */  
  26. public class UploadRequestWrapper extends HttpServletRequestWrapper {  
  27.   
  28.     private static final String MULTIPART_HEADER = "Content-type";  
  29.   
  30.     // 是否是上传文件  
  31.     private boolean multipart;  
  32.   
  33.     // map,保存所有的域  
  34.     private Map<String, Object> params = new HashMap<String, Object>();  
  35.   
  36.     @SuppressWarnings("all")  
  37.     public UploadRequestWrapper(HttpServletRequest request) {  
  38.   
  39.         super(request);  
  40.   
  41.         // 判断是否为上传文件  
  42.         multipart = request.getHeader(MULTIPART_HEADER) != null   
  43.                     && request.getHeader(MULTIPART_HEADER).startsWith("multipart/form-data");  
  44.   
  45.         //是文件上传  
  46.         if (multipart) {  
  47.   
  48.             try {  
  49.                 // 使用apache的工具解析  
  50.                 DiskFileUpload upload = new DiskFileUpload();//代替 DiskFileUpload   
  51.                 upload.setHeaderEncoding("utf8");  
  52.   
  53.                 // 解析,获得所有的文本域与文件域  
  54.                 List<FileItem> fileItems = upload.parseRequest(request);  
  55.   
  56.                 for (Iterator<FileItem> it = fileItems.iterator(); it.hasNext();) {  
  57.   
  58.                     // 遍历  
  59.                     FileItem item = it.next();  
  60.                     if (item.isFormField()) {  
  61.   
  62.                         // 如果是文本域,直接放到map里  
  63.                         params.put(item.getFieldName(), item.getString("utf8"));  
  64.   
  65.                     } else {  
  66.   
  67.                         // 否则,为文件,先获取文件名称  
  68.                         String filename = item.getName().replace("\", "/");  
  69.                         filename = filename.substring(filename.lastIndexOf("/") + 1);  
  70.   
  71.                         // 保存到系统临时文件夹中  
  72.                         File file = new File(System.getProperty("java.io.tmpdir"), filename);  
  73.   
  74.                         // 保存文件内容  
  75.                         OutputStream ous = new FileOutputStream(file);  
  76.                         ous.write(item.get());  
  77.                         ous.close();  
  78.   
  79.                         // 放到map中  
  80.                         params.put(item.getFieldName(), file);  
  81.                     }  
  82.                 }  
  83.   
  84.             } catch (Exception e) {  
  85.                 e.printStackTrace();  
  86.             }  
  87.         }  
  88.     }  
  89.   
  90.     @Override  
  91.     public Object getAttribute(String name) {  
  92.   
  93.         // 如果为上传文件,则从map中取值  
  94.         if (multipart && params.containsKey(name)) {  
  95.             return params.get(name);  
  96.         }  
  97.         return super.getAttribute(name);  
  98.     }  
  99.   
  100.     @Override  
  101.     public String getParameter(String name) {  
  102.   
  103.         // 如果为上传文件,则从map中取值  
  104.         if (multipart && params.containsKey(name)) {  
  105.             return params.get(name).toString();  
  106.         }  
  107.         return super.getParameter(name);  
  108.     }  
  109.   
  110.     public static void main(String[] args) {  
  111.   
  112.         System.out.println(System.getProperties().toString().replace(", ", " "));  
  113.   
  114.     }  
  115.   
  116. }  
[html] view plain copy
 
    1. <!--  文件上传 Filter -->  
    2. <filter>  
    3.     <filter-name>uploadFilter</filter-name>  
    4.     <filter-class>servlet.filter.upload.UploadFilter</filter-class>  
    5. </filter>  
    6. <filter-mapping>  
    7.     <filter-name>uploadFilter</filter-name>  
    8.     <url-pattern>/*</url-pattern>  
    9. </filter-mapping>  
原文地址:https://www.cnblogs.com/KingIceMou/p/7808870.html