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 |