Spring Boot之拦截器与过滤器(完整版)
作者:liuxiaopeng
链接:http://www.cnblogs.com/paddix
作者:蓝精灵lx
原文:https://blog.csdn.net/liuxiao723846/article/details/80656492
参考以上两位作者文章链接进行实验整合,仅供学习交流
一、拦截器与过滤器
先理解一下AOP的概念,AOP不是一种具体的技术,而是一种编程思想。
在面向对象编程的过程中,我们很容易通过继承、多态来解决纵向扩展。
但是对于横向的功能,比如,在所有的service方法中开启事务,或者统一记录日志等功能,面向对象的是无法解决的。所以AOP——面向切面编程其实是面向对象编程思想的一个补充。而我们今天讲的过滤器和拦截器都属于面向切面编程的具体实现。
过滤器(Filter)与拦截器()主要区别包括以下几个方面:
Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。
Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,使用更方便。
二、过滤器的实现
(1)自定义一个实现javax.servlet.Filter接口的过滤器类
package com.test.domain; import javax.servlet.*;
import java.io.IOException; public class LogCostFilter implements Filter {
//servlet容器初始化时
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
//servlet容器存在时
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
long start = System.currentTimeMillis();
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Execute cost="+(System.currentTimeMillis()-start));
}
//servlet容器销毁时
@Override
public void destroy() { }
}
这段代码的逻辑比较简单,就是在方法执行前先记录时间戳,然后通过过滤器链完成请求的执行,在返回结果之间计算执行的时间。这里需要主要,这个类必须继承Filter类。
可以看出,Filter的生命周期由Servlet容器相关
(2)在Spring boot中,我们需要FilterRegistrationBean来完成配置。其实现过程如下:
package com.test.config;
import com.test.domain.LogCostFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class FilterConfig { @Bean
public FilterRegistrationBean registration(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new LogCostFilter());//实例化Filter类
filterRegistrationBean.addUrlPatterns("/*");//设置匹配模式,这里设置为所有,可以按需求设置为"/hello"等等
filterRegistrationBean.setName("LogCostFilter");//设置过滤器名称
filterRegistrationBean.setOrder();//设置执行顺序
return filterRegistrationBean;
}
}
启动服务器访问任意URL皆可得到打印的时间戳
过滤器的另一种实现方法:可以在启动类上使用 @ServletComponentScan("com.test.domian.FilterCostConfig")和实现了Filter接口的自定义类上使用注解 @WebFilter(urlPatterns = "/*",filterName = "LogCostFilter"),不过@WebFilter这个注解是Servlet3.0的规范,且并没有指定执行的顺序,其执行顺序依赖于Filter的名称,是根据Filter类名(注意不是配置的filter的名字)的字母顺序倒序排列,并且@WebFilter指定的过滤器优先级都高于FilterRegistrationBean配置的过滤器。
三、拦截器的实现
使用拦截器来实现上面同样的功能,记录请求的执行时间。
(1)自定义一个实现HandlerInterceptor 接口的拦截器类:
package com.test.interceptor; import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class LogcostInterceptor implements HandlerInterceptor {
long start = System.currentTimeMillis();
//preHandle是在请求执行前执行的
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
start = System.currentTimeMillis();
return true;
//返回true,postHandler和afterCompletion方法才能执行
// 否则false为拒绝执行,起到拦截器控制作用
} //postHandler是在请求结束之后,视图渲染之前执行的,但只有preHandle方法返回true的时候才会执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("Interception cost="+(System.currentTimeMillis()-start));
} //afterCompletion是视图渲染完成之后才执行,同样需要preHandle返回true,
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
//该方法通常用于清理资源等工作
}
}
这里我们需要自定义一个类来实现HandlerInterceptor这个接口,实现里面的三个方法,具体说明已写在方法注释中
(2)拦截器类的配置:
package com.test.config; import com.test.interceptor.LogcostInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; @Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
/**
* 静态资源配置
*/
/*@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/img/**")
.addResourceLocations("classpath:/imgs/"); super.addResourceHandlers(registry);
}*/ /**
* 默认首页配置
*/
// @Override
// public void addViewControllers(ViewControllerRegistry registry) {
// registry.addViewController("/").setViewName("forward:/index");
// registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
// super.addViewControllers(registry);
// } /**
* interceptor配置
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogcostInterceptor())
//添加需要验证登录用户操作权限的请求
.addPathPatterns("/**")
//这里add为“/**”,下面的exclude才起作用,且不管controller层是否有匹配客户端请求,拦截器都起作用拦截
// .addPathPatterns("/hello")
//如果add为具体的匹配如“/hello”,下面的exclude不起作用,且controller层不匹配客户端请求时拦截器不起作用 //排除不需要验证登录用户操作权限的请求
.excludePathPatterns("/wang")
.excludePathPatterns("/css/**")
.excludePathPatterns("/js/**")
.excludePathPatterns("/images/**");
//这里可以用registry.addInterceptor添加多个拦截器实例,后面加上匹配模式
super.addInterceptors(registry);//最后将register往这里塞进去就可以了
}
}
这里我们重写了addInterceptors这个方法,进行拦截器的配置,主要配置项就两个,一个是指定拦截器(定义方法行为),第二个是指定拦截的URL(模式匹配)。
注释部分的静态资源配置和默认首页配置本人还未做实验,应该没问题的
再启动系统访问任意一个URL即可得到打印的时间戳
现在我们权限和认证更多的是在Spring Boot中整合使用shiro或者Spring Security来完成,比较少用自定义拦截器了,不过可以用拦截器实现其他功能,比如ip黑名单等等特殊场景
Spring Boot之拦截器与过滤器(完整版)的更多相关文章
- Spring Boot配置拦截器及实现跨域访问
拦截器功能强大,能够深入方法前后,常应用于日志记录.权限检查和性能检测等,几乎是项目中不可或缺的一部分,本文就来实现Spring Boot自定义拦截器的配置. 理论指导 问:Spring Boot怎么 ...
- spring boot 使用拦截器,注解 实现 权限过滤
http://www.cnblogs.com/zhangXingSheng/p/7744997.html spring boot 使用拦截器 实现 用户登录拦截 http://www.cnblogs. ...
- Spring Boot (20) 拦截器
动态资源和静态资源 拦截器可以算是aop的一种实现,专门拦截对动态资源的后台请求,也就是拦截对控制层的请求,主要用于判断用户是否有权限请求后台.拦截器不会拦截静态资源,如spring boot默认静态 ...
- Spring Boot整合拦截器
过滤器和监听器都属于Servlet 的api,还可以使用 Spring 提供的拦截器(HandlerInterceptor)进行改更精细的控制.
- spring boot 添加拦截器
构建一个spring boot项目. 添加拦截器需要添加一个configuration @Configuration @ComponentScan(basePackageClasses = Appli ...
- spring boot 添加拦截器的简单实例(springBoot 2.x版本,添加拦截器,静态资源不可访问解决方法)
spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor 一.HandlerInterceptor HandlerInterceptor是s ...
- 【第四十章】Spring Boot 自定义拦截器
1.首先编写拦截器代码 package com.sarnath.interceptor; import javax.servlet.http.HttpServletRequest; import ja ...
- spring boot的拦截器简单使用
1.spring boot拦截器默认有: HandlerInterceptorAdapter AbstractHandlerMapping UserRoleAuthorizationIntercept ...
- Spring Aop、拦截器、过滤器的区别
Filter过滤器:拦截web访问url地址.Interceptor拦截器:拦截以 .action结尾的url,拦截Action的访问.Spring AOP拦截器:只能拦截Spring管理Bean的访 ...
随机推荐
- jQuery 和 YUI (Yahoo User Interface) 各自的优缺点有哪些?具体的使用场景是怎样的?
张经纬,前端工程师 知乎用户.赵勇杰.知乎用户 等人赞同 其实jQuery和YUI的侧重点是不一样的. jQuery专注于DOM的操作,他通过继承的方式给传入的对象增加了新的方法,从而使我们可以通过链 ...
- 自定义控件(视图)2期笔记14:自定义视图之View事件分发 dispatchTouchEvent,onTouch,onTouchEvent,onClick逻辑顺序过程
1. 这里我们先从案例角度说明dispatchTouchEvent,onTouch,onTouchEvent,onClick逻辑顺序过程: (1)首先我们重写一个MyButton 继承自 Button ...
- 1562. [NOI2009]变换序列【二分图】
Description Input Output Sample Input 5 1 1 2 2 1 Sample Output 1 2 4 0 3 HINT 30%的数据中N≤50: 60%的数据中N ...
- [SHOI2008]小约翰的游戏
题目 不会,抄论文 这是一个非常牛逼的东西,叫做\(anti\)博弈,就是进行最后一次操作的人输 我们考虑一下这道题 显然如果石子个数都是\(1\),那么有奇数堆石子先手必败,有偶数堆石子先手必胜 如 ...
- MySQL无法存储Emoji表情问题
数据插入的时候报错: 1366 - Incorrect string value: '\xF0\x9F\x98\x81' for column 'job' at row 23 解决办法: 1.修改配置 ...
- ls: Call From hdoop2/192.168.18.87 to hdoop2:8020 failed on connection exception: java.net.ConnectException: 拒绝连接; For more details see
场景: 预发环境中,同事已经搭建了一套hadoop集群,由于版本与所需不符,所以需要替换版本 问题描述: 在配置文件都准确的情况下,启动hadoop,出现以下报错: 启动之前初始化: 初始化目录 ...
- 串口调试助手vc源程序及其详细编写过程
串口调试助手vc源程序及其详细编写过程 目次: 1.建立项目 2.在项目中插入MSComm控件 3.利用ClassWizard定义CMSComm类控制变量 4.在对话框中添加控件 5.添加串口事件 ...
- 第一次码java感想及前三次作业总结
写在前面 嗯,首先是java,这学期第一次oo作业布置下来的周末才开始看的,第一次作业因此写得有些手忙脚乱.不过大概看了一遍后发现比c好用,入门更简单吧,好多操作直接import一下就能用了,码代码的 ...
- Scala 方法和函数
package com.bigdata // /** Scala 方法和函数:Scala中既有函数也有方法,大多数情况下我们都可以不去理会他们之间的区别. * * 方法:Scala 中的方法跟 Jav ...
- lua表类型
Lua的表的定义: typedef struct Table { CommonHeader; lu_byte flags; lu_byte lsizenode; /* log2 of size of ...