上一篇👉:SpringMVC---- SpringMVC---- SpringMVC文件上传
🚴大家好!我是近视的脚踏实地,后边这系列是自己自学Spring框架的学习笔记,这篇文章学习关于SpringMVC 拦截器的 相关知识
唯有行动 才能解除你所有的不安
1. SpringMVC拦截器
1.1 拦截器(interceptor)的作用
Spring MVC 的拦截器
类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理
和后处理
。
(这个拦截器的功能相当于web阶段学习的那个filter,那么我们知道,filter是对于我们访问的目标资源进行相应的干预,比如我有个目标资源Servlet,如果你的请求地址没有写错,一般就能直接访问到目标资源,但是我们学到这个filter之后发现,即使地址没写错,你这个目标资源也不一定被访问到,因为中间有filter的过滤器,如果这个filter放行的话才能访问拿到目标资源,不放行就访问不到目标资源,这里的interceptor跟filter过滤器的功能是一样的,那么咋子SpringMVC技术当中,我们的目标资源就是Controller当中的一些方法,同样目前也是只要url没写错,那个方法肯定是百分之百可以被访问到。学了拦截器就知道写对了地址也不一定可以访问那个资源方法)
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(Interceptor Chain)
。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。
(我们之前接触到过filterChain,叫过滤器链,它是把一个一个的filter串到一起,那么我们在访问目标资源的时候,那一个一个的filter都执行完毕,最终才能访问到目标资源。这个地方也是一样的道理,Interceptor串成一串,第一个放行了,还有第二个,第三个,当这些Interceptor都放行了才能访问到对应的目标资源。 )
1.2 拦截器和过滤器区别
区别 | 过滤器 | 拦截器 |
---|---|---|
使用范围 | 是 servlet 规范中的一部分,任何Java Web 工程都可以使用 | 是 SpringMVC 框架自己的,只有使用了SpringMVC 框架的工程才能用 |
拦截范围 | 在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截 | 只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的 |
(filter可以对所有资源进行拦截,包括静态资源,Interceptor只能对Controller中方法进行拦截,静态资源拦截不了。)
1.3 拦截器是快速入门
自定义拦截器很简单,只有如下三步:
1️⃣:创建拦截器类实现HandlerInterceptor接口
(实现HandlerInterceptor接口,内部有相应的方法需要我们去实现)
2️⃣:配置拦截器
(在springmvc.xml中进行配置)
3️⃣:测试拦截器的拦截效果
首先来看环境,有个TargetController,就是我们要访问的目标资源,内部有个show方法,对应的虚拟地址是/target,那么现在启动这个工程,因为是没有Intercepor,最终是跳转到index.jsp,这里访问的目标方法就是这个show方法,这里创建了一个modelAndView,然后在modelAndView当中设置了一个数据,然后在设置跳转到index.jsp页面
然后把服务启动测试👇:,那么发现环境准备是没问题的
那么按照前边的步骤,我们就可以开始来实现拦截器
1️⃣:创建拦截器类实现HandlerInterceptor接口
(这里有三个方法需要我们去重写)
public class MyInterceptor1 implements HandlerInterceptor {
//在目标方法(这里就是那个show方法)执行之前 执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle.....");
return false;
}
//在目标方法执行之后 视图对象返回之前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle.....");
}
//在流程都执行完毕后 执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion....");
}
}
2️⃣:配置拦截器
(在<mvc:interceptors>中可以配很多个拦截器,然后在<mvc:interceptor>标签,首先bean就是刚刚写的MyInterceptor1的全限定类名,就是告诉spring,我的拦截器就是它。接着<mvc:mapping path,就是相当于与filter的url-pattern,代表配置对哪些资源进行拦截操作)
<!--5、配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--对哪些资源进行拦截操作-->
<mvc:mapping path="/**"/>
<bean class="monter.zf.interceptor.MyIntercepto1"/>
</mvc:interceptor>
</mvc:interceptors>
3️⃣:测试拦截器的拦截效果(编写目标方法)
@Controller
public class TargetController {
@RequestMapping("/target")
public ModelAndView show(){
System.out.println("目标资源执行......");
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("name","monster");
modelAndView.setViewName("index");
return modelAndView;
}
}
3️⃣:测试拦截器的拦截效果(访问网址),可以发现并没有视图的展示
然后看到控制台只有preHandle…输出了,
这是因为刚刚在写preHandle时,返回的是false,那么后边的就不会执行了,所以目标方法也没有得到执行,也没有返回视图。所以改成true放行。
再来测试👇:
接着,我们对那三个方法包括配置做一下详细的介绍,首先是preHandle,这个方法是在目标方法执行之前会执行,可以看到它的参数是request、response、 handler。那么主要我们可以用到request和response获得一些请求的内容,比如http请求被封装到request当中,然后就可以从request里边获取作相应于的操作,然后return返回的结果是代表你这个开关是打开还是不打开,意味着如果返回true,代表放行,如果返回false,代表不放行。那么如果不放行,我们可以通过response进行转发或者重定向,转向其他资源而避开目标资源。
接着是postHandle方法,这个方法是在目标方法执行之后 视图对象返回之前执行。它除了有preHandle的三个参数外,它还有modelAndView这么一个形参,那么这个modelAndView我们知道就是我们那个模型的最终视图封装的。这个模型和视图封装了之后,在这个地方进行获取,获取之后可以把它相应的根据实际情况改掉。比如我们在目标中设置了name=monster,那么现在我们就可以在这里边把monster改成其他的,也可以把视图改成其他的。
最后这个afterCompletion方法就是在流程都执行完毕后 执行,这个用到比较少。第一个方法是用的比较多的。
比如下面编写代码完成一个小功能,就是如果你携带参数叫yes的话,就放行,最终就能访问到目标资源,如果没有带参数或者带参数不是yes的话,那就不放行,而是转发到一个error.jsp的视图👇:
启动服务器进行测试,不带param参数👇:
带参数param但是不等于yes👇:
带参数param且等于yes👇:
接着postHandle方法一般就是对modelAndView进行相应的修改工作,比如说可以在这里边把之前在目标方法中设置的monster修改成ZF,那么这样最终看到的资源是就是ZF
测试👇:
(其实它的逻辑就是,你在访问时,它先走preHandle方法,然后我们携带的参数是yes,最终会返回true放行,放行就会执行到目标资源方法,在执行show方法之后,在modelAndView中设置了一个name叫monster,然后最终返回这个modelAndView,但是还没有解析渲染返回客户端,因为还有postHandle方法,因此目标方法中返回的modelAndView就传到了postHandle方法中,然后我们在这个方法内部又把那个那么改掉了,改为了ZF,最终再去解析这个视图返回时,就是ZF了。)
1.4 多拦截器操作
同上,在编写一个MyHandlerInterceptor2操作👇:,测试执行顺序
然后再去配置一下👇:
启动服务器测试👇:
看到控制台👇:
(可以看到1的preHandle先执行,然后是2的preHandle执行,接着是目标方法执行,然后是postHandle2先执行,在是postHandle1。和我们之前学的filter是一样的。就是先过去再回去。先1后2的主要原因是配置文件中的配置的顺序,记住不是编写的顺序)
1.5 拦截器方法说明
方法名 | 说明 |
---|---|
preHandle() | 方法将在请求处理之前进行调用,该方法的返回值是布尔值Boolean类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法 |
postHandle() | 该方法是在当前请求进行处理之后被调用,前提是preHandle 方法的返回值为true 时才能被调用,且它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作 |
afterCompletion() | 该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行,前提是preHandle 方法的返回值为true 时才能被调用 |
1.6 知识要点
自定义拦截器步骤:
1️⃣:创建拦截器类实现HandlerInterceptor接口
2️⃣:配置拦截器
3️⃣:测试拦截器的拦截效果
下一篇👉SpringMVC---- SpringMVC异常处理机制
本篇博客到这就完啦,非常感谢您的阅读🙏,那么下一篇将会继续学习关于SpringMVC 异常处理机制的 相关知识,如果对您有帮助,可以帮忙点个赞或者来波关注鼓励一下喔😬