Servlet、Filter、Listener、Interceptor的做用和区别

1、概念html

一、Servletjava

Servlet是一种运行服务器端的Java应用程序,具备独立于平台和协议的特性,而且能够动态的生成Web页面,它工做在客户端请求与服务器响应的中间层。Servlet 的主要功能在于交互式地浏览和修改数据,生成动态Web内容。这个过程为:程序员

1) 客户端发送请求至服务器端;web

2) 服务器将请求信息发送至Servlet;spring

3) Servlet 生成响应内容并将其传给服务器。响应内容动态生成,一般取决于客户端的请求;数据库

4) 服务器将响应返回给客户端。apache

在 Web 应用程序中,一个 Servlet 在一个时刻可能被多个用户同时访问。这时 Web 容器将为每一个用户建立一个线程来执行 Servlet。若是 Servlet 不涉及共享资源的问题,没必要关心多线程问题。但若是 Servlet 须要共享资源,须要保证 Servlet 是线程安全的。最新版本3.1,为了简化开发流程,Servlet 3.0 引入了注解(annotation),这使得 web 部署描述符 web.xml 再也不是必须的选择。编程

二、Filter缓存

Filter是一个能够复用的代码片断,能够用来转换HTTP请求、响应和头信息。Filter不像Servlet,它不能产生一个 请求或者响应,它只是修改对某一资源的请求,或者修改从某一的响应。Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、作一些业务逻辑判断等。其工做原理是,只要你在web.xml 文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就能够对请求或响应(Request、Response)统一设置编码,简化操做;同时还可 进行逻辑判断,如用户是否已经登录、有没有权限访问该页面等等工做。它是随你的web应用启动而启动的,只初始化一次,之后就能够拦截相关请求,只有当你的web应用中止或从新部署的时候才销毁。Filter可认为是Servlet的一种“变种”,它主要用于对用户请求HttpServletRequest进行预处理,也能够对HttpServletResponse进行后处理,是个典型的处理链。它与Servlet的区别在于:它不能直接向用户生成响应。完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。安全

Filter有以下几个用处:

  • 在HttpServletRequest到达Servlet以前,拦截客户的HttpServletRequest。

  • 根据须要检查HttpServletRequest,也能够修改HttpServletRequest头和数据。

  • 在HttpServletResponse到达客户端以前,拦截HttpServletResponse。

  • 根据须要检查HttpServletResponse,也能够修改HttpServletResponse头和数据。

Filter有以下几个种类:

  • 用户受权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。

  • 日志Filter:详细记录某些特殊的用户请求。

  • 负责解码的Filter:包括对非标准编码的请求解码。

  • 能改变XML内容的XSLT Filter等。

  • Filter可负责拦截多个请求或响应;一个请求或响应也可被多个请求拦截。

建立一个Filter只需两个步骤:

  • 建Filter处理类;

  • web.xml文件中配置Filter。

下面先介绍一个简单的记录日志的Filter,这个Filter负责拦截全部的用户请求,并将请求的信息记录在日志中。

 

public class LogFilter implements Filter {

    

     //FilterConfig可用于访问Filter的配置信息

    private FilterConfig config;

 

    //实现初始化方法

    public void init(FilterConfig config) {

        this.config = config;

    }

 

    //实现销毁方法

    public void destroy() {

        this.config = null;

    }

 

    //执行过滤的核心方法

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException,ServletException {

        

   //---------下面代码用于对用户请求执行预处理---------

        //获取ServletContext对象,用于记录日志

        ServletContext context = this.config.getServletContext();

        long before = System.currentTimeMillis();

        System.out.println("开始过滤...");

        //将请求转换成HttpServletRequest请求

        HttpServletRequest hrequest = (HttpServletRequest) request;

        //记录日志

        context.log("Filter已经截获到用户的请求地址: " + hrequest.getServletPath());

        //Filter只是链式处理,请求依然放行到目的地址

        chain.doFilter(request, response);

        

  //---------下面代码用于对服务器响应执行后处理---------

        long after = System.currentTimeMillis();

        //记录日志

        context.log("过滤结束");

        //再次记录日志

        context.log("请求被定位到" + hrequest.getRequestURI() + "所花的时间为: " + (after - before));

    }

}

 

上面程序实现了doFilter()方法,实现该方法就可实现对用户请求进行预处理,也可实现对服务器响应进行后处理——它们的分界线为是否调用了chain.doFilter(),执行该方法以前,即对用户请求进行预处理;执行该方法以后,即对服务器响应进行后处理。

在上面的请求Filter中,仅在日志中记录请求的URL,对全部的请求都执行chain.doFilter (request,reponse)方法,当Filter对请求过滤后,依然将请求发送到目的地址。若是须要检查权限,能够在Filter中根据用户请求 的HttpSession,判断用户权限是否足够。若是权限不够,直接调用重定向便可,无须调用 chain.doFilter(request,reponse)方法。

在web.xml文件中咱们须要对其须要拦截的请求配置监听范围,或者说过滤哪些url。

 

<filter>    <filter-name>logfilter</filter-name>    <filter-class>com.mine.test.LogFilter</filter-class>
</filter>
<filter-mapping>    <filter-name>logfilter</filter-name>    <!--配置过滤的范围 后缀符合即过滤 此处为所有过滤-->    <url-pattern>/*</url-pattern>
</filter-mapping>

在web.xml文件中配置该Filter,使用init-param元素为该Filter配置参数,init-param可接受以下两个子元素:

param-name:指定参数名;

param-value:指定参数值。

其实struts2自己就依托于一个总过滤器:

 

<filter>   <filter-name>struts2</filter-name>   <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>    <filter-name>struts2</filter-name>    <url-pattern>/*</url-pattern>
</filter-mapping>

 

多个匹配的Filter,是按照其在web.xml中配置的顺序来执行的。 

因此这也就是,把本身的Filter或者其余的Filter(好比UrlRewrite的Filter)放在Struts的DispatcherFilter的前面的缘由。由于,它们须要在请求被Struts2框架处理以前,作一些前置的工做。 

当Filter被调用,而且进入了Struts2的DispatcherFilter中后,Struts2会按照在Action中配置的Interceptor Stack中的Interceptor的顺序,来调用Interceptor。 

三、Listener

监听器,从字面上能够看出Listener主要用来监听应用。经过listener能够监听web服务器中某一个执行动做,并根据其要求做出相应的响应。通俗的语言说就是在application,session,request三个对象建立消亡或者往其中添加修改删除属性时自动执行代码的功能组件。好比spring 的总监听器会在服务器启动的时候实例化咱们配置的bean对象 、hibernate 的 session 的监听器会监听session的活动和生命周期,负责建立、关闭session等活动。

Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次,随web应用的中止而销毁。主要做用是: 作一些初始化的内容添加工做、设置一些基本的内容、好比一些参数或者是一些固定的对象等等。

四、Interceptor

是在面向切面编程的,就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法,是基于JAVA的反射机制。好比动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者作其它业务逻辑的操做),也能够在你调用方法后打印出字符串,甚至在你抛出异常的时候作业务逻辑的操做。

Servlet、Filter、Listener是配置到web.xml中(web.xml 的加载顺序是:context-param -> listener -> filter -> servlet ),Interceptor不配置到web.xml中,Struts的拦截器配置到struts.xml中,Spring的拦截器配置到spring.xml中。

2、生命周期

一、Servlet

通常继承HttpServlet(通常的,通用Servlet由javax.servlet.GenericServlet实现Servlet接口。程序设计人员能够经过使用或继承这个类来实现通用Servlet应用。javax.servlet.http.HttpServlet实现了专门用于响应HTTP请求的Servlet,提供了响应对应HTTP标准请求的doGet()、doPost()等方法),web.xml配置servlet时若是加上load-on-start=1,Web应用启动时候加载Servlet。

(在servlet的配置当中,<load-onstartup>1</load-on-startup>的含义是:标记容器是否在启动的时候就加载这个servlet。当值为0或者大于0时,表示容器在应用启动时就加载这个Servlet;当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。正数的值越小,启动该servlet的优先级越高。)

当Servlet被部署在应用服务器中(应用服务器中用于管理Java组件的部分被抽象成为容器) 之后,由容器控制Servlet的生命周期。除非特殊指定,不然在容器启动的时候,Servlet是不会被加载的,Servlet只会在第一次请求的时候被加载和实例化。Servlet一旦被加载,通常不会从容器中删除,直至应用服务器关闭或从新启动。但当容器作内存回收动做时,Servlet有可能被删除。也正是由于这个缘由,第一次访问Servlet所用的时间要大大多于之后访问所用的时间。

Servlet在服务器的运行生命周期为,在第一次请求(或其实体被内存垃圾回收后再被访问)时被加载并执行一次初始化方法,跟着执行正式运行方法,以后会被常驻并每次被请求时直接执行正式运行方法,直到服务器关闭或被清理时执行一次销毁方法后实体销毁。Java服务器页面(JSP)是HttpServlet的扩展。因为HttpServlet大可能是用来响应HTTP请求,并返回Web页面(例如HTML、XML), 因此不可避免地,在编写Servlet时会涉及大量的HTML内容,这给Servlet的书写效率和可读性带来很大障碍,JSP即是在这个基础上产生的。 其功能是使用HTML的书写格式,在适当的地方加入Java代码片段,将程序员从复杂的HTML中解放出来,更专一于Servlet自己的内容。JSP在首次被访问的时候被应用服务器转换为Servlet,在之后的运行中,容器直接调用这个Servlet,而再也不访问JSP页面。JSP的实质仍然是Servlet。

(1)装入:启动服务器时加载Servlet的实例; 
(2)初始化:Web服务器启动时或web服务器接收到请求时,或者二者之间的某个时刻启动。初始化工做由init()方法负责执行完成; 
(3)调用:从第一次到之后的屡次访问,都是只调用doGet()或doPost()方法; 
(4)销毁:中止服务器时调用destroy()方法,销毁实例。 

 二、Filter

必须实现javax.Servlet.Filter接口,而且必须定义如下三个方法:init(),destory(),doFilter(),空实现也行。 

(1)启动服务器时加载过滤器的实例,并调用init()方法来初始化实例; 
(2)每一次请求时都只调用方法doFilter()进行处理; 
(3)中止服务器时调用destroy()方法,销毁实例。

三、Listener

Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次,随web应用的中止而销毁。

web.xml 的加载顺序是:context-param -> listener -> filter -> servlet 

四、Interceptor

以Struts的拦截器为例,加载了struts.xml之后,初始化相应拦截器。当action请求来时调用intercept方法,服务器中止销毁interceptor。

 3、职责

一、Servlet

  • 建立并返回一个包含基于客户请求性质的动态内容的完整的html页面;

  • 建立可嵌入到现有的html页面中的一部分html页面(html片断);

  • 读取客户端发来的隐藏数据;

  • 读取客户端发来的显示数据;

  • 与其余服务器资源(包括数据库和java的应用程序)进行通讯;

  • 经过状态代码和响应头向客户端发送隐藏数据。

二、Filter

Filter可以在一个请求到达servlet以前预处理用户请求,也能够在离开Servlet时处理http响应:

  • 在执行Servlet以前,首先执行Filter程序,并为之作一些预处理工做;

  • 根据程序须要修改请求和响应;

  • 在Servlet被调用以后截获Servlet的执行

三、listener

职责如概念。

Servlet2.4规范中提供了8个Listener接口,能够将其分为三类,分别以下:

第一类:与ServletContext有关的Listener接口。包括:ServletContextListener、ServletContextAttributeListener

第二类:与HttpSession有关的Listner接口。包括:HttpSessionListener、 HttpSessionAttributeListener、HttpSessionBindingListener、                     HttpSessionActivationListener;

第三类:与ServletRequest有关的Listener接口,包括:ServletRequestListner、ServletRequestAttributeListener

四、Interceptor

与过滤器十分类似,经过层层拦截,处理用户的请求和响应。

4、几个区别

一、Servlet 流程是短的,url传来以后,就对其进行处理,以后返回或转向到某一本身指定的页面。它主要用来在业务处理以前进行控制。

二、Filter 流程是线性的, url传来以后,检查以后,可保持原来的流程继续向下执行,被下一个Filter, Servlet接收等,而Servlet 处理以后,不会继续向下传递。Filter功能可用来保持流程继续按照原来的方式进行下去,或者主导流程,而servlet的功能主要用来主导流程。

Filter可用来进行字符编码的过滤,检测用户是否登录的过滤,禁止页面缓存等。

三、Servlet,Filter都是针对url之类的,而Listener是针对对象的操做的,如session的建立,session.setAttribute的发生,在这样的事件发生时作一些事情。

可用来进行:Spring整合Struts,为Struts的action注入属性,Web应用定时任务的实现,在线人数的统计等

四、Interceptor 拦截器,相似于Filter,不过在struts.xml中配置,不是在web.xml,而且不是针对URL的,而是针对action,当页面提交 action时,进行过滤操做,至关于struts1.x提供的plug-in机制,能够看做,前者是Struts1.x自带的Filter,而 Interceptor 是struts2 提供的Filter.

与filter不一样点:

(1)不在web.xml中配置,而是在struts.xml中完成配置,与action在一块儿

(2)可由action本身指定用哪一个interceptor 来在接收以前作事    

五、Struts2中的过滤器和拦截器的区别与联系:

(1)拦截器是基于java反射机制的,而过滤器是基于函数回调的。
(2)过滤器依赖与servlet容器,而拦截器不依赖与servlet容器。
(3)拦截器只能对Action请求起做用,而过滤器则能够对几乎全部请求起做用。
(4)拦截器能够访问Action上下文、值栈里的对象,而过滤器不能。
(5)在Action的生命周期中,拦截器能够屡次调用,而过滤器只能在容器初始化时被调用一次。      

5、执行流程图

一、Servlet

   

二、Filter

 

三、Listener

四、Interceptor

相关文章
相关标签/搜索