自定义拦截器:

一、若想实现自定义拦截器,需要实现 org.springframework.web.servlet.HandlerInterceptor 接口。

二、HandlerInterceptor API

1. 接口中定义了三个方法

2.preHandle()

(1)调用时机

在 org.springframework.web.servlet.DispatcherServlet#doDispatch 方法中。

org.springframework.web.servlet.HandlerExecutionChain#applyPreHandle 具体的调用过程

可以看到,preHander() 方法的调用是在调用目标方法前调用的。

同时可以看到,通过循环,调用了所有的拦截器,并且如果自定义的拦截器的 preHandler() 返回 false 的情况下,还是会去调用拦截器的 afterCompletion() 方法。

(2)可以获取到的资源

HttpServletRequest、HttpServletResponse、以及目标处理器。

3.postHandler()

(1)调用的时机

可以看到在调用目标方法后,渲染视图前调用的 postHandler() 方法。

具体的调用过程:

去调用每一个拦截器的 postHandler() 方法,注意循环的方式,可以看到拦截器栈 preHandler() 和 postHandler() 方法调用形成了一个 U 形。

(2)可以获取到的资源

HttpServletRequest、HttpServletResponse、目标hanler 处理器、以及返回的 ModelAndView 对象。

3.afterCompletion()

(1)调用时机

可以看到,org.springframework.web.servlet.DispatcherServlet#doDispatch 执行逻辑的过程,捕获到异常后,最终都是由拦截器的 afterCompletion() 方法进行的处理。

(2)可以获取到的资源

HttpServletReques, HttpServletResponse, 目标 handler 处理器, 所有的异常信息

4. HandlerInterceptor 家族

三、实现自定义的拦截器

1.继承 HandlerInterceptorAdapter ,按照实际需求实现对应的方法就ok。

2.在 SpringMVC Config 文件中配置。

e1:

/**
* @author solverpeng
* @create 2016-09-01-15:56
*/
public class FirstInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
<mvc:interceptors>
<bean class="com.nucsoft.springmvc.interceptor.FirstInterceptor"/>
</mvc:interceptors>

说明:此种配置可以拦截器所有请求。

e2:

/**
* @author solverpeng
* @create 2016-09-01-16:08
*/
public class SecondInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondInterceptor#preHandle");
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("SecondInterceptor#postHandle");
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("SecondInterceptor#afterCompletion");
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/test/**"/>
<bean class="com.nucsoft.springmvc.interceptor.SecondInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

说明:只会拦截路径以 test 开头的请求。如:http://localhost:8080/springmvc/test/testInterceptor02 会被 SecondInterceptor 拦截。

四、拦截器的几个用处

1.性能监控

/**
* 计算每次请求耗时
* @author solverpeng
* @create 2016-09-01-17:46
*/
public class ConsumeTimeInterceptor extends HandlerInterceptorAdapter{
// SpringMVC 是单例的,所以对于每一次请求,从 ThreadLocal 中获取。
private NamedThreadLocal<Long> consumeTime = new NamedThreadLocal<>("consume_time"); @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
consumeTime.set(System.currentTimeMillis());
System.out.println("ConsumeTimeInterceptor#preHandle");
return true;
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("ConsumeTimeInterceptor#afterCompletion");
Long threadEnd = System.currentTimeMillis();
Long threadStart = consumeTime.get();
Long consume = threadEnd - threadStart;
if(consume > 10) {
System.out.println("add to log: " + consume);
}
}
}
<mvc:interceptors>
<bean class="com.nucsoft.springmvc.interceptor.ConsumeTimeInterceptor"/>
<bean class="com.nucsoft.springmvc.interceptor.FirstInterceptor"/>
</mvc:interceptors>

控制台输出:

从中也可以看出:拦截器的顺序与 SpringMVC 中配置的顺序是一致的。

2.登录检测

检测用户是否登录。

异常处理

1.局部的

在目标 handler 类中,声明一个有 @ExceptionHandler 标注的方法,通过 @ExceptionHandler 的 value 的属性来指定需要处理的异常类型。

可以处理的异常可以是一个类型,也可以是多个类型。如:

@ExceptionHandler(value = {ArithmeticException.class})

@ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class})

如:

@Controller
public class SpringTest {
@ExceptionHandler(value = {ArithmeticException.class})
public String handleArithmeticException(Exception ex) {
System.out.println("spring test class");
ex.printStackTrace();
return "error";
}
}

handleArithmeticException() 只能处理 SpringTest 控制器中出现的 ArithmeticException 类型的异常。

2.全局的

(1)基于注解

声明一个统一的异常处理类:

需要对异常处理类添加 @ControllerAdvice 注解,对异常处理方法的标注还和局部的情况一样。如:

@ControllerAdvice
public class HandlerException { @ExceptionHandler({ArithmeticException.class})
public String handlerArithmeticException(Exception ex) {
ex.printStackTrace();
return "error";
} }

handlerArithmeticException() 可以处理所有处理器发生的 ArithmeticException 类型的异常。

(2)基于xml

如:

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"
id="simpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="ArithmeticException">error</prop>
</props>
</property>
</bean>

通过属性 exceptionMappings 来指定要处理的异常,以及出现异常返回的页面。

3.优先级

基于xml>局部>全局

4.如何在异常页面得到异常信息

request.getAttribute("javax.servlet.error.exception")

5.@ResponseStatus

可以对全局的异常类标注 @ResponseStatus 注解,通过其 value 属性来指定返回的 Http状态码。是 HttpStatus 枚举类型。

来指定返回对应状态码的错误页面。

父子容器配置

SpringMVC 层容器可以作为 Spring 容器的子容器:

即 Web 层容器可以引用业务层容器的 Bean,而业务层容器却访问不到 WEB 层容器 Bean。

SpringMVC Config:

<context:component-scan base-package="com.nucsoft.springmvc" use-default-filters="false">
<!-- 只扫描 @Controller 和 @ControllerAdvice 注解-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>

Spring Config:

<context:component-scan base-package="com.nucsoft.springmvc">
<!-- 不扫描 @Controller 和 @ControllerAdvice 注解-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>

SpringMVC——自定义拦截器、异常处理以及父子容器配置的更多相关文章

  1. SpringMvc自定义拦截器

    SpringMvc也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义拦截器必须实现HandlerInterceptor接口 -preHandle():这个方法在业务处理器 ...

  2. springmvc 自定义拦截器实现未登录用户的拦截

    第一步:编写自定义拦截器类,该类继承HandlerInterceptorAdapter,重写preHandle方法  第二步:配置springmvc.xml文件,定义拦截器属性  登录请求的mappi ...

  3. SpringBoot2.X自定义拦截器实战及新旧配置对比(核心知识)

    简介: 讲解拦截器使用,Spingboot2.x新版本配置拦截拦截器和旧版本SpringBoot配置拦截器区别讲解 1.@Configuration 继承WebMvcConfigurationAdap ...

  4. springmvc 自定义拦截器

    <mvc:interceptors> <!-- 配置自定义的拦截器 --> <bean class="com.atguigu.springmvc.interce ...

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

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

  6. JavaEE开发之SpringMVC中的自定义拦截器及异常处理

    上篇博客我们聊了<JavaEE开发之SpringMVC中的路由配置及参数传递详解>,本篇博客我们就聊一下自定义拦截器的实现.以及使用ModelAndView对象将Controller的值加 ...

  7. SpringMVC(四)-- 文件下载、自定义拦截器、异常处理

    1.文件下载 用ResponseEntity<byte[]> 返回值完成文件下载 具体参见本博客之前的<文件上传下载> @RequestMapping(value=" ...

  8. SpringMVC 文件上传&拦截器&异常处理

    文件上传 Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的 MultipartResolver 实现的.Spring 用 Jakarta Commons FileUpload ...

  9. springMVC整理04--文件上传 & 拦截器 & 异常处理

    1.  文件上传 SpringMVC 的文件上传非常简便,首先导入文件上传依赖的 jar: <!-- 文件上传所依赖的 jar 包 --> <dependency> <g ...

随机推荐

  1. Centos6.6下安装MariaDB步骤,利用yum进行安装

    1.在/etc/yum.repos.d/下建立MariaDB.repo文件 可以在Win下编辑好此文件,然后通过SSH远程复制过去. 2.MariaDB.repo内容要根据MariaDB官方提供的re ...

  2. H5 缓存机制浅析 移动端 Web 加载性能优化

    腾讯Bugly特约作者:贺辉超 1 H5 缓存机制介绍 H5,即 HTML5,是新一代的 HTML 标准,加入很多新的特性.离线存储(也可称为缓存机制)是其中一个非常重要的特性.H5 引入的离线存储, ...

  3. dojo Provider(script、xhr、iframe)源码解析

    总体结构 dojo/request/script.dojo/request/xhr.dojo/request/iframe这三者是dojo提供的provider.dojo将内部的所有provider构 ...

  4. hadoop rpc基础

    第一部分: hadoop rpc基础 RPC,远程程序调用,分布式计算中C/S模型的一个应用实例. 同其他RPC框架一样,Hadoop分为四个部分: 序列化层:支持多种框架实现序列化与反序列化 函数调 ...

  5. AlwaysON同步的原理及可用模式

    新一代读写分离技术——AlwaysOn 早在SQL Server 2005的时候微软就已经实现了数据库的查询分离技术——发布订阅.但生产库和查询库的同步性能较差,时常出现性能问题,因此在大型生产环境中 ...

  6. 如何在 IIS 上搭建 mercurial server

    mercurial server 对于代码管理工具,更多的人可能更熟悉 Git 一些(Git 太火了).其实另外一款分布式代码管理工具也被广泛的使用,它就是 mercurial.多人协作时,最好能够通 ...

  7. IOS UIView 01-View开始深入 绘制像素到屏幕上

    注:本人是翻译过来,并且加上本人的一点见解. 前言 一个像素是如何绘制到屏幕上去的?有很多种方式将一些东西映射到显示屏上,他们需要调用不同的框架.许多功能和方法的结合体.这里我们大概的看一下屏幕之后发 ...

  8. 第九回 Microsoft.Practices.Unity.Interception实现基于数据集的缓存(针对六,七,八讲的具体概念和配置的解说)

    返回目录 概念 Microsoft.Practices.Unity.Interception是一个拦截器,它隶属于Microsoft.Practices.Unity组成之中,主要完成AOP的功能,而实 ...

  9. 说说设计模式~装饰器模式(Decorator)

    返回目录 装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序, ...

  10. Atitti 文本分类  以及 垃圾邮件 判断原理 以及贝叶斯算法的应用解决方案

    Atitti 文本分类  以及 垃圾邮件 判断原理 以及贝叶斯算法的应用解决方案 1.1. 七.什么是贝叶斯过滤器?1 1.2. 八.建立历史资料库2 1.3. 十.联合概率的计算3 1.4. 十一. ...