目录
过滤器
Filter是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。
使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。接下来介绍,在SpringBoot如何实现过滤器.
实现过滤器
WebFilter注解
使用该注解进行配置,启动项目时会自动扫描:
@WebFilter(urlPatterns = "/*",filterName ="filtername" )
public class SrvletFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("f00000000000000000000000000000000");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("1111111111111111111111111111");
}
@Override
public void destroy() {
}
}
But:
该注解是由Servlet提供的,启动项目时并不会生效,所以还要在启动类加上注解:
@ServletComponentScan("过滤器所在的包"),让过滤器生效。
@SpringBootApplication
@ServletComponentScan("com.cc.boot1.filter")
public class Boot1Application {
public static void main(String[] args) {
SpringApplication.run(Boot1Application.class, args);
}
}
SpringBoot配置过滤器
该方法和上面一种的filter类的差距仅仅是没有@WebFilter注解,但是要写一个配置类对过滤器进行配置。
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<Ljq> a(){
FilterRegistrationBean<Ljq> a = new FilterRegistrationBean<>();
a.setFilter(new Ljq());
a.addUrlPatterns("/*");
a.setName("glqglq");
//设置执行顺序,值越小,越优先
a.setOrder(1);
return a;
}
}
拦截器概念
拦截器(Interceptor)是一种用于动态拦截请求处理流程的机制。它允许开发者在请求到达控制器(Controller)之前或响应返回给客户端之后,对请求和响应进行预处理和后处理。拦截器是AOP(面向切面编程)思想在Spring MVC中的具体实现之一。
作用
拦截器主要用于在请求处理流程中的特定点执行自定义逻辑,其作用包括但不限于:
- 权限验证:检查用户是否拥有访问某个资源的权限。
- 日志记录:记录请求和响应的详细信息,便于问题追踪。
- 请求预处理:在请求到达控制器之前对请求数据进行修改或补充。
- 响应后处理:在响应返回给客户端之前对响应数据进行修改或添加额外的头信息。
拦截器和过滤器的区别
归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
拦截内容不同:Filter对所有访问进行增强,Interceptor仅对SpringMVC的访问进行增强
入门拦截器
在controller包下新建Interceptor包,在里面编写一个类,实现HandlerInterceptor接口,重写里面的三个方法。
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; /** * Spring MVC拦截器,用于在请求处理的不同阶段执行特定操作。 * 本拦截器通过实现HandlerInterceptor接口,提供了请求前处理、请求后处理以及请求完成后的回调方法。 * 使用@Component注解声明为Spring管理的组件,会自动被Spring容器检测并注册为拦截器。 */ @Component public class ProjectInterceptor implements HandlerInterceptor { /** * 在请求处理之前执行(Controller方法调用之前) * @param request HTTP请求对象 * @param response HTTP响应对象 * @param handler 被调用的处理器对象 * @return boolean 返回true表示继续流程,返回false则中断流程 * @throws Exception 可能抛出的异常 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("perHandle..."); return true; } /** * 在整个请求处理完成后执行(视图渲染结束后) * 主要用于资源清理、统计信息收集等收尾工作 * @param request HTTP请求对象 * @param response HTTP响应对象 * @param handler 被调用的处理器对象 * @param ex 处理过程中抛出的异常(如果有) * @throws Exception 可能抛出的异常 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion..."); } /** * 在请求处理之后,视图渲染之前执行(Controller方法调用之后) * @param request HTTP请求对象 * @param response HTTP响应对象 * @param handler 被调用的处理器对象 * @param modelAndView 模型和视图对象,可用于修改模型数据或视图(可为null) * @throws Exception 可能抛出的异常 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); } }
在配置包下创建类,继承WebMvcConfigurationSupport,重写addResourceHandlers
和addInterceptors:
import com.cc.controller.interception.ProjectInterceptor; 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.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /** * Spring MVC 配置类,用于自定义Web配置 * 继承WebMvcConfigurationSupport类可覆盖默认的MVC配置 * 注意:在Spring Boot项目中,更推荐实现WebMvcConfigurer接口替代继承此类 */ @Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Autowired private ProjectInterceptor projectInterceptor; //注入拦截器 /** * 配置静态资源处理 * 将/pages/**路径的请求映射到类路径下的/pages目录 * @param registry 资源处理器注册器,用于管理静态资源路径映射 */ @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { //过滤访问静态资源 // 注册projectInterceptor拦截器,并设置拦截路径 registry.addResourceHandler("/pages/**").addResourceLocations("/pages"); } /** * 注册自定义拦截器并配置拦截规则 * @param registry 拦截器注册器,用于管理请求拦截规则 */ @Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(projectInterceptor).addPathPatterns("/users","/users/*"); } }
接下来尝试发送请求:
说明拦截器可以在方法的前和后增强方法。
再次发送请求
并没有被拦截,原因是:
添加拦截路径即可:
简化写法
前面新建了SpringMVC配置类,继承的是WebMvcConfigurationSupport,该部分可以直接写在SpringMVC配置类中,实现WebMvcConfigurer接口,重写addInterceptor方法。
@Configuration
@ComponentScan({"com.cc.controller"}) //不加载SpringMvcSupport
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/users","/users/*");
}
}
拦截器的执行流程
多拦截器的执行顺序
当配置多个拦截器时,会形成拦截器链。
直接复制前面写的拦截器,修改,并对它进行配置:
重新发送请求,就可以观察到拦截器的执行顺序:
由此可得拦截器的执行顺序:
- 拦截器的运行顺序参照拦截器的添加顺序为准
- 执行了controller后执行的顺序相反
- 当拦截器出现对原始数据的拦截,后面的拦截器均会终止运行
- 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作