Spring MVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。本文将代码演示和文字描述详解拦截器的原理与使用
1.什么是拦截器
说明
- Spring MVC 也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能.
- 自定义的拦截器必须实现 HandlerInterceptor 接口
自定义拦截器的三个方法
- preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。
- postHandle():这个方法在目标方法处理完请求后执行
- afterCompletion():这个方法在完全处理完请求后被调用,可以在该方法中进行一些资源 清理的操作。
2.自定义拦截器执行流程图
自定义拦截器执行流程说明
- 如果 preHandle 方法 返回 false, 则不再执行目标方法, 可以在此指定返回页面
- postHandle 在目标方法被执行后执行. 可以在方法中访问到目标方法返回的 ModelAndView 对象
- 若 preHandle 返回 true, 则 afterCompletion 方法 在渲染视图之后被执行.
- 若 preHandle 返回 false, 则 afterCompletion 方法不会被调用
- 在配置拦截器时,可以指定该拦截器对哪些请求生效,哪些请求不生效,如果不配置默认对所有请求生效
3.自定义拦截器应用实例
1.快速入门
● 应用实例需求
完成一个自定义拦截器,学习一下如何配置拦截器和拦截器的运行流程
● 应用实例-代码实现
1.自定义拦截器
/**
* 自定义拦截器
*/
@Component
public class MyInterceptor01 implements HandlerInterceptor {
/**
* 1.preHandle 方法在目标方法执行前被执行
* 2.如果返回fasle则不在执行目标方法
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor01 --preHandle");
return true;
}
/**
* 1. 在目标方法执行后,会执行postHandle
* 2. 该方法可以获取到 目标方法,返回的ModelAndView对象
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor01-postHandle");
}
/**
*1. afterCompletion() 在视图渲染后被执行, 这里可以进行资源清理工作
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor01-afterCompletion");
}
}
2.配置拦截器
拦截配置有三种方式
(1)不指定拦截规则,默认拦截所有
<!--配置自定义拦截器-spring配置文件-->
<mvc:interceptors>
<!--第一种方式,不指定拦截规则默认拦截所有请求-->
<ref bean="myInterceptor01"></ref>
</mvc:interceptors>
(2)指定明确的拦截路径
<!--配置自定义拦截器-spring配置文件-->
<mvc:interceptors>
<!--第一种方式,不指定拦截规则默认拦截所有请求-->
<!--<ref bean="myInterceptor01"></ref>-->
<!--第二种指定拦截路径-->
<mvc:interceptor>
<mvc:mapping path="/hi"/>
<ref bean="myInterceptor01"/>
</mvc:interceptor>
</mvc:interceptors>
(3)通配符方式,也可用于指定不拦截路径
<!--配置自定义拦截器-spring配置文件-->
<mvc:interceptors>
<!--第一种方式,不指定拦截规则默认拦截所有请求-->
<!--<ref bean="myInterceptor01"></ref>-->
<!--第二种指定拦截路径-->
<!-- <mvc:interceptor>
<mvc:mapping path="/hi"/>
<ref bean="myInterceptor01"/>
</mvc:interceptor>-->
<mvc:interceptor>
<!--通配符方式 表示拦截 /h 打头的路径-->
<mvc:mapping path="/h*"/>
<!--/hello不拦截-->
<mvc:exclude-mapping path="/hello"/>
<!--指定对哪个拦截器配置-->
<ref bean="myInterceptor01"/>
</mvc:interceptor>
</mvc:interceptors>
3.创建FurnHandler.java
@Controller
public class FurnHandler {
@RequestMapping(value = "/hi")
public String hi(User user) {
System.out.println("---FurnHandler--hi()---");
return "success";
}
@RequestMapping(value = "/hello")
public String hello() {
System.out.println("---FurnHandler--hello()---");
return "success";
}
@RequestMapping(value = "/ok")
public String ok() {
System.out.println("---FurnHandler--ok()---");
return "success";
}
}
4.interceptor.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试自定义拦截器</title>
</head>
<body>
<h1>测试自定义拦截器</h1>
<a href="<%=request.getContextPath()%>/hi" rel="external nofollow" >测试自定义拦截器-hi</a><br><br>
<a href="<%=request.getContextPath()%>/hello" rel="external nofollow" >测试自定义拦截器-hello</a><br/><br/>
<a href="<%=request.getContextPath()%>/ok" rel="external nofollow" >测试自定义拦截器-ok</a><br><br>
</body>
</html>
5.测试
2.注意事项和细节
1、默认配置是都所有的目标方法都进行拦截, 也可以指定拦截目标方法, 比如只是拦截 hi
<mvc:interceptor>
<mvc:mapping path="/hi"/>
<ref bean="myInterceptor01"/>
</mvc:interceptor>
2、mvc:mapping 支持通配符, 同时指定不对哪些目标方法进行拦截
<mvc:interceptor>
<mvc:mapping path="/h*"/>
<mvc:exclude-mapping path="/hello"/>
<ref bean="myInterceptor01"/>
</mvc:interceptor>
3、拦截器需要配置才生效,不配置是不生效的.
4、如果 preHandler() 方法返回了 false, 就不会执行目标方法(前提是你的目标方法被拦截 了), 程序员可以在这里根据业务需要指定跳转页面.
3.Debug执行流程
4.多个拦截器
1.多个拦截器执行流程示意图
执行流程可以参考filter过滤器,执行顺序根据配置的先后顺序
2.应用实例
代码实现
新增拦截器
@Component
public class MyInterceptor02 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor02-preHandle");
return true;
}
@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");
}
}
配置拦截器
<!--配置自定义拦截器-spring配置文件-->
<mvc:interceptors>
<!--第一种方式,不指定拦截规则默认拦截所有请求-->
<!--<ref bean="myInterceptor01"></ref>-->
<!--第二种指定拦截路径-->
<!-- <mvc:interceptor>
<mvc:mapping path="/hi"/>
<ref bean="myInterceptor01"/>
</mvc:interceptor>-->
<mvc:interceptor>
<!--通配符方式 表示拦截 /h 打头的路径-->
<mvc:mapping path="/h*"/>
<!--/hello不拦截-->
<mvc:exclude-mapping path="/hello"/>
<!--指定对哪个拦截器配置-->
<ref bean="myInterceptor01"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/hi"/>
<ref bean="myInterceptor02"/>
</mvc:interceptor>
</mvc:interceptors>
这里我们定义了两个拦截器myInterceptor01和myInterceptor02,两个拦截器都会对ip:port/工程路径/hi的请求进行拦截,执行结果如下图所示:
执行流程说明:拦截器的执行先后顺序根据配置的先后顺序执行
3.主要事项和细节
- 如果第 1 个拦截器的 preHandle() 返回 false , 后面都不在执行
- 如果第2个 拦 截 器 的 preHandle() 返 回 false , 就 直 接 执 行 第1个 拦 截 器 的 afterCompletion()方法, 如果拦截器更多,规则类似
- 说明: 前面说的规则,都是目标方法被拦截的前提
在实际开发中我们常用拦截器对登录进行验证
到此这篇关于SpringMVC超详细介绍自定义拦截器的文章就介绍到这了,更多相关SpringMVC拦截器内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!
本文标题为:SpringMVC超详细介绍自定义拦截器
基础教程推荐
- java实现多人聊天系统 2023-05-19
- Java文件管理操作的知识点整理 2023-05-19
- Java并发编程进阶之线程控制篇 2023-03-07
- ConditionalOnProperty配置swagger不生效问题及解决 2023-01-02
- Java数据结构之对象比较详解 2023-03-07
- Java实现查找文件和替换文件内容 2023-04-06
- springboot自定义starter方法及注解实例 2023-03-31
- Java实现线程插队的示例代码 2022-09-03
- JDK数组阻塞队列源码深入分析总结 2023-04-18
- java基础知识之FileInputStream流的使用 2023-08-11