filter
新建 timefilter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@component
public class timefilter implements filter {
@override
public void init(filterconfig filterconfig) throws servletexception {
system.out.println( "time filter init" );
}
@override
public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception {
system.out.println( "time filter start" );
long starttime = system.currenttimemillis();
filterchain.dofilter(servletrequest, servletresponse);
long endtime = system.currenttimemillis();
system.out.println( "time filter consume " + (endtime - starttime) + " ms" );
system.out.println( "time filter end" );
}
@override
public void destroy() {
system.out.println( "time filter init" );
}
}
|
启动服务器,在浏览器输入:http://localhost:8080/hello?name=tom
可以在控制台输出如下结果:
time filter start
name: tom
time filter consume 3 ms
time filter end
可以看到,filter 先执行,再到真正执行 hellocontroller.sayhello() 方法。
通过 timefilter.dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) 方法的参数可以看出,我们只能得到原始的 request 和 response对象,不能得到这个请求被哪个 controller 以及哪个方法处理了,使用interceptor 就可以获得这些信息。
interceptor
新建 timeinterceptor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
@component
public class timeinterceptor extends handlerinterceptoradapter {
private final namedthreadlocal< long > starttimethreadlocal = new namedthreadlocal<>( "starttimethreadlocal" );
@override
public boolean prehandle(httpservletrequest request, httpservletresponse response, object handler) throws exception {
system.out.println( "time interceptor prehandle" );
handlermethod handlermethod = (handlermethod) handler;
// 获取处理当前请求的 handler 信息
system.out.println( "handler 类:" + handlermethod.getbeantype().getname());
system.out.println( "handler 方法:" + handlermethod.getmethod().getname());
methodparameter[] methodparameters = handlermethod.getmethodparameters();
for (methodparameter methodparameter : methodparameters) {
string parametername = methodparameter.getparametername();
// 只能获取参数的名称,不能获取到参数的值
//system.out.println("parametername: " + parametername);
}
// 把当前时间放入 threadlocal
starttimethreadlocal.set(system.currenttimemillis());
return true ;
}
@override
public void posthandle(httpservletrequest request, httpservletresponse response, object handler, modelandview modelandview) throws exception {
system.out.println( "time interceptor posthandle" );
}
@override
public void aftercompletion(httpservletrequest request, httpservletresponse response, object handler, exception ex) throws exception {
// 从 threadlocal 取出刚才存入的 starttime
long starttime = starttimethreadlocal.get();
long endtime = system.currenttimemillis();
system.out.println( "time interceptor consume " + (endtime - starttime) + " ms" );
system.out.println( "time interceptor aftercompletion" );
}
}
|
注册 timeinterceptor
把 timeinterceptor 注入 spring 容器
1
2
3
4
5
6
7
8
9
10
11
|
@configuration
public class webconfig extends webmvcconfigureradapter {
@autowired
private timeinterceptor timeinterceptor;
@override
public void addinterceptors(interceptorregistry registry) {
registry.addinterceptor(timeinterceptor);
}
}
|
启动服务器,在浏览器输入:http://localhost:8080/hello?name=tom
可以在控制台输出如下结果:
1
2
3
4
5
6
7
8
9
10
|
time filter start
time interceptor prehandle
handler 类:com.nextyu.demo.web.controller.hellocontroller
handler 方法:sayhello
name: tom
time interceptor posthandle
time interceptor consume 40 ms
time interceptor aftercompletion
time filter consume 51 ms
time filter end
|
可以看到,filter 先于 interceptor 执行,再到真正执行 hellocontroller.sayhello() 方法。通过 interceptor 方法上的 handler 参数,我们就可以得到这个请求被哪个 controller 以及哪个方法处理了。但是不能直接获取到这个方法上的参数值(在这里就是 hellocontroller.sayhello(string name) 方法参数 name 的值),通过 aspect 就可以获取到。
aspcet
新建 timeaspect
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
@aspect
@component
public class timeaspect {
@around ( "execution(* com.nextyu.demo.web.controller.*.*(..))" )
public object handlecontrollermethod(proceedingjoinpoint pjp) throws throwable {
system.out.println( "time aspect start" );
object[] args = pjp.getargs();
for (object arg : args) {
system.out.println( "arg is " + arg);
}
long starttime = system.currenttimemillis();
object object = pjp.proceed();
long endtime = system.currenttimemillis();
system.out.println( "time aspect consume " + (endtime - starttime) + " ms" );
system.out.println( "time aspect end" );
return object;
}
}
|
启动服务器,在浏览器输入:http://localhost:8080/hello?name=tom
可以在控制台输出如下结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
time filter start
time interceptor prehandle
handler 类:com.nextyu.demo.web.controller.hellocontroller
handler 方法:sayhello
time aspect start
arg is tom
name: tom
time aspect consume 0 ms
time aspect end
time interceptor posthandle
time interceptor consume 2 ms
time interceptor aftercompletion
time filter consume 4 ms
time filter end
|
可以看到,filter 先执行,再到 interceptor 执行,再到 aspect 执行,再到真正执行 hellocontroller.sayhello() 方法。
我们也获取到了 hellocontroller.sayhello(string name) 方法参数 name 的值。
请求拦截过程图
1
2
3
4
5
|
graph td
httprequest-->filter
filter-->interceptor
interceptor-->aspect
aspect-->controller
|