java_过滤器和拦截器的区别

时间:2021-08-20 22:02:57
 

1、拦截器是基于java的反射机制的,而过滤器是基于函数回调
2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求
起作用
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容
器初始化时被调用一次
拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
下面通过实例来看一下过滤器和拦截器的区别:
使用拦截器进行/admin 目录下jsp页面的过滤
<package name="newsDemo" extends="struts-default"
        namespace="/admin">
        <interceptors>
            <interceptor name="auth" class="com.test.news.util.AccessInterceptor" />
            <interceptor-stack name="authStack">
                <interceptor-ref name="auth" />
            </interceptor-stack>
        </interceptors>
        <!-- action -->
        <action name="newsAdminView!*" class="newsAction"
            method="{1}">
            <interceptor-ref name="defaultStack"/>
            <interceptor-ref name="authStack">
            </interceptor-ref>
下面是我实现的Interceptor class:
package com.test.news.util;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.test.news.action.AdminLoginAction;
/**
* @author chaoyin
*/
public class AccessInterceptor extends AbstractInterceptor {
    private static final long serialVersionUID = -4291195782860785705L;
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
         ActionContext actionContext = actionInvocation.getInvocationContext();
         Map session = actionContext.getSession();
   
        //except login action
         Object action = actionInvocation.getAction();
        if (action instanceof AdminLoginAction) {
            return actionInvocation.invoke();
         }
        //check session
        if(session.get("user")==null ){
            return "logout";
         }
        return actionInvocation.invoke();//go on
     }
}
       过滤器:是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符.
使用过滤器进行/admin 目录下jsp页面的过滤,首先在web.xml进行过滤器配置:
    <filter>
        <filter-name>access filter</filter-name>
        <filter-class>
             com.test.news.util.AccessFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>access filter</filter-name>
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>
下面是过滤的实现类:
package com.test.news.util;
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;
import javax.servlet.http.HttpSession;
public class AccessFilter implements Filter {
/**
* @author chaoyin
*/
    public void destroy() {
     }
    public void doFilter(ServletRequest arg0, ServletResponse arg1,
             FilterChain filterChain) throws IOException, ServletException {
         HttpServletRequest request = (HttpServletRequest)arg0;
         HttpServletResponse response = (HttpServletResponse)arg1;
         HttpSession session = request.getSession();
        if(session.getAttribute("user")== null && request.getRequestURI().indexOf("login.jsp")==-1 ){
             response.sendRedirect("login.jsp");
            return ;
         }
         filterChain.doFilter(arg0, arg1);
     }
    public void init(FilterConfig arg0) throws ServletException {
     }
}
  评论这张
 转发至微博
 转发至微博
 0人  |  分享到:      

 

 


=====================================================================================================================
现在来说说Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。主要作用是:做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。下面利用监听器对数据库连接池DataSource的初始化演示它的使用:
11: public class MyServletContextListener implements ServletContextListener {
  12: 
  13:       // 应用监听器的销毁方法
  14:       public void contextDestroyed(ServletContextEvent event) {
  15:           ServletContext sc = event.getServletContext();
  16:           // 在整个web应用销毁之前调用,将所有应用空间所设置的内容清空
  17:           sc.removeAttribute("dataSource");
  18:           System.out.println("销毁工作完成...");
  19:       }
  20: 
  21:       // 应用监听器的初始化方法
  22:       public void contextInitialized(ServletContextEvent event) {
  23:           // 通过这个事件可以获取整个应用的空间
  24:           // 在整个web应用下面启动的时候做一些初始化的内容添加工作
  25:           ServletContext sc = event.getServletContext();
  26:           // 设置一些基本的内容;比如一些参数或者是一些固定的对象
  27:           // 创建DataSource对象,连接池技术 dbcp
  28:           BasicDataSource bds = new BasicDataSource();
  29:           bds.setDriverClassName("com.mysql.jdbc.Driver");
  30:           bds.setUrl("jdbc:mysql://localhost:3306/hibernate");
  31:           bds.setUsername("root");
  32:           bds.setPassword("root");
  33:           bds.setMaxActive(10);//最大连接数
  34:           bds.setMaxIdle(5);//最大管理数
  35:           //bds.setMaxWait(maxWait); 最大等待时间
  36:           // 把 DataSource 放入ServletContext空间中,
  37:           // 供整个web应用的使用(获取数据库连接)
  38:           sc.setAttribute("dataSource", bds);
  39:           System.out.println("应用监听器初始化工作完成...");
  40:           System.out.println("已经创建DataSource...");
  41:       }
  42: }
web.xml中配置如下,很简单:

     1: <!-- 配置应用监听器  -->
     2:     <listener>
     3:         <listener-class>dc.gz.listeners.MyServletContextListener</listener-class>
     4:     </listener>
这样配置好了之后,以后在web应用中就可以通过ServletContext取得BasicDataSource对象,从而获取与数据库的连接,提高性能,方便使用。


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

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

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

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


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

函数回调: 自己定义函数,让系统去调用首先你要明白什么是函数指针。通过函数指针,可以得到函数所在的内存位置,从而执行该函数。在正常的程序执行过程中,调用方一般都是遇到函数就立即执行。而回调函数则是调用方通过函数指针的形式把函数储存起来。这样在合适的时机调用方就可以通过这个函数指针执行某个功能。回调函数可以说是一种订阅、分发的机制。被调用方可以通过订阅的形式将自己的处理函数以函数指针的形式交给调用方。当调用方需要执行这个回调函数的时候,就会通过分发的形式回调被调用方。回调函数的机制可以说无处不在,比如Channie Liu 所说的MFC消息机制,再比如HOOK,等等都是通过回调函数机制来执行的。但是回调函数并不是系统独有的机制。你完全可以在自己的程序中通过函数指针来实现一套回调函数。还有回调函数并不是面向对象编程,在某些情况下可以使用观察者模式来代替它。在.net中已经使用是事件的方式代替了回调函数来实现消息相应。