string boot 与 自定义interceptor的实例讲解

时间:2022-09-01 13:52:43

前面学习过过滤器, 但是过滤器是针对servlet的, 用在springmvc和spring boot里面, 功能上, 感觉并不是很好用.

那这里来学习一下拦截器.

一. 拦截器的执行顺序

1. 目录

string boot 与 自定义interceptor的实例讲解

2. 拦截器

拦截器里面, 我加了三个(first,two,third), 但是内容都差不多.

?
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, 才会继续下面的执行.

拦截器注册:

?
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);
  }
}

为了验证执行顺序, 这里使用了 thymeleaf, 然后在前台访问了我后台传过去的属性, 在访问的时候, 就会打印信息到控制台

?
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>

在访问 localhost:8080/first/index 的时候, 就会在控制台输出响应的信息.

string boot 与 自定义interceptor的实例讲解

这样, 就能看出单个拦截器的执行顺序.

1. 在控制器方法执行之前, 执行的 prehandle 方法

2. 执行控制器的action方法

3. 执行完action, 解析view之前(如果有的话), 执行拦截器的 posthandle 方法

4. 解析view

5. 解析完之后, 执行 aftercompletion 方法

当注册多个拦截器的时候, 执行顺序, 如图上所示了.

二. 拦截器实现权限验证

同样的, 先加入权限拦截器

?
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 {
  }
}

然后注册权限拦截器

?
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);
  }
}

在控制器中加入登录控制器, 提供登录页面和注销方法

?
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";
  }
}

这里我做了一个免登录注解, 可以加在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 {
}

注解里面, 并不需要任何内容.

登录页面(这里登录页面只是为了注销用的, 所以访问过这个页面之后, 就表示登录成功了).

?
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="注销" 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("注销成功");
          }
        }
      });
    });
  });
</script>
</body>
</html>

结果演示方式:

在浏览器中, 先打开 http://localhost:8080/login/index 页面, 然后在新标签中访问 http://localhost:8080/first/index 页面.

你会发现访问 first/index 的时候, 是可以访问的.

此时, 在login/index页面中, 点击注销按钮之后, 再刷新 first/index 页面, 就会直接跳去登录页面.

以上这篇string boot 与 自定义interceptor的实例讲解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:http://www.cnblogs.com/elvinle/archive/2017/12/23/8093062.html