# SpringBoot3教程 - 12 拦截器配置
拦截器可以对请求进行预处理和后处理的一种机制。
例如:
- 在请求被处理前,执行一些公共逻辑,例如检查用户是否认证、是否有权限访问受保护的资源、日志记录等;
- 可以在请求被处理前,对请求的数据进行预处理,还可以对返回的结果进行统一处理。
拦截器是依赖于SpringMVC框架的,基于 Java 的反射机制,是属于面向切面编程(AOP)的一种运用。拦截器只能对 controller 请求进行拦截,而对其他的一些请求则无法拦截,例如访问静态资源的请求。
下面介绍一下 SpringBoot 中拦截器的使用配置。
最常用的就是拦截请求,查看请求是否携带登录凭证,如果没有,就返回请登录信息。
# 12.1 创建拦截器
- 定义一个类并实现
HandlerInterceptor
接口。 - 可以根据需求实现接口中的三个方法:
preHandle
(在请求处理之前调用)、postHandle
(在请求处理之后,但在视图渲染之前调用)和afterCompletion
(在整个请求结束之后调用)。
举个栗子:
创建一个拦截器,拦截请求后,查看请求头中是否有认证信息,没有就拦截掉。
package com.doubibiji.hellospringboot.interceptor;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
/**
* 请求之前调用
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取请求头中的Authorization属性,并验证登录是否有效
String authorization = request.getHeader("Authorization");
// 这里只是简单判断一下,实际可能要查询缓存
if (StrUtil.isEmpty(authorization)) {
// 这里可以抛出异常,在后面学习如何对异常进行统一处理
throw new RuntimeException("请登录");
}
return true; // 返回true则继续处理请求,
}
}
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
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
添加 @Component
注解,交由 Spring 来管理。
# 12.2 配置拦截器
拦截器已经创建了,下面需要配置拦截器拦截哪些请求。
首先创建一个配置类,实现 WebMvcConfigurer
接口,在配置类中实现 addInterceptors()
方法,进行配置。
// 可以将配置类统一放在一个包下管理
package com.doubibiji.hellospringboot.config;
import com.doubibiji.hellospringboot.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired // 注入拦截器
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 根据需要取消拦截指定的请求
List<String> excludePathList = new ArrayList<>();
excludePathList.add("/login");
excludePathList.add("/register");
excludePathList.add("/error");
// 拦截所有请求,排除指定请求
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**").excludePathPatterns(excludePathList);
// ...如果有多个拦截器,可以addInterceptor()多次
}
}
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
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
可以设置拦截器拦截哪些请求,和排除拦截哪些请求。
# 12.3 编写测试Controller
编写一个Controller,提供接口测试一下。
根据配置不会拦截 /login
,但是会拦截 /hello
。
package com.doubibiji.hellospringboot.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorldController {
@GetMapping("/hello")
public String hello() {
return "Hello World!";
}
@GetMapping("/login")
public String login() {
return "Login!";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
当访问 http://localhost:8080/login ,没问题;
当访问 http://localhost:8080/hello ,拦截返回错误信息;