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 |