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 ...
随机推荐
- 关于windows10的使用
关于windows10的使用 个人习惯设置 打开我的电脑之后,不是定位到此电脑,而是定位到快速访问. [解决办法] 用win + 箭头 快捷键将窗口靠边之后,另一边出现多个窗口 [解决办法] win ...
- 周鸿祎与85后的座谈(一):人人需要Mentor,世界没有奇迹
我们公司现在有将近 4000 人,我觉得里面肯定是卧虎藏龙.百里挑一的话,也有 40 个伟大的人才.但是,即使是天才,如果没有前辈的帮助,最后也会变成庸才,是做不出什么大事的.举例来说,每一个跳水冠军 ...
- html5之range
第一次以这种方式做笔记,希望可以加强自己对新知识的理解,更希望能得到更多朋友的指正. 言归正传: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 ...
- Scala_继承
继承 Scala与Java在继承方面的区别 Scala中的继承与Java有着显著的不同: 重写一个非抽象方法必须使用override修饰符 只有主构造器可以调用超类的主构造器 在子类中重写超类的抽象方 ...
- [violet2]sillyz
题意:定义S(n) = n*各数位之积,然后给定L<=R<=10^18,求有多少个n在[L,R]区间内 思路: 看了半天无从下手..看完题解才豁然开朗.. 具体思路看vani神博客吧.讲的 ...
- file新建文件及文件夹
1.获取包名的根目录:mRootPath = getFilesDir().getParent(); // ====mRootPath===/data/data/com.yoyu.file 获取SD卡 ...
- Swift3 使用系统UIAlertView方法做吐司效果
/** *显示弹出信息 */ class func showAlertMessage(_ str:String,showtime Num:Double){ let alert = UIAlertVie ...
- poj3253哈夫曼树
Fence Repair Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java ...
- Markdown中怎么上传图片
在网站中使用了Markdown编辑器,但是不能支持图片的直接粘贴
- ADO.NET系列之事务和调用存储过程
ADO.NET系列之Connection对象 ADO.NET系列之Command对象 ADO.NET系列之DataAdapter对象 ADO.NET系列之事务和调用存储过程 前几篇我们介绍了Conne ...