SpringBoot高级开发(10)SpringBoot中的拦截器【用于处理验证登录等问题】

发布时间 2023-12-08 16:17:45作者: 东方春

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