文章目录
一、什么是拦截器?
1.概念
Spring MVC中的拦截器(Interceptor)类似于ServLet中的过滤器(Filter),它主要用于拦截用户请求并作出相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。
定义:拦截器是一种动态拦截方法调用的机制,在SpringMVC中动态拦截controller方法的执行;
tomcat所有请求资源中分为静态资源和动态资源,动态资源。
在web容器中,有着监听器、过滤器、servlet几种配置,Tomcat启动时加载配置有着先后顺序。顺序: context-param -> listener -> filter -> servlet/,而SpringMVC框架中在web.xml中配置dispatcherServlet为一个Servlet。所以根据发送的请求 例:(/books) 访问动态资源时先经过过滤器No.1\过滤器No.2等等,然后由SpringMvc的中央处理(DispatcherServlet)将请求交给对应的处理器(Controller)进行处理。因此,拦截器诞生,它的作用就是拦截controller的请求在其前后执行一些操作。
2.拦截器的作用
(1)拦截器通常在指定的方法调用前后执行一些操作
(2)在某些条件下阻止原始方法的执行,通常用于权限校验,确保只有具备相应权限的用户才能访问特定的方法或资源。
(3)拦截器允许在不修改原有代码的情况下,通过在方法调用前后插入额外的代码来实现功能的增强。
3.拦截器和过滤器的相同点和不同点
(1)相同点:
体现AOP思想:它们都采用了面向切面编程的思想,可以对方法进行增强,实现例如日志记录、登录鉴权等功能。
设定执行顺序:拦截器和过滤器都可以通过Order注解来设定它们处理请求的先后顺序。
(2)不同点:
实现原理:过滤器是依赖于Servlet容器的,它是通过实现Filter接口并注册到web.xml中或使用@WebFilter注解来配置的。而拦截器则是Spring框架的一部分,它通过实现HandlerInterceptor接口并且通常通过Spring的配置来管理。
作用范围:过滤器可以拦截所有请求,包括静态资源和非静态资源的请求。而拦截器只能拦截到controller的请求。
方法不同:过滤器有init(), doFilter(), destroy()三个方法,其中doFilter()对于每次请求都会被调用。拦截器则有preHandle(), postHandle(), afterCompletion()方法,它们分别在请求处理的不同阶段被调用。
二、拦截器的使用
1.导入maven所需要的依赖及根目录下创建所需要的包和类
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
2.配置ServletContainersInitConfig类
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
getServletFilters这个过滤器用于设置请求和响应的字符编码为UTF-8,解决中文乱码的问题
3.配置SpringMvcConfig类
@Configuration
@ComponentScan({"com.example.demo2.controller","com.example.demo2.config"})
@EnableWebMvc
public class SpringMvcConfig {
}
4.定义controller.interceptor目录下的ProjectInterceptor类
在controller目录下创建拦截器的类方便ComponentScan扫描拦截器的bean,简化操作。
@Component
public class ProjectInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
因为在HandlerInterceptor接口中三个方法都是default类型,所以就不需要在所有的实现类中全部重写该default方法,哪个实现类需要新增该方法,就在哪个实现类中进行实现。
idea中ctrl+o选择三个方法进行重写。
5.配置SpringMvcSupport类
这个类中 addResourceHandler方法作用是Spring MVC 框架将请求映射到相应的静态资源,方便访问静态资源。
addInterceptors方法主要作用是注册拦截器,对请求的动态资源进行拦截。
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/books");
}
}
ctrl+o选中addInterceptors方法,拦截请求的路径/books
6.创建BookoController类
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping
public String getAll() {
System.out.println("book getAll");
return "{'module':'book getAll'}";
}
7.创建Book类
Book类中属性分别为id、type 、name、description,get和set方法省略了
private Integer id;
private String type;
private String name;
private String description;
8.测试
运行Tomcat后在postman中发送Get请求回到控制台查看效果
总结:preHandle: 在请求处理之前执行。在这个例子中,先打印了"Prehandle",表示在处理请求之前执行了拦截器的预处理逻辑。
book getAll: 这是controller方法的调用,用于获取所有的书籍信息。
postHandle: 在请求处理之后,视图渲染之前执行。在这个例子中,它打印了"Posthandle",表示在处理请求并准备渲染视图之前执行了拦截器的后处理方法。
afterCompletion: 在整个请求结束之后执行。