首页 >> 百科

过滤器和拦截器的区别(拦截器和过滤器的简单解释)

2022-12-02 百科 135 作者:admin

周末有朋友加我微信,问我一个问题:大哥,()和()有什么区别?听到标题,我的第一感觉就是:“简单”!

毕竟这两个工具在开发中的使用频率都挺高的,应用也比较简单,但是刚要回复他的时候,却不知从何下手。不,我已经工作了这么长时间来回答这样一个基本问题,我失去了我的主人。

我通常会想到简单的知识点,但通常不会太注意细节。曾经被别人问过,我也说不出原因。

说到底还是对这些知识了解不够,一直停留在会用的阶段,以至于现在“见了就没用”!这是底子薄的典型表现,哎~,其实我就是浮肿了!

知耻而后勇。下面我们结合实践,更直观地感受一下两者的区别。

我们在项目中同时配置了拦截器和过滤器。

过滤器的配置相对简单。可以直接实现接口,也可以通过@注解拦截具体的url。可以看到接口中定义了三个方法。

init() :该方法在容器开始初始化过滤器时调用,整个生命周期只会调用一次。【注意】:该方法必须执行成功,否则过滤器将不起作用。

() : 容器中的每一个请求都会调用这个方法来调用下一个过滤器。

():当容器销毁过滤器实例时调用该方法。一般在方法中销毁或关闭资源,在过滤器的整个生命周期中只会调用一次。

@

班级 {

@

无效初始化(){

.out.("前置");

}

@

空白 ( , , ) , {

.out.("处理中");

.(, );

}

@

空白 () {

。前哨”);

}

}

拦截器是一个链式调用。一个应用中可以同时存在多个拦截器,一个请求也可以触发多个拦截器,每个拦截器的调用会按照其声明的顺序依次执行。

先写一个简单的拦截器处理类,通过传递实现对请求的拦截,看到接口中也定义了三个方法。

() : 这个方法会在请求被处理之前被调用。“注意”:如果该方法的返回值为false,则视为本次请求结束,不仅自身拦截器失效,还会导致其他拦截器不再执行。

():只有当()方法的返回值为true时才会执行。将在调用 in 中的方法之后,在返回渲染视图之前调用。《有趣的事》:()方法的调用顺序与()相反。最先声明的拦截器()方法先执行,而()方法后执行。

():只有当()方法的返回值为true时才会执行。整个请求结束,对应的视图渲染完成后执行。

@

班级 {

@

( , , ) {

.out.("前置");

真的;

}

@

空白 ( , , , ) {

.out.("处理中");

}

@

无效(,,,前){

。前哨”);

}

}

注册自定义拦截器处理类,通过 .

@

班级 {

@

空白 ( ) {

。(新的 ())。(”/**”);

。(新的 ())。(”/**”);

}

}

过滤器和拦截器都体现了AOP编程思想,都可以实现日志记录和登录认证等功能,但是两者之间有很多区别,接下来会一一说明。

过滤器和拦截器的底层实现是非常不同的。过滤器是基于函数回调实现的,而拦截器是基于Java的反射机制(动态代理)实现的。

专注于这里的过滤器!

我们自定义的过滤器中会执行一个()方法,这个方法有一个参数,但实际上是一个回调接口。in是它的实现类,这个实现类内部还有一个()方法,就是回调方法。

{

void ( 变量 1, 变量 2) , ;

}

中,我们可以获取到我们的自定义类,在其内部回调方法中调用每个自定义过滤器(),并执行()方法。

{ 的最后一堂课

@

空白 ( , ) {

。忽略

(,);

}

空白 ( , ) {

如果(位置 < n){

//获取位置

图 = [位置];

=.();

...

。(, , 这个);

}

}

}

并且各自会先执行自己的()过滤逻辑,最后在执行结束前执行.(,),即回调in的()方法,通过循环执行实现函数回调。

@

空白 ( , , ) , {

.(, );

}

我们看到实现了javax..接口,而这个接口是在规范中定义的,也就是说的使用依赖于容器,所以只能在web程序中使用。

拦截器()是一个组件,由容器管理。它不依赖于其他容器,可以单独使用。不仅可以用在web程序中,还可以用在 , Swing 等程序中。

过滤器和拦截器的触发时机也不一样。让我们看看下面的图片。

过滤器在请求进入容器之后,但在进入之前进行预处理,请求结束是在处理之后。

拦截器在请求进入后和进入前进行预处理,在相应的视图渲染完成后请求结束。

上面我们同时配置了过滤器和拦截器,然后构建接收请求进行测试。

@

@()

类测试{

@("/测试1")

@

测试 1(a) {

.out.("我是");

无效的;

}

}

在项目启动过程中,发现的init()方法是随着容器的启动而初始化的。

这时候浏览器发送请求,F12看到其实有两个请求,一个是我们自定义的请求,一个是访问静态图标资源的请求。

看到控制台的打印日志如下:

执行顺序:处理->预处理->我->处理->处理后

加工

正面

加工

后部

加工

过滤器执行两次,拦截器只执行一次。这是因为过滤器几乎可以对所有进入容器的请求起作用,而拦截器只会对中间请求或访问目录下的资源请求起作用。

在实际业务场景中,应用于过滤器或拦截器时,不可避免地会引入一些服务来处理业务逻辑。

接下来我们在过滤器和拦截器中都注入,看看有什么区别?

@

班级 {

@

无效一个(){

.out.("我是方法A");

}

}

注入过滤器,发起请求测试,日志正常打印“我是方法A”。

@

;

@

空白 ( , , ) , {

.out.("处理中");

。一个();

.(, );

}

加工

我是方法A

正面

我是

加工

后部

在拦截器中注入,发起请求测试一下,结果TM报错,调试发现为什么注入为Null?

这是加载顺序引起的问题。之前加载拦截器,Bean由它来管理。

拦截者:我今天要进洞房;哥:你别闹,我还没生你媳妇呢!

解决方法也很简单,我们在注册拦截器之前手动注入。“注意”:() 实例注册在.() 中。

@

班级 {

@豆

(){

.out.("注入");

新的 ();

}

@

空白 ( ) {

.(()).("/**");

}

}

在实际开发过程中,会同时存在多个过滤器或拦截器。但是,有时我们希望某个过滤器或拦截器先执行,这就涉及到它们的执行顺序。

过滤器使用@Order注解来控制执行顺序,过滤器的级别由@Order控制。值越小,级别越高,最先执行。

@命令(。)

@

班级 {

拦截器默认的执行顺序是它的注册顺序,也可以通过Order手动设置和控制。值越小,执行越早。

@

空白 ( ) {

.(new ()).("/**").order(2);

.(new ()).("/**").order(1);

.(new ()).("/**").order(3);

}

看输出结果,发现先声明的拦截器()方法先执行,但是()方法后执行。

()方法的调用顺序其实和()是相反的!如果在实际开发中对执行顺序有严格要求,这一点要特别注意。

正面

正面

正面

我是

加工

加工

加工

后部

治疗后

治疗后

“那为什么会这样?” 要得到答案,只能看源码了。我们要知道,服务器中的所有请求都必须经过核心组件进行路由,其()方法才会被执行,拦截器()和()方法在其中被调用。

空白 ( , ) {

尝试 {

…………

尝试 {

// 获取当前可以执行的适配器

ha = (.());

// last- ,如果由 .

=.();

isGet = "GET".();

如果 (isGet || "HEAD".()) {

long = ha.(, .());

如果 (。()) {

.debug("[" () "] 的最后一个值是:" );

}

如果 (新的 (, ).() && isGet) {

;

}

}

// 注意:执行()方法

如果 (!。(, )) {

;

}

// 注意:【包括我们的业务逻辑,当抛出异常时,会被Try并捕获】

mv = ha.(, , .());

如果 (。()) {

;

}

(, MV);

// 注意:执行中的方法【抛出异常时不能执行】

.(, , MV);

}

}

…………

}

看看(),()这两个方法是怎么调用的,就会明白为什么()和()的执行顺序是相反的。

( , ) {

[] = 这个.();

如果(!。()) {

for(int i = 0; i < .; this. = i ) {

= [我];

如果这。)) {

this.on(, , ()null);

错误的;

}

}

}

真的;

}

无效(,,@mv){

[] = 这个.();

如果(!。()) {

for(int i = . - 1; i >= 0; --i) {

= [我];

.(, , 这个., mv);

}

}

}

事实证明,当两个方法调用拦截器 array[] 时,循环的顺序是相反的。. . ,导致 () 和 () 方法的执行顺序颠倒。

相信大多数人都能熟练使用过滤器和拦截器,但是两者的区别还是需要多了解一下,不然在开发中使用不当时不时会出现奇怪的问题。以上内容比较简单,新手要向老手学习复习,希望大家积极补充缺失的部分。如有理解上的错误,还望大家不吝赐教。

关于我们

最火推荐

小编推荐

联系我们


Copyright 8S新商盟 Rights Reserved.
联系YY号:2949821684
邮箱:chenjing919994@sohu.com
备案号:浙ICP备2023016511号-1