SpringMVC——自定义拦截器、异常处理以及父子容器配置
自定义拦截器:
一、若想实现自定义拦截器,需要实现 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——自定义拦截器、异常处理以及父子容器配置的更多相关文章
- SpringMvc自定义拦截器
SpringMvc也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义拦截器必须实现HandlerInterceptor接口 -preHandle():这个方法在业务处理器 ...
- springmvc 自定义拦截器实现未登录用户的拦截
第一步:编写自定义拦截器类,该类继承HandlerInterceptorAdapter,重写preHandle方法 第二步:配置springmvc.xml文件,定义拦截器属性 登录请求的mappi ...
- SpringBoot2.X自定义拦截器实战及新旧配置对比(核心知识)
简介: 讲解拦截器使用,Spingboot2.x新版本配置拦截拦截器和旧版本SpringBoot配置拦截器区别讲解 1.@Configuration 继承WebMvcConfigurationAdap ...
- springmvc 自定义拦截器
<mvc:interceptors> <!-- 配置自定义的拦截器 --> <bean class="com.atguigu.springmvc.interce ...
- SpringMVC—Struts2拦截器学习网址整理
引自:http://blog.csdn.net/wp1603710463/article/details/49982683 SpringMVC—Struts2拦截器学习网址整理 最近项目中遇到权限相关 ...
- JavaEE开发之SpringMVC中的自定义拦截器及异常处理
上篇博客我们聊了<JavaEE开发之SpringMVC中的路由配置及参数传递详解>,本篇博客我们就聊一下自定义拦截器的实现.以及使用ModelAndView对象将Controller的值加 ...
- SpringMVC(四)-- 文件下载、自定义拦截器、异常处理
1.文件下载 用ResponseEntity<byte[]> 返回值完成文件下载 具体参见本博客之前的<文件上传下载> @RequestMapping(value=" ...
- SpringMVC 文件上传&拦截器&异常处理
文件上传 Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的 MultipartResolver 实现的.Spring 用 Jakarta Commons FileUpload ...
- springMVC整理04--文件上传 & 拦截器 & 异常处理
1. 文件上传 SpringMVC 的文件上传非常简便,首先导入文件上传依赖的 jar: <!-- 文件上传所依赖的 jar 包 --> <dependency> <g ...
随机推荐
- 前端自动化测试工具doh学习总结(一)
前言 项目中需要用到前端自动化测试,自己被当作一个探针研究了下目前用的比较多的web自动化测试工具.一开始研究的是的selenium,但由于项目使用了大量的dijit控件,写起testCase来很费劲 ...
- [.net 面向对象编程基础] (21) 委托
[.net 面向对象编程基础] (20) 委托 上节在讲到LINQ的匿名方法中说到了委托,不过比较简单,没了解清楚没关系,这节中会详细说明委托. 1. 什么是委托? 学习委托,我想说,学会了就感觉简 ...
- 如何让Hadoop读取以gz结尾的文本格式的文件
背景: 搜索引擎在build全量时,会产生数G的xml的中间文件,我需要去查询这些中间文件中,是否有某个特殊的字符.xml文件有很多,每个都有几百M,存储在hdfs上,而且是以gz结尾的文本格式的文件 ...
- java提高篇(二五)-----HashTable
在java中与有两个类都提供了一个多种用途的hashTable机制,他们都可以将可以key和value结合起来构成键值对通过put(key,value)方法保存起来,然后通过get(key ...
- Android多线程分析之四:MessageQueue的实现
Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...
- 一个用微软官方的OpenXml读写Excel 目前网上不太普及的方法。
新版本的xlsx是使用新的存储格式,貌似是处理过的XML. 传统的excel处理方法,我真的感觉像屎.用Oldeb不方便,用com组件要实际调用excel打开关闭,很容易出现死. 对于OpenXML我 ...
- 鸟哥的Linux私房菜——基础学习篇 —— 笔记2
at 语法 == 注意,输入at之后便进入命令行模式 ------- 不管怎么样,只会执行一次. [test @test test]# at [-m] TIME (输入工作指令)[test @test ...
- 基础才是重中之重~AutoMapper为已有目标对象映射
回到目录 AutoMapper各位一定不会陌生,大叔之前的文章中也提到过,曾经也写过扩展方法,以方便程序开发人员去使用它,而在最近,大叔在一个API项目里,在一个POST请求由DTO对象为实体对象赋值 ...
- Atitit 教育与培训学校 的计划策划 v2
Atitit 教育与培训学校 的计划策划 1. 历史大趋势,教育的普及化1 2. 我们的目标,人人可以接受硕士博士教育,确保全球60亿人的普世化教育1 3. 学校的注册,可以选择在全球费用最优惠的地方 ...
- 初了解JS设计模式,学习笔记
什么是设计模式. 回答这个问题,往往我们得先知道我们为什么需要设计模式,正是因为有需求才会有设计模式,难道不是吗? 我们为什么需要设计模式. 如果没有按照设计模式去写,你的代码很可能是乱无肆忌写的,也 ...