1、介绍
拦截器(Interceptor)是一种特殊的组件,它可以在请求处理的过程中对请求和响应进行拦截和处理。拦截器可以在请求到达目标处理器之前、处理器处理请求之后以及视图渲染之前执行特定的操作。拦截器的主要目的是在不修改原有代码的情况下,实现对请求和响应的统一处理。
2、场景
权限控制:拦截器可以在请求到达处理器之前进行权限验证,从而实现对不同用户的访问控制。【最常用的】
日志记录:拦截器可以在请求处理过程中记录请求和响应的详细信息,便于后期分析和调试。
接口幂等性校验:拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。
数据校验:拦截器可以在请求到达处理器之前对请求数据进行校验,确保数据的合法性。
缓存处理:拦截器可以在请求处理之后对响应数据进行缓存,提高系统性能。
3、实例
以登录验证为例子。如果没有拦截器在每一个接口中都要通过传入的token验证该user是否为登录状态,且所有接口的验证代码一直。这种情况,就可以将该验证放到拦截器里
(1)定义一个拦截器
package com.zytz.backend;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zytz.backend.entity.User;
import com.zytz.backend.service.UserService;
@Component
public class AdminLoginInterceptor implements HandlerInterceptor{
@Autowired
private UserService userService;
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception {
//处理完毕后,需要将该user从ThreadLocal中删除啊
User.removeUser();
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//通过请求数据得到了当前登录用户的对象
User user = userService.getUserByReq(request);//这个内部函数,是通过token获取当前用户的一个对象
//保存到ThreadLocal,防止其他服务需要使用
User.saveUser(user);
//非管理员,则返回false
if(!user.IsAdmin()){
//验证失败的情况下,也需要返回json数据啊
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
ObjectMapper objectMapper = new ObjectMapper();
response.getWriter().println(objectMapper.writeValueAsString(/* 这里是一个HashMap字典,用来返回json数据 */);
return false;
}
return true;
}
}
User类的关于ThreadLocal的代码
public class User {
private static final ThreadLocal<User> threadLocalUser = new ThreadLocal<>();
public static void saveUser(User user){
threadLocalUser.set(user);
}
public static User getUser(){
return threadLocalUser.get();
}
public static void removeUser(){
threadLocalUser.remove();
}
}
(2)配置拦截器
@Configuration
public class MvcConfig implements WebMvcConfigurer{
@Autowired
private AdminLoginInterceptor adminLoginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(adminLoginInterceptor)//添加拦截器
.addPathPatterns("/transaction/*");//拦截这些transaction路径
//如果需要排除一个不需要的拦截路径,可以继续.excludePathPatterns(XXX);
}
}
(3)controller中
controller的代码被简化了,如果不需要User的信息则直接查询数据,如果需要User的数据可以通过ThreadLocal来获取当前用户的信息
@RequestMapping("/transaction/transaction_all")//获得所有交易
public HashMap<String,Object> getAllTransactions(HttpServletRequest req)
{
//User user = User.getUser();
//XXXX
List<TransactionData> list = transactionDataService.getAllTransactions();
XXXX
XXXX