SpringMVC系列十一: 文件上传与自定义拦截器

news2024/11/27 5:29:38

文章目录

  • SpringMVC文件上传
    • 基本介绍
    • 需求分析 / 图解
    • 应用实例-代码实现
  • 自定义拦截器
    • 什么是拦截器
    • 自定义拦截器执行流程分析图
    • 自定义拦截器应用实例
      • 快速入门
      • 注意事项和细节
      • Debug执行流程
    • 多个拦截器
      • 多个拦截器执行流程示意图
      • 应用实例1
        • 代码实现
        • 注意事项和细节
      • 应用实例2
    • 作业布置

上一讲, 我们学习的是

在这里插入图片描述

SpringMVC文件上传

基本介绍

1.Spring MVC 为文件上传提供了直接的支持, 这种支持是通过即插即用的 MultipartResolver 实现的. SpringJakata Commons FileUpload 技术实现了一个 MultipartResolver 实现类: CommonsMultipartResolver

2.SpringMVC 上下文中默认没有装配 Multipartresolver, 因此默认情况下不能处理文件的上传工作, 如果想使用 Spring 的文件上传功能, 需现在上下文中配置 MultipartResolver

需求分析 / 图解

在这里插入图片描述

应用实例-代码实现

1.引入springmvc文件上传需要的jar包 spingmvc上传文件需要的jar
在这里插入图片描述

2.在web路径下创建fileUpload.jsp

<body>
<h1>文件上传的演示</h1>
<form action="?" method="post" enctype="multipart/form-data">
    文件介绍:<input type="text" name="introduce"/><br/>
    选择文件:<input type="file" name="file"/><br/>
    <input type="submit" value="上传文件"/>
</form>
</body>

3.配置文件过滤器, 在web.xml中, 使用Spring提供的, 前面已经配置过了 传送

4.配置文件上传解析器, 在springDispatcherServlet-servlet.xml, 简单看一下CommonsMultipartResolver源码

<!--配置文件上传需要的bean-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

5.在com.zzw.web.fileupload下新建FileUploadHandler.java


 * @author 赵志伟
 * @version 1.0
 * 处理文件上传的handler
 */
@SuppressWarnings({"all"})
@Controller
public class FileUploadHandler {

    //编写方法, 处理文件上传的请求
    @RequestMapping(value = "/fileUpload")
    public String fileUpload(@RequestParam(value = "file") MultipartFile file,
                             HttpServletRequest request, String introduce) throws IOException {
        //接收到提交的文件名
        String originalFilename = file.getOriginalFilename();
        System.out.println("你上传的文件名=" + originalFilename);
        System.out.println("文件的介绍=" + introduce);
        //得到要把上传的文件保存到哪个路径[全路径: 包括文件名]
        String fileFullPath =
                request.getServletContext().getRealPath("/img/" + originalFilename);
        //创建文件
        File saveToFile = new File(fileFullPath);
        //将上传的文件, 转存到saveToFile
        file.transferTo(saveToFile);
        return "success";
    }
}

6.回填``fileUpload.jspaction`

<form action="<%=request.getServletContext()%>/fileUpload" method="post" enctype="multipart/form-data">

7.完成测试[页面方式], 看文件是否成功上传 http://localhost:8088/springmvc/fileUpload.jsp

在这里插入图片描述

在这里插入图片描述

简单地debug一下transferTo()

在这里插入图片描述
在这里插入图片描述

8.完成测试[postman方式]

在这里插入图片描述
在这里插入图片描述

自定义拦截器

什么是拦截器

●说明
1.Spring MVC也可以使用拦截器对请求进行拦截处理, 用户可以自定义拦截器来实现特定的功能.
2.自定义的拦截器必须实现HandlerInterceptor接口

●自定义拦截器的三个方法
1.preHandle(): 这个方法在业务处理器处理请求之前被调用, 在该方法中对用户请求 request 进行处理.
2.postHandler(): 这个方法在目标方法处理完请求后执行
3.afterCompletion(): 这个方法在完全处理完请求后被调用, 可以在该方法中进行一些资源清理的操作.

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

在这里插入图片描述

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

自定义拦截器应用实例

快速入门

●应用实例需求
完成一个自定义拦截器, 学习一下如何配置拦截器和拦截器的运行流程

●应用实例-代码实现
1.com.zzw.web.interceptor包下新建MyInterceptor01.java

@Component
public class MyInterceptor01 implements HandlerInterceptor {

    /**
     * 解读
     * 1. preHandle() 在目标方法执行前被执行
     * 2. 如果preHandle() 返回false, 不再执行目标方法
     * 3. 该方法可以获取到request, response, handler
     * 4. 这里根据业务, 可以进行拦截, 并指定跳转到哪个页面
     *
     * @param request  current HTTP request
     * @param response current HTTP response
     * @param handler  chosen handler to execute, for type and/or instance evaluation
     * @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      current HTTP request
     * @param response     current HTTP response
     * @param handler      the handler (or {@link HandlerMethod}) that started asynchronous
     *                     execution, for type and/or instance examination
     * @param modelAndView the {@code ModelAndView} that the handler returned
     *                     (can also be {@code null})
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("--MyInterceptor01-- postHandle()被执行...");

    }

    /**
     * 解读
     * 1. afterCompletion() 在视图渲染后被执行, 这里可以进行资源清理工作
     * 2.
     *
     * @param request  current HTTP request
     * @param response current HTTP response
     * @param handler  the handler (or {@link HandlerMethod}) that started asynchronous
     *                 execution, for type and/or instance examination
     * @param ex       any exception thrown on handler execution, if any; this does not
     *                 include exceptions that have been handled through an exception resolver
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("--MyInterceptor01-- afterCompletion()被执行...");

    }
}

2.在springDispatcherServlet-servlet.xml 配置拦截器

注意: 拦截器是由spring管理的 ; 过滤器是由web.xml管理的

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

<!--加入两个常规配置-->
<!--支持SpringMVC的高级功能, 比如JSR303校验, 映射动态请求-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--将springmvc不能处理的请求, 交给tomcat处理, 比如css, js-->
<mvc:default-servlet-handler/>

3.在com.zzw.ewb.interceptor包 下新建FurnHandler.java

@Controller
public class FurnHandler {

    @RequestMapping(value = "/hi")
    public String hi() {
        System.out.println("--FurnHandler-- hi()...");
        return "success";
    }

    @RequestMapping(value = "/hello")
    public String hello() {
        System.out.println("--FurnHandler-- hello()...");
        return "success";
    }
}

4.web路径下创建interceptor.jsp

<head>
    <title>测试自定义拦截器</title>
</head>
<body>
<h1>测试自定义拦截器</h1>
<a href="<%=request.getContextPath()%>/hi">测试自定义拦截器-hi</a><br/><br/>
<a href="<%=request.getContextPath()%>>/hello">测试自定义拦截器-hello</a>
</body>

5.测试

浏览器测试 http://localhost:8088/springmvc/interceptor.jsp

在这里插入图片描述
–MyInterceptor01-- preHandle() 被执行…
–FurnHandler-- hi()…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor01-- afterCompletion()被执行…
 
–MyInterceptor01-- preHandle() 被执行…
–FurnHandler-- hello()…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor01-- afterCompletion()被执行…

postman测试
在这里插入图片描述
在这里插入图片描述
–MyInterceptor01-- preHandle() 被执行…
–FurnHandler-- hi()…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor01-- afterCompletion()被执行…
 
–MyInterceptor01-- preHandle() 被执行…
–FurnHandler-- hello()…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor01-- afterCompletion()被执行…

注意事项和细节

1.默认配置是将所有的目标方法都进行拦截, 也可以指定拦截目标方法, 比如只拦截hi

<!--配置自定义拦截器-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 支持通配符, 同时指定不对哪些目标方法进行拦截

<!--配置自定义拦截器-spring配置文件-->
<mvc:interceptors>
    <!--解读
    1. 第三种配置方式
    2. mvc:mapping path="/h*" 通配符方式 表示拦截 /h 打头的路径
    3. mvc:exclude-mapping path="/hello" /hello不拦截
    4. ref bean="myInterceptor01" 指定对哪个拦截器配置
    -->
    <mvc:interceptor>
        <mvc:mapping path="/h*"/>
        <mvc:exclude-mapping path="/hello"/>
        <ref bean="myInterceptor01"/>
    </mvc:interceptor>
</mvc:interceptors>

FurnHandler添加方法

@RequestMapping(value = "/ok")
public String ok() {
    System.out.println("--FurnHandler-- ok()...");
    return "success";
}

interceptor.jsp添加标签

<a href="<%=request.getContextPath()%>/ok">测试自定义拦截器-ok</a>

在这里插入图片描述

3.拦截器需要配置才生效, 不配置是不生效的.

4.如果preHandler() 方法返回了false, 就不会执行目标方法(前提是你的目标方法被拦截了), 程序员可以在这里根据业务需要指定跳转页面.

Debug执行流程

1.prehandle()

在这里插入图片描述

在这里插入图片描述

2.目标方法
在这里插入图片描述

3.postHandle()
在这里插入图片描述
视图解析
在这里插入图片描述
一直点下一步
在这里插入图片描述

4.render()
在这里插入图片描述

5.afterCompletion()
在这里插入图片描述

解释一下model数据怎么来的? 用 postman 再走一圈

get请求
在这里插入图片描述
post请求
在这里插入图片描述

断点打到 preHandle

在这里插入图片描述

目标方法

在这里插入图片描述

postHandle

在这里插入图片描述

render

在这里插入图片描述

afterCompletion

在这里插入图片描述

多个拦截器

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

在这里插入图片描述

在这里插入图片描述

应用实例1

代码实现

1.com.zzw.web.interceptor.MyInterceptor02

@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.配置springDispathcerServlet-servlet.xml

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/h*"/>
        <mvc:exclude-mapping path="/hello"/>
        <ref bean="myInterceptor01"/>
    </mvc:interceptor>

    <!--解读
    1.配置的第二个拦截器
    2.多个拦截器在执行时, 是按照顺序执行的
    -->
    <mvc:interceptor>
        <mvc:mapping path="/h*"/>
        <ref bean="myInterceptor02"/>
    </mvc:interceptor>
</mvc:interceptors>

3.测试
–MyInterceptor01-- preHandle() 被执行…
–MyInterceptor02-- preHandle() 被执行…
–FurnHandler-- hi()…
–MyInterceptor02-- postHandle()被执行…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor02-- afterCompletion()被执行…
–MyInterceptor01-- afterCompletion()被执行…

注意事项和细节

1.如果第1个拦截器的preHandle()返回false, 后面都不执行
在这里插入图片描述

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

3.说明: 前面说的规则, 目标方法被拦截是前提

应用实例2

1.需求: 如果用户提交的数据有禁用词(比如 病毒). 则, 在第1个拦截器就返回, 不执行目标方法, 功能效果如图

2.web路径/WEB-INF/pages/warning.jsp

<head>
    <title>警告</title>
</head>
<body>
<h1>不要乱讲话</h1>
</body>

3.修改MyInterceptor01

@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)) {
        //请求转发到warning.jsp
        //这里是原生的请求转发, 不是springmvc里的
        request.getRequestDispatcher("/WEB-INF/pages/warning.jsp").forward(request, response);
        return false;
    }
    System.out.println("得到keyword=" + keyword);
    return true;
}

3.postman测试
在这里插入图片描述

–MyInterceptor01-- preHandle() 被执行…
得到keyword=赵志伟
–MyInterceptor02-- preHandle() 被执行…
–FurnHandler-- hi()…
–MyInterceptor02-- postHandle()被执行…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor02-- afterCompletion()被执行…
–MyInterceptor01-- afterCompletion()被执行…

再次测试
在这里插入图片描述

–MyInterceptor01-- preHandle() 被执行…

作业布置

1.把前面我们学过的SpringMVC文件上传, 自定义拦截器和相关代码和案例, 自己写一遍. 一定要自己写一遍, 否则没有印象, 理解不会深入
2.简述SpringMVC自定义拦截器工作流程, 并画出示意图
3.debug自定义拦截器源码, 加深理解(不用每一条语句都debug), 重点是梳理流程.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1834887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

汇编语言程序设计 - 新建一个文件:d:\abc.txt,从键盘输入文件的内容(不超过100个字符)

80x86汇编习题 题目描述&#xff1a;编写一个程序&#xff0c;新建一个文件&#xff1a;d:\abc.txt&#xff0c;从键盘输入文件的内容&#xff08;不超过100个字符&#xff09; 思路&#xff1a; 1&#xff0c;定义好文件名&#xff0c;记得末尾0 2&#xff0c;定义好缓冲区…

C#开发-集合使用和技巧(六)特殊转换方法SelectMany的介绍和用法

介绍 SelectMany 方法在C#中用于将集合中的元素转换为其他类型的集合&#xff0c;并将这些集合扁平化为一个单一的序列。它是LINQ的一部分&#xff0c;允许你在一个序列上进行投影和过滤操作&#xff0c;然后将结果合并成一个序列。 方法定义 public static IEnumerable<…

【Python机器学习实战】 | 基于决策树的药物研究分类预测

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

Python内置debug库: pdb用法详解

文章目录 0. 引言1. 基本用法1.1 设置断点1.2 通过命令行启动 pdb 2. 常用命令2.1 n (next)2.2 s (step)2.3 c (continue)2.4 l (list)2.5 p (print)2.6 h (help)2.7 b (break)2.8 cl (clear)2.9 q (quit) 3. 例子 0. 引言 pdb&#xff08;Python Debugger&#xff09;是Pytho…

【Redis】分布式锁基本理论与简单实现

目录 分布式锁解释作用特性实现方式MySQL、Redis、Zookeeper三种方式对比 原理 reids分布式锁原理目的容错redis简单分布式锁实现锁接口实现类下单场景的实现容错场景1解决思路优化代码 容错场景2Lua脚本Redis利用Lua脚本解决多条命令原子性问题 释放锁的业务流程Lua脚本来表示…

SpringMVC系列九: 数据格式化与验证及国际化

SpringMVC 数据格式化基本介绍基本数据类型和字符串自动转换应用实例-页面演示方式Postman完成测试 特殊数据类型和字符串自动转换应用实例-页面演示方式Postman完成测试 验证及国际化概述应用实例代码实现注意事项和使用细节 注解的结合使用先看一个问题解决问题 数据类型转换…

游泳耳机哪个牌子好性价比高?精选高性价比的四大游泳耳机!

在现代社会中&#xff0c;随着健身和水中运动的普及&#xff0c;游泳耳机作为一种关键的健身配件&#xff0c;正日益受到广泛关注和需求。无论是在游泳池畅游还是深潜海底&#xff0c;好的游泳耳机不仅能提供高品质的音乐享受&#xff0c;更能保护耳朵免受水压和湿润环境的侵害…

训练营第四十一天| 1035.不相交的线53. 最大子序和392.判断子序列115.不同的子序列

1035.不相交的线 力扣题目链接(opens new window) 我们在两条独立的水平线上按给定的顺序写下 A 和 B 中的整数。 现在&#xff0c;我们可以绘制一些连接两个数字 A[i] 和 B[j] 的直线&#xff0c;只要 A[i] B[j]&#xff0c;且我们绘制的直线不与任何其他连线&#xff08;…

线上扭蛋机小程序开发,潮玩时代的创新发展

随着互联网的发展&#xff0c;扭蛋机市场也进行了创新发展&#xff0c;线上扭蛋机小程序为市场带来了新活力。扭蛋机小程序将传统的模式与互联网结合&#xff0c;打造一个便捷有趣的扭蛋机市场。 一、扭蛋机小程序 在扭蛋机小程序上&#xff0c;用户通过扭蛋机抽取各种系列的…

实现锚点链接点击tab跳转到指定位置 并且滚动鼠标顶部锚点的样式也跟随变化

实现效果如下 不管是点击还是 滚动鼠标 顶部的样式也会跟随变化 点击会跳转到指定的位置 通过IntersectionObserver 监听是否可见 下面代码可以直接执行到vue的文件 <template><div><ul class"nav"><li v-for"tab in tabs" :key…

【Java】已解决Spring框架中的org.springframework.dao.DuplicateKeyException异常

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决Spring框架中的org.springframework.dao.DuplicateKeyException异常 一、问题背景 在使用Spring框架进行数据库操作时&#xff0c;有时会遇到org.springframework.dao.Duplicate…

HTML 全局属性介绍及示例

HTML 全局属性是一组可以在任何HTML元素中使用的属性。这些属性提供了一种方式来定义元素的通用行为或外观。以下是一些常见的HTML全局属性及其示例。 id id 属性为元素提供了一个唯一的标识符。它不能在 <head>, <html>, <meta>, <script>, <sty…

LearnOpenGL 及 ShaderToy 的 CMake 构建框架

文章目录 构建目标具体框架根目录src 目录app 目录import.cmake其他 CMake 函数 使用框架实际效果摄像机坐标变换使用 assimp 库加载模型shadertoy 测试 framebuffer 离屏渲染 其他 为了复习 OpenGL&#xff08;主要是看到 shadertoy 上有好玩的着色器&#xff09;&#xff0c;…

Python类的优势及应用场景深度分析(代码封装与组织、继承与代码复用、多态与接口、状态管理与行为封装)(python class)

文章目录 Python 类的优势及应用场景深度分析1. 代码封装与组织1.1 封装性示例代码&#xff1a;用户账户管理 1.2 组织性 2. 继承与代码复用2.1 继承性示例代码&#xff1a;员工管理系统 3. 多态与接口3.1 多态性示例代码&#xff1a;图形渲染 4. 状态管理与行为的封装4.1 状态…

记录一下 Chrome浏览器打印时崩溃问题

问题描述&#xff1a; 为了查看页面内存占用情况&#xff0c;按F2,打开Memory chrome浏览器点击“打印”按钮&#xff0c;或Ctrl P 时出现如下页面 一直以为是页面问题&#xff0c;每次打印的时候遇到这种 崩溃现象 就是重新刷新页面 但今天刚开一个页面&#xff0c;内存 …

微信小程序 - 出于性能原因,对长行跳过令牌化。长行的长度可通过 “editor.maxTokenizationLineLength” 进行配置

问题描述 出于性能原因&#xff0c;对长行跳过令牌化。长行的长度可通过 “editor.maxTokenizationLineLength” 进行配置。 解决方案 设置 - 编辑器设置 - 更多编辑器设置... 搜索&#xff1a;maxtoken&#xff0c;原来是 20000&#xff0c;我改成了 200000 即可~

电脑已删除的文件在回收站找不到怎么办?数据恢复办法分享!

电脑中的数据已经成为了我们生活和工作的重要部分。无论是珍贵的照片、重要的文档&#xff0c;还是日常的工作文件&#xff0c;我们都希望能够妥善保存很久。 然而&#xff0c;误删除文件的情况时有发生&#xff0c;而当我们急切地打开回收站试图找回这些文件时&#xff0c;却…

Bev感知:sparse query

文章目录 1. 显示Bev方法介绍1.1 2D to 3D: LSS-based1.1.1 优点1.1.2 缺点1.2. 3D to 2D: BevFormer1.2.1 缺点1.2.2优点1.3 常见的Bev感知的问题2. Sparse query2.1 PETRv1创新点3D 位置编码实验对比2.2 PETRv22.2.1 时序对齐2.2.2 Feature guided 3D PE2.2.3 多任务2.2.3 性…

功能测试的内容与目的是什么?

在软件开发与测试过程中&#xff0c;功能测试是不可或缺的关键步骤&#xff0c;它主要关注软件产品是否能够按照设计规格和用户需求实现预定的功能。功能测试的内容与目的&#xff0c;简单来讲&#xff0c;就是验证软件的各种特性和功能是否正确、完整且符合预期&#xff0c;确…

【C#】汽车租赁系统设计与实现

目的&#xff1a; 设计一个简单的汽车租赁系统&#xff0c;包含以下功能&#xff1a; 添加车辆&#xff1a;用户可以添加新的车辆到系统中&#xff0c;包括车辆的品牌、型号、车牌号、日租金等信息。查找车辆&#xff1a;用户可以通过车牌号或者品牌来查找车辆&#xff0c;并…