区别:

过滤器 filter(java回调)

针对 http 请求,所有的 web 请求都会最先通过过滤器,依赖 web 环境。无法控制访问的方法、类粒度。

使用场景:设置全局请求的字符集返回,用户登陆鉴权

拦截器interceptor(java反射)

拦截器可以在方法执行之前 (preHandle) 和方法执行之后 (afterCompletion) 进行操作,回调操作 (postHandle),可以获取执行的方法的名称。可以控制获取请求的方法,但无法获取请求里面的参数。

使用场景:接口幂等性校验(拦截指定注解接口,对请求 token 进行校验是否重复)、接口防刷限流(拦截指定注解接口,记录接口次数于 redis,比较大小放行)

Spring AOP

Aspect : 可以自定义切入的点,可以获取执行方法的参数 (ProceedingJoinPoint.getArgs()),但是拿不到 http 请求。针对粒度更小的 target

通过其他方式如 RequestContextHolder 获得

ServletRequestAttributes servletRequestAttributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

使用场景:接口统一打印请求时间日志,声明式事务,请求参数安全验证

三者执行顺序

doFileter before(过滤器) -> preHandle(拦截器) -> postHandel(controller)(拦截器) -> afterCompletion(拦截器) -> doFilter after(过滤器)

SpringBoot 使用拦截器

1.自定义SessionConfiguration实现接口WebMvcConfigurer重写过滤器addInterceptors
@Configuration
public class SessionConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration interceptor = registry.addInterceptor(new SessionInterceptor());
        /**
         * 添加拦截的路径
         * /为根路径
         * /*为一级路径
         * /** 为所有路径包括多级
         */
        interceptor.addPathPatterns("/**");

        //排除不拦截的,包括自己登录的页面不用拦截
        interceptor.excludePathPatterns("/login");
        interceptor.excludePathPatterns("/user/handle");
    }
}

其中拦截器SessionInterceptor代码如下

public class SessionInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入拦截器");
        if (request.getRequestURI().equals("/login")) {
            return true;
        }

        //验证session是否存在
        Object user = request.getSession().getAttribute("session_user");
        if (user == null) {
            response.sendRedirect("/login");
            return false;
        }
            return true;
    }
}

控制器代码:

@Controller
@RequestMapping("/user")
public class HandleController {

    @Autowired
    private UserDao userDao;

    @RequestMapping("/handle")
    public String handle(User user, HttpSession session) {

        Specification<User> specification = new Specification<User>() {
            @Nullable
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                criteriaQuery.where(criteriaBuilder.equal(root.get("name"), user.getName()));
                return null;
            }
        };

        boolean flag = true;
        String json = "";

        User user1 = (User) userDao.findOne(specification).get();
        if (user1 == null) {
            json = "用户不存在,登录失败!";
        } else if (!user.getPwd().trim().equals(user1.getPwd().trim())) {
            System.out.println(user1.toString());
            flag = false;
            json = "密码不正确!请重新登录!";
        }

        if (flag) {
            session.setAttribute("session_user", user1);
            json = "登录成功";
            return "index";
        } else {
            return "login";
        }
    }
}

项目地址:GitHub

上次更新时间: 2024/5/7 05:59:02