为什么需要过滤器?
在项目开发中,经常会涉及到重复代码的实现;如:判断用户是否登录,只有登录的用户才具有操作权限。
解决这类问题有两种方式:
1、抽取重复代码并封装,在用到的地方手动调用。
2、使用过滤器。
过滤器相关API
|-- interface Filter 过滤器核心接口
Void init(filterConfig); 初始化方法,在服务器启动时候执行
Void doFilter(request,response,filterChain); 过滤器拦截的业务处理方法
Void destroy(); 销毁过滤器实例时候调用
|-- interface FilterConfig 获取初始化参数信息
String getInitParameter(java.lang.String name) ; //根据名字获取初始化参数
Enumeration getInitParameterNames() //过去所有初始化参数的名字
|-- interface FilterChain 过滤器链参数;一个个过滤器形成一个执行链;
void doFilter(ServletRequest request, ServletResponse response) ; 执行下一个过滤器或放行
过滤器执行流程
(1)用户访问服务器。
(2)过滤器对servlet请求进行拦截。
(3)先进入过滤器进行过滤处理。
(4)过滤器处理完后,放行;此时请求到达servlet/JSP.
(5)servlet处理。
(6)servlet处理完后,再回到过滤器,最后在由tomcat服务器响应用户;
时序图:
过滤器执行过程测试代码:
1 public class HelloFilter implements Filter{ 2 3 // 创建实例 4 public HelloFilter(){ 5 System.out.println("1. 创建过滤器实例"); 6 } 7 8 @Override 9 public void init(FilterConfig filterConfig) throws ServletException { 10 System.out.println("2. 执行过滤器初始化方法"); 11 12 // 获取过滤器在web.xml中配置的初始化参数 13 String encoding = filterConfig.getInitParameter("encoding"); 14 System.out.println(encoding); 15 16 // 获取过滤器在web.xml中配置的初始化参数 的名称 17 Enumeration<String> enums = filterConfig.getInitParameterNames(); 18 while (enums.hasMoreElements()){ 19 // 获取所有参数名称:encoding、path 20 String name = enums.nextElement(); 21 // 获取名称对应的值 22 String value = filterConfig.getInitParameter(name); 23 System.out.println(name + " " + value); 24 } 25 } 26 27 // 过滤器业务处理方法: 在请求到达servlet之前先进入此方法处理公用的业务逻辑操作 28 @Override 29 public void doFilter(ServletRequest request, ServletResponse response, 30 FilterChain chain) throws IOException, ServletException { 31 System.out.println("3. 执行过滤器业务处理方法"); 32 // 放行 (去到Servlet) 33 // 如果有下一个过滤器,进入下一个过滤器,否则就执行访问servlet 34 chain.doFilter(request, response); 35 36 System.out.println("5. Servlet处理完成,又回到过滤器"); 37 } 38 39 @Override 40 public void destroy() { 41 System.out.println("6. 销毁过滤器实例"); 42 } 43 44 }
使用过滤器处理编码格式
1 // 过滤器业务处理方法:处理的公用的业务逻辑操作 2 @Override 3 public void doFilter(ServletRequest req, ServletResponse res, 4 FilterChain chain) throws IOException, ServletException { 5 6 // 转型 7 final HttpServletRequest request = (HttpServletRequest) req; 8 HttpServletResponse response = (HttpServletResponse) res; 9 10 // 一、处理公用业务 11 request.setCharacterEncoding("UTF-8"); // POST提交有效 12 response.setContentType("text/html;charset=UTF-8"); 13 14 /* 15 * 出现GET中文乱码,是因为在request.getParameter方法内部没有进行提交方式判断并处理。 16 * String name = request.getParameter("userName"); 17 * 18 * 解决:对指定接口的某一个方法进行功能扩展,可以使用代理! 19 * 对request对象(目标对象),创建代理对象! 20 */ 21 HttpServletRequest proxy = (HttpServletRequest) Proxy.newProxyInstance( 22 request.getClass().getClassLoader(), // 指定当前使用的累加载器 23 new Class[]{HttpServletRequest.class}, // 对目标对象实现的接口类型 24 new InvocationHandler() { // 事件处理器 25 @Override 26 public Object invoke(Object proxy, Method method, Object[] args) 27 throws Throwable { 28 // 定义方法返回值 29 Object returnValue = null; 30 // 获取方法名 31 String methodName = method.getName(); 32 // 判断:对getParameter方法进行GET提交中文处理 33 if ("getParameter".equals(methodName)) { 34 35 // 获取请求数据值【 <input type="text" name="userName">】 36 String value = request.getParameter(args[0].toString()); // 调用目标对象的方法 37 38 // 获取提交方式 39 String methodSubmit = request.getMethod(); // 直接调用目标对象的方法 40 41 // 判断如果是GET提交,需要对数据进行处理 (POST提交已经处理过了) 42 if ("GET".equals(methodSubmit)) { 43 if (value != null && !"".equals(value.trim())){ 44 // 处理GET中文 45 value = new String(value.getBytes("ISO8859-1"),"UTF-8"); 46 } 47 } 48 return value; 49 } 50 else { 51 // 执行request对象的其他方法 52 returnValue = method.invoke(request, args); 53 } 54 55 return returnValue; 56 } 57 }); 58 59 // 二、放行 (执行下一个过滤器或者servlet) 60 chain.doFilter(proxy, response); // 传入代理对象 61 }
使用过滤器处理无效数据
1 public class DateFilter implements Filter { 2 3 // 初始化无效数据 4 private List<String> dirtyData; 5 @Override 6 public void init(FilterConfig filterConfig) throws ServletException { 7 // 模拟几个数据 8 dirtyData = new ArrayList<String>(); 9 dirtyData.add("NND"); 10 dirtyData.add("炸使馆"); 11 } 12 13 @Override 14 public void doFilter(ServletRequest req, ServletResponse res, 15 FilterChain chain) throws IOException, ServletException { 16 17 // 转型 18 final HttpServletRequest request = (HttpServletRequest) req; 19 HttpServletResponse response = (HttpServletResponse) res; 20 21 // 一、处理公用业务 22 request.setCharacterEncoding("UTF-8"); // POST提交有效 23 response.setContentType("text/html;charset=UTF-8"); 24 25 HttpServletRequest proxy = (HttpServletRequest) Proxy.newProxyInstance( 26 request.getClass().getClassLoader(), // 指定当前使用的累加载器 27 new Class[]{HttpServletRequest.class}, // 对目标对象实现的接口类型 28 new InvocationHandler() { // 事件处理器 29 @Override 30 public Object invoke(Object proxy, Method method, Object[] args) 31 throws Throwable { 32 // 定义方法返回值 33 Object returnValue = null; 34 // 获取方法名 35 String methodName = method.getName(); 36 // 判断:对getParameter方法进行GET提交中文处理 37 if ("getParameter".equals(methodName)) { 38 39 // 获取请求数据值【 <input type="text" name="userName">】 40 String value = request.getParameter(args[0].toString()); // 调用目标对象的方法 41 42 // 获取提交方式 43 String methodSubmit = request.getMethod(); // 直接调用目标对象的方法 44 45 // 判断如果是GET提交,需要对数据进行处理 (POST提交已经处理过了) 46 if ("GET".equals(methodSubmit)) { 47 if (value != null && !"".equals(value.trim())){ 48 // 处理GET中文 49 value = new String(value.getBytes("ISO8859-1"),"UTF-8"); 50 } 51 } 52 53 // 中文数据已经处理完: 下面进行无效数据过滤 54 //【如何value中出现dirtyData中数据,用****替换】 55 for (String data : dirtyData) { 56 // 判断当前输入数据(value), 是否包含无效数据 57 if (value.contains(data)){ 58 value = value.replace(data, "*****"); 59 } 60 } 61 // 处理完编码、无效数据后的正确数据 62 return value; 63 } 64 else { 65 // 执行request对象的其他方法 66 returnValue = method.invoke(request, args); 67 } 68 69 return returnValue; 70 } 71 }); 72 73 // 二、放行 (执行下一个过滤器或者servlet) 74 chain.doFilter(proxy, response); // 传入代理对象 75 } 76 77 78 79 @Override 80 public void destroy() { 81 82 } 83 }
web.xml文件中的配置
1 <!--1. 编码处理过滤器配置 2 <filter> 3 <filter-name>encoding</filter-name> 4 <filter-class>cn.itcast.a_loginFilter.EncodingFilter</filter-class> 5 </filter> 6 <filter-mapping> 7 <filter-name>encoding</filter-name> 8 <url-pattern>/*</url-pattern> 9 </filter-mapping> 10 --> 11 12 <!-- 2. 无效数据过滤器配置 --> 13 <filter> 14 <filter-name>dataFilter</filter-name> 15 <filter-class>cn.itcast.b_filter_data.DateFilter</filter-class> 16 </filter> 17 <filter-mapping> 18 <filter-name>dataFilter</filter-name> 19 <url-pattern>/*</url-pattern> 20 </filter-mapping>