博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
springmvc拦截器讲解
阅读量:7095 次
发布时间:2019-06-28

本文共 5621 字,大约阅读时间需要 18 分钟。

hot3.png

        关于springmvc拦截器,我们先说说什么是拦截器,我不喜欢那种教科书式的解释,所以在这里打个比喻。

        拦截器,打个比喻,就是一种把请求拦截下来的功能,好比古代的强盗,把你拦截下来打劫一番,交点过路费,就放你通行,没钱就把你over了。

        springmvc拦截器也是一样,设置好后可以拦截所有请求,也可以拦截指定请求,好比占山为王的强盗,拦截所有路过山头的过客,也有些小团伙,就拦截这条主干道的过客。    

        大致理解后,我们就来试试拦截器。

        第一步:搭建一个空的springmvc demo,可以参考我之前的文章,我们专门来研究下springmvc 拦截器。

        第二步:写一个拦截器

import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;public class Interceptor implements HandlerInterceptor{	@Override	public void afterCompletion(HttpServletRequest arg0,			HttpServletResponse arg1, Object arg2, Exception arg3)			throws Exception {		System.out.println("Interceptor:afterCompletion方法......");	}	@Override	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,			Object arg2, ModelAndView arg3) throws Exception {		System.out.println("Interceptor:postHandle方法......");	}	@Override	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,			Object arg2) throws Exception {		System.out.println("Interceptor:preHandle方法......");		return true;	}

        再写一个controller

@Controller@RequestMapping("/cc/function/interceptor/")public class InterceptorController extends BaseController {        /**	 * 测试interceptor	 * @param request	 * @return	 */	@RequestMapping("test_interceptor")	public ModelAndView test_interceptor(HttpServletRequest request){		ModelAndView mav = new ModelAndView("/cc/function/interceptor/test_intceptor");		System.out.println("执行controller方法。。。");		return mav;	}		/**	 * interceptor跳转	 * @param request	 * @return	 */	@RequestMapping("interceptor_ok")	public ModelAndView interceptor_ok(HttpServletRequest request){		ModelAndView mav = new ModelAndView("/cc/function/interceptor/success");		return mav;	}}

        在后写两个jsp页面;如下

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@include file="/WEB-INF/core/core.jsp" %>
测试interceptor
连接跳转
<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@include file="/WEB-INF/core/core.jsp" %>
interceptor_ok success

        现在准备工作都做完了,开始实现拦截器的功能!

        要实现拦截器的功能,必须要在springmvc的配置文件里进行配置,配置如下

        

        然后我们重启项目,在浏览器地址栏输入以下网址

         http://localhost:8080/shopping/cc/function/interceptor/test_interceptor.xhtml

        是不是正常跳转了呢?不论有没有跳转,先看控制台,分别打印了如下语句:        

        Interceptor:preHandle方法......

        执行controller方法。。。

        Interceptor:postHandle方法......

        Interceptor:afterCompletion方法......

        那么很明显拦截器生效了,并且是三个方法都调用了,三个方法先后顺序如下:

        preHandle>>controller>>postHandle>>afterCompletion

        如果你的控制台只输出了一条语句(Interceptor:preHandle方法......),并且没有跳转,没有执行controller输出语句(执行controller方法。。。),那么恭喜你,你被拦截了,为什么被拦截呢?

        因为preHandle方法有一个返回值,类型是boolean 如果返回的是false,则被拦截,如果返回的是true,则被放行,有些版本的springmvc实现的方法返回值自动是false,大家注意了!

        如果你的页面既没跳转,后台一条语句也没有,那么你要检查你的springmvc配置,很明显controller没有被扫描到,地址无效!!!

        现在的配置下,默认是拦截所有请求,大家可以点击页面中的连接,控制台会再输出三条语句,但是如果说我的业务不需要拦截所有请求,只要拦截某一个请求,怎么办呢?同样是在配置文件中修改,如下:

        

        然后我们继续重启项目,还是那个地址:

        依旧输出四句话:

        Interceptor:preHandle方法......

        执行controller方法。。。

        Interceptor:postHandle方法......

        Interceptor:afterCompletion方法......

        如果这时点击页面上的连接,则不会在有语句输出。

        当然,地址也是可以灵活的,比如这样:

    /cc/function/interceptor/*.xhtml

        表示所有以该地址开头的连接都会被拦截。

        那么现在又有一个问题,如果项目里设置了多个拦截器,先执行哪个呢?

        所以我们再写一个拦截器测试下执行的先后顺序 ,内容如下:

import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;public class Interceptor_temp implements HandlerInterceptor{	@Override	public void afterCompletion(HttpServletRequest arg0,			HttpServletResponse arg1, Object arg2, Exception arg3)			throws Exception {		System.out.println("Interceptor_temp:afterCompletion方法......");	}	@Override	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,			Object arg2, ModelAndView arg3) throws Exception {		System.out.println("Interceptor_temp:postHandle方法......");	}	@Override	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,			Object arg2) throws Exception {		System.out.println("Interceptor_temp:preHandle方法......");		return true;	}}

        新的拦截器文件名叫做Interceptor_temp.java,内容和上一个拦截器相同。

        然后我们再配置下xml文件,把之前的地址也给去掉,内容如下:

        

        现在我们重启系统,还是那个网页,还是那个连接,观察控制台输出语句:

        Interceptor:preHandle方法......

        Interceptor_temp:preHandle方法......

        执行controller方法。。。

        Interceptor_temp:postHandle方法......

        Interceptor:postHandle方法......

        Interceptor_temp:afterCompletion方法......

        Interceptor:afterCompletion方法......

        拦截器1(preHandle)>>拦截器2(preHandle>>controller>>拦截器2(postHandle)>>拦截器1(postHandle>>拦截器2(afterCompletion)>>拦截器1(afterCompletion

        单从方法上看,执行顺序都是一样的:

        preHandle>>controller>>postHandle>>afterCompletion

        区别的是拦截器的执行顺序,那么为什么会执行的这么不规律呢?其实如果弄明白原理,你就会知道这个是规律的了。

        首选要知道这几个方法是什么意思,干什么用的。

        preHandle:预处理,就是说在执行我的请求命令前,先对我的请求做一个处理,常见的使用场景是字符串编码,转为utf-8;字符串屏蔽,比如贴吧评论中一些要被和谐的关键字;登录权限控制,检查用户是否登录,等等......

        postHandle:返回处理;

        afterCompletion:后处理

        postHandle和afterCompletion用的比较少,或者说更多的时候要搭配preHandle方法用,用于请求成功后的返回操作,多用于日志记录等情况。

        现在明白了方法含义,再看看两个拦截器的执行顺序,是不是就有点眉目了?

        首先,拦截器是有排序的,排序按在xml里的注册的顺序,按照xml中注册的顺序依次执行拦截功能。

        还是打个强盗的比喻,从A地到B地,按照xml中拦截器注册的顺序,遇到拦截器1这伙强盗,拦截下来打劫一番,交点钱,放过去了,又遇到拦截器2这伙强盗,又被拦截下来打劫一番,又交点钱放过去了,到达B地了。在B地办完事想回A地,原路返回,强盗的位置是不变的,所以你先遇到拦截器2这伙强盗,被拦截下来,交了钱放走,又遇到拦截器1这伙强盗,又被抢了钱,放走。完事了你突然发现有货物丢在路上了,赶紧回去找,找到货物再回A地,然后悲催的又被拦截器2和拦截器1这两伙强盗先后再打劫一番。

        这就是拦截器执行原理。

        所以我们可以看出,拦截器虽然用处很大,但是不宜设置太多,这会造成项目执行效率降低的后果。

        以上就是我对拦截器的一个简单的描述,希望可以帮助大家对拦截器的理解。


代码手打,难免有漏字、错字、描述不清现象,欢迎大家批评指教,切勿人身攻击,如果觉得有用,就告诉我一声,给我点鼓励!

转载于:https://my.oschina.net/tiandaochouqincai/blog/601794

你可能感兴趣的文章
Java synchronized详解
查看>>
Frameset使用教程
查看>>
局域网与internet
查看>>
request
查看>>
Beyond Compare乱码问题汇总
查看>>
线程和线程池
查看>>
Camstar开发常用数据库表及其关联
查看>>
html中的一些按钮之类的操作
查看>>
走进 AQS 瞧一瞧看一看
查看>>
NO18 linux开机自启动设置--开机流程--中文乱码--查看行数
查看>>
Java的四种内部类
查看>>
10-16C#for...循环语句(2)
查看>>
CentOS查看软件源提供的软件版本命令
查看>>
caffe 学习记录1及网络结构
查看>>
html5学习笔记——html新增属性(四)
查看>>
收藏的链接
查看>>
【原创】5月份月会总结
查看>>
手机号码归属地查询
查看>>
IO和socket编程
查看>>
Docker结合Jenkins构建持续集成环境
查看>>