网站后台编辑框不显示,现在建设网站都用什么软件,助农网站策划书,网站开发网站设计的标准本篇主要介绍Spring Boot的统一功能处理中的拦截器。
目录
一、拦截器的基本使用
二、拦截器实操
三、浅尝源码
初始化DispatcherServerlet
处理请求#xff08;doDispatch)
四、适配器模式 一、拦截器的基本使用
在一般的学校或者社区门口#xff0c;通常会安排几个…
本篇主要介绍Spring Boot的统一功能处理中的拦截器。
目录
一、拦截器的基本使用
二、拦截器实操
三、浅尝源码
初始化DispatcherServerlet
处理请求doDispatch)
四、适配器模式 一、拦截器的基本使用
在一般的学校或者社区门口通常会安排几个保安大爷来进行身份验证只有身份符合要求的人才会被放行否则则会被大爷拦住而拦截器就像我们程序的保安大爷只有通过我们自己定义的拦截规则请求才能被放行到目标接口上。 下面我们来看看如何在Spring Boot中使用拦截器 在项目中设置拦截我们需要先自己定义一些拦截器里面包含一些具体的拦截规则定义拦截器的代码如下
1)首先创建一个拦截类通常以“Interceptor”作为类名的后半部分这里我们定义一个LoginInterceptor类意为与登录相关的拦截器然后让该类实现一个HandlerInterceptor接口具体如下
Component
public class LoginInterceptor implements HandlerInterceptor {}(2)重写三个方法 Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {}Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
其中preHandle为在目标方法执行前要执行的方法其返回值如果为true则会被放行去执行目标方法为false则拦截我们可以在这个方法里根据需求定义拦截规则。postHandle为目标方法执行后要执行的方法。afterCompletion为最后视图渲染完后最后执行的方法由于现在都是前后端分离了后端一般不处理视图因此这个方法不需要过多了解。
定义好拦截器后我们还需要配置拦截器具体配置流程如下
(1)创建配置类一般以Config结尾这里以为WebConfig实现WebMvcConfigurer接口
public class WebConfig implements WebMvcConfigurer {
}
(2)然后重写addInterceptor方法
Overridepublic void addInterceptors(InterceptorRegistry registry) {}
(3)然后我们在里面添加我们需要配置的拦截器具体如下 这里我们可以通过Autowired注入一个LoginInterceptor对象也可以直接在参数里new一个只要是传入一个实现前面的HandlerInterceptor接口的类的对象即可。
(4)然后在配置我们需要拦截的路径即请求url中ip地址端口号的后面的部分 这里的”/**表示任意路径例如“/user/book、/user”等另外还有“/*他只能表示一级路径例如
”/user/book等。
(4)由于通常我们并不需要所有路径都进行拦截例如登录请求因此我们还需要排除一些路径让这些路径不被拦截具体如下 5最后我们还需要把这个类放到Spring容器里由于这里与配置相关所有使用Configuration。
二、拦截器实操 接下来我们来实操一下。首先我们创建一个Controller类在里面定义一个login方法这里只是简单测试一下不进行密码校验只是给用户设置一个登录状态而已 然后再添加几个测试方法 然后我们再来定义一下拦截器再preHandle方法中设置一下拦截规则只有处于登录状态才能放行 并在另外两个方法中打印日志来进行观察 然后在注册配置一下拦截器不拦截login方法其他全部拦截 最后我们通过postMan构造请求来访问一下这些方法.
先访问一下test01 可以发现返回的响应为空也就是说请求被拦截器拦截到了。
然后我们再来访问一下login 可以发现响应有数据了但由于我们请求中没有传值导致接口中的两个参数为空所以返回了false。接下来我们补上这两个值再访问一下 可以发现响应中返回true了同时这也意味着我们现在已经给用户设置成登录状态了此时我们再来访问test01 可以发现响应已经有数据了。这也就意味着这个请求已经被拦截器放行了。
最后我们再来看一下 控制台的日志
可以发现拦截器是严格按照顺序执行相关方法的 如果请求被拦截了则只会执行postHandle方法就返回了如果请求被放行则会按顺序执行完拦截器中的三个方法。并且对于配置中没有涉及到的路径和被排除的路径则根本不会进入到拦截器。
三、浅尝源码
接下来我们来浅浅阅读一下与拦截器相关的部分源码。
初始化DispatcherServerlet
仔细观察日志可以发现当我们的服务器接收到第一个来自前端的请求时会初始化一个dispatcherServerlet类。 它的初始化方法为init(),具体实现是在其父类HttpServerletBean中实现的 init方法首先创建了一个PropertyValues类这个类我并不知道是干嘛的但根据其名称可以大体猜出来应该是去读一些配置并且下面的if语句 判断这个对象是否为空不为空才去执行相关逻辑因此可以推测出if语句里应该是去根据读到的配置去进行一些设置。在init方法最后执行了一个initServerletBean方法我们来具体看一下这个方法 转到定义可以发现HttpServerletBean中并未实现这个方法接下来我们去其子类看一下 可以发现其子类FrameworkServerlet重写了这个方法并具体进行了实现。仔细观察可以发现这个方法主要是在打印日志日志的内容就是我们在前面控制台所看到的 并且 这里还进行了计时并打印在了日志里。除去日志的部分可以发现这个方法就只剩下try-catch中的内容了 接下来我们继续进入到其中的initWebAppliactionContext ()来看一下 根据名字可以发现这个方法应该是用来 初始化WebApplicationContext的并且通过代码大致可以发现这个方法会先去从类的成员属性中获取WebAppliactionContext如果成员属性不为空则会直接用成员属性的如果为空则调用findWebApplication去寻找一个并使用如果没找到则去创建一个。执行完上面第一个红框里的内容后wac应该是已经不再为空了的接下来调用onRefresh方法可以发现这里加了锁来防止线程安全问题。接下来我们进到onRefresh方法来看一下 可以发现FrameWorkServerlet中并未进行实现我们再进到其子类看一下 可以发现子类进行了实现并且此时这个子类就是我们要初始化的DispatchServerlet。然后我们再看看这个方法里使用的initStrategies方法: 通过方法名称可以发现这个方法是在进行一些初始化然后再通过具体代码可以发现这个方法初始化了九个组件这些组件就是Spring的九大组件其名称如下
MultipartResolver文件上传解析器LocaleResolver区域解析器ThemeResolver:主题解析器HandlerMappings:处理器映射器HandlerAdapters处理器适配器HandlerExceptionResolvers:异常处理器解析器RequestToviewNameTranslator视图名称转换器ViewResolvers视图解析器FlashMapManagerFlashMap管理器
初始化这些组件后DispatchServerlet就初始化完了。
处理请求doDispatch)
初始化完成后DispatchServerlet就能进行请求的处理了处理请求主要通过DispatchServerlet类的doDispatch方法来对请求调度给Controller来执行下面我们来详细看一下这个方法
首先它会去获取一个与请求对应的处理器然后再根据处理器去获取一个能够使用的适配器 然后再根据适配器来顺序执行拦截器的相关方法以及目标方法 然后处理视图并执行最后的afterCompletion方法 四、适配器模式
在前面浅尝源码时提到了适配器这个概念适配器使用到了一种设计模式 --- 适配器模式。适配器模式能将一个类的接口转换成符合客户期待的接口从而使原本并不能兼容使用的接口也能使用了。简单来说就是有一个接口由于兼容问题并不能直接使用需要在中间加上一个适配器才能够使用这个接口。例如我们生活中的转接头当我们的手机是Type_c的充电口而我们却只有苹果的数据线时这根苹果的数据线自然是冲不了我们的手机的此时就需要一个转接头了通过转接头我们就可以给手机充电了。此处转接头就相当于我们的的适配器而转接头的设计就相当于是是适配器模式这种设计思想 可能有人会说为什么 不在一开始就设计成兼容的接口呢这样就没必要大费周章弄一个适配器了这样固然好但人并不是万能的总会有我们意想不到的情况出现面面俱到几乎是不可能的就像使用Type-c接口的手机厂商肯定不会想到有人会用苹果的数据线来充电但既然这个需求是存在的也就不能不去实现了重新设计的话成本又太高因此就只能使用适配器这一无奈之举了。