关于过滤器,拦截器,监听器具体应用上的区别

概念上的区别都能查到,题主想了解的是,这三者在应用上有哪些自己不可以被其他两者替代的地方。
比如在某种功能上其中一种可以实现但另外两者做不到,或者其中一种可以很方便的实现但是另外两者想实现相同功能却很复杂。
比如List<String>和String[],虽然都可以存储多个String,但是如果不确定有多少个String需要存储,那么List<String>显然可以很容易实现这个功能。
再比如队和栈,双队可以实现栈的功能,双栈也可以实现队的功能,但是在先入先出和先入后出的情况,分别使用队和栈是可以方便实现的,而非要强行使用另外一种,也能实现,就是比较复杂。
所以同理,我想了解的是具体实现功能上的区别,而不是概念。

——————————————题主修改分隔线——————————————
在网上查询的过滤器和拦截器的区别,基本都是以下一模一样的5行话。

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

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

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

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

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

要么就是具体的实现的代码,关键是看不出应用上的区别,求大神指教。


——————————————回答分隔线——————————————

1.监听器是在发生关注的事件后回调开发者提供的方法
2.过滤器和拦截器没啥区别
3.List只是一个接口 对应的实现有很多 要看场景 比如删除、添加操作频繁 用java.util.LinkedList 如果只是想让SDK帮助你完成数组拓展 用java.util.ArrayList 如果要求线程安全 或者容量限制 那又用其他的容器了 看需求啊
4.双端队列和栈需要维护的引用数不同 所以添加、删除、对象大小都不同 如果你不需要双向遍历 当然用栈或者普通队列好一些啊

别想这些没用的了..

——————————————回答分隔线——————————————

我也来说说,希望能够帮到你。科学知识果然和哲学息息相关,这个世界是唯物主义的,人类设计的一切东西其实在生活里都能找到原型,也就是设计的灵感其实来源于生活。比如声纳定位其实来自蝙蝠夜行,飞机借鉴了鸟类,蛙人穿的衣服参考了青蛙。。。。。。软件领域更是如此,这些名词的含义就是生活里面的含义。

过滤器(Filter):

过滤器换一种表达就是预处理(pre processing)或者后处理(post processing),你说到的依赖于servlet容器,我觉得这是狭隘层次上的定义,你用米进行煮饭前要做什么,要用水先对米进行清洗,浸泡一下,这就是预处理;你榨完果汁后是直接喝吗,不,还要用筛子将果渣过滤掉,这就是后处理,对数据进行预处理或者后处理就是过滤器要做的工作,常见的应用有将请求中的数据进行转码,日志系统,系统缓存这些都是要依赖过滤器来实现,servlet中通过实现servlet中给的接口从而实现自定义过滤器,当有多个过滤器时就形成了过滤器链,也就是要依次经过过滤器链中的过滤器才能最终到达实际目标.

拦截器(Interceptor):

顾名思义,就是对数据进行拦截,从这个定义上看,似乎和过滤器很像,但是拦截器要做的工作更多是安全方面,比如用户验证,判断是否登陆。和过滤器的一个区别就是拦截器不一定会到达目标,也就是他可以拒绝你的请求,但是过滤器是一定会到达目标,但是在到达目标前或者后要进行一些操作.

监听器:

显然就是生活中的监视,和监听相关的概念就是事件,这些名词在生活中其实都经常接触。事件往大了说就是动作的序列,往小了说就是一个动作。想想电影中某个大boss叫你去监视某个人,那么你就充当了监听器的作用,监视的作用意义何在,就是当被监视对象出现了某个状态时要做出处理(触发某个方法),一般大boss会对你说如果那个人作出了什么举动(出现了某个状态),那么你就怎么怎么样,你监视的对象的动作或者说状态就是所谓的事件,而你(监听器)对这个状态的处理就是处理方法。举javascript中的例子来说,鼠标点击事件(onClick一个动作),键盘按下事件(onKeyDown,onKeyPress一个动作)等,显然javascript给相应对象设置了监听器。


——————————————回答分隔线——————————————

网上确实没找到现成的回答, 但对于三者的具体应用场景,还是有的.
题主自己没有用过, 就很难体会到.

过滤器:
过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),
或者在传入servlet或者 struts的action前统一设置字符集,
或者去除掉一些非法字符(聊天室经常用到的,一些骂人的话)。。。

拦截器:
进行权限验证,或者是来判断用户是否登陆,日志记录,或者限制时间点访问。
我自己用过拦截器,是用户每次登录时,都能记录一个登录时间。 (这点用拦截器明显合适,用过滤器明显不合适,因为没有过滤任何东西)

监听器:
没找到网上的,我写给你 当你要触发一个事件,但这件事既不是过滤,又不是拦截,那很可能就是监听! 联想到Windows编程里的,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。监听器的概念类似于这些。

由此可以看出三者的用法完全不同,不存在什么交集。 亲自做过项目就知道了。

——————————————回答分隔线——————————————

约定:

过滤器:用于属性甄别,对象收集(不可改变过滤对象的属性和行为)

监听器:用于对象监听,行为记录(不可改变监听对象的属性和行为)
拦截器:用于对象拦截,行为干预(可以改变拦截对象的属性和行为)


过滤器:对象收集

监听器:行为记录

拦截器:行为干预

能力逐渐增强:过滤器-->监听器-->拦截器


——————————————回答分隔线——————————————

206 人赞同了该回答

如果题主的问题是在问Struts下这三者的区别,随便看看就好。

以下回答从设计模式的角度分析它们的不同。一个个来。

过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。
拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。
监听器(Listener):当一个事件发生的时候,你希望获得这个事件发生的详细信息,而并不想干预这个事件本身的进程,这就要用到监听器。

======================================

                                                                    
更形象一点表示:

过滤器:只想要在一堆东西里面选个B



拦截器:把水流变小点,把鱼都拦住!顺便发个电

监听器:题主一定会说上面是个水利工程,其实发电的原理是这样的。。

======================================
                                                                                        

设计模式的命名都跟真实的场景有密切相关性,只要理解了命名,就理解了模式。题主在网上搜到的东西都是关于模式在Struts中的具体实现,虽然它们的确都在Struts中很常用,然而然而跟action、反射没有半毛钱关系,甚至跟Java都没有关系。不过显然题主对Java比较熟悉,碰巧我也比较熟悉Java,那不妨以Java举例:

Filter:
// 填充100个带有随机字母标签的球
List<String> array = new ArrayList<>();
Random r = new Random();
String[] balls = new String[]{"A", "B", "C"};
for (int i = 0; i < 100; i++)
  array.add(balls[r.nextInt(3)]);

// 只拿出B的来。不明白的自行学习Java 8
array = array.stream().filter(ball -> ball.equals("B")).collect(Collectors.toList());

Interceptor:
class River {
  // 流量
  int volume;

  // 总鱼数
  int numFish;
}

class PowerGenerator {
  double generate (int volume) {
    // 假设每一百立方米水发一度电
    return volume / 100;
  }
}

interface Interceptor {
  void intercept (River river);
}

class SomeInterceptor implements Interceptor {
  PowerGenerator generator = new PowerGenerator();

  @Override
  public void intercept (River river) {
    // 消耗了1000立方米水来发电
    int waterUsed = 1000;

    // 水量减少了1000。请不要跟我讨论水电站原理的问题,
    // 我就那么一比方
    river.volume -= waterUsed;

    // 发电
    generator.generate (waterUsed);

    // 拦截所有的鱼
    river.numFish = 0;
  }
}

class RiverController {
  Interceptor interceptor;

  void flow(River river) {
    // 源头积累下来的水量和鱼
    river.volume += 100000
    river.numFish += 1000

    // 经过了大坝
    interceptor.intercept(river);

    // 下了点雨
    river.volume += 1000
  }

  void setInterceptor (Interceptor interceptor) {
    this.interceptor = interceptor
  }
}

class Main {
  public static void main (String args[]) {
    RiverController rc = new RiverController;
    Interceptor inter = new SomeInterceptor();

    // 这一步通常叫做控制反转或依赖注入,其实也没啥子
    rc.setInterceptor(inter);

    rc.flow(new River());
  }
}

Listener:
// 监听器
interface BedListener {
  // 监听器在参数中收到了某个事件,而这个事件往往是只读的
  // 监听器的方法名通常以"on"开头
  void onBedSound (String sound);
}

class Neighbor {
  BedListener listener;

  // 依然是所谓控制反转
  setListener (BedListener listener) {
    this.listener = listener;
  }

  void doInterestingStuff () {
    // 根据当地法律法规,部分内容无法显示

    // 将事件发送给监听器
    listener.onBedSound("嘿咻");
    listener.onBedSound("oyeah");
  }
}

class Main {
  public static void main (String args[]) {
    Neighbor n = new Neighbor();
    n.setListener (sound -> generatePower());
    n.doInterestingStuff();
  }

  private static void generatePower() {
    // 根据当地法律法规,部分内容无法显示
  }
}

======================================

                                                                                        
在真实使用中,很多人,不管是新手还是老手会犯的一个错误是,在不该改变对象状态的时候强制改变它,或者在应该传入只读参数时传入了可变参数。

上面的例子中,Filter的例子是JDK提供的函数,如果你在这里改变了对象的状态(当然例子里的String类型本来就不可以改变),就违背了filter的约定。

同样的,在Listener中不管是传入了可变的对象,或是对该对象进行了修改,都是违背设计模式约定的做法,会给其他读代码的人造成困扰。

而Interceptor几乎可以对流程做任何事情,所以没有什么特别要注意的地方,用这一类接口的时候仔细读文档,设计这一类接口的时候仔细写文档吧。

三幅大图系无节操手绘,凑和着看吧。

—————回复1分隔线————

飞面神下一只猪 (提问者)

看完了,非常感谢您的回答。
有几个问题还想再请教下。
1.以你的例子而言,过滤器是不是也可以实现在一条河过来的时候只让鱼通过?而拦截器也能做到拦住非B的球从而只让B通过?
2.最后三段话,是指过滤器和拦截器在大部分的情况下都是通用的。但是尽量为了代码的可读性,尽量不要在过滤器中对对象进行改变的操作,如果需要改变对象,则应该使用拦截器?
3.还是题目中提到的问题,有没有某个具体的功能,用其中某种可以方便的实现,而用其他的,则比较困难?
再次感谢。

知乎用户 (作者) 回复飞面神下一只猪 (提问者)

三个问题其实是一个问题。拦截器是应用在某个流程中的,多数情况下会有一个贯穿流程的对象(栗子中的River),拦截器是可以对这个对象有读写权限的。过滤器要简单得多,它只是一个筛选的过程,所以它看到的是一个集合里单个的对象,而没有对整个集合有任何权限。一旦在过滤器里改变了对象,那它就是个不符合约定的过滤器,但它不会变成一个拦截器因为它没有访问贯穿流程的对象(filter栗子中的那个list)。所以主要区别在所操作的对象,而不是具体的功能。你说的拦截器和过滤器都可以把鱼都去掉,没错,但是拦截器看到的是River,过滤器只能看到鱼、水、沙等需要取舍的东西。这样说明白了不


来自:https://www.zhihu.com/question/35225845

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
拦截器过滤器监听器是Java中常用的三种应用组件,它们在不同的场景下有不同的作用。 1. 拦截器(Interceptor): 拦截器是一种在方法调用前后、异常抛出前后等特定点进行拦截的组件。它可以用于实现日志记录、权限验证、性能监控等功能。在Java中,拦截器常用于框架(如Spring)中,通过AOP(面向切面编程)的方式来实现。拦截器可以对方法进行拦截,并在方法执行前后进行一些处理。 2. 过滤器(Filter): 过滤器是一种用于在请求到达目标资源之前或之后进行预处理或后处理的组件。它可以用于实现请求参数处理、字符编码转换、请求拦截等功能。在Java Web开发中,过滤器常用于对请求进行预处理,如验证用户身份、设置字符编码等。过滤器可以对请求进行拦截,并在请求到达目标资源之前或之后进行一些处理。 3. 监听器(Listener): 监听器是一种用于监听特定事件并采取相应行动的组件。它可以用于实现应用程序的启动和关闭监听、会话创建和销毁监听、属性变化监听等功能。在Java中,监听器常用于Web应用程序中,通过监听特定事件来执行相应的逻辑。监听器可以监听特定事件的发生,并在事件发生时执行一些处理。 以下是一个简单的示例,展示了拦截器过滤器监听器应用: 1. 拦截器示例: ```java public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在方法调用前执行的逻辑 // ... return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 在方法调用后执行的逻辑 // ... } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在方法调用完成后执行的逻辑 // ... } } ``` 2. 过滤器示例: ```java public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // 过滤器初始化逻辑 // ... } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 过滤器处理逻辑 // ... chain.doFilter(request, response); } @Override public void destroy() { // 过滤器销毁逻辑 // ... } } ``` 3. 监听器示例: ```java public class MyListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { // 应用程序启动时执行的逻辑 // ... } @Override public void contextDestroyed(ServletContextEvent sce) { // 应用程序关闭时执行的逻辑 // ... } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值