SpringBoot拦截器-HandlerInterceptor接口
再说之前,先讲讲,想必我们对过滤器是非常熟悉的,在Servlet里面的web.xml里面的。那么许多人老是被这两个东西搞得晕头转向的。这里我举个例子说明他俩的区别:所以过滤器一定是在拦截器之前执行在web开发中,拦截器是经常用到的功能。它可以帮我们验证是否登陆、过滤静态资源等。在Spring中的拦截器分为了两种:实现一个HandlerInterceptor拦截器可以直接实现HandlerInter
一、前言
再说拦截器
之前,先讲讲过滤器
,想必我们对过滤器是非常熟悉的,在Servlet里面的web.xml里面的<filter>标签
。那么许多人老是被这两个东西搞得晕头转向的。这里我举个例子说明他俩的区别:
- 过滤器:当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。
就好比在一堆沙子中淘出金子,把沙子过滤掉
- 拦截器:当你有了金子,准备高兴兴的准备回家娶媳妇,路上突然遇到了强盗
- 情况一:必须忍痛割爱,把金子给他,但是你又于心不忍,于是偷偷藏了一些,仅存的金子又分出一些给了强盗,这算保证住了小命。
- 情况二:你坚决不给,于是强盗把你杀了,金子拿了,最后人才两矢。
小结
过滤器
就是直接pass大多数的,留下一部分的精英
拦截器
就是想尽办法在从这些精英中在阻拦你前进,甚至是不让你继续通过,能通过的一定是最强的。
所以过滤器一定是在拦截器之前执行
一、spring中的拦截器
在web开发中,拦截器是经常用到的功能。它可以帮我们验证是否登陆、过滤静态资源等。
在Spring中的拦截器分为了两种:
- HanlerInterceptor接口:拦截请求地址的拦截器
- MethodInterceptor接口:拦截方法的拦截器
1.1 HandlerInterceptor拦截器🔥
HandlerInterceptor是springMVC项目中的拦截器,它拦截的目标是请求的地址,
比MethodInterceptor先执行。
实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。
这两种方法殊途同归,其实HandlerInterceptorAdapter也就是声明了HandlerInterceptor接口中所有方法的默认实现,而我们在继承他之后只需要重写必要的方法。
下面我们来看下HandlerInterceptor的源码:
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
preHandler:
目标方法执行完成之前- postHanlder:目标方法执行完成之后
- afterComplete:页面渲染以后
一般而言,我们的登录拦截操做,等相关的拦截操做都可以定义在preHandler方法里面。
1.2 MethodInterceptor
MethodInterceptor
是AOP项目中的拦截器,它拦截的目标是方法。
实现MethodInterceptor拦截器大致也分为两种,一种是实现MethodInterceptor接口,另一种利用AspectJ的注解或配置。
让我们看看MethodInterceptor的源码:
public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation var1) throws Throwable;
}
这里我着重使用以下HandlerInterceptor
二、如何使用HandlerInterceptor
2.1 使用步骤
- 编写一个拦截器类,实现HandlerInterceptor接口,并实现preHandler方法(核心)
- 编写一个配置类,实现WebMvcConfigurer接口
- 实现接口里的addInterceptors方法
- 在方法里,将定义的拦截器类,注入到Spring容器里,并配置拦截规则
2.2 案例实战
老规矩,还是使用之前Thymeleaf阶段的一个登录进行演示
【前置工作】
controller层跳转逻辑
// 去登陆页
@GetMapping(value = {"/", "/login"})
public String loginPage() {
return "login";
}
// 登录请求
@PostMapping(value = "/login")
public String main(User user, HttpSession session, Model model) {
// 这块可以写一些数据库账号密码的逻辑操作
// ...
// 如果密码账号无误,ok登录 把登录信息放到Session作用域中
// 这里只做非空判断
if (!StringUtils.isEmpty(user.getUsername()) && user.getPassword().equalsIgnoreCase("123456")) {
// 保存登陆成功的用户
session.setAttribute("loginUser", user);
return "redirect:/main.html";
} else {
model.addAttribute("msg", "账号密码错误");
return "login";
}
}
// 解决表单重复提交 重定向
@GetMapping("/main.html")
public String mainPage(HttpSession session, Model model) {
// 拦截器里面进行登陆的拦截判断操做
return "main";
}
【步骤一】
编写一个LoginInterceptor类
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// logback日志输出获取拦截的URI
log.info("拦截的请求路径是{}"+request.getRequestURI());
// 登录拦截 需要在执行之前
HttpSession session = request.getSession();
Object loginUser = session.getAttribute("loginUser");
if (loginUser != null) {
return true; // 放行
}
// 阻止,并重定向到登录页
request.setAttribute("msg", "请先登录");
request.getRequestDispatcher("/").forward(request,response);
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}
【步骤二】
将拦截器注入并配置拦截规则
@Configuration
public class MyConfig implements WebMvcConfigurer {
/**
* 配置拦截规则与注入拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPattern 添加拦截规则 /** 拦截所有包括静态资源
// excludePathPattern 排除拦截规则 所以我们需要放开静态资源的拦截
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/")
.excludePathPatterns("/login")
.excludePathPatterns("/css/**","/fonts/**","/images/**","/js/**");
}
}
🔥🔥
说明
:如果我们在addInterceptors的方法里面使用addPathPattern
添加拦截路径的时候,使用/**
的方式进行拦截请求,那么这也就将静态资源也拦截掉了,所以我们可以通过excludePathPattern
来排除想放行的资源
【拦截效果】
【日志输出拦截URI】
更多推荐
所有评论(0)