1. 拦截器
1.1. 概念
Spring MVC中的拦截器(Interceptor
)类似于servlet中的过滤器(Filter
),它主要用于在特定的时间点,拦截用户请求并作出相应的处理。
拦截器和过滤器的实现方式不同。拦截器是使用动态代理,即反射机制来实现的。而过滤器则是依赖于servlet容器,通过函数回调的方式实现的。
1.2.拦截器处理流程
拦截器主要用来在三个时间点拦截用户的请求,对请求进行判断和处理。
这三个时间点分别是:preHandler、postHandler、afterCompletion
-
preHandler
返回值为boolean,在请求进入controller处理之前就拦截,通过返回值控制这个请求能否进入controller。
在这个方法中,我们一般进行身份认证的相关操作,认证通过就对请求放行,反之则不允许进入,并直接将请求返回。
需要注意的是,我们可以通过对这个方法参数中的response进行处理,来决定如果拦截以后,返回什么信息给请求方。
-
postHandle
无返回值。这个方法在controller执行结束并返回的时候拦截。
我们可以在这个方法中获取controller返回的ModulAndView对象,意味着我们可以对controller返回的内容进行再包装,比如添加一些公用的参数等数据。
-
afterCompletion
无返回值。这个方法是在客户端收到了返回的响应,并完成了视图的解析以后,再调用拦截器的afterCompetion方法。
需要注意的是,现在我们已经很少直接使用视图渲染页面了,但是请求正常结束,或被拦截返回,都会被afterCompletion拦截到。
这个方法的返回值中包含了异常信息,所以我们可以在这里做统一异常处理,或统一日志处理。
另外,如果有多个拦截器,拦截器之间出现了层叠关系,那么自然就会存在拦截的顺序。顺序如下图所示:
注意,只有afterCompletion是逆序执行的。
2. 代码实现
实现思路:
- 编写一个拦截器,继承HandlerInterceptor接口
- 编写(或修改)SpringMVC配置类,注册我们写的拦截器
目录结构如下
config
└─ WebMVCConfig # 配置springMVC框架信息
interceptor
└─ XXXInterceptor # 具体的拦截器
我们以一个登录身份验证的拦截为例子
简单来说,如果用户访问除了登录和注册的页面,就需要检验用户的请求是否包含token并校验,token合法才允许请求通过,否则将请求直接退回。
LoginInterceptor.java
验证登录拦截器类,内部对拦截到的内容进行具体处理,决定是否放行
/**
* 登录验证拦截器
* @Author Mosfield
* @Date 2023-6-7
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
JwtConfig jwtConfig;
/**
* 检查用户是否登录
* return true => 放行逻辑 => 可以继续走三层
* return false => 拦截 =>到此为止了
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从请求头里获取token
String token = request.getHeader("token");
try {
// ======================== 具体的验证的逻辑 (jwt 验证) ========================
Claims claims = JwtUtils.parseToken(token, jwtConfig.getSecureKey());
// 登录成功
return true;
} catch (Exception e) {
//被拦截了,我们需要给提示(请登陆后继续操作)
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(Result.error("请登陆后重试"));
//把json格式的数据写给前端
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(jsonStr);
return false;
}
}
}
WebMVCConfig.java
配置SpringMVC框架信息,注册拦截器
/**
* 对springMVC框架进行控制
* @Author Mosfield
*/
@Configuration // 标记当前的类是一个配置类,它单独加载
public class WebMVCConfig implements WebMvcConfigurer {
// 登录拦截器对象
@Autowired
LoginInterceptor loginInterceptor;
/**
* 对拦截器进行配置
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 需要放行的资源列表
ArrayList<String> acl = new ArrayList();
acl.add("/login");
acl.add("/register");
// 注册拦截器,并指定拦截器拦截哪些路径,放过哪些路径
registry.addInterceptor(loginInterceptor)
// 设置拦截路径 => /** 指全部拦截
.addPathPatterns("/**")
// 设置放行路径
.excludePathPatterns(acl);
}
}
Comments NOTHING