导言
一、拦截器
- 拦截器是什么?
简单的来说,就是一道阀门,在某个方法被访问之前,进行拦截,然后在之前或之后加入某些操作,拦截器是AOP 的一种实现策略。 - 拦截器主要做什么?
- 对正在运行的流程进行干预。
- 拦截器的代码实现。拦截器也主要有三个方法:
- 其中preHandle是在请求之前就进行调用,如果该请求需要被拦截,则返回false,否则true;
- postHandle是在请求之后进行调用,无返回值;
- afterCompletion是在请求结束的时候进行调用,无返回值。
二、创建项目 springboot-interceptor
- 根据 springboot 学习二:springboot 第一次创建 web 项目,打包项目并测试成功 博文,快速创建本项目:springboot-interceptor
- 项目依赖仅勾选web即可。
- 项目结构如下:(记得修改application配置文件的后缀为 yml)
三、Interceptor 快速入门
那么在 springBoot 中如何使用拦截器呢?
步骤:
- 创建一个类实现
HandlerInterceptor 接口
, - 再创建一个配置类实现
WebMvcConfigurer接口
,重写addInterceptors 方法
。
1. 创建拦截器类
创建我们自己的拦截器类并实现 HandlerInterceptor 接口。
package com.feng.springboot_interceptor.interceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor....在请求处理之前进行调用(Controller方法调用之前)");
String requestUrl = request.getRequestURI();
System.out.println("过滤器MyFilter拦截了请求为" + requestUrl);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor...请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
//HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor....在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对 应的视图之后执行(主要是用于进行资源清理工作)");
//HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
2. 修改 application.yml
修改 application.properties 加入开发接口通配地址
#凡是请求地址层级带有 open 都放行
open:
url: /**/open/**
3. 实现 WebMvcConfigurer
创建一个 Java 实现 WebMvcConfigurer , 并重写 addInterceptors 方法。
package com.feng.springboot_interceptor.config;
import com.feng.springboot_interceptor.interceptor.MyInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
@Value("${open.url}")
private String openUrl;
@Bean
public MyInterceptor getMyInterceptor() {
return new MyInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 拦截以 /api 开头的请求,但是排除 openUrl:/**/open/**。 即 :匹配这个(/**/open/**)URL的所有请求不拦截
registry.addInterceptor(getMyInterceptor()).addPathPatterns("/api/**").excludePathPatterns(openUrl);
// WebMvcConfigurer.super.addInterceptors(registry);
}
}
4. 创建接口Interceptorcontroller
package com.feng.springboot_interceptor.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class InterceptorController {
@GetMapping("/home/open/info")
public String home() {
return "欢迎来到首页";
}
@GetMapping("/user/interceptor")
public String interceptor() {
return "我被拦截了并通过了拦截器";
}
}
5. 项目结构
6. 测试
- 带有open
http://localhost:8080/api/open/home/info
不拦截 - 不带open
http://localhost:8080/api/user/interceptor
拦截
四、拦截校验用户是否登录实战
1. 加入需要权鉴接口、未登录接口
a、加入接口
@GetMapping("/open/unLogin") // 带 open 放行
public String getUnauthorized() {
return "登录失效,请重新登录";
}
b、全部接口
package com.feng.springboot_interceptor.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class InterceptorController {
@GetMapping("/home/open/info") // 带 open 放行
public String home() {
return "欢迎来到首页";
}
@GetMapping("/user/interceptor")
public String interceptor() {
return "我被拦截了并通过了拦截器";
}
@GetMapping("/open/unLogin") // 带 open 放行
public String getUnauthorized() {
return "登录失效,请重新登录";
}
}
2. 修改拦截器校验逻辑
package com.feng.springboot_interceptor.interceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor....在请求处理之前进行调用(Controller方法调用之前)");
String requestUrl = request.getRequestURI();
System.out.println(requestUrl + "被 MyInterceptor 拦截了"); //判断是否携带凭证就可以了
String token = request.getHeader("token");
if (StringUtils.isEmpty(token)) {
request.getRequestDispatcher("/api/open/unLogin").forward(request, response);
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor...请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
//HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor....在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对 应的视图之后执行(主要是用于进行资源清理工作)");
//HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
3. 测试
a. 首先访问 开放接口
http://localhost:8080/api/home/open/info
b. 访问 需权鉴接口
- 带 token
http://localhost:8080/api/user/interceptor
- 不带 token:
http://localhost:8080/api/user/interceptor