J2EE中 Servlet、Filter、Interceptor

来源:互联网 发布:centos ssh服务器配置 编辑:程序博客网 时间:2024/05/16 05:32
1)servlet和filter的区别 
Filter可认为是Servlet的一种“变种”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处 理,是个典型的处理链。它与Servlet的区别在于:它不能直接向用户生成响应。完整的流程是:Filter对用户请求进行预处理,接着将请求交给 Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。 

2)servlet、filter、interceptor的执行顺序 

通过上图可以看到,顺序应该是我们配的filter在前,之后是struts2的FilterDispatcher,然后是各个拦截器,最后原路 返回。

se a Filter when you want to filter and/or modify requests based on specific conditions. Use aServlet when you want to control, preprocess and/or postprocess requests.

The Sun Java EE tutorial mentions the following about filters:

A filter is an object that can transform the header and content (or both) of a request or response. Filters differ from web components in that filters usually do not themselves create a response. Instead, a filter provides functionality that can be “attached” to any kind of web resource. Consequently, a filter should not have any dependencies on a web resource for which it is acting as a filter; this way it can be composed with more than one type of web resource.

The main tasks that a filter can perform are as follows:

  • Query the request and act accordingly.
  • Block the request-and-response pair from passing any further.
  • Modify the request headers and data. You do this by providing a customized version of the request.
  • Modify the response headers and data. You do this by providing a customized version of the response.
  • Interact with external resources.

For authorization, a Filter is the best suited. Here's a basic kickoff example of how a filter checks requests for the logged-in user:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {    if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {        // User is not logged in. Redirect to login page.        ((HttpServletResponse) response).sendRedirect("login");    } else {        // User is logged in. Just continue with request.        chain.doFilter(request, response);    }}


Filter intercepts on HTTP requests matching its URL pattern and allows you to modify them. See also its javadoc:

A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.

Filters perform filtering in the doFilter method. Every Filter has access to a FilterConfigobject from which it can obtain its initialization parameters, and a reference to the ServletContextwhich it can use, for example, to load resources needed for filtering tasks.

Filters are configured in the deployment descriptor of a web application.

Examples that have been identified for this design are:

  • Authentication Filters
  • Logging and Auditing Filters
  • Image conversion Filters
  • Data compression Filters
  • Encryption Filters
  • Tokenizing Filters
  • Filters that trigger resource access events
  • XSL/T filters
  • Mime-type chain Filter

ServletContextListener intercepts on webapp's startup and shutdown and allows you to execute some code on startup and/or shutdown. See also its javadoc:

Interface for receiving notification events about ServletContext lifecycle changes.

In order to receive these notification events, the implementation class must be either declared in the deployment descriptor of the web application, annotated with WebListener, or registered via one of the addListener methods defined on ServletContext.

Implementations of this interface are invoked at theircontextInitialized(javax.servlet.ServletContextEvent) method in the order in which they have been declared, and at theircontextDestroyed(javax.servlet.ServletContextEvent) method in reverse order.

When to use the one or the other should now be obvious. Use a Filter if you want to intercept on HTTP requests maching a specific URL pattern because you want to check/modify the HTTP request/response. Use a ServletContextListener if you want to intercept on webapp's startup and/or shutdown.

http://www.cnblogs.com/Fskjb/archive/2010/03/27/1698448.html

下面从几个方面阐述一下题目中四个概念的区别与联系:

         1、概念

         2、生命周期

         3、职责

         4、执行过程

        

         一、概念:

         1、servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层。

         2、filter:filter是一个可以复用的代码片段,可以用来转换HTTP请求、响应和头信息。Filter不像Servlet,它不能产生一个请求或者响应,它只是修改对某一资源的请求,或者修改从某一的响应。

        3、listener:监听器,从字面上可以看出listener主要用来监听只用。通过listener可以监听web服务器中某一个执行动作,并根据其要求作出相应的响应。通俗的语言说就是在application,session,request三个对象创建消亡或者往其中添加修改删除属性时自动执行代码的功能组件。

         4、interceptor:是在面向切面编程的,就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法,比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

      5、servlet、filter、listener是配置到web.xml中,interceptor不配置到web.xml中,struts的拦截器配置到struts.xml中。spring的拦截器配置到spring.xml中。 

        二、生命周期:

        1、servlet:servlet的生命周期始于它被装入web服务器的内存时,并在web服务器终止或重新装入servlet时结束。servlet一旦被装入web服务器,一般不会从web服务器内存中删除,直至web服务器关闭或重新结束。
          (1)、装入:启动服务器时加载Servlet的实例; 
        (2)、初始化:web服务器启动时或web服务器接收到请求时,或者两者之间的某个时刻启动。初始化工作有init()方法负责执行完成; 
        (3)、调用:从第一次到以后的多次访问,都是只调用doGet()或doPost()方法; 
        (4)、销毁:停止服务器时调用destroy()方法,销毁实例。 

        

           2、filter:(一定要实现javax.servlet包的Filter接口的三个方法init()、doFilter()、destroy(),空实现也行) 
         (1)、启动服务器时加载过滤器的实例,并调用init()方法来初始化实例; 
         (2)、每一次请求时都只调用方法doFilter()进行处理; 
         (3)、停止服务器时调用destroy()方法,销毁实例。

         3、listener:类似于servlet和filter

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

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

       三、职责

       1、servlet:

        创建并返回一个包含基于客户请求性质的动态内容的完整的html页面;
        创建可嵌入到现有的html页面中的一部分html页面(html片段);
        读取客户端发来的隐藏数据;
        读取客户端发来的显示数据;
        与其他服务器资源(包括数据库和java的应用程序)进行通信;
        通过状态代码和响应头向客户端发送隐藏数据。

       2、filter:

        filter能够在一个请求到达servlet之前预处理用户请求,也可以在离开servlet时处理http响应:
        在执行servlet之前,首先执行filter程序,并为之做一些预处理工作;
        根据程序需要修改请求和响应;
        在servlet被调用之后截获servlet的执行

         3、listener:职责如概念。

          servlet2.4规范中提供了8个listener接口,可以将其分为三类,分别如下:
         第一类:与servletContext有关的listner接口。包括:ServletContextListener、ServletContextAttributeListener
         第二类:与HttpSession有关的Listner接口。包括:HttpSessionListner、HttpSessionAttributeListener、HttpSessionBindingListener、                      HttpSessionActivationListener;
         第三类:与ServletRequest有关的Listener接口,包括:ServletRequestListner、ServletRequestAttributeListener

        4、interceptor:与过滤器十分相似,通过层层拦截,处理用户的请求和响应。


        备注:web.xml 的加载顺序是:context-param -> listener -> filter -> servlet 。了解了这几个概念的区别以后,不难理论这个加载顺序了。


        四、几个区别:

        1,servlet 流程是短的,url传来之后,就对其进行处理,之后返回或转向到某一自己指定的页面。它主要用来在 业务处理之前进行控制.
        2,filter 流程是线性的, url传来之后,检查之后,可保持原来的流程继续向下执行,被下一个filter, servlet接收等,而servlet 处理之后,不会继续向下传递。filter功能可用来保持流程继续按照原来的方式进行下去,或者主导流程,而servlet的功能主要用来主导流程。
         filter可用来进行字符编码的过滤,检测用户是否登陆的过滤,禁止页面缓存等
        3, servlet,filter都是针对url之类的,而listener是针对对象的操作的,如session的创建,session.setAttribute的发生,在这样的事件发生时做一些事情。
     可用来进行:Spring整合Struts,为Struts的action注入属性,web应用定时任务的实现,在线人数的统计等
 
       4,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 来在接收之前做事
    

        5,struts2中的过滤器和拦截器的区别与联系:

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

        

        五、执行流程图:

         1、servlet:

           

          2、filter:

          

               

             

           3、listener:

             

           4、interceptor:

            

下面我们来验证一下:

web.xml:

<?xml version="1.0" encoding="UTF-8"?><web-app version="2.4"        xmlns="http://java.sun.com/xml/ns/j2ee"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  <welcome-file-list>    <welcome-file>login.jsp</welcome-file>  </welcome-file-list>   <filter>        <filter-name>MyFilter</filter-name>        <filter-class>filter.MyFilter</filter-class>  </filter>  <filter-mapping>        <filter-name>MyFilter</filter-name>        <url-pattern>/*</url-pattern>  </filter-mapping>   <filter>        <filter-name>struts2</filter-name>        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>  </filter>  <filter-mapping>        <filter-name>struts2</filter-name>        <url-pattern>/*</url-pattern>  </filter-mapping></web-app>
struts.xml(如下):

<!DOCTYPE struts PUBLIC         "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"         "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts>     <package name="default" extends="struts-default">        <interceptors>           <interceptor name="loginInterceptor" class="interceptor.LoginInterceptor" />           <interceptor-stack name="loginStack">              <interceptor-ref name="loginInterceptor" />              <interceptor-ref name="defaultStack" />           </interceptor-stack>        </interceptors>        <default-interceptor-ref name="loginStack"></default-interceptor-ref>        <global-results>           <result name="login">/login.jsp</result>        </global-results>        <action name="Login" class="action.LoginAction">           <result>/index.jsp</result>        </action>     </package> </struts>
login.jsp(如下):

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>My JSP 'index.jsp' starting page</title>  </head>   <body>    <h3>Login</h3>    <hr>    <form action="Login.action" method="POST">        Name: <input type="text" name="username" />        <input type="submit" value="submit" />    </form>  </body></html>
index.jsp(如下):

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>My JSP 'index.jsp' starting page</title>  </head>   <body>    <h3>Login Success!</h3>  </body></html>
filter.MyFilter(如下):

package filter; import java.io.IOException; import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse; public class MyFilter implements Filter {         public void destroy() {        }         public void doFilter(ServletRequest request, ServletResponse response,                        FilterChain chain) throws IOException, ServletException {                               System.out.println("请求过滤");                               chain.doFilter(request, response);                               System.out.println("返回过滤");                       }         public void init(FilterConfig arg0) throws ServletException {        } }
interceptor.LoginInterceptor(如下):

package interceptor; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class LoginInterceptor extends AbstractInterceptor {         private static final long serialVersionUID = -2796326480994355318L;         @Override        public String intercept(ActionInvocation ai) throws Exception {                               System.out.println("请求拦截");                               if(!"YOYO".equals(ServletActionContext.getRequest().getParameter("username"))){                        return "login";                }                               String result = ai.invoke();                               System.out.println("返回拦截");                               return result;        } }
action.LoginAction(如下):

package action; public class LoginAction {               public String execute(){                System.out.println("登陆ACTION");                               return "success";        } }

部署好后打开login.jsp,输入任意非"YOYO"字符,控制台打印出

请求过滤
请求拦截
返回过滤

 说明拦截之后还会按照原路返回;

如果输入"YOYO",则打印出

请求过滤
请求拦截
登陆ACTION
返回拦截
返回过滤

由此可以验证它的执行顺序,详细流程可以看最上面的图例。

原创粉丝点击