为什么需要过滤器?
在项目开发中,经常会涉及到重复代码的实现;如:判断用户是否登录,只有登录的用户才具有操作权限。
解决这类问题有两种方式:
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 Enumerationenums = filterConfig.getInitParameterNames();18 while (enums.hasMoreElements()){19 // 获取所有参数名称:encoding、path20 String name = enums.nextElement();21 // 获取名称对应的值22 String value = filterConfig.getInitParameter(name);23 System.out.println(name + "\t" + value);24 }25 }26 27 // 过滤器业务处理方法: 在请求到达servlet之前先进入此方法处理公用的业务逻辑操作28 @Override29 public void doFilter(ServletRequest request, ServletResponse response,30 FilterChain chain) throws IOException, ServletException {31 System.out.println("3. 执行过滤器业务处理方法");32 // 放行 (去到Servlet)33 // 如果有下一个过滤器,进入下一个过滤器,否则就执行访问servlet34 chain.doFilter(request, response);35 36 System.out.println("5. Servlet处理完成,又回到过滤器");37 }38 39 @Override40 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 @Override26 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 // 获取请求数据值【 】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 ListdirtyData; 5 @Override 6 public void init(FilterConfig filterConfig) throws ServletException { 7 // 模拟几个数据 8 dirtyData = new ArrayList (); 9 dirtyData.add("NND");10 dirtyData.add("炸使馆");11 }12 13 @Override14 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 @Override30 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 // 获取请求数据值【 】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 @Override80 public void destroy() {81 82 }83 }
web.xml文件中的配置
1 11 12 1314 17dataFilter 15cn.itcast.b_filter_data.DateFilter 1618 dataFilter 19/* 20