过滤器 拦截器

过滤器

过滤器拦截的是URL

Spring中自定义过滤器(Filter)一般只有一个方法,返回值是void,当请求到达web容器时,会探测当前请求地址是否配置有过滤器,有则调用该过滤器的方法(可能会有多个过滤器),然后才调用真实的业务逻辑,至此过滤器任务完成。过滤器并没有定义业务逻辑执行前、后等,仅仅是请求到达就执行。

特别注意:过滤器方法的入参有request,response,FilterChain,其中FilterChain是过滤器链,使用比较简单,而request,response则关联到请求流程,因此可以对请求参数做过滤和修改,同时FilterChain过滤链执行完,并且完成业务流程后,会返回到过滤器,此时也可以对请求的返回数据做处理。

两种方法使用过滤器,注入bean到ioc容器或者使用@WebServlet注解。

「注意」:@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们还需在配置类中加另外一个注解:@ServletComponetScan,指定扫描的包。定义过滤器类:HelloFilter,在过滤器类上添加@WebFilter注解配置过滤器名称、过滤路径等属性,通过@Order配置过滤器执行顺序。注意使用@WebServlet、@WebFilter、@WebListener等servlet注解时需要在springboot的启动类上添加@ServletComponentScan注解,否则不会生效。@Order值越小优先级越高。

//第一种,注册bean
@Order(value = 2)
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { System.out.println("myFilter提示:服务启动..........");
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("myFilter提示:调用过滤器Filter的doFilter()方法..........");
System.out.println("ip地址为"+servletRequest.getRemoteAddr());
//放行通过
filterChain.doFilter(servletRequest, servletResponse);
} @Override
public void destroy() { System.out.println("myFilter提示:服务关闭..........");
}
} @Configuration
public class MyFilterConfig {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
MyFilter filter = new MyFilter();
registrationBean.setFilter(filter);
//设置过滤器拦截请求
List<String> urls = new ArrayList<>();
urls.add("/*");
registrationBean.setUrlPatterns(urls);
return registrationBean;
}
}
//第二种,基于注解
@WebFilter(urlPatterns="/*", filterName = "myFilterByAnnotation")
@Order(value = 3)
public class MyFilterByAnnotation implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("myFilterByAnnotation提示:服务启动..........");
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("myFilterByAnnotation提示:调用过滤器Filter的doFilter()方法..........");
System.out.println("ip地址为"+servletRequest.getRemoteAddr());
//放行通过
filterChain.doFilter(servletRequest, servletResponse);
} @Override
public void destroy() { System.out.println("myFilterByAnnotation提示:服务关闭..........");
}
} @SpringBootApplication
@ServletComponentScan
@Import({Teacher.class})
public class SpringbootReviewApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(SpringbootReviewApplication.class, args);
} } //myFilter提示:调用过滤器Filter的doFilter()方法..........
//myFilterByAnnotation提示:调用过滤器Filter的doFilter()方法..........

拦截器

拦截器拦截的是URL,拦截器有三个方法,相对于过滤器更加细致,有被拦截逻辑执行前、后等。Spring中拦截器有三个方法:preHandle,postHandle,afterCompletion。分别表示如下:

  • public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o)表示被拦截的URL对应的方法执行前的自定义处理
  • public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView)表示此时还未将modelAndView进行渲染,被拦截的URL对应的方法执行后的自定义处理
  • public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e)表示此时modelAndView已被渲染,执行拦截器的自定义处理

拦截器的应用场景

1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page VIEW)等。

2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;

3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);

4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。

拦截器使用方法

1.在任务类增加注解 @Configuration 注册bean,继承 WebMvcConfigurerAdapter 代表配置拦截器的适配器

2.重写 addInterceptors 添加需要的拦截器地址及需要排除的拦截地址

SpringMVC 拦截器拦截 /* 和 /** 的区别:

  • /* : 匹配一级,即 /add , /query 等
  • /** : 匹配多级,即 /add , /add/user, /add/user/user… 等
@Slf4j
public class MyInterceptor implements HandlerInterceptor { long start;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
start = System.currentTimeMillis();
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
} /**
* 1、编写一个拦截器实现HandlerInterceptor接口
* 2、拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
* 3、指定拦截规则【如果是拦截所有,静态资源也会被拦截】
*/
@Configuration
public class AdminWebConfig implements WebMvcConfigurer { @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //所有请求都被拦截包括静态资源
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行的请求
}
}

拦截器原理

1、根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】

2、先来顺序执行 所有拦截器的 preHandle方法

  • 1、如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle
  • 2、如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion;

3、如果任何一个拦截器返回false。直接跳出不执行目标方法

4、所有拦截器都返回True。执行目标方法

5、倒序执行所有拦截器的postHandle方法。

6、前面的步骤有任何异常都会直接倒序触发 afterCompletion

7、页面成功渲染完成以后,也会倒序触发 afterCompletion

拦截器与过滤器的区别

1、拦截器是基于Java的反射机制的,而过滤器是基于函数回调。

2、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

3、拦截器只能对ACTION请求起作用,而过滤器则可以对几乎所有的请求起作用。

4、拦截器可以访问ACTION上下文、值栈里的对象,而过滤器不能访问。

5、在ACTION的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

6、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。过滤器 拦截器 AOP区别

AOP(面向切面)面向切面拦截的是类的元数据(包、类、方法名、参数等)相对于拦截器更加细致,而且非常灵活,拦截器只能针对URL做拦截,而AOP针对具体的代码,能够实现更加复杂的业务逻辑。三者功能类似,但各有优势,从过滤器--》拦截器--》切面,拦截规则越来越细致,执行顺序依次是过滤器、拦截器、切面。一般情况下数据被过滤的时机越早对服务的性能影响越小,因此我们在编写相对比较公用的代码时,优先考虑过滤器,然后是拦截器,最后是aop。比如权限校验,一般情况下,所有的请求都需要做登陆校验,此时就应该使用过滤器在最顶层做校验;日志记录,一般日志只会针对部分逻辑做日志记录,而且牵扯到业务逻辑完成前后的日志记录,因此使用过滤器不能细致地划分模块,此时应该考虑拦截器,然而拦截器也是依据URL做规则匹配,因此相对来说不够细致,因此我们会考虑到使用AOP实现,AOP可以针对代码的方法级别做拦截,很适合日志功能。

Springboot笔记<7>过滤器与拦截器的更多相关文章

  1. springboot中使用过滤器、拦截器、监听器

    监听器:listener是servlet规范中定义的一种特殊类.用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件.监听域对象的属性发生 ...

  2. springBoot之配置文件的读取以及过滤器和拦截器的使用

    前言 在之前的学习springBoot中,成功的实现了Restful风格的基本服务.但是想将之前的工程作为一个项目来说,那些是仅仅不够的.可能还需要获取自定义的配置以及添加过滤器和拦截器.至于为什么将 ...

  3. springboot(五)过滤器和拦截器

    前言 过滤器和拦截器二者都是AOP编程思想的提现,都能实现诸如权限检查.日志记录等.二者有一定的相似之处,不同的地方在于: Filter是servlet规范,只能用在Web程序中,而拦截器是Sprin ...

  4. springboot配置监听器、过滤器和拦截器

    监听器:listener是servlet规范中定义的一种特殊类.用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件.监听域对象的属性发生 ...

  5. 【spring-boot神器】第一篇:拦截器,过滤器,监听器,控制器,消息转换器,AOP执行顺序

    整理一下这几天学习的资料和代码 第一部分.上代码 1.spring各种器的实现,idea搭建spring-boot的教程在这里http://www.jianshu.com/p/9082a533fa3c ...

  6. springboot环境下配置过滤器和拦截器

    以前我们在配置过滤器和拦截器的时候,都是一个类继承一个接口,然后在xml中配置一下就ok 但是,但是,这是springboot的环境,没有xml的配置.所以我们还要继续学习啊啊啊啊啊~~~~~ 先简单 ...

  7. SpringBoot入坑指南之六:使用过滤器或拦截器

    在Web应用中,常常存在拦截全部或部分请求进行统一处理的应用场景,如权限校验.参数校验.性能监控等. 在SpringMVC框架中,我们可以通过过滤器或拦截器实现相关功能,spring-boot-sta ...

  8. SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂)

    SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂) 在实际开发过程中,经常会碰见一些比如系统启动初始化信息.统计在线人数.在线用户数.过滤敏/高词汇.访问权限控制(URL级别 ...

  9. Springboot 过滤器和拦截器详解及使用场景

    一.过滤器和拦截器的区别 1.过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的.请求结束返回也是,是在servlet处理完后,返回给前端之前. 2.拦截 ...

  10. 过滤器,拦截器,aop区别与使用场景

    1. 什么是过滤器 过滤器,顾名思义就是起到过滤筛选作用的一种事物,只不过相较于现实生活中的过滤器,这里的过滤器过滤的对象是客户端访问的web资源,也可以理解为一种预处理手段,对资源进行拦截后,将其中 ...

随机推荐

  1. SpringSecurity学习笔记-前后端分离

    1. 简介 Spring Security是Spring家族中的一个安全管理框架.相比于另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富. 一般来说中大型的项目都是使用Sp ...

  2. AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗

    最近在研究AI Agent如何调用三方API,整理了一篇文章,分享给大家. 调用三方 API(Function Calling)不是通过提示词(Prompt)来实现的,而是通过函数调用机制(Funct ...

  3. Unsloth更快训练大模型并导出GGUF - Windows

    环境搭建 系统环境 需要Nvidia显卡,至少8G显存,且专用显存与共享显存之和大于20G 建议将非安装版的环境文件都放到非系统盘,方便重装或移植 以Windows11为例,非安装环境文件都放在 E ...

  4. 【Linux】2.3 Linux目录结构

    基本介绍 linux 的文件系统是采用级层式的树状目录结构,在此结构中的最上层是根目录"/",然后在此目录下再创建其他的目录. 深刻理解 linux 树状文件目录是非常重要的,这里 ...

  5. 【Docker】命令行操作

    Docker常用命令 帮助命令 docker version docker info docker --help Docker 客户端 docker 客户端非常简单 ,我们可以直接输入 docker ...

  6. 【SpringMVC】数据转换 & 数据格式化

    数据转换 & 数据格式化 & 数据校验 数据转换 数据绑定流程 Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinder ...

  7. Quart.NET - 教程 11: 高级 (企业级) 特性

    译者注: 目录在这 Quartz.NET 3.x 教程 原文在这 Lesson 11: Advanced (Enterprise) Features 集群 集群目前仅适用于 AdoJobStore ( ...

  8. 实现Andriod的APP中文名

    让程序编译后,就会自动生成中文名,以及启动界面. 1. 2.AndroidManifest.xml的修改. 如果新建project,自动生成,否则要手动 3. 4.ok了.到手机端看结果吧

  9. python发送QQ邮件,自定义邮件内容

    怎么发QQ邮件,网上的例子很多,就不介绍了,具体可参考:https://www.jianshu.com/p/0f8c5e4e7054 这里主要把自定义邮件内容写一下 # -*- coding: utf ...

  10. 极客时间上新 .NET + AI 体系课

    课程特色 1️⃣ 全网首个.NET+AI体系化课程(没有之一!) 2️⃣ Semantic Kernel + Kernel Memory 核心知识全覆盖 3️⃣ 每课时基于Polyglot Noteb ...