前面學(xué)習(xí)過(guò)過(guò)濾器, 但是過(guò)濾器是針對(duì)servlet的, 用在springmvc和spring boot里面, 功能上, 感覺(jué)并不是很好用.
那這里來(lái)學(xué)習(xí)一下攔截器.
一. 攔截器的執(zhí)行順序
1. 目錄
2. 攔截器
攔截器里面, 我加了三個(gè)(first,two,third), 但是內(nèi)容都差不多.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package org.elvin.boot.interceptor; import org.springframework.web.servlet.handlerinterceptor; import org.springframework.web.servlet.modelandview; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; public class firstinterceptor implements handlerinterceptor { @override public boolean prehandle(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, object o) throws exception { system.out.println( "firstinterceptor prehandle" ); return true ; } @override public void posthandle(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, object o, modelandview modelandview) throws exception { system.out.println( "firstinterceptor posthandle" ); } @override public void aftercompletion(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, object o, exception e) throws exception { system.out.println( "firstinterceptor aftercompletion" ); } } |
prehandle 返回true, 才會(huì)繼續(xù)下面的執(zhí)行.
攔截器注冊(cè):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package org.elvin.boot.interceptor; import org.springframework.context.annotation.configuration; import org.springframework.web.servlet.config.annotation.interceptorregistry; import org.springframework.web.servlet.config.annotation.webmvcconfigureradapter; @configuration public class registerinterceptor extends webmvcconfigureradapter { @override public void addinterceptors(interceptorregistry registry) { registry.addinterceptor( new firstinterceptor()); registry.addinterceptor( new twointerceptor()); registry.addinterceptor( new thirdinterceptor()); super .addinterceptors(registry); } } |
為了驗(yàn)證執(zhí)行順序, 這里使用了 thymeleaf, 然后在前臺(tái)訪問(wèn)了我后臺(tái)傳過(guò)去的屬性, 在訪問(wèn)的時(shí)候, 就會(huì)打印信息到控制臺(tái)
1
2
3
4
5
6
7
8
9
10
11
|
package org.elvin.boot.pojo; public class book { private string name ; public string getname() { system.out.println( "view : book'name is " + name); return name; } public void setname(string name) { this .name = name; } } |
controller:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package org.elvin.boot.controller; import org.elvin.boot.pojo.book; import org.springframework.stereotype.controller; import org.springframework.ui.model; import org.springframework.web.bind.annotation.getmapping; import org.springframework.web.bind.annotation.requestmapping; @controller @requestmapping ( "first" ) public class firstcontroller { private string controllerpath = "first/" ; @getmapping ( "index" ) public string index(model model){ system.out.println( "controller : firstcontroller index doing..." ); book book = new book(); book.setname( "spring boot" ); model.addattribute( "book" , book); return controllerpath + "index" ; } } |
view:
1
2
3
4
5
6
7
8
9
10
|
<!doctype html> <html lang= "en" > <head> <meta charset= "utf-8" /> <title>title</title> </head> <body> <h1 th:text= "${book.name}" ></h1> </body> </html> |
在訪問(wèn) localhost:8080/first/index 的時(shí)候, 就會(huì)在控制臺(tái)輸出響應(yīng)的信息.
這樣, 就能看出單個(gè)攔截器的執(zhí)行順序.
1. 在控制器方法執(zhí)行之前, 執(zhí)行的 prehandle 方法
2. 執(zhí)行控制器的action方法
3. 執(zhí)行完action, 解析view之前(如果有的話), 執(zhí)行攔截器的 posthandle 方法
4. 解析view
5. 解析完之后, 執(zhí)行 aftercompletion 方法
當(dāng)注冊(cè)多個(gè)攔截器的時(shí)候, 執(zhí)行順序, 如圖上所示了.
二. 攔截器實(shí)現(xiàn)權(quán)限驗(yàn)證
同樣的, 先加入權(quán)限攔截器
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
|
package org.elvin.boot.interceptor; import org.elvin.boot.annotation.nologin; import org.springframework.util.stringutils; import org.springframework.web.method.handlermethod; import org.springframework.web.servlet.handlerinterceptor; import org.springframework.web.servlet.modelandview; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import javax.servlet.http.httpsession; public class logininterceptor implements handlerinterceptor { @override public boolean prehandle(httpservletrequest request, httpservletresponse response, object handle) throws exception { handlermethod method = (handlermethod ) handle; class <?> controllertype = method.getbeantype(); if (method.getmethodannotation(nologin. class ) != null || controllertype.getannotation(nologin. class ) != null ){ return true ; } httpsession session = request.getsession(); string token = (string)session.getattribute( "token" ); if (!stringutils.isempty(token)){ return true ; } response.sendredirect( "/login/index" ); return false ; } @override public void posthandle(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, object o, modelandview modelandview) throws exception { } @override public void aftercompletion(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, object o, exception e) throws exception { } } |
然后注冊(cè)權(quán)限攔截器
1
2
3
4
5
6
7
8
9
10
11
12
|
package org.elvin.boot.interceptor; import org.springframework.context.annotation.configuration; import org.springframework.web.servlet.config.annotation.interceptorregistry; import org.springframework.web.servlet.config.annotation.webmvcconfigureradapter; @configuration public class registerinterceptor extends webmvcconfigureradapter { @override public void addinterceptors(interceptorregistry registry) { registry.addinterceptor( new logininterceptor()); super .addinterceptors(registry); } } |
在控制器中加入登錄控制器, 提供登錄頁(yè)面和注銷(xiāo)方法
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
|
package org.elvin.boot.controller; import org.elvin.boot.annotation.nologin; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.controller; import org.springframework.web.bind.annotation.getmapping; import org.springframework.web.bind.annotation.postmapping; import org.springframework.web.bind.annotation.requestmapping; import org.springframework.web.bind.annotation.responsebody; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import javax.servlet.http.httpsession; @nologin @controller @requestmapping ( "login" ) public class logincontroller { @autowired private httpservletrequest request; @autowired private httpservletresponse response; private string controllerpath = "login/" ; //@nologin @getmapping ( "index" ) public string index(){ httpsession session = request.getsession(); session.setattribute( "token" , "token" ); return controllerpath + "index" ; } //@nologin @postmapping ( "checkout" ) @responsebody public string checkout(){ httpsession session = request.getsession(); session.setattribute( "token" , null ); return "ok" ; } } |
這里我做了一個(gè)免登錄注解, 可以加在controller上, 也可以加在 action 上.
1
2
3
4
5
6
7
8
9
|
package org.elvin.boot.annotation; import java.lang.annotation.elementtype; import java.lang.annotation.retention; import java.lang.annotation.retentionpolicy; import java.lang.annotation.target; @target ({elementtype.type, elementtype.method}) @retention (retentionpolicy.runtime) public @interface nologin { } |
注解里面, 并不需要任何內(nèi)容.
登錄頁(yè)面(這里登錄頁(yè)面只是為了注銷(xiāo)用的, 所以訪問(wèn)過(guò)這個(gè)頁(yè)面之后, 就表示登錄成功了).
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
|
<!doctype html> <html xmlns:th= "http://www.thymeleaf.org" > <head> <meta charset= "utf-8" /> <title>title</title> </head> <body> <div class = "container" > <input type= "button" value= "注銷(xiāo)" id= "checkout" /> </div> <script th:src= "@{/js/jquery-1.11.1.js}" ></script> <script th:inline= "javascript" > $(function () { $( ".container" ).delegate( "#checkout" , "click" , function () { $.ajax({ url: [[@{/login/checkout}]], type: 'post' , data: {}, success: function (res) { if (res == "ok" ) { alert( "注銷(xiāo)成功" ); } } }); }); }); </script> </body> </html> |
結(jié)果演示方式:
在瀏覽器中, 先打開(kāi) http://localhost:8080/login/index 頁(yè)面, 然后在新標(biāo)簽中訪問(wèn) http://localhost:8080/first/index 頁(yè)面.
你會(huì)發(fā)現(xiàn)訪問(wèn) first/index 的時(shí)候, 是可以訪問(wèn)的.
此時(shí), 在login/index頁(yè)面中, 點(diǎn)擊注銷(xiāo)按鈕之后, 再刷新 first/index 頁(yè)面, 就會(huì)直接跳去登錄頁(yè)面.
以上這篇string boot 與 自定義interceptor的實(shí)例講解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.cnblogs.com/elvinle/archive/2017/12/23/8093062.html