和大彪一起来学习-SpringMvc之第四回(拦截器使用)
2015-02-04 20:09
447 查看
一、拦截器介绍
springmvc中的拦截器,简单来说就是对用户的请求进行拦截,我们可以在拦截用请求后进行预处理和后处理,可以在这里做日志记录、权限控制、请求用时计算等操作。和Servlet api中的Filter有点类似。二、拦截器使用
1、编写拦截器
我们要自己编写拦截器,比较常用的方法是实现org.springframework.web.servlet.HandlerInterceptor类,我把这个类的源码贴出来吧,内部就三个方法,我们的业务可以在方法中实现。package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** 拦截器接口,内部就3个方法 **/ public interface HandlerInterceptor { /**[调用前] controller执行前调用此方法 返回true表示继续执行,返回false中止执行 这里可以加入登录校验、权限拦截等 **/ boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; /**[调用后,但还未渲染视图] controller执行后但未返回视图前调用此方法 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示 **/ void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; /**[调用后,已经渲染视图] controller执行后且视图返回后调用此方法 这里可得到执行controller时的异常信息 这里可记录操作日志,资源清理等 **/ void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; }好的,那么下面我们尝试写个类来实现它,先把简单的拦截器先用起来。我们再来研究配置,下面增加了一些文件。
拦截器:
package com.billstudy.springmvc.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; /** * 自定义拦截器01 * @author Bill * @since V1.0 2015/02/04 */ public class MyInterceptor01 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor01.preHandle()"); return true;<span style="white-space:pre"> </span>// 这里返回true,则请求可以到Controller中 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor01.postHandle()"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor01.afterCompletion()"); } }
Controller:
package com.billstudy.springmvc.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; /** * 通过请求本Controller内部方法,结合拦截器测试效果 * @author Bill * @since V1.0 2015/02/04 */ @Controller @RequestMapping("/demo") public class DemoController { @RequestMapping("/demo01") public ModelAndView demo01(HttpServletRequest request,HttpServletResponse response){ System.out.println("DemoController.demo01()"); ModelAndView result = new ModelAndView("/demo"); result.addObject("msg", "我是萌哒哒的msg"); return result; } }
demo.jsp
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>demo page</title> </head> <body> msg:${msg} </body> </html>
springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd "> <!-- auto scanner class path --> <context:component-scan base-package="com.billstudy.springmvc" /> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/pages" /> <property name="suffix" value=".jsp" /> </bean> <mvc:interceptors> <mvc:interceptor> <!-- path="/user/*.do" /user/所有请求 path="/*/*" 任意两级请求 path="*" 无效 path="/**" 任意请求 --> <mvc:mapping path="/**"/> <bean class="com.billstudy.springmvc.interceptor.MyInterceptor01" /> </mvc:interceptor> </mvc:interceptors> </beans>
好的,下面部署到Tomcat测试下。
控制台输出:
怎么样,效果是这样的吧。
三、配置和运行流程说明
我们前面在springmvc-servlet.xml中配置拦截器时,是配置的全局拦截器,也就是说所有映射器请求都会被拦截。因为我们可以配置多个Mapping。若是只想对某单个Mapping使用拦截器可以在其内部注入一个interceptors的属性,通过查看源码。我们发现在所有的Mapping父类,也就是org.springframework.web.servlet.handler.AbstractHandlerMapping,它内部有Listinterceptors
= new ArrayList()这么一个集合。所以所有的Mapping都可以通过它注入拦截器链。
假设我们只想个单个Mapping注入拦截器可以这么配置:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="<span style="color:#ff0000;">interceptors</span>"> <list> <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1" /> <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2" /> <span style="color:#ff0000;">// ... 可以配置多个,按配置的顺序调用</span> </list> </property> </bean>配置全局的拦截器就是:
<mvc:interceptors> <mvc:interceptor> <!-- path="/user/*.do" /user/所有请求 path="/*/*" 任意两级请求 path="*" 无效 path="/**" 任意请求 --> <mvc:mapping path="/**"/> <bean class="com.billstudy.springmvc.interceptor.MyInterceptor01" /> </mvc:interceptor> <span style="color:#ff0000;"><!-- 这里也可以配置多个 mvc:interceptor 标签 --></span> </mvc:interceptors>
下面测试一下,preHandle,postHandle,afterCompletion的运行规则,我们可以多写几个Interceptor来测试。
增加了2个拦截器后,配置修改如下:
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.billstudy.springmvc.interceptor.MyInterceptor01" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.billstudy.springmvc.interceptor.MyInterceptor02" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.billstudy.springmvc.interceptor.MyInterceptor03" /> </mvc:interceptor> <!-- 这里也可以配置多个 mvc:interceptor 标签 --> </mvc:interceptors>
目前所有的拦截器都是简单打印运行的方法,以及所有的preHandler都是返回true,那么我们来看看请求后。控制台打印的顺序是怎样的?
我们可以看到,pre是按照配置的顺序调用的。而post,after则是逆序调用的。 有没有一种递归的感觉,哈哈..
下面来测试将Interceptor 的 preHandler返回false,那么请求到了这里之后就会截断,并且访问不了Controller.那这个时候,拦截器又是如何运行的呢?
修改后代码如下:
package com.billstudy.springmvc.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; /** * 自定义拦截器02 * @author Bill * @since V1.0 2015/02/04 */ public class MyInterceptor02 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor02.preHandle()"); <strong><span style="color:#cc0000;">return false; // 这里返回false,请求在这里被截断!</span></strong> } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor02.postHandle()"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor02.afterCompletion()"); } }
运行输出:
咦,拦截器2的after和拦截器3的方法输入哪去了?post好像一个都不见了,这是为什么呢?
1.首先请求按照拦截器配置的顺序,进入到拦截器1的preHandler方法,这个时候返回true,继续执行
2.进入拦截器链2的preHandler,这里返回了false,那么请求在这里就被哄回家了,相当于springmvc 告诉它。你被拦截了,后面的操作你进行不了,回去吧。 哈哈
3.这个时候,萌哒哒的请求就没办法了,只能打道回府了。 但是因为它通过了拦截器1的preHandler的方法,所以after方法会被执行.
4.至于拦截器3,请求根本没有接触到,所以和拦截器3所有相关方法都没有被执行.
请求被哄回去之后,因为它没有抵达 com.billstudy.springmvc.controller.DemoController.demo01(HttpServletRequest, HttpServletResponse) 这个方法,所以msg的值也是空的.那我们页面其实是这样的:
拦截器三个方法运行结论:
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内所有拦截器返成功调用
afterCompletion只有preHandle返回true才调用
好了,到这里就结束了,拦截器你会用了吗?这里是 热爱生活,热爱技术,喜欢交友的大彪
. (ps:最近加班又多起来了,更新频率没那么快,抱歉啊。回到家整个人都有点晕晕的。。 ^ _ ^ ) 目前springmvc更新就到这里结束了,项目开发也差不多够用了呢,后面打算写下mybatis相关。
相关文章推荐
- 和大彪一起来学习-SpringMvc之第四回(拦截器使用) 分类: SpringMvc 2015-02-04 20:09 571人阅读 评论(0) 收藏
- 和大彪一起来学习-SpringMvc之第四回(拦截器使用) 分类: SpringMvc 2015-02-04 20:09 572人阅读 评论(0) 收藏
- 和大彪一起来学习-SpringMvc之第三回(注解使用详解) 分类: SpringMvc 2015-01-23 22:40 600人阅读 评论(0) 收藏
- 和大彪一起来学习-SpringMvc之第三回(注解使用详解)
- SpringMVC学习总结(五).拦截器的使用
- SpringMVC学习(十)-拦截器简单使用
- 和大彪一起来学习-SpringMvc之第二回(控制器,适配器说明) 分类: SpringMvc 2015-01-18 22:21 623人阅读 评论(0) 收藏
- 和大彪一起来学习-SpringMvc之第一回(框架了解和第一个SpringMvc程序) 分类: SpringMvc 2015-01-14 21:08 635人阅读 评论(0) 收藏
- SpringMVC学习记录(七)--拦截器的使用
- Springmvc第三讲学习笔记,拦截器Interceptor的使用
- 和大彪一起来学习-SpringMvc之第二回(控制器,适配器说明)
- springMvc源码学习之:spirngMvc的拦截器使用
- SpringMVC学习记录(七)--拦截器的使用
- 和大彪一起来学习-SpringMvc之第一回(框架了解和第一个SpringMvc程序)
- 和大彪一起来学习-SpringMvc之第二回(控制器,适配器说明) 分类: SpringMvc 2015-01-18 22:21 622人阅读 评论(0) 收藏
- 和大彪一起来学习-SpringMvc之第一回(框架了解和第一个SpringMvc程序) 分类: SpringMvc 2015-01-14 21:08 636人阅读 评论(0) 收藏
- springMVC学习(12)-使用拦截器
- SpringMVC学习记录(七)--拦截器的使用
- 【spring MVC学习二】springMVC简单使用
- springmvc 拦截器使用注意点