SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的

在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式

第一种方式是:

要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口或者是这个类继承实现了HandlerInterceptor 接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter ;

第二种方式是:

实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。

实现HandlerInterceptor接口

HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。

(1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顾名思义,该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。

(一般用来做登录校验,跟权限的验证)

(2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作(也就是返回的modelMap)。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行,这和Struts2 里面的Interceptor 的执行过程有点类型。Struts2 里面的Interceptor 的执行过程也是链式的,只是在Struts2 里面需要手动调用ActionInvocation 的invoke 方法来触发对下一个Interceptor 或者是Action 的调用,然后每一个Interceptor 中在invoke 方法调用之前的内容都是按照声明顺序执行的,而invoke 方法之后的内容就是反向的。

3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。

接下来是使用,

第一步要定义Interceptor类:

public class ShopLoginInterceptor extends HandlerInterceptorAdapter{
/*
* 主要做事前拦截,即用户操作发生前,改写preHandle里面的逻辑,进行拦截
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
//从session中取出用户信息来
Object userObj = request.getSession().getAttribute("user");
if (userObj != null) {
//若用户信息不为空,则将session里的用户信息转换成PersonInfo实体类对象
PersonInfo user = (PersonInfo) userObj;
//做空值判断,确保userId不为空并且该长号的可用状态为1,并且用户类型为店家(再判断usertype是否为2店家)
if (user != null && user.getUserId() != null
&& user.getUserId() > 0 && user.getEnableStatus() == 1)
//若通过验证则返回true,拦截器返回true之后,用户接下来的操作得以正常执行
return true;
}
//若不满足登录验证,则直接跳转到账号登录页面
PrintWriter out = response.getWriter();
//拼接js代码
out.println("<html>");
out.println("<script>");
out.println("window.open ('" + request.getContextPath()
+ "/local/login?usertype=2','_self')");
out.println("</script>");
out.println("</html>");
return false;
}
}

还有一个Interceptor类:

/**
* 店家管理系统操作验证拦截器
* @author L
*
*/
public class ShopPermissionInterceptor extends HandlerInterceptorAdapter {
/**
* 主要做事前拦截,即用户操作发生前,改写preHandle里的逻辑,进行用户操作权限的拦截
* @param request 请求
* @param response 响应
* @param handler controller
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
//从session中获取当前选择的店铺
Shop currentShop = (Shop) request.getSession().getAttribute(
"currentShop");
@SuppressWarnings("unchecked")
//从session中获取当前用户可操作的店铺列表
List<Shop> shopList = (List<Shop>) request.getSession().getAttribute(
"shopList");
//非空判断
if (currentShop != null && shopList != null) {
for (Shop shop : shopList) {
//如果当前店铺在可操作的列表里则返回true,进行接下来的用户操作
if (shop.getShopId() == currentShop.getShopId()) {
return true;
}
}
}
//若不满足拦截器的验证则返回false终止用户操作的执行
return false;
}
}

第二步是配置拦截器:

<!-- 5.权限拦截器 -->
<mvc:interceptors>
<!-- 校验是否已经登录了店家管理系统的拦截器 登陆了才能做对店铺的相关操作,所有相关请求都会被拦截先进入前面定义好的ShopLoginInterceptor类中校验-->
<mvc:interceptor>
<mvc:mapping path="/shopadmin/**" />
<bean id="ShopInterceptor" class="xyspgl.interceptor.ShopLoginInterceptor" />
</mvc:interceptor>
<!-- 校验是否对店铺有操作权限的拦截器 ,用户不能操作不属于自己的店铺-->
<mvc:interceptor>
<mvc:mapping path="/shopadmin/**" />
<!-- shoplist page 排除不需要校验的方法,只有在这两个方法获取完店铺列表后,才存在相关操作权限问题-->
<mvc:exclude-mapping path="/shopadmin/shoplist" />
<mvc:exclude-mapping path="/shopadmin/getshoplist" />
<!-- shopregister page 这三个方法也不需要拦截,就是注册相关的-->
<mvc:exclude-mapping path="/shopadmin/getshopinitinfo" />
<mvc:exclude-mapping path="/shopadmin/registershop" />
<mvc:exclude-mapping path="/shopadmin/shoppoperation" />
<!-- shopmanage page 店铺管理页面的两个方法也不需要拦截,因为这两个方法在调用的时候,并没有
生成currentshop的session,因此对它做拦截是没有意义的,拦截了就进入不了 -->
<mvc:exclude-mapping path="/shopadmin/shopmanagement" />
<mvc:exclude-mapping path="/shopadmin/getshopmanagementinfo" />
<bean id="ShopPermissionInterceptor"
class="xyspgl.interceptor.ShopPermissionInterceptor" />
</mvc:interceptor>
</mvc:interceptors>

当然在controller层等需要你将一些数据set入session中来当做拦截器类中的校验条件

Spring拦截器(学习笔记)的更多相关文章

  1. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  2. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  3. SpringMVC—Struts2拦截器学习网址整理

    引自:http://blog.csdn.net/wp1603710463/article/details/49982683 SpringMVC—Struts2拦截器学习网址整理 最近项目中遇到权限相关 ...

  4. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

  5. Spring拦截器中通过request获取到该请求对应Controller中的method对象

    背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置.我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Control ...

  6. spring拦截器中修改响应消息头

    问题描述 前后端分离的项目,前端使用Vue,后端使用Spring MVC. 显然,需要解决浏览器跨域访问数据限制的问题,在此使用CROS协议解决. 由于该项目我在中期加入的,主要负责集成shiro框架 ...

  7. spring cloud(学习笔记)高可用注册中心(Eureka)的实现(二)

    绪论 前几天我用一种方式实现了spring cloud的高可用,达到两个注册中心,详情见spring cloud(学习笔记)高可用注册中心(Eureka)的实现(一),今天我意外发现,注册中心可以无限 ...

  8. Spring 拦截器实现+后台原理(HandlerInterceptor)

    过滤器跟拦截器的区别 spring mvc的拦截器是只拦截controller而不拦截jsp,html 页面文件的.这就用到过滤器filter了,filter是在servlet前执行的,你也可以理解成 ...

  9. Spring拦截器和过滤器

    什么是拦截器 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对象,允许开发者 ...

  10. Android安装器学习笔记(一)

    Android安装器学习笔记(一) 一.Android应用的四种安装方式: 1.通过系统应用PackageInstaller.apk进行安装,安装过程中会让用户确认 2.系统程序安装:在开机的时候自动 ...

随机推荐

  1. pandas 选择列或者添加列生成新的DataFrame

    选择某些列 import pandas as pd # 从Excel中读取数据,生成DataFrame数据 # 导入Excel路径和sheet name df = pd.read_excel(exce ...

  2. 爬取伯乐在线文章(五)itemloader

    ItemLoader 在我们执行scrapy爬取字段中,会有大量的CSS或是Xpath代码,当要爬取的网站多了,要维护起来很麻烦,为解决这类问题,我们可以根据scrapy提供的loader机制. 导入 ...

  3. 004_浅析Python的GIL和线程安全

    在这里我们将介绍Python的GIL和线程安全,希望大家能从中理解Python里的GIL,以及GIL的前世今生. 对于Python的GIL和线程安全很多人不是很了解,通过本文,希望能让大家对Pytho ...

  4. GitHub存储库泄露了API令牌和加密密钥

    导读 北卡罗莱纳州立大学(NCSU)学者的一项研究表明,一些GitHub存储库泄漏API令牌和密码密钥.研究人员分析了分布在数百万存储库中的10亿多个GitHub文件.研究人员使用GitHub搜索AP ...

  5. 20175329 2018-2019-3《Java程序设计》第三周学习总结

    学号 20175329 2018-2019-3<Java程序设计>第三周学习总结 教材学习内容总结 第四章 第四章主要介绍JAVA中的类与对象的划分,其中有很多复杂的概念以及知识点需要花很 ...

  6. Java内存模型与线程安全

    原文链接:blog.edreamoon.com Java内存模型 计算机cpu的运算能力强大,但是数据的存储相对于cpu运算能力需要消耗大量时间,为了充分利用运算能力引入了缓存,但是也为计算机系统带来 ...

  7. BZOJ1069 SCOI2007 最大土地面积 凸包、旋转卡壳

    传送门 在这里假设可以选择两个相同的点吧-- 那么选出来的四个点一定会在凸包上 建立凸包,然后枚举这个四边形的对角线.策略是先枚举对角线上的一个点,然后沿着凸包枚举另一个点.在枚举另一个点的过程中可以 ...

  8. Ueditor使用以及遇到的问题

    原来用的是Kindeditor这个编辑器,但很久没更新了,最新版是13年更新的.现在要换成百度的Ueditor, 在这里记录Ueditor的使用流程和遇到的问题. 一.下载 1.Ueditor官网 这 ...

  9. disconf原理 “入坑”指南

    之前有了解过disconf,也知道它是基于zookeeper来做的,但是对于其运行原理不太了解,趁着周末,debug下源码,也算是不枉费周末大好时光哈 :) .关于这篇文章,笔者主要是参考discon ...

  10. 封装自己的dapper lambda扩展-设计篇

    前言 昨天开源了业务业余时间自己封装的dapper lambda扩展,同时写了篇博文<编写自己的dapper lambda扩展-使用篇>简单的介绍了下其使用,今天将分享下它的设计思路 链式 ...