spring拦截器(2018-05-27 Spring拦截器和Skywalking冲突)
本文目录
- 2018-05-27 Spring拦截器和Skywalking冲突
- SpringBoot配置拦截器空指针异常
- springboot的登录用拦截器还是sercurity
- SpringBoot 三种拦截http请求方式Filter,interceptor和aop
- SpringBoot系列:4.session和鉴权—过滤器和拦截器
- Spring Security自定义拦截器
- SpringBoot:访问拦截器HandlerInterceptor的使用
- spring mvc用html5 拦截器怎么配置
- springmvc拦截器怎么用
- 如何配置springdispatcher拦截指定页面
2018-05-27 Spring拦截器和Skywalking冲突
skywalking-5.0.0-alpha 已经修复的版本 skywalking-5.0.0-beta
在观察项目中的日志时,发现 有一个拦截全部Controller方法的日志切面WebRequestInterceptor类
该方法会拦截skywalking的某个方法。
导致每次Web请求,Controller虽然被执行一次,但是doAround会被执行两次。 如果在doAround中做了某些身份认证,Token校验之类的,则产生了不必要的重复请求。
在doAround中打印: 会发现调用了getSkyWalkingDynamicField。
这个方法由skywalking-agent的InstMethodsInter 生成的: SkyWalkingAgent通过
找到一个具体实现类
然后调用define
然后生成了InstMethodsInter 这个类intercept的方法中:
interceptor.afterMethod对应 GetBeanInterceptor 的 afterMethod, 这里会调用getSkyWalkingDynamicField ,但是 这里会被WebRequestInterceptor拦截!!! 。
getSkyWalkingDynamicField出自EnhancedInstance
在InstMethodsInter.afterMethod调用getSkyWalkingDynamicField的时候,不小心会被Spring的Aspect拦截。
导致重复调用了一次WebRequestInterceptor的doAround。
改写JoinPoint,并排除getSkyWalkingDynamicField方法 :
果然一个月之前官方已经修复了这个BUG 修复的原理就是把Spring的org.springframework.aop.support.MethodMatchers 的matches 静态方法给增强了,那就是让Spring忽略EnhancedInstance接口的所有方法! 这方法既粗暴,又优雅,非常值得学习。
相关链接 issue #1114 pull #1118
SpringBoot配置拦截器空指针异常
拦截器中,@AutoWaired一个service,运行的时候发现该service对象为空 对应的配置 尝试过: 结果,对象还是为空 加载类上启动就报错 最终,查阅博客找到一个解决方案 最终 我对于这次问题的解决的理解是 在此多谢博客, dzl84394的专栏
springboot的登录用拦截器还是sercurity
过滤器你自己本身的业务系统用拦截器和过滤器都可以。我这里说一下为什么spring security使用过滤器而不是拦截器。因为作为一个通用的安全框架不应该耦合其他web框架的元素。很显然拦截器是spring mvc或struts等框架提供的,如果基于拦截器势必耦合这些框架,就做不到通用了。Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
SpringBoot 三种拦截http请求方式Filter,interceptor和aop
***隐藏网址*** 这三种拦截方式的拦截顺序是:filter—》Interceptor--》ControllerAdvice--》@Aspect --》Controller; 这三种方式的区别: 1.过滤器Filter可以拿到原始的HTTP请求和响应的信息, 但是拿不到你真正处理请求方法的信息,也就是方法的信息。 2.拦截器Interceptor可以拿到原始的HTTP请求和响应的信息,也可以拿到你真正处理请求方法的信息,但是拿不到传进参数的那个值。 3.切片Aspect,既然Spring那么支持AOP,可以拿到原始的HTTP请求和响应的信息, 也可以拿到你真正处理请求方法的信息,也可以传进参数的那个值。 实现Filter接口 实现 HandlerInterceptor 接口,然后配置进Spring。 配置进spring pom.xml 添加Aop支持
SpringBoot系列:4.session和鉴权—过滤器和拦截器
本文主要介绍下,SpringBoot的web项目中,
使用redis保存并共享session,可以实现集群内的登录信息共享。SpringBoot项目中,通过在 application.yml 增加redis的配置,即可实现对session的存储和修改。
那么session是在何时被处理的?session的key又是如何生成的呢?这里实际使用了web项目中的过滤器。
***隐藏网址***
在SpringBoot中的web项目中,有几个默认的过滤器,其中一个就是用来处理session的: SessionRepositoryFilter
SessionRepositoryFilter 主要的成员是两个接口,都有多个可选的实现类,通过这两个成员就实现了对session的解析。
当然也可以实现一个自己的过滤器,主要有两种方式:
下面我们使用第一种方式实现一个限制指定IP的过滤器:
通过过滤器解析session后,就可以根据session中保存的内容,判断当前登录的用户权限。
这里是通过一个拦截器实现的,在拦截器中可以直接通过 HttpServletRequest.getSession() 方法直接获取session的信息。
一个简单的拦截器实现如下:
定义之后要注册到处理流程中:
先来看下过滤器和拦截器的执行顺序,通过debug得到的执行顺序如下图:
在大部分场景中,过滤器和拦截器都是可互换的,使用哪个都可以。
过滤器和拦截器也有些区别,这里不谈实现和规范的差异,就说下使用中可能涉及的区别:
最后对于过滤器和拦截器的应用场景,说下个人的总结。基于执行顺序,方法参数和SpringBoot中的一些实现类来看。
以上内容属个人学习总结,如有不当之处,欢迎在评论中指正
Spring Security自定义拦截器
HttpSecurity实际上就是在配置Spring security的过滤器链,比如:CSRF,CORS,表单登录等,每个配置器对应一个过滤器,可以通过HttpSecurity配置过滤器的行为。 甚至可以像CRSF一样直接关闭过滤器,例如:SessionManagement Spring Security通过SessionManagermentConfigurer来配置SessionManagerment的行为,与SessionManagermentConfigurer类似的配置器还有CorsConfigurer,RememberMeConfigurer等,他们都实现了SecurityConfigurer的标准接口。 SessionManagementConfigurer是在configure方法中将最终的SessionManagementFilter插入过滤器链来实现会话管理的。 除了Spring security提供的过滤器外,我们还可以添加自己的过滤器以实现更多的功能,这些都是可以在HttpSecurity中实现 虽然Spring Security 的过滤器链对过滤器没有特殊要求,只要继承了Filter即可,但是在Spring体系中,推荐使用OnePerRequestFilter来实现,它可以确保一次请求只会通过一次该过滤器(Filter实际并不能保证这一点) ***隐藏网址*** 非常爽眼~
SpringBoot:访问拦截器HandlerInterceptor的使用
完成
应用场景 1、日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。 2、权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。 3、性能监控:典型的是慢日志。
拦截器我想大家都并不陌生,最常用的登录拦截、或是权限校验、或是防重复提交、或是根据业务像12306去校验购票时间,总之可以去做很多的事情。
定义一个Interceptor 非常简单方式也有几种,我这里简单列举两种
1、类要实现Spring 的HandlerInterceptor 接口
2、类继承实现了HandlerInterceptor 接口的类,例如 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter
preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView (这个博主就基本不怎么用了);
afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);
------------
这样在我们业务中比如要记录系统日志,日志肯定是在afterCompletion之后记录的,否则中途失败了,也记录了,那就扯淡了。一定是程序正常跑完后,我们记录下那些对数据库做个增删改的操作日志进数据库。所以我们只需要继承HandlerInterceptorAdapter,并重写afterCompletion一个方法即可,因为preHandle默认是true。
运行流程总结如下:
1、拦截器执行顺序是按照Spring配置文件中定义的顺序而定的。
2、会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则按顺序加载完preHandle方法。
3、然后执行主方法(自己的controller接口),若中间抛出异常,则跟return false效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。
4、在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的preHandle方法return false,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行)
WebMvcConfigurer配置类其实是Spring内部的一种配置方式,采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制,可以 自定义一些Handler,Interceptor,ViewResolver,MessageConverter 。基于java-based方式的spring mvc配置,需要创建一个 配置 类并实现 WebMvcConfigurer 接口;
在Spring Boot 1.5版本都是靠重写 WebMvcConfigurerAdapter 的方法来添加自定义拦截器,消息转换器等。SpringBoot 2.0 后,该类被标记为@Deprecated(弃用)。官方推荐直接实现WebMvcConfigurer或者直接继承WebMvcConfigurationSupport,方式一 实现WebMvcConfigurer接口( 推荐),方式二继承WebMvcConfigurationSupport类
其中常用的方法:
以前写SpringMVC的时候,如果需要访问一个页面,必须要写Controller类,然后再写一个方法跳转到页面,感觉好麻烦,其实重写WebMvcConfigurer中的addViewControllers方法即可达到效果了
值的指出的是,在这里重写addViewControllers方法,并不会覆盖 WebMvcAutoConfiguration (Springboot自动配置)中的addViewControllers(在此方法中,Spring Boot将“/”映射至index.html),这也就意味着 自己的配置和Spring Boot的自动配置同时有效 ,这也是我们推荐添加自己的MVC配置的方式。
比如,我们想 自定义静态资源映射目录 的话,只需重写addResourceHandlers方法即可。
注:如果继承WebMvcConfigurationSupport类实现配置时必须要重写该方法,具体见其它文章
此时会注册一个默认的Handler:DefaultServletHttpRequestHandler,这个Handler也是用来处理静态文件的,它会尝试映射/。当DispatcherServelt映射/时(/ 和/ 是有区别的),并且没有找到合适的Handler来处理请求时,就会交给DefaultServletHttpRequestHandler 来处理。注意:这里的静态资源是放置在web根目录下,而非WEB-INF 下。 可能这里的描述有点不好懂(我自己也这么觉得),所以简单举个例子,例如:在webroot目录下有一个图片:1.png 我们知道Servelt规范中web根目录(webroot)下的文件可以直接访问的,但是由于DispatcherServlet配置了映射路径是:/ ,它几乎把所有的请求都拦截了,从而导致1.png 访问不到,这时注册一个DefaultServletHttpRequestHandler 就可以解决这个问题。其实可以理解为DispatcherServlet破坏了Servlet的一个特性(根目录下的文件可以直接访问),DefaultServletHttpRequestHandler是帮助回归这个特性的。
这个方法是用来 配置视图解析器 的,该方法的参数ViewResolverRegistry 是一个注册器,用来注册你想自定义的视图解析器等。ViewResolverRegistry 常用的几个方法:
spring mvc用html5 拦截器怎么配置
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判断当前时间是否是购票时间。1、定义Interceptor的实现类 SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式: 第一种方式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口,或者是这个类继承实现了HandlerInterceptor 接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter ; 第二种方式是实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。2、实现HandlerInterceptor接口HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。 (1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顾名思义,该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。 (2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行,这和Struts2 里面的Interceptor 的执行过程有点类型。Struts2 里面的Interceptor 的执行过程也是链式的,只是在Struts2 里面需要手动调用ActionInvocation 的invoke 方法来触发对下一个Interceptor 或者是Action 的调用,然后每一个Interceptor 中在invoke 方法调用之前的内容都是按照声明顺序执行的,而invoke 方法之后的内容就是反向的。 (3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。下面是一个简单的代码说明: view plain copy***隐藏网址******隐藏网址*** import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class SpringMVCInterceptor implements HandlerInterceptor { /** * preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,SpringMVC中的Interceptor拦截器是链式的,可以同时存在 * 多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行,而且所有的Interceptor中的preHandle方法都会在 * Controller方法调用之前调用。SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令preHandle的返 * 回值为false,当preHandle的返回值为false的时候整个请求就结束了。 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub return false; } /** * 这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之 * 后,也就是在Controller的方法调用之后执行,但是它会在DispatcherServlet进行视图的渲染之前执行,也就是说在这个方法中你可以对ModelAndView进行操 * 作。这个方法的链式结构跟正常访问的方向是相反的,也就是说先声明的Interceptor拦截器该方法反而会后调用,这跟Struts2里面的拦截器的执行过程有点像, * 只是Struts2里面的intercept方法中要手动的调用ActionInvocation的invoke方法,Struts2中调用ActionInvocation的invoke方法就是调用下一个Interceptor * 或者是调用action,然后要在Interceptor之前调用的内容都写在调用invoke之前,要在Interceptor之后调用的内容都写在调用invoke方法之后。 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } /** * 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行, * 这个方法的主要作用是用于清理资源的,当然这个方法也只能在当前这个Interceptor的preHandle方法的返回值为true时才会执行。 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub } } 3、定义的拦截器类加到SpringMVC的拦截体系中 view plain copy《span style="font-size:12px;"》 《mvc:interceptors》 《!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求 --》 《bean class="com.host.app.web.interceptor.AllInterceptor"/》 《mvc:interceptor》 《mvc:mapping path="/test/number.do"/》 《!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 --》 《bean class="com.host.app.web.interceptor.LoginInterceptor"/》 《/mvc:interceptor》 《/mvc:interceptors》《/span》 由上面的示例可以看出可以利用mvc:interceptors标签声明一系列的拦截器,然后它们就可以形成一个拦截器链,拦截器的执行顺序是按声明的先后顺序执行的,先声明的拦截器中的preHandle方法会先执行,然而它的postHandle方法和afterCompletion方法却会后执行。 在mvc:interceptors标签下声明interceptor主要有两种方式: (1)直接定义一个Interceptor实现类的bean对象。使用这种方式声明的Interceptor拦截器将会对所有的请求进行拦截。 (2)使用mvc:interceptor标签进行声明。使用这种方式进行声明的Interceptor可以通过mvc:mapping子标签来定义需要进行拦截的请求路径。 经过上述两步之后,定义的拦截器就会发生作用对特定的请求进行拦截了。
springmvc拦截器怎么用
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆等。
一. 使用场景
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反 向代理,如apache可以自动记录);
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实 现。
5、OpenSessionInView:如Hibernate,在进入处理器打开Session,在完成后关闭Session。
本质也是AOP(面向切面编程),也就是说符合横切关注点的所有功能都可以放入拦截器实现。
二. 拦截接口
public interface HandlerInterceptor { boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; }
如何配置springdispatcher拦截指定页面
《!-- 拦截器配置 --》 《mvc:interceptors》 《!-- session超时 --》 《mvc:interceptor》 《mvc:mapping path="/*/*"/》 《bean class="com.ziyou.platform.interceptor.SessionTimeoutInterceptor"》 《property name="allowUrls"》 《list》 《!-- 如果请求中包含以下路径,则不进行拦截 --》 《value》/login《/value》 《value》/js《/value》 《value》/css《/value》 《value》/image《/value》 《value》/images《/value》 《/list》 《/property》 《/bean》 《/mvc:interceptor》 《/mvc:interceptors》 《!-- 自定义异常处理,SimpleMappingExceptionResolver这个类可以是个空类,但是要写,方便在java代码里面使用 --》 《bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"》 《property name="exceptionMappings"》 《props》 《prop key="com.ziyou.platform.interceptor.SessionTimeoutException"》redirect:/login《/prop》 《/props》 《/property》 《/bean》
更多文章:
powerpoint没保存怎么恢复(电脑死机导致PPT没保存该如何恢复)
2024年6月29日 19:32
eof函数的返回值的数据类型(EOF是什么类型的量C语言问题)
2024年7月13日 19:09
安装ubuntu的分区详细教程(ubuntu 14.04安装怎么分区)
2024年8月13日 11:00
embed函数-embed函数语法-记住吧?iframe 和 embed的区别
2024年7月4日 16:25
编辑器怎么同步到公众号(秀米编辑器内容编辑完了怎么弄到微信公众平台里去)
2024年8月19日 09:55
oracle基本语句增删改(oracle增删改都建 触发器 可以建一个触发器吗)
2024年8月12日 07:10
listview点击item跳转(ListView怎样点击Item跳转到下一个Activity)
2024年9月29日 17:25
lenovoutility是什么软件(lenovo utility是否可以开机禁止)
2024年7月23日 14:36
java模拟器下载中文版(JAVA模拟器在那里下载 可以在电脑上玩)
2024年7月8日 10:46
滚动条怎么设置大小值(Excel 2003 如何设置滚动条大小)
2024年8月8日 07:30
cocos下载(cocos2dx官网有4个下载文件下载哪一个)
2024年7月24日 12:31
python编程加法(在Python编程中运行print(’加法计算12+9=’,12+9),运行结果是)
2024年7月12日 22:45