SpringBoot:访问拦截器HandlerInterceptor的使用

SpringBoot:访问拦截器HandlerInterceptor的使用,第1张

完成

应用场景

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 常用的几个方法:

1:创建拦截器类,实现HandlerInterceptor接口

2:创建java类,继承WebMvcConfigurerAdapter,重写addInterceptors方法

实例化拦截器类并将其添加到拦截器链中。

3:访问 http://localhost:8080/freemarker 可见日志,后台已经拦截到

本文主要介绍下,SpringBoot的web项目中,

使用redis保存并共享session,可以实现集群内的登录信息共享。SpringBoot项目中,通过在 application.yml 增加redis的配置,即可实现对session的存储和修改。

那么session是在何时被处理的?session的key又是如何生成的呢?这里实际使用了web项目中的过滤器

在SpringBoot的web项目中,启动的tomcat在处理http请求时,有一个很重要的类: ApplicationFilterChain 。每个http请求在处理时都会通过这个类。这个类负责按顺序处理全部已注册的 Filter ,也就是过滤器。通过实现tomcat中的 Filter 接口,就可以定义一个过滤器。

在SpringBoot中的web项目中,有几个默认的过滤器,其中一个就是用来处理session的: SessionRepositoryFilter

SessionRepositoryFilter 主要的成员是两个接口,都有多个可选的实现类,通过这两个成员就实现了对session的解析。

当然也可以实现一个自己的过滤器,主要有两种方式:

下面我们使用第一种方式实现一个限制指定IP的过滤器:

通过过滤器解析session后,就可以根据session中保存的内容,判断当前登录的用户权限。

这里是通过一个拦截器实现的,在拦截器中可以直接通过 HttpServletRequest.getSession() 方法直接获取session的信息。

一个简单的拦截器实现如下:

定义之后要注册到处理流程中:

先来看下过滤器和拦截器的执行顺序,通过debug得到的执行顺序如下图:

在大部分场景中,过滤器和拦截器都是可互换的,使用哪个都可以。

过滤器和拦截器也有些区别,这里不谈实现和规范的差异,就说下使用中可能涉及的区别:

最后对于过滤器和拦截器的应用场景,说下个人的总结。基于执行顺序,方法参数和SpringBoot中的一些实现类来看。

以上内容属个人学习总结,如有不当之处,欢迎在评论中指正


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/11726555.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-18
下一篇2023-05-18

发表评论

登录后才能评论

评论列表(0条)

    保存