spring boot 与 自定义interceptor
前面学习过过滤器, 但是过滤器是针对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的更多相关文章
- Spring Boot2 系列教程(十八)Spring Boot 中自定义 SpringMVC 配置
用过 Spring Boot 的小伙伴都知道,我们只需要在项目中引入 spring-boot-starter-web 依赖,SpringMVC 的一整套东西就会自动给我们配置好,但是,真实的项目环境比 ...
- Spring Boot 引入自定义yml
喜欢yml配置文件格式的人性化,也喜欢properties配置文件管理方式的人性化, 那么下面我们就来看一下 yml 是如何配置和使用类似properties管理方式的人性化. 配置文件 设置Spri ...
- Spring Boot (一): Spring Boot starter自定义
前些日子在公司接触了spring boot和spring cloud,有感于其大大简化了spring的配置过程,十分方便使用者快速构建项目,而且拥有丰富的starter供开发者使用.但是由于其自动化配 ...
- spring boot项目自定义数据源,mybatisplus分页、逻辑删除无效解决方法
Spring Boot项目中数据源的配置可以通过两种方式实现: 1.application.yml或者application.properties配置 2.注入DataSource及SqlSessio ...
- 小代学Spring Boot之自定义Starter
想要获取更多文章可以访问我的博客 - 代码无止境. 上一篇小代同学在Spring Boot项目中配置了数据源,但是通常来讲我们访问数据库都会通过一个ORM框架,很少会直接使用JDBC来执行数据库操作的 ...
- Spring Boot中自定义注解+AOP实现主备库切换
摘要: 本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的 ...
- 【spring boot】spring boot的自定义banner修改+spring boot启动项目图标修改
1.启动Spring Boot项目后会看到这样的图案,这个图片其实是可以自定义的,打开网站 http://patorjk.com/software/taag/#p=display&h=3&am ...
- Spring Boot实现自定义注解
在Spring Boot项目中可以使用AOP实现自定义注解,从而实现统一.侵入性小的自定义功能. 实现自定义注解的过程也比较简单,只需要3步,下面实现一个统一打印日志的自定义注解: 1. 引入AOP依 ...
- spring boot通过自定义注解和AOP拦截指定的请求
一 准备工作 1.1 添加依赖 通过spring boot创建好工程后,添加如下依赖,不然工程中无法使用切面的注解,就无法对制定的方法进行拦截 <dependency> <group ...
随机推荐
- 基于MATLAB的Sobel边缘检测算法实现
图像边缘就是图像灰度值突变的地方,也就是图像在该部分的像素值变化速度非常之快,就比如在坐标轴上一条曲线有刚开始的平滑突然来个大转弯,在变化出的导数非常大. Sobel算子主要用作边缘检测,它是一离散型 ...
- node-lessons
教程:https://github.com/alsotang/node-lessons 0 nvm 的全称是 Node Version Manager,之所以需要这个工具,是因为 Node.js 的各 ...
- SRM482
250pt 题意:给定n把锁,第i轮每间隔i个打开一个木有打开的.问最后打开的事几 思路:直接vector模拟 code: #line 7 "LockersDivOne.cpp" ...
- JBoss 系列四十九:JBoss 7/WildFly 中端口使用列表
JBoss 7中端口使用列表 JBoss 7中所有配置都在一个文件中(standaone*.xml, domain.xml),和之前的JBoss相比JBoss 7用到的端口变少,我们将以表格的形式列出 ...
- scikit-FEM-例2-用Morley元在方形区域上解板弯曲问题
""" Author: kinnala Solve the Kirchhoff plate bending problem in a unit square with c ...
- Android-Kotlin-空值处理&字符串比较&常量
空值处理: [案例一:] 1.Kotlin对控制处理很严格,默认就不能写null,否则编译都不通过: 描述Car汽车对象: package cn.kotlin.kotlin_base01 /** * ...
- Android-HttpClient-Get与Post请求登录功能
HttpClient 是org.apache.http.* 包中的: 第一种方式使用httpclient-*.jar (需要在网上去下载httpclient-*.jar包) 把httpclient-4 ...
- mysql 返回结果按照指定的id顺序返回
mysql> ,,,,) order by field(id,,,,,) limit ,; +----+-------+------+ | id | name | sex | +----+--- ...
- .net core Area独立成单独的dll文件
以前做MES项目遇到过这个情况,一个项目有7到8个大模块,生产.质量.物耗.电子看板.设备等,每个模块都有大量业务,这样使用mvc结构如果所有模块放在一个目录中,那么势必会产生很多问题,各模块代码不好 ...
- 数据导出之winfrom导出word(一)
我们常会用winfrom程序开发小工具,使用dataGridView控件展示数据.同时,我们也会有将这些数据导出的需求. 本篇文章介绍了开发过程中遇到的问题. 一.引用组件 首先,需要在窗体程序中引用 ...