拦截器interceptor总结

拦截器

  • 一. 概念
    • 拦截器和AOP的区别:
    • 拦截器和过滤器的区别:
  • 二. 配置方法
    • 2.1 定义拦截器bean
    • 2.2 定义配置类
    • 2.3 执行流程
    • 2.4 简化方法:将拦截器类配置到SpringMvcConfig中 ★
  • 三. 案例:使用拦截器中校验登录
    • (1)定义拦截器类
    • (2)配置拦截器

一. 概念

引入
消息从浏览器发送到服务端,请求会先到达Tomcat服务器;
将请求划分成动态、静态资源;处理动态;
动态的资源经过Filter过滤器;
过滤器放行后才是Spring,中央控制器会根据访问分发到controller中;
controller操作执行完后,返回数据给浏览器;

当如果想让每个controller被访问之前和后做一件事---- 拦截器

拦截器interceptor总结_第1张图片
如:权限控制,需要看访问是否有权限访问这个controller;

定义:拦截器是一种动态拦截方法调用的机制,在SpringMVC中动态拦截controller方法的执行;

作用
1. 在指定的方法调用前后执行预先设定的代码(增强);
2. 阻止原始方法的执行(如权限控制)

拦截器和AOP的区别:

AOP是原始方法确定会被调用,在调用前后做增强处理,拦截器不仅能增强,还决定你能不能调用方法;

拦截器和过滤器的区别:

1.归属不同,Filter属于Servlet技术,Interceptor拦截器属于SpringMVC技术;
SpringMVC的功能可以在拦截器中操作,但不能在Filter中操作;
2.拦截范围不同:
Filter过滤器是在Tomcat服务器阶段配置,能对所有请求进行增强;
拦截器仅仅是对SpringMVC阶段操作,SpringMVC能接受哪些访问取决于容器启动配置中的设置:

二. 配置方法

2.1 定义拦截器bean

(1)在controller层新建一个拦截器层,创建一个自定义interceptor拦截器类,配置成bean;
拦截器interceptor总结_第2张图片

(2)自定义拦截器类 实现 HandlerInterceptor,并重写preHandlepostHandleafterCompletion三个方法;

拦截器是bean,要添加 @Component注解

preHandle方法返回false会终止原始操作,原始操作后面的也不再执行;而true会都执行。可以用此增加判断逻辑,满足则true,不满足则false。

(3)让SpringMVC加载到拦截器bean;
保证SpringMVC能扫描到:
此时拦截器类就在controller目录下,不需要改;
拦截器interceptor总结_第3张图片

2.2 定义配置类

(1)在config包下定义一个SpringMvcSupport配置类,类似addResourceHandlers分发者服务,继承WebMvcConfiguartionSupport实现 addIntercepter方法;
拦截器interceptor总结_第4张图片

(2)将之前定义的拦截器类ProjectInterceptor的bean注入,
再指定路径,如当调用“/books”请求时拦截;
拦截器interceptor总结_第5张图片
(3)让SpringMVC能扫描到配置类:
拦截器interceptor总结_第6张图片

效果
拦截器interceptor总结_第7张图片
后台:
可以看出,通过拦截器对原有方法增强了;除此之外也可以 preHandle 返回false,则拦截;
在这里插入图片描述

注意:
只有books 才会被拦截;而books/100 不会被拦截!
改: books, books/* 即可;

2.3 执行流程

在拦截器类中,preHandle方法返回false会终止原始方法及其之后的所有操作;而返回true会都执行。
拦截器interceptor总结_第8张图片

2.4 简化方法:将拦截器类配置到SpringMvcConfig中 ★

只需要两步:
① 定义拦截器类
②在SpringMvcConfig中去配置拦截器类
拦截器interceptor总结_第9张图片

缺点:拦截器类和Spring绑定在一起了,侵入性较强;

三. 案例:使用拦截器中校验登录

登陆验证即需要前端请求 /user/me页面,用来查询当前登录的用户信息;

问题1:当用户越来越多的时候,都需要校验用户的登录,不能每一个Controller中都来写业务逻辑;
解决:拦截器---------SpringMVC中动态拦截controller方法的执行,在所有的【controller之前】去执行!

问题2:拦截器校验完后还需要用户信息;
解决:用户信息缓存在ThreadLocal,后续业务就可以直接从Threadlocal获取用户;
(每个请求到服务都是独立的线程,如果不用ThreadLocal而是存于本地变量,则可能在多线程并发时修改的安全问题,而ThreadLocal会将数据存到线程内部的工作空间的map去保存,即每个线程都有独立的存储空间,相互之间没有干扰)
然后在controller中,通过threadLocal中取出User信息!

业务逻辑
拦截器interceptor总结_第10张图片

(1)定义拦截器类

在utls层定义拦截器类,实现HandlerInterceptor,重写preHandleafterCompletion方法
在preHandle做用户校验的逻辑;
在afterCompletion销毁用户信息(ThreadLocal要主动remove(),防止内存泄漏);

①从request中可以获取session;
②获取session中的用户;
③判断用户是否存在;
④不存在则拦截
⑤存在则保存到ThreadLocal
⑥放行

在这里插入图片描述

Threadlocal:
在utls层的UserHolder中,定义了ThreadLocal的相关方法,设为静态方便调用;
注意静态变量在【类加载】时就会自动初始化!
拦截器interceptor总结_第11张图片

(2)配置拦截器

将拦截器类直接配置到SpringMvcConfig中(简化方法):
并设置拦截路径:排除掉不需要拦截就可以访问的路径(如shop店铺、blog博客)(也可以配置拦截哪些路径):
拦截器interceptor总结_第12张图片

假设拦截器放行,则请求到达Controller,还需要完成剩余业务逻辑:
需要把当前登录的用户信息返回到前端:
之前在拦截其中把用户信息放到了UserHolder中的ThreadLocal中,只需要调用UserHolder类的静态方法get就可以取出;
拦截器interceptor总结_第13张图片

你可能感兴趣的:(后端框架及组件,servlet,java,spring)