区别:
过滤器 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 使用拦截器
SessionConfiguration
实现接口WebMvcConfigurer
重写过滤器addInterceptors
1.自定义@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