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. Problem UVA11134-Fabled Rooks(贪心)

    Problem UVA11134-Fabled Rooks Accept: 716  Submit: 6134Time Limit: 3000mSec Problem Description We w ...

  2. 静默安装Oracle12.2数据库

    实验环境: 操作系统:Redhat 6.4 64位 数  据 库:Oracle 12c R2   一. 安装前准备 1. 创建用户和组 [root@wjq ~]# groupadd -g 1000 o ...

  3. Python:Day13

    id() 查看内存地址 和while循环一样,在for循环中也可以使用break和continue,两者效果一样. repr

  4. 010_vim和python整合开发

    一.vim-go使用经验总结 Official Webset: https://github.com/fatih/vim-go-tutorial :GoFmt #格式化golang代码 二. 1. 一 ...

  5. ESP32:mdns协议

    mdns(即多播dns,Multicast DNS)主要实现了在没有传统DNS服务器的情况下使局域网内的主机实现相互发现和通信,使用的端口为5353,遵从dns协议,使用现有的DNS信息结构.语法和资 ...

  6. The first day in cnblogs

    2018.12.16,学习OI的第4个月零20天,我在博客园开通了属于自己的博客.

  7. C语言中__attribute__ ((at())绝对定位的应用

    C语言中的关键字__attribute__ ,当时大一学C语言中没有接触过,后来工作中搞RFID的蓝牙标签卡开发,用的是MSP430G2332,直接用的是绝对定位: 1 const uint8_t f ...

  8. UIToolBar - 官方文档

    继承关系:UIToolBar -> UIView -> UIResponder -> NSObject. toolBar是一个工具栏,用于显示一个或多个按钮.其按钮叫做toolBar ...

  9. 朱晔和你聊Spring系列S1E9:聊聊Spring的那些注解

    本文我们来梳理一下Spring的那些注解,如下图所示,大概从几方面列出了Spring的一些注解: 如果此图看不清楚也没事,请运行下面的代码输出所有的结果. Spring目前的趋势是使用注解结合Java ...

  10. 关于 HTTP GET/POST 请求参数长度最大值的一个理解误区(转载)

    1. Get方法长度限制 Http Get方法提交的数据大小长度并没有限制,HTTP协议规范没有对URL长度进行限制.这个限制是特定的浏览器及服务器对它的限制.下面就是对各种浏览器和服务器的最大处理能 ...