自定义拦截器

1.什么是拦截器

说明:

拦截器与过滤器的区别

SpringMVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。

  1. SpringMVC 也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能

  2. 自定义的拦截器必须实现 HandlerInterceptor 接口

  3. 自定义拦截器的三个方法:

(1)preHandle():该方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理

(2)postHandle():该方法在目标方法处理完请求之后执行

(3)afterCompletion():该方法在完全处理完请求之后被调用,可以在该方法中进行一些资源清理的操作

2.自定义拦截器执行流程分析图

● 自定义拦截器执行流程说明

拦截器中方法的执行顺序是 preHandle -> Controller -> postHandle -> afterCompletion,只有preHandle返回true,才会执行后面的方法

  1. 如果 preHandle 方法返回 false, 则不再执行目标方法及之后的拦截方法,可以在该方法指定返回页面
  2. postHandle 在目标方法被执行后执行,可以在 postHandle 方法中访问到目标方法返回的 ModelAndView 对象
  3. 若 preHandle 返回 true, 则 afterCompletion 方法在渲染视图之后被执行
  4. 若 preHandle 返回 false, 则 afterCompletion 方法不会被调用
  5. 配置拦截器时可以指定该拦截器对哪些请求生效,哪些请求不生效,如果不指定则默认对所有目标方法生效

3.应用实例

3.1快速入门

完成一个自定义拦截器,学习如何配置拦截器和拦截器的运行流程。

(1)创建拦截器 MyInterceptor01.java

package com.li.web.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* @author 李
* @version 1.0
*/
//需要标识为component注入到spring容器中
@Component
public class MyInterceptor01 implements HandlerInterceptor {
/**
* 1.preHandle 方法在目标方法执行前被执行
* 2.如果 preHandle 方法返回了false,则目标方法不再被执行
* 3.preHandle方法可以获取到 request,response,handler
* 4.如果该方法返回了 false,你可以指定跳转到哪个页面
* @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.postHandle 方法可以获取到目标方法返回的 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 方法在视图渲染后被执行
* 2.在 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)在 spring 的容器文件中配置拦截器

<!--配置自定义拦截器-->
<mvc:interceptors>
<!--
1.第一种配置方式
2.直接使用ref引用到对应的 myInterceptor01
3.这种方式会拦截所有的目标方法
-->
<ref bean="myInterceptor01"/>
</mvc:interceptors>

(3)测试 Controller

package com.li.web.interceptor;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; /**
* @author 李
* @version 1.0
*/
@Controller
public class TestHandler {
@RequestMapping(value = "/hi")
public String hi() {
System.out.println("===TestHandler--hi()===");
return "success";
} @RequestMapping(value = "/hello")
public String hello() {
System.out.println("===TestHandler--hello()===");
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">测试自定义拦截器-hi</a><br/><br/>
<a href="<%=request.getContextPath()%>/hello">测试自定义拦截器-hello</a>
</body>
</html>

(5)启动 tomcat,访问 interceptor.jsp,分别点击两个超链接

后台输出如下:

可以看到方法的执行顺序为:preHandler-->目标方法-->postHandle-->afterCompletion,并且拦截器对Controller 所有的方法都进行了拦截。

3.2注意事项和使用细节

  1. 默认配置是对所有的目标方法都进行拦截,也可以指定拦截某个目标方法,如在 spring 容器文件中配置:

    <!--配置自定义拦截器-->
    <mvc:interceptors>
    <!--
    1.第二种配置方式
    2.mvc:mapping path="/hi" 指定要拦截的目标方法的路径
    3.ref bean="myInterceptor01" 指定对哪个拦截器进行配置
    -->
    <mvc:interceptor>
    <mvc:mapping path="/hi"/>
    <ref bean="myInterceptor01"/>
    </mvc:interceptor>
    </mvc:interceptors>
  2. mvc:mapping 支持通配符,同时可以指定不对哪些目标方法进行拦截,例如:

    <!--配置自定义拦截器-->
    <mvc:interceptors>
    <!--
    1.第三种配置方式
    2.mvc:mapping path="/h*" 表示拦截 /h 开头的路径的目标方法
    3.mvc:exclude-mapping path="/hello" 表示不拦截指定路径的目标方法
    4.ref bean="myInterceptor01" 指定对哪个拦截器进行配置
    -->
    <mvc:interceptor>
    <!--h开头的目标方法都被拦截-->
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor01"/>
    </mvc:interceptor>
    </mvc:interceptors>
  3. 拦截器需要配置才生效,不配置是不生效的

  4. 如果 preHandle() 方法返回了 false,就不会执行目标方法(前提是目标方法指定了拦截),你可以在该方法中根据业务指定要跳转的页面

3.3Debug执行流程

(1)在自定义拦截器 MyInterceptor01 的 preHandle 方法中打上断点,点击 debug

(2)浏览器访问页面 interceptor.jsp,点击第一个链接,访问目标方法 hi()

(3)后台光标跳转到断点处,此时 preHandle 方法已经拿到了目标方法,说明 preHandle 方法在目标方法前执行

(4)在目标方法 hi 中添加断点,点击 resume,光标跳转到断点处

(5)在拦截器的 postHandle 方法中添加断点,点击 resume,光标如期跳转到该断点处。在该方法中可以拿到目标方法对应的 ModelAndView 对象,其中 view 就是指定的要返回的页面,model 就是目标方法的数据。

(6)ModelAndView 对象在 DispatcherServlet 的 resolveViewName 方法进行解析,返回视图,视图在 render 方法中进行视图渲染

(7)在拦截器的 afterCompletion 方法中打上断点,点击 resume,光标跳转到该断点处

(8)这一个拦截流程就结束了,再次点击 resume,就会向客户端返回数据

4.多个拦截器

4.1多个拦截器执行流程示意图

4.2实例演示1-执行流程

4.2.1代码实现

(1)在3.1中快速入门中已经创建了一个拦截器,现在创建第二个拦截器 MyInterceptor02.java

package com.li.web.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* @author 李
* @version 1.0
*/
@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()===");
}
}

(2)在 spring 的容器文件中配置拦截器

<!--配置自定义拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--h开头的目标方法都被拦截-->
<mvc:mapping path="/h*"/>
<mvc:exclude-mapping path="/hello"/>
<ref bean="myInterceptor01"/>
</mvc:interceptor>
<!--
第二个拦截器
多个拦截器在执行时,按照配置的顺序执行
-->
<mvc:interceptor>
<mvc:mapping path="/h*"/>
<ref bean="myInterceptor02"/>
</mvc:interceptor>
</mvc:interceptors>

(3)interceptor.jsp 不变

(4)完成测试,浏览器访问 jsp 页面,点击访问目标方法 hi

(5)后端输出如下:与分析的流程一致。

(6)如果把第二个拦截器的 preHandle 方法返回值改为 false,重新访问目标方法测试,后台输出如下:

4.2.2注意事项和使用细节

  1. 如果第一个拦截器的 preHandle() 返回 false,后面都不再执行,包括目标方法

  2. 如果第二个拦截器的 preHandle() 返回 false,就直接执行第一个拦截器的 afterCompletion() 方法,如果拦截器更多,规则类似。

  3. 以上两条规则,都是在目标方法符合被拦截条件的前提下。

4.3实例演示2-跳转至指定页面

需求:如果用户提交的数据有禁用词(比如:病毒),则在第一个拦截器就返回,不执行目标方法,跳转至执行页面

4.3.1代码实现

(1)修改 MyInterceptor01.java 的 preHandle 方法

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("===MyInterceptor01--preHandle()===");
//获取用户提交的关键字
String keyword = request.getParameter("keyword");
if ("病毒".equals(keyword)) {
//请求转发到指定页面
request.getRequestDispatcher("/WEB-INF/pages/warning.jsp")
.forward(request, response);
return false;
}
System.out.println("keyword=" + keyword);
return true;
}

(2)warning.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>警告</title>
</head>
<body>
<h1>你的信息中含有违规词</h1>
</body>
</html>

(3)在 postman 中进行测试

测试1:无违禁词

后台输出:

测试2:含违禁词

后台输出:

5.练习

  1. 将之前的 SpringMVC 文件上传、自定义拦截器相关代码和案例过一遍
  2. 简述 SpringMVC 自定义拦截器工作流程,并画出示意图
  3. debug 自定义拦截器源码,加深理,梳理流程

day13-自定义拦截器的更多相关文章

  1. spring mvc <mvc:annotation-driven/> 自定义拦截器不走

    <mvc:annotation-driven/> 这个便签会注册2个自定义拦截器,所以导致请求过来就会自己去走注册的这2个拦截器和定义的一堆bean 但是这个便签是必须得定义的 直接贴代码 ...

  2. 12.Struts2自定义拦截器

    12.自定义拦截器        拦截器是Struts2的一个重要特性.因为Struts2的大多数核心功能都是通过拦截器实现的. 拦截器之所以称之为“拦截器”,是因为它可以拦截Action方法的执行, ...

  3. 【Java EE 学习 35 下】【struts2】【struts2文件上传】【struts2自定义拦截器】【struts2手动验证】

    一.struts2文件上传 1.上传文件的时候要求必须使得表单的enctype属性设置为multipart/form-data,把它的method属性设置为post 2.上传单个文件的时候需要在Act ...

  4. SpringMVC——自定义拦截器、异常处理以及父子容器配置

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

  5. Struts2 自定义拦截器

    自定义拦截器(权限管理),包含了对ajax和表单请求的拦截 package com.interceptor; import java.io.IOException; import java.io.Pr ...

  6. Struts2自定义拦截器

    1. 需求 自定义拦截器实现,用户登录的访问控制. 2. 定义拦截器类 public class LoginInterceptor extends AbstractInterceptor { @Ove ...

  7. SpringMvc自定义拦截器

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

  8. struts2基础——自定义拦截器

    一.自定义拦截器 默认的拦截器能实现的功能是有限的,Struts2 支持自定义拦截器. 二.拦截器类 1.实现 Interceptor 接口 2.继承 AbstractInterceptor 抽象类, ...

  9. Apache CXF自定义拦截器

    为什么设计拦截器?1.为了在webservice请求过程中,能动态操作请求和响应数据,CXF设计了拦截器 拦截器分类: 1.按所处的位置分:服务器端拦截器,客户端拦截器. 2.按消息的方向分:入拦截器 ...

  10. web开发(二十一)之自定义拦截器的使用

    转自博客:http://blog.csdn.net/pkgk2013/article/details/51985817 拦截器的作用 拦截器,在AOP(Aspect-Oriented Programm ...

随机推荐

  1. python(牛客)试题解析2 - 中等

    导航 一.NC192 二叉树的后序遍历 二.NC117 合并二叉树 三.求长度最长的的连续子序列使他们的和等于sum 四.按顺序取出固定长度内容并合并两个数组为一个新数组 五.输出所有结果小于k的整数 ...

  2. kettel

    下载教程:(目前最高版本7.1) 1.网址:https://community.hitachivantara.com/docs/DOC-1009855 2.

  3. Spring Security(8)

    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 之前虽然实现了角色和权限之间的简单配对,但是如果每一个角色都要重新来过一次,就有点呆板了.如果能够配置一个「角色模板」,再通过这个模板来配置其他 ...

  4. 【大数据面试】【框架】Linux命令、Shell工具、常见Shell脚本(群起脚本、数仓导入)

    一.Linux 1.常用高级命令 ps -ef:查看进程详情,ps -ef|grep dae可以搜索指定进程,-e表示环境变量 ps -au:以用户为主的详细格式,显示进程平均占用资源,不包括cmd列 ...

  5. 同时容器,k8s和docker区别是什么? 如何简单理解k8s和docker

    1.k8s是一个开源的容器集群管理系统,可以实现容器集群的自动化部署.自动扩缩容.维护等功能. 2.Docker是一个开源的应用容器引擎,开发者可以打包他们的应用及依赖到一个可移植的容器中,发布到流行 ...

  6. 云原生架构(二)环境搭建(Mac上安装Docker+Kubernetes+Istio一条龙)

    一.背景 Istio 项目由 Google 和 IBM 的团队与 Lyft 的 Envoy 团队合作启动.它已经完全在 GitHub 上公开开发.目前已经是"Service Mesh服务网格 ...

  7. JuiceFS CSI Driver 常见问题排查指南

    Kubernetes 作为资源调度和应用编排的开源系统,正在成为云计算和现代 IT 基础架构的通用平台.JuiceFS CSI Driver 实现了容器编排系统的存储接口,使得用户可以在 Kubern ...

  8. cs231n__2. K-nearest Neighbors

    CS231n 2 K-Nearest Neighbors note ---by Orangestar 1. codes: import numpy as np class NearestNeighbo ...

  9. 云知声: 基于 JuiceFS 的超算平台存储实践

    云知声从一家专注于语音及语言处理的技术公司,现在技术栈已经发展到具备图像.自然语言处理.信号等全栈式的 AI 能力,是国内头部人工智能独角兽企业.公司拥抱云计算,在智慧医疗.智慧酒店.智慧教育等方面都 ...

  10. MySQL优化三,SQL语法

    ## 1.3.MySQL调优 前言:在前面的基础之上把相应的数据库表设计得很完美,建立了好用的索引,如果SQL语句中没有使用到相应索引的话,也是白搭,如何设计好一点的SQL,则是一大问题 ### 1. ...