filter listener interceptor

阅读更多

过滤器(filter),是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts2的action进行业务逻辑,

比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者struts2的action前统一设置字符集,或者去除掉一些非法字符

 

拦截器(interceptor),是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,

在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

 

拦截器与过滤器的区别 :

拦截器是基于java的反射机制的,而过滤器是基于函数回调。

拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后-过滤后      个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,

做一些前期的数据处理,接着把处理后的数据发给对应的Action;Action处理完成返回后,拦截器还可以做其他过程,再向上返回到过滤器的后续操作。

 

监听器:这个东西在c/s模式里面经常用到,他会对特定的事件产生产生一个处理。监听在很多模式下用到。比如说观察者模式,就是一个监听来的。又比如struts2可以用监听来启动。

Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理。

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

 

1.过滤器

 

Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断等。其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request、Response)统一设置编码,简化操作;同时还可进行逻辑判断,如用户是否已经登陆、有没有权限访问该页面等等工作。它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁,以下通过过滤编码的代码示例来了解它的使用:

package web;

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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 主要目的:过滤字符编码;其次,做一些应用逻辑判断等.   
//Filter跟web应用一起启动   
//当web应用重新启动或销毁时,Filter也被销毁   
public class MyFilter implements Filter {
	private FilterConfig filterConfig = null;

	@Override
	public void destroy() {
		 System.out.println("MyCharsetFilter准备销毁...");   
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain chain) throws IOException, ServletException {
	    HttpServletRequest request = (HttpServletRequest)arg0;   
        HttpServletResponse response = (HttpServletResponse)arg1;   
        // 获取web.xm设置的编码集,设置到Request、Response中         
        request.setCharacterEncoding(filterConfig.getInitParameter("charset"));          
        response.setContentType(filterConfig.getInitParameter("contentType"));         
        response.setCharacterEncoding(filterConfig.getInitParameter("charset"));            
       // 将请求转发到目的地   
        chain.doFilter(request, response); 
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		 this.filterConfig = arg0;   
         System.out.println("MyFilter初始化...");  
	}

}

 

     
      filter   
      web.MyFilter   
         
          charset   
          UTF-8   
         
         
          contentType   
          text/html;charset=UTF-8   
         
     
     
      filter   
         
      /*   
     

 

四月 28, 2015 8:31:44 下午 org.apache.catalina.core.StandardService start
信息: Starting service Catalina
四月 28, 2015 8:31:44 下午 org.apache.catalina.core.StandardEngine start
信息: Starting Servlet Engine: Apache Tomcat/6.0.39
MyFilter初始化...
四月 28, 2015 8:31:44 下午 org.apache.coyote.http11.Http11Protocol start
信息: Starting Coyote HTTP/1.1 on http-8080
四月 28, 2015 8:31:44 下午 org.apache.jk.common.ChannelSocket init
信息: JK: ajp13 listening on /0.0.0.0:8009

 

 

2.监听器

 

现在来说说Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。主要作用是: 做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。下面利用监听器对数据库连接池DataSource的初始化演示它的使用: 

package web;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.tomcat.dbcp.dbcp.BasicDataSource;

/**  
 * Web应用监听器  
 */   
public class MyServletContextListener implements ServletContextListener {     
    // 应用监听器的销毁方法   
    public void contextDestroyed(ServletContextEvent event) {   
        ServletContext sc = event.getServletContext();   
        // 在整个web应用销毁之前调用,将所有应用空间所设置的内容清空   
        sc.removeAttribute("dataSource");   
       System.out.println("销毁工作完成...");   
    }   
   
    // 应用监听器的初始化方法   
    public void contextInitialized(ServletContextEvent event) {   
        // 通过这个事件可以获取整个应用的空间   
        // 在整个web应用下面启动的时候做一些初始化的内容添加工作   
        ServletContext sc = event.getServletContext();   
        // 设置一些基本的内容;比如一些参数或者是一些固定的对象   
        // 创建DataSource对象,连接池技术 dbcp   
        BasicDataSource bds = new BasicDataSource();   
        bds.setDriverClassName("com.mysql.jdbc.Driver");                       bds.setUrl("jdbc:mysql://localhost:3306/hibernate");   
        bds.setUsername("root");   
        bds.setPassword("root");   
        bds.setMaxActive(10);//最大连接数   
        bds.setMaxIdle(5);//最大管理数   
        //bds.setMaxWait(maxWait); 最大等待时间   
        // 把 DataSource 放入ServletContext空间中,   
        // 供整个web应用的使用(获取数据库连接)   
        sc.setAttribute("dataSource", bds);   
        System.out.println("应用监听器初始化工作完成...");   
        System.out.println("已经创建DataSource...");   
    }   
}   

 

  
  web.MyServletContextListener
  

 

信息: Starting service Catalina
四月 28, 2015 8:34:59 下午 org.apache.catalina.core.StandardEngine start
信息: Starting Servlet Engine: Apache Tomcat/6.0.39
应用监听器初始化工作完成...
已经创建DataSource...
MyFilter初始化...
四月 28, 2015 8:35:00 下午 org.apache.coyote.http11.Http11Protocol start

 

 

3.拦截器

拦截器是在面向切面编程中应用的,就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法。是基于JAVA的反射机制。拦截器不是在web.xml,比如struts在struts.xml中配置.

 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable  
{  
Object result = null;  
System.out.println("before invoke method :" + method.getName());  
result = method.invoke(this.targetObj, args);  
System.out.println("after invoke method : " + method.getName());  
return result;  
}  

 

总结:

 

1.过滤器:所谓过滤器顾名思义是用来过滤的,在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者struts的action前统一设置字符集,或者去除掉一些非法字符(聊天室经常用到的,一些骂人的话)。filter 流程是线性的, url传来之后,检查之后,可保持原来的流程继续向下执行,被下一个filter, servlet接收等.

 

2.监听器:这个东西在c/s模式里面经常用到,他会对特定的事件产生产生一个处理。监听在很多模式下用到。比如说观察者模式,就是一个监听来的。又比如struts可以用监听来启动。Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理。

 

3.java的拦截器 主要是用在插件上,扩展件上比如 hibernate spring struts2等 有点类似面向切片的技术,在用之前先要在配置文件即xml文件里声明一段的那个东西.

from:http://m.blog.csdn.net/blog/Shb_derek/9041197

 

 

 

 

 

 

 

共同点:

对一类url,或所有url进行业务处理

对各种url之类进行匹配,查找,执行相应操作,与action相比较而言,action只能针对某一特定的url进行匹配,进行操作 如:

action对应的url是固定的,对于struts1.x可能一个action只有一个url

对于struts2.0,一个action可能有多个url,看它实现的方法数量,不过这些url在提交之前都是已经的,固定的。而上面四种可以对任意url进行操作,如*.action

 

区别:

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 来在接收之前做事

 

一,servlet

1, 在web.xml中配置

  Servlet 

 

AutoServlet

    com.servlet.AutoServlet

 AutoServlet

 /AutoServlet

 

2,定义AutoServlet,继承HttpServlet,实现方法doGet, doPost

3, 应用:

(1)Struts1.x 就是一个Servlet, 它会在doGet方法中读取配置文件struts-config.xml进行action的匹配,进行   业务处理

(2)验证码生成(也可用action来做)

 

 

二,filter

1, web.xml配置

checkUrl

com.lvjian.filter.CheckUrl

  name

  asong    

                              //初始化传参,得到时在filter的init方法中用filterConfig.getInitParameter( "name" )

checkUrl

/*

 

2, 继承 javax.servlet.Filter,实现 doFilter(HttpServletRequest request, HttpServletResponse response FilterChain filterChain) 等方法  

 

      HttpServletRequest request = (HttpServletRequest) req;

      HttpServletResponse response = (HttpServletResponse) res;

      //获取用户请求的URI

     String request_uri = request.getRequestURI();

    //获取web应用程序的上下文路径

     String contextPath = request.getContextPath();

    //去除上下文路径,得到剩余部分的路径

     String uri = request_uri.substring(contextPath.length());

    //创建会话session

    HttpSession session = request.getSession(true);

 

    //保持原有流程不变

     filterChain.doFilter( servletRequest , servletResponse );   

 

3,应用:

(1)Struts2.0

  2) 进行字符编码的过滤,检测用户是否登陆的过滤等

 

           (3)禁止页面缓存,原理就是对各个请求的url令其为空,在doFilter加入:

 

                   request.setCharacterEncoding("GB2312");//设置编码 

                   ((HttpServletResponse)response).setHeader("Pragma","No-cache"); 

                   ((HttpServletResponse)response).setHeader("Cache-Control","no-cache"); 

                   ((HttpServletResponse)response).setHeader("Expires","0");//禁止缓存 

 

 

三,listener

 

1, 在web.xml中配置

 

   

       demo.listener.MyContextLoader

 

  //这样服务器就会在启动时创建MyContextLoader的一个实例,并开始监听servlet,session的操作

2, 实现

 常用的listener有:

  (1) ServletContextListener 监听ServletContext。

        当创建ServletContext时,激发 contextInitialized(ServletContextEvent sce)方法;

       当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。

 

  (2)ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。

 

  (3)HttpSessionListener 监听HttpSession的操作。

          当创建一个Session时,激发 session Created(HttpSessionEvent se)方法;

          当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se)方法。

 

 

 (4)HttpSessionAttributeListener 监听HttpSession中的属性的操作。

        当在Session增加一个属性时,激发 attributeAdded(HttpSessionBindingEvent se) 方法;

        当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEventse)方法;

        当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。 

 

四,interceptor

1, 在struts.xml中配置

 

创建一个strus.xml的子配置文件struts-l99-default.xml,它继承与struts2的struts-default,此配置文件是其他子配置文件的父类,只要是继承与该文件的配置文件所声明的路径都会被它过滤 .

 

方法1. 普通配置法

 

   

 

 

    /register.jsp

    /result.jsp

 

   

   

   

   

方法2. 配置拦截器栈(即将多个interceptor串联的一种元素)。然后在中引入该拦截器栈就可以了。

 

  执行顺序为先配置的先执行

  这样做的原因是:多个action有相同的多个interceptor时,如一般自己写一个,系统默认的有一个,要注入两个,

  对多个action都写这两个,不利于修改,可以写成一个链,只需引用此链即可。

 

 

(1)拦截目标对象(被代理对象),这里目标对象就是action;(2)拦截器(一个类,动态的将某些方法插入到目标对象的某方法的before、after);(3)对目标对象生成的(动态)代理对象(代理对象内部方法综合了目标对象方法+拦截器方法)。程序最终执行的是目标对象的代理,而这个代理已经插入了interceptor。拦截器作用:拦截action。interceptor相当于一个入口和出口,通过interceptor进入action,执行完action的代码再通过interceptor出去。针对"struts2 -- interceptor(Interceptor怎么写)"这篇文章的MyInterceptor.class和MyInterceptor2.class。根据下面的配置文件执行程序

             

 

   

 

   

       

       

   

 

    /register.jsp

    /result.jsp

 

   

方法3. 修改默认拦截器,将自定义的拦截器栈定义为struts2的默认拦截器。

 

 

   

   

       

       

   

 

 

 

    /register.jsp

    /result.jsp

 

3. extends MethodFilterInterceptor的拦截器如何配置哪些方法该拦截、哪些方法不该拦截(针对方法拦截的配置)

 

 

   

 

    /register.jsp

    /result.jsp

   

   

        queryAll, execute

   

   

 

   

2, 实现

interceptor类似于filter, 自定义filter是实现javax.servlet.Filter来完成,而interceptor类似,它通过实现com.opensymphony.xwork2.interceptor.Interceptor来自定义实现。

该接口提供了三个方法:

 

1)      void init(); 在该拦截器被初始化之后,在该拦截器执行拦截之前,系统回调该方法。对于每个拦截器而言,此方法只执行一次。

 

2)      void destroy();该方法跟init()方法对应。在拦截器实例被销毁之前,系统将回调该方法。

 

3)      String intercept(ActionInvocation invocation) throws Exception; 该方法是用户需要实现的拦截动作。该方法会返回一个字符串作为逻辑视图。

 

除此之外,继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor是更简单的一种实现拦截器类的方式,因为此类提供了init()和destroy()方法的空实现,这样我们只需要实现intercept方法。

 

 

 

 

3, 应用

[java] view plaincopyprint?

import java.util.Map;  

   

import com.opensymphony.xwork2.Action;  

   

import com.opensymphony.xwork2.ActionInvocation;  

   

import com.opensymphony.xwork2.interceptor.AbstractInterceptor;  

   

/** 

  

* 权限检查拦截器 

  

  

* @author qiujy 

  

* @version 1.0 

  

*/  

   

public class AuthorizationInterceptor extends AbstractInterceptor {  

   

/* 

  

* 拦截Action处理的拦截方法 

  

  

*/  

   

public String intercept(ActionInvocation invocation) throws   

   

Exception {  

   

   

   

   

//清除后台页面的缓存  

HttpServletResponse response = ServletActionContext.getResponse();  

   

   

   

// ServletActionContext 自动提供,可让其获得request,session,response等  

response.setHeader("Pragma","No-cache");  

response.setHeader("Cache-Control","no-cache");  

response.setHeader("Expires","0");  

   

   

   

   

Map session = invocation.getInvocationContext().getSession();  

String userName = (String) session.get("userName");  

   

   

   

if (null != userName && userName.equals("test")) {  

   

    System.out.println("拦截器:合法用户登录---");  

   

    return invocation.invoke(); //保持原来的流程不改变  

   

} else {  

   

    System.out.println("拦截器:用户未登录---");  

   

    return Action.LOGIN; //返回到配置文件中名字为login的action  

   

}  

   

}  

   

}  

 http://blog.csdn.net/dracotianlong/article/details/9083249

 

 

 

首先,JSP/Servlet规范中定义了Servlet、Filter、Listener这三种角色,并没有定义Interceptor这个角色,Interceptor是某些MVC框架中的角色,比如Struts2中,Interceptor是用来拦截Action中的方法的调用,在被拦截的Action方法被执行前,先执行响应的拦截器中的方法。
servlet、filter、listener是配置到web.xml中,interceptor不配置到web.xml中,struts的拦截器配置到struts.xml中。spring的拦截器配置到spring.xml中。


servlet、filter、listener三者的加载顺序与它们在 web.xml 文件中配置的先后顺序无关。即不会因为filter写在listener的前面而会先加载filter:加载它们的先后顺序是:listener -> filter -> servlet
同时还存在着这样一种配置节:context-param,它用于向 ServletContext 提供键值对,即应用程序上下文信息。我们的 listener, filter 等在初始化时会用到这些上下文中的信息,那么 context-param 配置节是不是应该写在 listener 配置节前呢?实际上 context-param 配置节可写在任意位置,因此真正的加载顺序为:context-param -> listener -> filter -> servlet


context-param、listener、 filter、 servlet的加载顺序不是配置时先后顺序的影响,但是多个filter时,filter之间的加载顺是受影响的。web 容器启动时初始化每个 filter 时,是按照 filter 配置节出现的顺序来初始化的,当请求资源匹配多个 filter-mapping 时,filter 拦截资源是按照 filter-mapping 配置节出现的顺序来依次调用 doFilter() 方法的。


==================================Filter=============================================
filter过滤器是在Java Servlet规范2.3中定义的,在Java Servlet规范2.3出来之前,是没有filter这个角色的。
filter这个角色是用来:在请求到达servlet之前,先截获请求,对请求先做一些预处理(例如编码转换,权限验证)。处理完后在把请求转发给servlet或把不符合某些规则的请求丢弃掉,不再转发给servlet了。当servlet处理好请求后,返回响应给浏览器时,filter拦截响应,对响应做一些处理之后,再返回给浏览器。由此可见,filter这个角色的职责就是:帮servlet做一些前期预处理工作(先于servlet处理request)和善后工作(后于servlet处理response)的辅助角色,它就像servlet的助手一样,但它并不是必须的,因为在之前没有filter的时候,servlet也能很好地工作。只是如果有filter的帮助的话,servlet就能更专注处理一些核心的业务。
多个filter可以协同工作,它们之间采用了职责链的设计模式来协同工作。一个filter处理完后,调用下一个filter来处理,每个filter负责处理不同的工作,而这些filter之间可以根据需要灵活组合。filter的先后顺序按filter在web.xml中配置的先后顺序。
filter需要servlet容器(tomcat)的支持,能运行filter的servlet容器必须实现在Java Servlet规范2.3版中定义的功能。servlet容器是对javax.servlet.Filter这个接口进行编程的,所以你自己写的filter必须直接或间接的实现了javax.servlet.Filter这个接口,否则servlet容器不能跟你定义的filter进行交互(因为在编程实现容器时,就把javax.servlet.Filter这个接口编进容器代码中了,容器只能调用javax.servlet.Filter接口的实现类)。




=====================================Listener============================================
listener是对事件进行监听和处理的角色,它采用观察者模式,只有当在这个listener上注册了的事件
发生时,listener才会执行事件处理方法。这些事件举例:上下文(context)加载事件;session创建或销毁事件;容器、session或请求的属性设置或移除事件等。


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




=====================================Interceptor=========================================
Interceptor是某些MVC框架中的角色,比如Struts2中,Interceptor是用来拦截Action中的方法的调用,在被拦截的Action方法被执行前,先执行响应的拦截器中的方法。interceptor:是在面向切面编程的,就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法,比如动态代理就是拦截器的简单实现。filter是在servlet前面拦截请求,而interceptor是利用面向切面编程的技术,在Struts的内部Action中拦截调用方法请求。

from:http://blog.csdn.net/zuoluoboy/article/details/19750699

 

你可能感兴趣的:(filter listener interceptor)