SpringMVC的请求如以下这样的图所看到的:

能够看出全部的请求都要通过Dispatherservlet来接收,然后通过Handlermapping来决定使用哪个控制器,再依据ViewResolver来决定返回哪个视图.从流程来看,Handlermapping就是我们能够实现拦截器的第一种方法.另外另一种是实现WebRequestInterceptor接口,或者继承其子类.


一.实现HandlerInterceptor接口

实现HandlerInterceptor接口或者继承HandlerInterceptor的子类,比方比方Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter ,以下讲实现其接口的写法,先看一下这个接口的三个方法.

- 方法preHandle: 顾名思义,该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中能够同一时候存在多个Interceptor 。

每个Interceptor 的调用会依据它的声明顺序依次运行,并且最先运行的都是Interceptor 中的preHandle 方法,所以能够在这种方法中进行一些前置初始化操作或者是对当前请求的一个预处理。也能够在这种方法中进行一些推断来决定请求是否要继续进行下去。

该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,兴许的Interceptor 和Controller 都不会再运行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法。假设已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。

- 方法postHandle:由preHandle 方法的解释我们知道这种方法包含后面要说到的afterCompletion 方法都仅仅能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才干被调用。

postHandle 方法。顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后运行。可是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们能够在这种方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的。也就是说先声明的Interceptor 的postHandle 方法反而会后运行,这和Struts2 里面的Interceptor 的运行过程有点类型。

Struts2 里面的Interceptor 的运行过程也是链式的,仅仅是在Struts2 里面须要手动调用ActionInvocation 的invoke 方法来触发对下一个Interceptor 或者是Action 的调用。然后每个Interceptor 中在invoke 方法调用之前的内容都是依照声明顺序运行的,而invoke 方法之后的内容就是反向的。

- 方法afterCompletion:该方法也是须要当前相应的Interceptor 的preHandle 方法的返回值为true 时才会运行。顾名思义。该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了相应的视图之后运行。这种方法的主要作用是用于进行资源清理工作的。

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; public class SpringMVCInterceptor implements HandlerInterceptor { /**
* preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,SpringMVC中的Interceptor拦截器是链式的。能够同一时候存在
* 多个Interceptor。然后SpringMVC会依据声明的前后顺序一个接一个的运行,并且全部的Interceptor中的preHandle方法都会在
* Controller方法调用之前调用。 SpringMVC的这样的Interceptor链式结构也是能够进行中断的。这样的中断方式是令preHandle的返
* 回值为false。当preHandle的返回值为false的时候整个请求就结束了。 */
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// TODO Auto-generated method stub
return false;
} /**
* 这种方法仅仅会在当前这个Interceptor的preHandle方法返回值为true的时候才会运行。postHandle是进行处理器拦截用的,它的运行时间是在处理器进行处理之
* 后,也就是在Controller的方法调用之后运行。可是它会在DispatcherServlet进行视图的渲染之前运行,也就是说在这种方法中你能够对ModelAndView进行操
* 作。这种方法的链式结构跟正常訪问的方向是相反的,也就是说先声明的Interceptor拦截器该方法反而会后调用。这跟Struts2里面的拦截器的运行过程有点像,
* 仅仅是Struts2里面的intercept方法中要手动的调用ActionInvocation的invoke方法,Struts2中调用ActionInvocation的invoke方法就是调用下一个Interceptor
* 或者是调用action。然后要在Interceptor之前调用的内容都写在调用invoke之前,要在Interceptor之后调用的内容都写在调用invoke方法之后。
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub } /**
* 该方法也是须要当前相应的Interceptor的preHandle方法的返回值为true时才会运行。该方法将在整个请求完毕之后,也就是DispatcherServlet渲染了视图运行,
* 这种方法的主要作用是用于清理资源的。当然这种方法也仅仅能在当前这个Interceptor的preHandle方法的返回值为true时才会运行。
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub } }

二.实现WebRequestInterceptor接口

WebRequestInterceptor 中也定义了三个方法。我们也是通过这三个方法来实现拦截的。这三个方法都传递了同一个參数WebRequest ,那么这个WebRequest 是什么呢?这个WebRequest 是Spring 定义的一个接口,它里面的方法定义都基本跟HttpServletRequest 一样,在WebRequestInterceptor 中对WebRequest 进行的全部操作都将同步到HttpServletRequest 中,然后在当前请求中一直传递。

  • 方法preHandle:方法将在请求处理之前进行调用,也就是说会在Controller 方法调用之前被调用。这种方法跟HandlerInterceptor 中的preHandle 是不同的。主要差别在于该方法的返回值是void 。也就是没有返回值,所以我们一般主要用它来进行资源的准备工作,比方我们在使用Hibernate 的时候能够在这种方法中准备一个Hibernate 的Session 对象,然后利用WebRequest 的setAttribute(name, value, scope) 把它放到WebRequest 的属性中。这里能够说说这个setAttribute 方法的第三个參数scope ,该參数是一个Integer 类型的。在WebRequest 的父层接口RequestAttributes 中对它定义了三个常量:

    SCOPE_REQUEST :它的值是0 ,代表仅仅有在request 中能够訪问。

    SCOPE_SESSION :它的值是1 ,假设环境同意的话它代表的是一个局部的隔离的session。否则就代表普通的session。并且在该session范围内能够訪问。

    SCOPE_GLOBAL_SESSION :它的值是2 ,假设环境同意的话。它代表的是一个全局共享的session,否则就代表普通的session,并且在该session 范围内能够訪问。

  • 方法postHandle:该方法将在请求处理之后。也就是在Controller 方法调用之后被调用,可是会在视图返回被渲染之前被调用,所以能够在这种方法里面通过改变数据模型ModelMap 来改变数据的展示。该方法有两个參数,WebRequest 对象是用于传递整个请求数据的,比方在preHandle 中准备的数据都能够通过WebRequest 来传递和訪问。ModelMap 就是Controller 处理之后返回的Model 对象,我们能够通过改变它的属性来改变返回的Model 模型。

  • 方法afterCompletion:该方法会在整个请求处理完毕,也就是在视图返回并被渲染之后运行。所以在该方法中能够进行资源的释放操作。

    而WebRequest 參数就能够把我们在preHandle 中准备的资源传递到这里进行释放。Exception 參数表示的是当前请求的异常对象。假设在Controller 中抛出的异常已经被Spring 的异常处理器给处理了的话,那么这个异常对象就是是null 。

import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.WebRequestInterceptor; public class AllInterceptor implements WebRequestInterceptor { /**
* 在请求处理之前运行,该方法主要是用于准备资源数据的,然后能够把它们当做请求属性放到WebRequest中
*/
@Override
public void preHandle(WebRequest request) throws Exception {
// TODO Auto-generated method stub
System.out.println("AllInterceptor...............................");
request.setAttribute("request", "request", WebRequest.SCOPE_REQUEST);//这个是放到request范围内的,所以仅仅能在当前请求中的request中获取到
request.setAttribute("session", "session", WebRequest.SCOPE_SESSION);//这个是放到session范围内的,假设环境同意的话它仅仅能在局部的隔离的会话中訪问。否则就是在普通的当前会话中能够訪问
request.setAttribute("globalSession", "globalSession", WebRequest.SCOPE_GLOBAL_SESSION);//假设环境同意的话。它能在全局共享的会话中訪问。否则就是在普通的当前会话中訪问
} /**
* 该方法将在Controller运行之后,返回视图之前运行。ModelMap表示请求Controller处理之后返回的Model对象,所以能够在
* 这种方法中改动ModelMap的属性,从而达到改变返回的模型的效果。
*/
@Override
public void postHandle(WebRequest request, ModelMap map) throws Exception {
// TODO Auto-generated method stub
for (String key:map.keySet())
System.out.println(key + "-------------------------");;
map.put("name3", "value3");
map.put("name1", "name1");
} /**
* 该方法将在整个请求完毕之后,也就是说在视图渲染之后进行调用。主要用于进行一些资源的释放
*/
@Override
public void afterCompletion(WebRequest request, Exception exception)
throws Exception {
// TODO Auto-generated method stub
System.out.println(exception + "-=-=--=--=-=-=-=-=-=-=-=-==-=--=-=-=-=");
} }

三.拦截器的配置

1.mvc:interceptors标签来声明须要增加到SpringMVC拦截器链中的拦截器

    <mvc:interceptors>
<!-- 使用bean定义一个Interceptor。直接定义在mvc:interceptors根以下的Interceptor将拦截全部的请求 -->
<bean class="com.host.app.web.interceptor.AllInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/test/number.do"/>
<!-- 定义在mvc:interceptor以下的表示是对特定的请求才进行拦截的 -->
<bean class="com.host.app.web.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

由上面的演示样例能够看出能够利用mvc:interceptors标签声明一系列的拦截器,然后它们就能够形成一个拦截器链。拦截器的运行顺序是按声明的先后顺序运行的,先声明的拦截器中的preHandle方法会先运行,然而它的postHandle方法和afterCompletion方法却会后运行。

在mvc:interceptors标签下声明interceptor主要有两种方式:

(1)直接定义一个Interceptor实现类的bean对象。使用这样的方式声明的Interceptor拦截器将会对全部的请求进行拦截。

(2)使用mvc:interceptor标签进行声明。使用这样的方式进行声明的Interceptor能够通过mvc:mapping子标签来定义须要进行拦截的请求路径。

经过上述两步之后。定义的拦截器就会发生作用对特定的请求进行拦截了。


原文链接 http://haohaoxuexi.iteye.com/blog/1750680


样例:

近期正好写了一个简单的登录验证拦截器:

以下拦截器,推断session里面是否存在登录,存在且同意訪问,不存在则跳转到登录页面

package com.aust.interceptor;

import com.aust.model.system.SysUser;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; public class LoginUserInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String url = httpServletRequest.getRequestURI();
if (url.indexOf("system/login")>0){
return true;
}
//推断session是否已登录
HttpSession session = httpServletRequest.getSession();
SysUser user = (SysUser) session.getAttribute("loginsucess");
if (user != null){
return true;
}
//运行到这里说明没有session,须要拦截
httpServletRequest.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(httpServletRequest,httpServletResponse);
return false;
} @Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { }
}

须要在springMVC.xml中配置:

    <!--訪问拦截-->
<mvc:interceptors>
<!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根以下的Interceptor将拦截全部的请求 -->
<!--<bean class="com.host.app.web.interceptor.AllInterceptor"/>-->
<mvc:interceptor>
<!-- 对system下的请求全部拦截 -->
<mvc:mapping path="/system/*"/>
<!-- 定义在mvc:interceptor以下的表示是对特定的请求才进行拦截的 -->
<bean class="com.aust.interceptor.LoginUserInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

这样就实现了訪问拦截功能


项目演示样例能够參考:

SSM框架整合: https://github.com/nl101531/JavaWEB

SpringMVC学习记录(七)--拦截器的使用的更多相关文章

  1. SpringMVC 学习笔记(六)拦截器

    5.1.处理器拦截器简介 Spring Web MVC的处理器拦截器(如无特殊说明,下文所说的拦截器即处理器拦截器) 类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理. ...

  2. SpringMVC学习笔记九:拦截器及拦截器的简单实用

    SpringMVC中的interceptor拦截器是非常重要的,它的主要作用就是拦截指定的用户请求,并进行相应的预处理和后处理. 拦截时间点在"处理器映射器根据用户提交的请求映射出所要执行的 ...

  3. SpringMVC学习记录七——sjon数据交互和拦截器

    21       json数据交互 21.1      为什么要进行json数据交互 json数据格式在接口调用中.html页面中较常用,json格式比较简单,解析还比较方便. 比如:webservi ...

  4. springMVC学习 十二 拦截器

    一 拦截器概述 拦截器技术比较像java web技术中的过滤器技术,都是发送 请求时被拦截器拦截,在控制器的前后添加额外功能.但是和Spring中的Aop技术是由区别的.AOP 在特定方法前后扩充(一 ...

  5. SpringMVC学习08(拦截器)

    8.拦截器 概述 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理.开发者可以自己定义一些拦截器来实现特定的功能. 过滤器与拦截器的区别: ...

  6. springMVC学习(12)-使用拦截器

    一.拦截器配置和测试: 1)定义两个拦截器,(要实现HandlerInterceptor接口) HandlerInterceptor1: package com.cy.interceptor; imp ...

  7. springMVC学习记录3-拦截器和文件上传

    拦截器和文件上传算是springmvc中比较高级一点的内容了吧,让我们一起看一下. 下面先说说拦截器.拦截器和过滤器有点像,都可以在请求被处理之前和请求被处理之到做一些额外的操作. 1. 实现Hand ...

  8. SpringMVC学习笔记:拦截器和过滤器

    首先说明一下二者的区别: 1. 拦截器基于java的反射机制,而过滤器是基于函数回调 2. 拦截器不依赖于servlet容器,过滤器依赖servlet容器 3. 拦截器只能对action请求起作用,而 ...

  9. <SpringMvc>入门七 拦截器

    什么是拦截器 1.SpringMVC框架中的拦截器用于 对处理器 进行预处理和后处理的技术. 2.可以定义拦截器链,按照顺序执行. 3.拦截器和过滤器功能类似,区别在 拦截器 过滤器 过滤器是Serv ...

随机推荐

  1. bzoj 2142 国家集训队试题 礼物

    问题转化成求C(N,M) mod P p为非素数,那么我们可以将P分解质因数, 也就是 π pi^ci的形式,因为这些pi^ci是互质的,所以我们可以用crt将他们合并 那么问题就转化成了快速求C(N ...

  2. sphinx 分词搭建手册

    步奏1. yum install make gcc g++ gcc-c++ libtool autoconf automake imake mysql-devel libxml2-devel expa ...

  3. POJ3264(线段树求区间最大最小值)

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 41162   Accepted: 19327 ...

  4. python基础===取txt文件的若干行到另一个文件

    #取txt文件 的若干行到另一个txt f1 = open(r'F:\movie.txt','rb') f2= open(r'F:\movie2.txt','ab') i=0 while True: ...

  5. kernelchina.org内核研究

    kernelchina.org 内核研究 转自:http://www.kernelchina.org

  6. Mac-item+zsh

    $brew cask install iterm2 $ sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/m ...

  7. 2.如何使用python连接hdfs

    总所周知,python是一门很强大的语言,主要在于它有着丰富的第三方模块,当然连接hdfs的模块也不例外. 在python中有一个模块也叫hdfs,可以使用它连接hadoop的hdfs.直接pip i ...

  8. synchronized 修饰static方法

    •1.依靠对象锁锁定 初始化一个对象时,自动有一个 对象锁. synchronized {普通方法}依靠对象锁工作,多线程访问synchronized方法,一旦某个进程抢得锁之后,其他的进程只有排队对 ...

  9. Java语言中的协变和逆变(zz)

    转载声明: 本文转载至:http://swiftlet.net/archives/1950 协变和逆变指的是宽类型和窄类型在某种情况下的替换或交换的特性.简单的说,协变就是用一个窄类型替代宽类型,而逆 ...

  10. H5中使用Web Storage来存储结构化数据

    在上一篇对Web Storage的介绍中,可以看到,使用Storage保存key—value对时,key.value只能是字符串,这对于简单的数据来说已经够了,但是如果需要保存更复杂的数据,比如保存类 ...