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

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

一. 拦截器的执行顺序

1. 目录

2. 拦截器

拦截器里面, 我加了三个(First,Two,Third), 但是内容都差不多.

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

拦截器注册:

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, 然后在前台访问了我后台传过去的属性, 在访问的时候, 就会打印信息到控制台

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:

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:

<!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 的时候, 就会在控制台输出响应的信息.

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

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

2. 执行控制器的action方法

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

4. 解析view

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

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

二. 拦截器实现权限验证

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

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

然后注册权限拦截器

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

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

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 上.

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

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

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

<!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 页面, 就会直接跳去登录页面.

spring boot 与 自定义interceptor的更多相关文章

  1. Spring Boot2 系列教程(十八)Spring Boot 中自定义 SpringMVC 配置

    用过 Spring Boot 的小伙伴都知道,我们只需要在项目中引入 spring-boot-starter-web 依赖,SpringMVC 的一整套东西就会自动给我们配置好,但是,真实的项目环境比 ...

  2. Spring Boot 引入自定义yml

    喜欢yml配置文件格式的人性化,也喜欢properties配置文件管理方式的人性化, 那么下面我们就来看一下 yml 是如何配置和使用类似properties管理方式的人性化. 配置文件 设置Spri ...

  3. Spring Boot (一): Spring Boot starter自定义

    前些日子在公司接触了spring boot和spring cloud,有感于其大大简化了spring的配置过程,十分方便使用者快速构建项目,而且拥有丰富的starter供开发者使用.但是由于其自动化配 ...

  4. spring boot项目自定义数据源,mybatisplus分页、逻辑删除无效解决方法

    Spring Boot项目中数据源的配置可以通过两种方式实现: 1.application.yml或者application.properties配置 2.注入DataSource及SqlSessio ...

  5. 小代学Spring Boot之自定义Starter

    想要获取更多文章可以访问我的博客 - 代码无止境. 上一篇小代同学在Spring Boot项目中配置了数据源,但是通常来讲我们访问数据库都会通过一个ORM框架,很少会直接使用JDBC来执行数据库操作的 ...

  6. Spring Boot中自定义注解+AOP实现主备库切换

    摘要: 本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的 ...

  7. 【spring boot】spring boot的自定义banner修改+spring boot启动项目图标修改

    1.启动Spring Boot项目后会看到这样的图案,这个图片其实是可以自定义的,打开网站 http://patorjk.com/software/taag/#p=display&h=3&am ...

  8. Spring Boot实现自定义注解

    在Spring Boot项目中可以使用AOP实现自定义注解,从而实现统一.侵入性小的自定义功能. 实现自定义注解的过程也比较简单,只需要3步,下面实现一个统一打印日志的自定义注解: 1. 引入AOP依 ...

  9. spring boot通过自定义注解和AOP拦截指定的请求

    一 准备工作 1.1 添加依赖 通过spring boot创建好工程后,添加如下依赖,不然工程中无法使用切面的注解,就无法对制定的方法进行拦截 <dependency> <group ...

随机推荐

  1. C#-vs2012学习笔记-惊奇于vs的强大和便利

    网站常用功能自动完成,包括网页和数据库.

  2. 【repost】 原生JS执行环境与作用域深入理解

    首先,我们要知道执行环境和作用域是两个完全不同的概念. 函数的每次调用都有与之紧密相关的作用域和执行环境.从根本上来说,作用域是基于函数的,而执行环境是基于对象的(例如:全局执行环境即window对象 ...

  3. ajax请求也可以用form表单向后台提交数据!!!!

    激动的我简直语无伦次,不说了上代码,用ajax实现form表单数据的请求,啦啦啦啦 html: <form> <input name="userName" val ...

  4. noip第10课资料

  5. Swagger UI教程 API 文档神器 搭配Node使用

    ASP.NET Web API 使用Swagger生成在线帮助测试文档 Swagger 生成 ASP.NET Web API 前言 swagger ui是一个API在线文档生成和测试的利器,目前发现最 ...

  6. Navicat连接mysql8.0.1版本出现1251--Client does not support authentication protocol requested by server的解决

    转载自:https://blog.csdn.net/XDMFC/article/details/80263215 好不容易安装好mysql,但又出现了mysql客户端版本太低的问题.根据参考的这篇博客 ...

  7. kafka_shell操作

    单机版 开启进程: ./bin/kafka-server-start.sh config/server.properties 查看topic列表: ./bin/kafka-topics.sh --li ...

  8. tarjan算法的补充POJ2533tarjan求度

    做题时又遇到了疑惑,说明一开始就没有完全理解 基于dfs的tarjan,搜索时会有四种边 树枝边:DFS 时经过的边,即 DFS 搜索树上的边 前向边:与 DFS 方向一致,从某个结点指向其某个子孙的 ...

  9. shell 命令 rz sz

    尝试了几个版本,下面的是可用的 https://segmentfault.com/a/1190000012166969

  10. unigui1404在delphi10.2.2安装

    unigui1404在delphi10.2.2安装 UNIGUI1404不能直接在DELPHI10.2.2下面编译安装,在10.2.1下面是可以的. 这里讲下怎样安装的方法: 1)执行FMSoft_u ...