Spring拦截器(学习笔记)
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拦截器(学习笔记)的更多相关文章
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- Spring 源码学习笔记11——Spring事务
Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...
- SpringMVC—Struts2拦截器学习网址整理
引自:http://blog.csdn.net/wp1603710463/article/details/49982683 SpringMVC—Struts2拦截器学习网址整理 最近项目中遇到权限相关 ...
- Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点
Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...
- Spring拦截器中通过request获取到该请求对应Controller中的method对象
背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置.我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Control ...
- spring拦截器中修改响应消息头
问题描述 前后端分离的项目,前端使用Vue,后端使用Spring MVC. 显然,需要解决浏览器跨域访问数据限制的问题,在此使用CROS协议解决. 由于该项目我在中期加入的,主要负责集成shiro框架 ...
- spring cloud(学习笔记)高可用注册中心(Eureka)的实现(二)
绪论 前几天我用一种方式实现了spring cloud的高可用,达到两个注册中心,详情见spring cloud(学习笔记)高可用注册中心(Eureka)的实现(一),今天我意外发现,注册中心可以无限 ...
- Spring 拦截器实现+后台原理(HandlerInterceptor)
过滤器跟拦截器的区别 spring mvc的拦截器是只拦截controller而不拦截jsp,html 页面文件的.这就用到过滤器filter了,filter是在servlet前执行的,你也可以理解成 ...
- Spring拦截器和过滤器
什么是拦截器 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对象,允许开发者 ...
- Android安装器学习笔记(一)
Android安装器学习笔记(一) 一.Android应用的四种安装方式: 1.通过系统应用PackageInstaller.apk进行安装,安装过程中会让用户确认 2.系统程序安装:在开机的时候自动 ...
随机推荐
- UVA817-According to Bartjens(DFS)
Problem UVA817-According to Bartjens Accept: 270 Submit: 2071Time Limit: 1000 mSec Memory Limi ...
- 4-cookie 简介
1.eclipse中tomcate镜像位置:D:\javaTools\eclipse\workspace\.metadata\.plugins\org.eclipse.wst.server.core\ ...
- 3-jsp 内置对象、转发与重定向
1.request:请求常用api: getParameter("name"):获取页面表单单个元素的值 getParameterValues("name"): ...
- Linux 通过rinetd端口转发来访问内网服务
可以通过端口映射的方式,来通过具有公网的云服务器 ECS 访问用户名下其它未购买公网带宽的内网 ECS 上的服务.端口映射的方案有很多,比如 Linux 下的 SSH Tunnel.rinetd,Wi ...
- Java多线程(七)——线程休眠
一.sleep()介绍 sleep() 定义在Thread.java中.sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”.sleep()会指定休眠时间,线程 ...
- jsp相关基础知识
一.JSP简介 JSP全称是Java Server Page,它和Servlet一样,也是sun公司推出的一套开发动态web资源的技术,称为JSP/Servlet规范.其本质也是一个Servlet. ...
- springmvc+thymeleaf搭建框架启动报错
最近项目开发需要用到thymeleaf前端界面模板引擎,所以提前了解学习一下,但是在框架搭建好了之后启动tomcat一直提示如下错误: org.springframework.beans.factor ...
- Java基础之数据比较Integer、Short、int、short
基础很重要,基础很重要,基础很重要.重要的事情说三遍,. 今天聊一聊Java的数据比较,这个范围比较大,基础类型的比较.引用类型的比较. 前提: 1.Java和c#都提供自动装箱和自动拆箱操作,何为自 ...
- Dockerfile cnetos7_nginx1.15.10
FROM centos:7 MAINTAINER yuyongxr yuyongxr@gmail.com LABEL Discription="centos7+nginx1.15.10&qu ...
- python第八章:多任务--小白博客
多线程threading 多线程特点: #线程的并发是利用cpu上下文的切换(是并发,不是并行)#多线程执行的顺序是无序的#多线程共享全局变量#线程是继承在进程里的,没有进程就没有线程#GIL全局解释 ...