Filter过滤器

一、Filter 过滤器概述

  1. Filter是JavaEE三大核心技术(Servlet 、 Filter 、 Listener)之一
  2. FIlter作用是拦截对资源的访问 , 拦截下来后可以控制是否允许通过 , 或者在允许通过前后做一些额外的操作 。
  3. 所谓的拦截其实就是对代表请求的request、对象和代表 响应的response对象拦截下来 , 进行控制
  4. 一个过滤器可能拦截多个资源 , 一个资源也可能被多个过滤器拦截
  5. 这种多个拦截器拦截一个资源的模式成为责任链模式 。
  6. 常用场景:
    1. 就与URL的访问权限控制
    2. 全站乱码解决过滤器
    3. 过滤敏感词汇
    4. 压缩响应

二、 过滤器的开发

  1. 想要开发一个过滤器 , 需要两个步骤

    1. 写一个类实现Filter接口
    2. 在web.xml中配置过滤器
  2. Filter接口:
    1. init(FilterConfig)

      1. 初始化的方法 , 当Filter被初始化时 , 调用此方法 , 执行初始化操作
    2. destory()
      1. 销毁方法, 在Filter被销毁之前调用 , 执行善后操作
    3. doFilter(ServletRequest request , ServletResponse response , FilterChain chain)
      1. 核心方法 ,在存活期间 , 过滤器拦截到对资源的访问 会造成此方法的执行 , 需要在这个方法中设计过滤器的核心逻辑代码
  3. 配置过滤器

    <filter> -- 配置一个过滤器<filter-name>FirstFilter</filter-name> -- 过滤器的名字<filter-class>com.tarena.filter.FirstFilter</filter-class> -- 过滤器的类
    </filter>
    <filter-mapping> -- 过滤器的拦截路径配置,可以配置多个<filter-name>FirstFilter</filter-name> -- 为哪个名字的过滤器配置<url-pattern>/*</url-pattern> -- 拦截哪个路径资源可以配置多个<servlet-name>XxxServlet</servlet-name> -- 拦截哪个名字的Servlet<dispatcher></dispatcher> -- 指定过滤器拦截哪种方式对资源的访问,可以取值为REQUEST FORWARD INCLUDE ERROR,如果不配置,默认只拦截REQUEST方式的访问。可以配置多个。
    </filter-mapping>
    

三、生命周期

  1. 在web应用启动时 , 会创建处web应用中配置的过滤器对象 , 创建出过滤器对象会立即调用init方法进行初始化操作 , 之后一直存活 , 直到web应用被销毁时 , Filter跟着被销毁.在销毁之前会自动调用destory方法执行善后操作 。 在存活期间 , 每当拦截到资源访问 , 就执行doFilter方法 , 来执行过滤器的 逻辑 , 如果不做操作 , 则 默认拦截 , 可以通过FilterChain类的对象的 doFilter方法实现对资源访问的放行 。 并且可以在doFilter前后做一些操作 。

四、 细节

  1. 如果一个资源被多个过滤器拦截 , 多个 拦截器的拦截顺序取决于在web.xml文件中配置过滤器时的先后顺序 。
  2. 多个 过滤器的执行 , 类似于方法 一层一层调用的过程 ,, 一层一层往里钻, 然后在一层层一层往外出 。

五、 和Filter开发相关的对象

  1. FilterConfig:

    1. init方法的参数
    2. 代表FIlter在web.xml文件中的配置对象
    3. 可以用来获取Filter在Web.xml文件中的初始化配置参数
    4. 可以用来获取ServletContext对象

      public void init(FilterConfig filterConfig) throws ServletException {System.out.println("init....");//1.filterConfig功能1:获取filter的初始化参数Enumeration<String> names = filterConfig.getInitParameterNames();while(names.hasMoreElements()){String name = names.nextElement();String value = filterConfig.getInitParameter(name);System.out.println(name+"~"+value);}//2.获取ServletContext对象ServletContext sc = filterConfig.getServletContext();}
      
  2. FilterChain:
    1. doFilter方法参数
    2. 代表过滤器链
    3. 提供了doFilter方法 ,放行当前过滤器 , 执行后续过滤器 , 如果后续没有过滤器则调用到相应的资源 。

六、Filter案例

  1. 全站乱码解决过滤器

    1. 在web开发过程中 , 存在请求参数乱码和响应输出乱码 。
    2. 之前的开发中 , 在所有的Servlet和jsp页面中 , 需要手动解决这两种乱码
    3. 可以通过开发过滤器拦截所有的资源访问 , 在过滤器中解决全站乱码问题 。
    4. 具体解决请求响应乱码问题:

      1. 在web.xml文件 中配置全局的编码类型
      <!-- 全局配置 -->
      <context-param><param-name>encode</param-name><param-value>utf-8</param-value>
      </context-param>
      2. 在过滤器初始化时获取全局配置的编码 , 并保存到过滤器中
      private String encode = null;
      public void init(FilterConfig config) throws ServletException {encode = (String) config.getServletContext().getAttribute("encode");
      }3. 解决响应乱码:
      在doFilter方法中
      response.setCharacterEncoding(encode);
      response.setContentType("text/html;charset="+encode);
      4. 解决请求参数乱码//方案一:
      //      request.setCharacterEncoding(encode); //只能解决Post请求参数的乱码//可以解决Post和Get请求类型的参数乱码//但是在转码的时候需要指定具体的参数名称  ,转码之后要重新放入request中供servlet拿取更是不能实现 , 所以 不可行
      //      String param = new String(request.getParameter("xxxx").getBytes("iso-8859-1") , encode);//方案二://request中的请求参数本身无法改变 //那么 换一个思路 想办法改造和获取请求参数相关的方法 在方法内加上解决乱码的代码 //这样通过这些方法获取请求参数时 解决好乱码再返回 用起来就感觉 乱码被解决了一样//改造原有request方法方案一: //继承//继承只能先改造在创建实例 , 但是现在已经有了request对象,  就算通过继承改造了ServletRequest类也不会影响到已有的对象 , 排除//改造原有request方法方案二://装饰设计模式//1. 新建一个类 , 实现与被改造对象相同的接口//2. 通过狗仔方法传入被改造的对象并保存在本类中//3. 然后实现接口中所有的方法 , 如果需要改造则在对应的方法里写出逻辑 , 如果不需要改造的方法 ,则直接通过传入的没被改造的参数对象调用原有的方法即可//这种方案 的缺点 ,如果被改造的方法 中方法过多时 ,这个操作会十分繁琐 。//改造原有的request对象方案三://在装饰设计模式的基础上实现//通过源码 发现Servlet包下已经提供了一个ServletRequestWrapper类 , 它实现了与ServletRequest相同的接口//也就是说他就是java中已经提供的供开发者修改request对象中方法的入口//新建一个类继承ServletRequestWrapper类之后 ,通过构造方法 把原始对象传进去 , 然后只重写需要改造的方法即可代码//public class EncodeFilter implements Filter{/*** 当前web应用编码集*/private String encode = null;/*** 初始化方法*/public void init(FilterConfig filterConfig) throws ServletException {//获取ServletContext对象ServletContext sc = filterConfig.getServletContext();//读取初始化参数 中的 编码集 配置this.encode = sc.getInitParameter("encode");}/*** 过滤方法*/public void doFilter(final ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {//--全站响应乱码response.setCharacterEncoding(encode);response.setContentType("text/html;charset="+encode);//--全站请求乱码 - 通过装饰器 装饰request 修改其中的和获取请求参数相关的方法 增加了乱码解决的代码ServletRequest myReq = new MyServletRequest((HttpServletRequest) request);//放行资源chain.doFilter(myReq, response);}/*** 销毁方法*/public void destroy() {}/*** 内部类 ServletRequest的装饰类 改造了获取请求参数相关的方法 增加了乱码解决的代码*///继承了HttpServletRequestWrapper ,这个父类本身就是 HttpServletRequest的装饰器  在其中提供方法的默认的实现 不想改造的方法 不用管 想改造的方法 覆盖父类方法即可class MyServletRequest extends HttpServletRequestWrapper{private ServletRequest request = null;private boolean hasNotEncode = true;//构造器 接受传入的request保存在类的内部public MyServletRequest(HttpServletRequest request) {super(request);this.request = request;}//覆盖和获取请求参数相关的方法@Overridepublic Map<String,String[]> getParameterMap() {try {//1.获取真正request的请求参数组成的mapMap<String,String[]>  map = request.getParameterMap();if(hasNotEncode){//由于真正的request对此map会缓存 所以解决乱码的操作 只需要做一次 此处通过hasNotEncode来控制//2.遍历mapfor(Map.Entry<String, String[]>entry : map.entrySet()){//3.获取当前遍历到的值的数组String [] values = entry.getValue();//4.遍历值的数组 for(int i = 0;i<values.length;i++){//5.解决乱码 存回数组values[i] = new String(values[i].getBytes("iso8859-1"),encode);}}hasNotEncode = false;}//6.返回解决完乱码的mapreturn map;} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}
      
  2. 用户30天内自动登录

    1. 在处理用户登录时 , 判断用户是否勾选30天内自动登录 , 如果用户名密码正确且勾选过该选项 , 则发送cookie , 将用户名密码保存30天。 为了安全起见 , 保存之前先对密码进行MD5加密
    2. 之后用户在来访问时经过自动登录过滤器被拦截 , 如果用户未登录 , 且带了自动登录的cookie , 并且其中的用户名密码都正确 , 则给给用户给自动登录 。但是无论自动登录与否都要对url放行 。
    3. 在LoginServlet中添加用户自动登录逻辑: 如果用户勾选 了自动登录 , 则将用户信息添加进cookie中保存在本地
    4. 在AutoLoginFilter中 拦截所有请求 , 先判断是否登录 , 在判断是否有自动登录cookie ,最后判断用户密码是否正确
    5. 自动登录过滤器源码

      public class AutoLoginFilter implements Filter{public void destroy() {}public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;
      //      1. 判断该用户是否 已经登录if(req.getSession(false) == null ||req.getSession(false).getAttribute("user") == null){System.out.println("用户未登录");
      //      2. 判断访问时是否带有自动登录cookieCookie[] cookies = req.getCookies();for(Cookie c :cookies){if("autologin".equals(c.getName())){System.out.println("带有自动登录cookie");String v = c.getValue();String[] vs = URLDecoder.decode(v , "utf-8").split("#");UserService us = BaseFactory.getBase().getInstance(UserService.class);
      //      3. 验证用户名密码是否正确User user = us.login(vs[0], vs[1]);if(user != null){System.out.println("开始登录");//三个条件都满足 , 添加登录标记req.getSession().setAttribute("user", user);System.out.println("自动登录成功");}break;}}}
      //      4. 无论是否自动 登录成功 , 都放行访问。  放行访问chain.doFilter(request , response);}public void init(FilterConfig arg0) throws ServletException {// TODO Auto-generated method stub}}
      

七、MD5加密算法

  1. 又称数据摘要算法 , 数据指纹算法
  2. 任意长度的二进制文件计算出128位二进制的再要信息 , 通常转换为32位16进制显示 。
  3. 明文相同算出的密文一定相同
  4. 明文不同算出的密文一定不同 (概率极低 , 所以一般认为是唯一的)
  5. 只能由明文算成密文 ,, 不能有密文算成明文
  6. 应用:
    1. 加密存储数据
    2. 文件完整性校验
    3. 数字签名

大数据WEB阶段(十五)JavaEE三大核心技术之过滤器相关推荐

  1. 大数据WEB阶段(五)jQuery

    jQuery 一.概述 什么是jQuery? jQuery是一个写的更少 , 但做的更多的轻量级的 javaScript函数库 . jQuery的优势? 可以简化JavaScript代码 可以向css ...

  2. 2021年大数据Hadoop(十五):Hadoop的联邦机制 Federation

    全网最详细的Hadoop文章系列,强烈建议收藏加关注! 后面更新文章都会列出历史文章目录,帮助大家回顾知识重点. 目录 本系列历史文章 前言 Hadoop的联邦机制 Federation 背景概述 F ...

  3. 2021年大数据HBase(十五):HBase的Bulk Load批量加载操作

    全网最详细的大数据HBase文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 HBase的Bulk Load批量加载操作 一.Bulk L ...

  4. 大数据WEB阶段 TransientDateAccessResourceException

    大数据WEB阶段 TransientDateAccessResourceException 一 . 分析 如果数据库保存的字段有时间 , 但是没有给该字段赋值时 ,则该字段默认是0000-00-00 ...

  5. 大数据WEB阶段(十六)JavaEE三大 核心技术之监听器Listener

    Listener监听器 一.概述 Servlet三大核心技术之一 Servlet.Filter.Listener Servlet技术规范中定义了八种监听器用来监听web应用开发中对应的事件. 监听器可 ...

  6. 大数据WEB阶段总结

    一.概述 HTTP协议 web容器 - Tomcat 静态web资源 - 本质上是文件 html css js 图片 音频 视频 flash- 动态web资源 - 本质上是程序 Servelt JSP ...

  7. 大数据WEB阶段(九)Servlet+Request

    Servlet与Request 一.概述 Servlet 是sun公司提供的一门用于开发动态web资源的技术 按照这套规范写出来的servlet可以放置在web应用中在servlet容器中运行 . 开 ...

  8. 大数据WEB阶段 (六)MySql详解(一)

    MySql(二) 一.概述 什么是数据库 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,简而言之就是存储数据的仓库. 数据库的分类 层次式数据库.网络式数据库.关系型数据库 数 ...

  9. 2021年大数据ELK(十五):Elasticsearch SQL简单介绍

    全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 Elasticsearch SQL简单介绍 一.SQL与Elasticsear ...

最新文章

  1. Spring Cloud分布式微服务云架构—源码结构图
  2. 基于ARM的linux嵌入式操作系统
  3. Skipping failed optional dependency /chokidar/fsevents
  4. Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(前言)
  5. 【数位DP】B-number(HDU 3652)
  6. 物联网基础知识_联网| 基础知识能力问答 套装1
  7. 前端学习(3222):函数式组件使用props
  8. ARM汇编编程基础之一 —— 寄存器
  9. asp.net中打印指定控件内容
  10. flink java旁路输出(Side Output),对原始流进行分流、复制
  11. asp.net core mcroservices 架构之 分布式日志(二)之自定义日志开发
  12. 大话IT第13期:2011年云计算市场年中盘点
  13. MYSQL的Commit与程序的原子性
  14. 9.Linux性能诊断 --- Web应用安全:攻击,防护与检测,IPv6,容器安全
  15. iOS修改手游服务器数据,iOS 教你修改运动步数(基于Healthkit)
  16. 【大厂面试必备系列】滑动窗口协议
  17. PPT动态文字制作过程
  18. 苹果电脑ping 不通本地网络
  19. 后缀数组(Suffix Array )
  20. Safair浏览器 时间戳转化兼容性问题。

热门文章

  1. dom解析和sax解析的区别及优缺点
  2. angular_ui-router ——依赖注入
  3. 能够提高开发效率的Eclipse实用操作
  4. 解决Windows 8系统假死的方法
  5. Linux线上环境部署zabbix,CentOS 7.3下Zabbix 4.0监控环境安装部署
  6. mysqld 进程非常多_MySQL binlog后面的编号最大是多大?
  7. 【数据结构总结】第一章:数据结构基本概念
  8. 按钮的android程序闪退,Android实例化控件有什么特殊要求吗??怎么程序加了这一段之后就闪退。。...
  9. 简单的jQuery扩展函数-让函数缓冲执行
  10. 深入理解asp.net中的 __doPostBack函数