上篇介绍了Filter过滤器的使用,提起过滤器,就不得不再提起另外一个叫做拦截器的东西。两者的作用类似,都可以实现拦截请求的作用,但其实两者有着非常大的区别。本篇,我们就来学习下拦截器的使用。
如果你是新手,且没看过我之前的一系列SpringBoot文章,建议至少看一下这一篇:
SpringBoot(四)SpringBoot搭建简单服务端_springboot做成服务_heart荼毒的博客-CSDN博客
如果你想从头到尾系统地学习,欢迎关注我的SpringBoot专栏,持续更新:
一、拦截器Interceptor
拦截器跟过滤器有着非常相似的作用,过滤器可以做到的事情,拦截器也可以做到,甚至可以做到更好。
Filter是Servlet的一个概念或者组件,而Interceptor是Spring的一个概念或组件。大家都知道,做web开发,最原始的时候不是用Spring或者SpringBoot,而是Jsp + servlet(我至今还记得大三的时候在机房上机,在那配置tomcat,配置Servlet....)。Spring以及后续的SpringBoot都是为了简化开发,在这里我们暂且不去详细的比较二者。
同样的,拦截器是位于客户端可服务端中间的组件,可以有0-多个,跟过滤器类似:
二、自定义拦截器
SpringBoot提供了对拦截器的支持,使用也非常方便。首先,实现HandlerInterceptor接口,创建一个拦截器。在这里,仅模拟拦截器的实现,写了个非常简单的逻辑,如果请求串包含"sb"就拦截,否则放行:
java
package com.zhaojun.server.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器处理中...");
String queryString = request.getQueryString();
if (queryString.contains("sb")) {
System.out.println("拦截");
return false;
}
System.out.println("放行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器处理结束...");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("请求结束...");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
接下来,需要去配置一下拦截器,创建一个Config类,实现WebMvcConfigurer接口,并且添加@Configuration注解:
java
package com.zhaojun.server.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/login");
}
}
三、验证拦截器是否生效
接下来,测试下拦截器是否生效。首先,使用不包含sb的url进行请求http://localhost:8080/login?name=zj&phone=156532890870&password=123456
看代码执行的流程:
可以看到,首先走到了preHandle,因为不包含特定字符sb,放行。然后依次走到了postHandle和afterCompletion。并且,因为我是接着上一篇的filter继续写的,细心的朋友可以看到,过滤器是在拦截器之前执行的。
接下来,使用包含特地字符sb的url进行请求。http://localhost:8080/login?name=sb&phone=156532890870&password=123456
可以看到,因为包含特定的字符sb,成功在preHandle进行了拦截。这样,因为拦截成功了,自然也不会执行后续的postHandlle和afterCompletion。
四、多个拦截器
学习过滤器的时候,我们可以设置多个过滤器。拦截器前面也提到过了,可以有0-多个。接下来,我们再创建一个拦截器,代码直接复制第一个的,只看下执行的流程:
java
package com.zhaojun.server.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Interceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器2处理中...");
String queryString = request.getQueryString();
if (queryString.contains("sb")) {
System.out.println("拦截");
return false;
}
System.out.println("放行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器2处理结束...");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("请求结束2...");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
相应的,需要在Config类中添加这个拦截器:
java
package com.zhaojun.server.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/login");
registry.addInterceptor(new Interceptor2());
}
}
分别用不含有sb的url 和含有sb的url请求,执行流程如下:
可以看到一些规则,在这里也简单的总结下:
(1)当第一个拦截器没有在preHandle进行拦截的情况下,会顺序执行到第二个拦截器的preHandle。
(2)如果第二个拦截器也没有在preHandle拦截,那么接下来依次倒序执行postHandle和afterCompletion。
(3)如果第一个拦截器没有拦截,第二个拦截器拦截了,那么会直接执行第一个拦截器的afterCompletion。
(4)如果第一个拦截器拦截了,那么后续的拦截器也不会再执行。