JAVA学习篇–javaweb之Filter具体解释[通俗易懂]

JAVA学习篇–javaweb之Filter具体解释

大家好,又见面了,我是全栈君。


DRP项目中,多次提到了Filter,它攻克了字符集的统一设置以及统一控制简单WebCache,从中我们能够体会到。它给我们带来的优点不不过降低代码量这么简单,它的出现避免了我们每一个页面反复的编写同样的代码,降低了我们的工作量。并且给维护带来了极大的便利。那么它是怎样实现统一管理的呢?既然它能统一管理某些反复的操作。那么它和AOP有什么关系呢?

 

Filter简单介绍

 

ServletAPI中提供了一个Filter接口,开发web应用时,假设编写的Java类实现了这个接口。则把这个java类称之为过滤器Filter。

通过Filter技术,开发者能够实现用户在訪问某个目标资源之前,对訪问的请求和响应进行拦截。简单说,就是能够实现web容器对某资源的訪问前截获进行相关的处理,还能够在某资源向web容器返回响应前进行截获进行处理。

 

下图是filter调用关系的UML:


             JAVA学习篇--javaweb之Filter具体解释[通俗易懂]


一个filter必须实现javax.servlet.Filter。

三个方法

1. voidsetFilterConfig(FilterConfig config) //设置filter 的配置对象;

2. FilterConfiggetFilterConfig() //返回filter的配置对象;

3. voiddoFilter(ServletRequest req,ServletResponse res,FilterChain chain) //运行filter的工作

 

Filter实现拦截的原理

 

Filter接口中有一个doFilter方法,当开发者编写好Filter类实现doFilter方法,并配置对哪个web资源进行拦截后。WEBserver每次在调用web资源的service方法之前(server内部对资源的訪问机制决定的),都会先调用一下filter的doFilter方法。

 

应用举例:

 

批量设置请求编码


public class EncodingFilter implements Filter {  
  
    private String encoding = null;  
  
    public void destroy() {  
        encoding = null;  
    }  
  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
        String encoding = getEncoding();  
        if (encoding == null){  
            encoding = "gb2312";  
        }  
        request.setCharacterEncoding(encoding);// 在请求里设置上指定的编码  
        chain.doFilter(request, response);  //通过控制对chain.doFilter的方法的调用,来决定是否须要訪问目标资源
    }  
  
    public void init(FilterConfig filterConfig) throws ServletException {  
        this.encoding = filterConfig.getInitParameter("encoding");  
    }  
  
    private String getEncoding() {  
        return this.encoding;  
    }  
  
}  

xml配置代码


<filter>  
    <filter-name>EncodingFilter</filter-name>  
    <filter-class>com.logcd.filter.EncodingFilter</filter-class>  
    <init-param>  
       <param-name>encoding</param-name>  
       <param-value>gb2312</param-value>  
    </init-param>  
</filter>  
  
<filter-mapping>  
   <filter-name>EncodingFilter</filter-name>  
   <url-pattern>/*</url-pattern>  
</filter-mapping>  

如上的代码完毕的功能为,不管进入那个页面,都要先运行EncodingFilter类的dofilter方法设置字符集

 

当中,doFilter()方法类似于Servlet接口的service()方法。当client请求目标资源的时候,容器就会调用与这个目标资源相关联的过滤器的doFilter()方法。

參数 request, response 为web 容器或 Filter 链的上一个 Filter 传递过来的请求和对应对象;參数 chain 代表当前 Filter 链的对象。

 

对于FilterChain接口。代表当前Filter链的对象。由容器实现,容器将事实上例作为參数传入过滤器对象的doFilter()方法中。

过滤器对象使用FilterChain对象调用过滤器链中的下一个过滤器,或者目标Servlet 程序去处理。也能够直接向client返回响应信息,或者利用RequestDispatcher的forward()和include()方法,以及HttpServletResponse的sendRedirect()方法将请求转向到其它资源。

这种方法的请求和响应參数的类型是 ServletRequest和ServletResponse,也就是说。过滤器的使用并不依赖于详细的协议。

 

Filter生命周期

 

和Servlet一样。Filter的创建和销毁也是由WEBserver负责。


与Servlet差别的是


1>在应用启动的时候就进行装载Filter类而servlet是在请求时才创建(但filter与Servlet的load-on-startup配置效果同样)。

2>容器创建好Filter对象实例后,调用init()方法。接着被Web容器保存进应用级的集合容器中去了等待着。用户訪问资源。

3>当用户訪问的资源正好被Filter的url-pattern拦截时,容器会取出Filter类调用doFilter方法,下次或多次訪问被拦截的资源时,Web容器会直接取出指定Filter对象实例调用doFilter方法(Filter对象常驻留Web容器了)。

4>当应用服务被停止或又一次装载了,则会运行Filter的destroy方法,Filter对象销毁。

 

Filter工作原理(运行流程)

     

    当client发出Web资源的请求时,Webserver依据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或修改,并依次通过过滤器链,最后把请求/响应交给请求的Web资源处理。

    请求信息在过滤器链中能够被改动,也能够依据条件让请求不发往资源处理器,并直接向客户机发回一个响应。

当资源处理器完毕了对资源的处理后,响应信息将逐级逆向返回。

相同在这个过程中。用户能够改动响应信息,从而完毕一定的任务。

    过滤链的优点是,运行过程中不论什么时候都能够打断,仅仅要不运行chain.doFilter()就不会再运行后面的过滤器和请求的内容。

                JAVA学习篇--javaweb之Filter具体解释[通俗易懂]


针对多个过滤器来说。比如。EncodingFilter负责设置编码,SecurityFilter负责控制权限,server会依照web.xml中过滤器定义的先后循序组装成一条链,然后一次运行当中的doFilter()方法。在实际使用时,就要特别注意过滤链的运行顺序问题,像EncodingFilter就一定要放在全部Filter之前,这样才干确保在使用请求中的数据前设置正确的编码。

 

总结:

 

对于filter的应用相信大家已经明确了,它基本的作用就是用户在訪问某个目标资源之前,对訪问的请求和响应进行拦截,做一些处理,然后再调用目标程序。这样做的优点是能够对一些公共的操作进行抽象,就拿设置字符集来说,假设不使用这样的方式,我们每一个页面都要写设置字符集的语句。

不但麻烦并且维护困难,可是假设使用filter的话。仅仅须要加入一个类。在xml中配置一下,假设不想使用了,将配置文件里的内容去除就可以。

 

事实上这就是一种AOP(Aspect OrientedProgramming),面向切面编程。

它的基本的意图是:将日志记录,性能统计,安全控制,事务处理。异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望能够将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

对于设置字符集来说,它并不是是业务逻辑的内容。对于这些内容的处理我们就能够提取出来。使用filter进行总体设置,这样的方式相当于对类中的内容做进一步的抽象,使我们的系统更加灵活。更加能应对变化!

 

解疑:

 

因为上篇博客介绍的动态代理,就是一种符合AOP的一种体现,如今我们又说Filter也符合AOP,那么大家一定会有一个疑问。动态代理和Filter处理问题的差别在哪里呢?First既然都符合AOP思想,那么一定都能够进行统一处理(事实上核心就是做进一步抽象)。

那么差别呢?

 

从表现形式上来说,两者确实非常相似。相同能够在你写的jsp、servlet代码的前后增加其他的动作,可是两者是有本质差别的。

1、 filter基于回调函数,我们须要实现的filter接口中doFilter方法就是回调函数,而动态代理则基于java本身的反射机制,假设对这样的形式不了解。能够去看看动态代理实现过程,这是aop的基础。这是两者最本质的差别。

2、 filter是依赖于servlet容器的。即仅仅能在servlet容器中运行。非常显然没有servlet容器就无法来回调doFilter方法。而动态代理与servlet容器无关。





版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115722.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • docker下载安装教程_安卓安装docker

    docker下载安装教程_安卓安装docker前言Docker提供轻量的虚拟化,你能够从Docker获得一个额外抽象层,你能够在单台机器上运行多个Docker微容器,而每个微容器里都有一个微服务或独立应用,例如你可以将Tomcat运行在一个D

    2022年8月6日
    25
  • 950. 郁闷的出纳员(Splay树)「建议收藏」

    950. 郁闷的出纳员(Splay树)「建议收藏」OIER 公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。

    2022年8月9日
    8
  • 递归简单举例_递归定义举例

    递归简单举例_递归定义举例刚接触递归的同学,可能难以理解递归,难以理解的点可能很多,例如:1.函数为什么可以在自己的内部又调用自己呢?2.既然可以自己调用自己,那么递归运行过程中一定回有很多层相互嵌套,到底什么时候不再嵌套呢?3.递归运行过程中,相互嵌套的多层之间会有参数传递,多层之间是否会相互影响?递归两个要素1.递归边界2.递归的逻辑——递归”公式”递归的过程一定有参数的变化,并且参

    2025年7月8日
    7
  • webstorm激活码永久2021_通用破解码

    webstorm激活码永久2021_通用破解码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月16日
    375
  • 解决Hmily与Feign冲突报错 NullPointerException

    解决Hmily与Feign冲突报错 NullPointerException在项目中使用了Hmily保证分布式事务的一致性,由于Hmily会注册一个HmilyFeignInterceptor,并且feign会将其添加到SynchronousMethodHandler中的requestInterceptors,当feign客户端执行HmilyFeignInterceptor中apply方法publicvoidapply(finalRequestTemplaterequestTemplate){Transmiter.getInstance

    2022年5月20日
    35
  • 左连接 ,右连接,内连接和全外连接的4者区别[通俗易懂]

    左连接 ,右连接,内连接和全外连接的4者区别[通俗易懂]基本定义:  leftjoin(左连接):返回包括左表中的所有记录和右表中连接字段相等的记录。  rightjoin(右连接):返回包括右表中的所有记录和左表中连接字段相等的记录。  innerjoin(等值连接或者叫内连接):只返回两个表中连接字段相等的行。  fulljoin(全外连接):返回左右表中所有的记录和左右表中连接字段相等的记录。举个例子: …

    2022年5月24日
    42

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号