拦截器(Interceptor)是一种特殊的组件,它可以在请求处理的过程中对请求和响应进行拦截和处理。拦截器可以在请求到达目标处理器之前、处理器处理请求之后以及视图渲染之前执行特定的操作。拦截器的主要目的是在不修改原有代码的情况下,实现对请求和响应的统一处理。
在 Spring Boot 中拦截器的实现分为两步:
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class TestInterceptor 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 方法。");
}
}
- preHandler 方法:在请求方法执行前被调用,也就是调用目标方法之前被调用。比如我们在操作数据之前先要验证用户的登录信息,就可以在此方法中实现,如果验证成功则返回 true,继续执行数据操作业务;否则就返回 false,后续操作数据的业务就不会被执行了。
- postHandle 方法:调用请求方法之后执行,但它会在 DispatcherServlet 进行渲染视图之前被执行。
- afterCompletion 方法:会在整个请求结束之后再执行,也就是在 DispatcherServlet 渲染了对应的视图之后再执行
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
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 AppConfig implements WebMvcConfigurer {
@Autowired
private UserInterceptor userInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//registry.addInterceptor(new UserInterceptor());
registry.addInterceptor(userInterceptor)
.addPathPatterns("/**")//拦截规则:/**拦截所有的请求
.excludePathPatterns("/user/reg")//不拦截
.excludePathPatterns("/user/login");
}
}
拦截规则:
- addPathPatterns:表示需要拦截的 URL
- /**:表示拦截任意方法(也就是所有方法)
- excludePathPatterns:表示需要排除的 URL
如果要排除所有静态资源:在这里有一个问题就是排除图片,图片的格式有很多,总不能一个一个排除,这样的情况我们可以在 resource 下的 static 创建一个 image 目录,把所有图片都放在这里边,排除 image 里边的所有东西
.excludePathPatterns("/image/**");
没有拦截器的的时候:用户调用来到后端程序,请求提交给Controller,Controller 处理请求访问 Service,Service 访问 Mapper,Mapper 访问数据库,然后数据库把结果在一层一层返回给用户
加拦截器:此时用户调用来到后端程序,先会来到拦截器进行预处理——返回 true,执行后边流程;返回 false,则返回非权限给页面
加拦截器代码原理:所有的 Controller 执行都会通过?个调度器 DispatcherServlet?来实现(而所有方法都会执行?DispatcherServlet 中的 doDispatch 调度方法,其中会执行?applyPreHandle?方法。这个方法含义是:执行所有的拦截器,所有拦截器不等于 false,才会进行之后的代码)
过滤器,顾名思义就是对事物进行过滤的,在Web中的过滤器,当然就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制,权限管理,过滤敏感词汇等。
过滤器可以使用 Servlet 3.0 提供的 @WebFilter 注解,配置过滤的 URL 规则,然后再实现 Filter 接口,重写接口中的 doFilter 方法,具体实现代码如下:
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@Component
@WebFilter(urlPatterns = "/*")
public class TestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器:执行 init 方法。");
}
@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器:开始执行 doFilter 方法。");
// 请求放行
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("过滤器:结束执行 doFilter 方法。");
}
@Override
public void destroy() {
System.out.println("过滤器:执行 destroy 方法。");
}
}
- init 方法:容器启动(初始化 Filter)时会被调用,整个程序运行期只会被调用一次。用于实现 Filter 对象的初始化。
- doFilter 方法:体的过滤功能实现代码,通过此方法对请求进行过滤处理,其中 FilterChain 参数是用来调用下一个过滤器或执行下一个流程。
- destory 方法:用于 Filter 销毁前完成相关资源的回收工作。
当我们使用过滤器时,过滤器会对浏览器的请求进行过滤,过滤器可以动态的分为3个部分:1.放行之前的代码,2.放行,3.放行后的代码,这3个部分分别会发挥不同作用。