算不上最全,但都是必备——Spring MVC这些不会不行啊

news2024/11/19 17:22:43

Spring MVC篇

Spring MVC执行流程

四大组件

  • 前端控制器DispatcherServlet
  • 处理器映射器HandlerMapping
  • 处理器适配器HandlerAdaptor
  • 视图解析器ViewResolver

视图阶段(JSP)

  1. 请求先到前端控制器DispatcherServlet

  2. DispatcherServlet将根据该请求的路径去处理器映射器HandlerMapping查handler(controller的一个方法)

  3. 映射器HandlerMapping找到后返回一个处理器执行链HandlerExecutionChain对象(封装了handler + 可能存在的拦截器链)

  4. 如果没有拦截器,DispatcherServlet通过该处理器执行链对象发请求给处理器适配器HandlerAdaptor调用处理器Handler

    为什么不直接发请求给处理器Handler,而是要走个处理器适配器HandlerAdaptor再转发给它呢?

      你的请求参数被接口接收有多种方式吧?(restful风格接收、参数位直接接收...)这里主要就是通过处理器适配器中一些处理参数的类型转换器,你的方法才能正常的接收这些参数。 你的返回值也多种形式吧?(String、MoudleAndView....),这些的返回值数据的转换也要靠处理器适配器中一些处理返回值的类型转换器来实现。
  5. 处理器响应数据给处理器适配器,它转换后返回个MoudleAndView给前端控制器

  6. 前端控制器拿着这个MoudleAndView找视图解析器ViewResolver去把逻辑视图转换为真正视图,返回个视图对象View给前端控制器

  7. 前端控制器就拿着这个视图对象去渲染视图JSP给前端页面

image.png

前后端分离阶段 (接口开发,异步请求)

  1. 请求先到前端控制器DispatcherServlet
  2. DispatcherServlet将根据该请求的路径去处理器映射器HandlerMapping查handler(controller的一个方法)
  3. 映射器HandlerMapping找到后返回一个处理器执行链HandlerExecutionChain对象(封装了handler + 可能存在的拦截器链)
  4. 如果没有拦截器,DispatcherServlet通过该处理器执行链对象发请求给处理器适配器HandlerAdaptor调用处理器Handler
  5. 如果这个方法是添加了@ResponseBody注解,则通过HttpMessageConverter来返回结果转换为JSON并响应
  6. 如果这个方法没有添加该注解,视图解析器来拼接视图前后缀到返回数据上,然后到/resources/static下找到对应的静态资源丢给视图解析器,解析到实际的视图对象后,DispatcherServlet 将结果数据传递给视图对象,视图对象负责将数据渲染成最终的响应内容。视图对象渲染完成后,DispatcherServlet 将响应返回给前端

image.png


过滤器和拦截器的区别

相同点

  • 拦截器与过滤器都是体现了AOP的思想,对方法实现增强,都可以拦截请求方法。
  • 拦截器和过滤器都可以通过Order注解设定执行顺序

不同点

  • 过滤器是在 Servlet 容器接收到请求之后,但在 Servlet被调用之前运行的;而拦截器则是在 Servlet 被调用之后,但在响应被发送到客户端之前运行的。

image.png

  • 过滤器是运行在Web服务器和Servlet容器之间的组件,可以拦截所有进出该容器的请求和响应;而拦截器则是针对具体的控制器方法进行拦截处理的,只在控制器内部执行。

  • 过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。

  • 过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用;拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。

  • 过滤器主要用于对请求进行预处理和过滤,例如设置字符集、登录验证、日志记录等操作;而拦截器则主要用于对请求进行流程控制,例如权限验证、参数注入、异常处理等操作。


Spring MVC的异常处理

在 Spring MVC 中,异常处理可以通过以下几种方式来实现:

  1. 异常处理器(ExceptionHandler)注解:通过在 Controller 类中的方法上添加 @ExceptionHandler 注解来指定要处理的异常。当抛出该类型的异常时,会夹带异常信息调用对应的异常处理方法。

@RestControllerAdvice
public class AGlobalExceptionHandlerController extends ABaseController {
 
    @ExceptionHandler(value = Exception.class)
    Object handleException(Exception e, HttpServletRequest request) {
        logger.error("请求错误,请求地址{},错误信息:", request.getRequestURL(), e);
        ResponseVO ajaxResponse = new ResponseVO();
        xxxxx设置一大堆要发给前端展示的消息到这个封装类ResponseVO中返给前端。XXXXXX
        return ajaxResponse;
    }
}
  1. 异常处理器接口(HandlerExceptionResolver) :可以自定义实现 HandlerExceptionResolver 接口来定义异常处理器。该接口允许实现多个异常处理器,在异常发生时根据优先级选择合适的处理器。

  2. 异常映射(@ResponseStatus)注解: 使用 @ResponseStatus 注解可以将特定异常映射到指定的HTTP响应状态码或自定义的错误页面。当抛出该异常时,会根据注解中的配置来进行相应的处理。

业务进行流程:

  1. 后端出现异常
  2. 抛出自定义异常
  3. 异常处理器@Exceptional捕获到该异常信息
  4. 执行异常处理器中自定义的方法
  5. 将捕捉到的自定义异常中的友好提示信息及其相关的响应码设置到统一的响应类对象中进行响应
  6. 前端接收到响应数据,提取响应信息用于展示给用户

全局异常处理业务搭建


SpringMvc的Controller是不是单例模式?

Spring MVC 的 Controller 默认是单例模式的。这意味着在应用程序的整个生命周期内,只会创建一个 Controller 实例,并且该实例会被多个请求共享。这样做的好处是可以减少对象创建和销毁的开销,提高性能。

然而需要注意的是,由于 Controller 是单例的,所以它必须是无状态的,不应该包含任何可以改变状态的成员变量。如果需要在 Controller 中保存状态,可以使用作用域为请求的成员变量或者使用其他方式来管理状态,比如使用 Session 或者数据库。

当然,如果需要每次请求都创建新的 Controller 实例,可以使用 @Scope 注解来设置为原型模式(Prototype),这样每次请求都会创建一个新的实例。


SpringMVC 用什么对象从后台向前台传递数据的?

不使用@responseBody / @RestController注解修饰

从后台向前台传递数据使用的是 ModelAndView 对象。ModelAndView 对象包含了数据模型(Model)和视图(View),其中数据模型是一个 Map 类型的对象,用于存储后台数据,而视图则是要展示数据的页面。

使用@responseBody / @RestController注解修饰

在使用 @ResponseBody 后,Spring 会自动将返回值转换为特定的格式,例如 JSON、XML 等,然后将其写入 HTTP 响应。需要注意的是,如果采用了 @ResponseBody,则需要使用 Jackson 库或其他类库来进行序列化(JSON 转换)。Spring 默认使用 Jackson 序列化 JSON 数据,如果需要使用其他序列化类库,可以在 Spring 配置文件中进行配置。


Spring MVC 拦截器

拦截器则主要用于对请求进行流程控制,例如权限验证、参数注入、异常处理等操作。

image.png

拦截器 Interceptor 定义

拦截器不仅可以在处理器之前执行,还可以在处理器之后执行。先看拦截器 Interceptor 在 Spring MVC 中的定义。

public interface HandlerInterceptor {
​
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
​
        return true;
    }
​
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                            @Nullable ModelAndView modelAndView) throws Exception {
    }
​
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                 @Nullable Exception ex) throws Exception {
    }   
}

在这里插入图片描述

前后端分离之后,Spring MVC 中的处理器方法执行后通常不会再返回视图,而是返回表示 json 或 xml 的对象,@Controller 方法返回值类型如果为 ResponseEntity 或标注了 @ResponseBody 注解,此时处理器方法一旦执行结束,Spring会将返回值转换为 json 或 xml,然后写入响应,后续也不会进行视图渲染,这时postHandle 将没有机会修改响应体内容。

如果需要更改响应内容,可以定义一个实现 ResponseBodyAdvice 接口的类,然后将这个类直接定义到 RequestMappingHandlerAdapter 中的 requestResponseBodyAdvice 或通过 @ControllerAdvice 注解添加到 RequestMappingHandlerAdapter。

拦截器配置

  • 自定义拦截器类,实现HandlerInterceptor 接口和Ordered接口
  • 自定义的拦截器选择性重写三大函数,重写顺序函数
  • 注册为Bean
  • 实现WebMvcConfigurer接口,注册自定义的拦截器
public class LoginInterceptor implements HandlerInterceptor, Ordered {
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("已登录");
        return true;
    }
​
    @Override
    public int getOrder() {
        return 2;
    }
}
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LogInterceptor());
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login");
    }
}
@Configuration
public class MvcConfig {
​
    @Order(2)
    @Bean
    public MappedInterceptor loginInterceptor() {
        return new MappedInterceptor(new String[]{"/**"}, new String[]{"/login"}, new LoginInterceptor());
    }
    
    @Order(1)
    @Bean
    public MappedInterceptor logInterceptor() {
        return new MappedInterceptor(null, new LoginInterceptor());
    }
}

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

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

相关文章

理解 R-CNN:目标检测的一场革命

一、介绍 对象检测是一项基本的计算机视觉任务,涉及定位和识别图像或视频中的对象。多年来,人们开发了多种方法来应对这一挑战,但基于区域的卷积神经网络(R-CNN)的发展标志着目标检测领域的重大突破。R-CNN 及其后续变…

深入探讨Linux中的文本文件查看命令

目录 前言1 cat命令2 less命令3 more命令4 head命令5 tail命令6 总结 前言 在Linux系统中,文本文件是日常工作中不可或缺的一部分,无论是配置文件、日志文件还是代码文件,都需要用到文本文件查看命令。在本文中,我们将深入研究一…

【深度学习】吴恩达课程笔记(四)——优化算法

笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ 【吴恩达课程笔记专栏】 【深度学习】吴恩达课程笔记(一)——深度学习概论、神经网络基础 【深度学习】吴恩达课程笔记(二)——浅层神经网络、深层神经网络 【深度学习】吴恩达课程笔记(三)——参数VS超参数、深度…

如何从 iCloud 恢复永久删除的照片?答案在这里!

在数字时代,丢失珍贵的照片可能会令人痛苦。然而,了解如何从 iCloud 恢复永久删除的照片可以带来一线希望。无论是意外删除还是技术故障,本指南都提供了 2023 年的最新方法来找回您的珍贵记忆。发现分步解决方案并轻松重新访问您的照片库。不…

智能供应链中的预测算法:理论与实践

💂 个人网站:【工具大全】【游戏大全】【神级源码资源网】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 引言 智能供应链已经成…

制作属于你的视觉小说,ComfyUI工作流#N3期AIGC训练营

什么是视觉小说? Visual Novel 最初这种形式被称为“有声小说” 视觉小说是一种源自日本的电子游戏类型,它以图像和文本为主要表现形式,通常包含大量的对话和故事情节。 (大量对话) 在视觉小说中,玩家可以通…

AJAX入门Day01笔记

Day01_Ajax入门 知识点自测 如下对象取值的方式哪个正确? let obj {name: 黑马 }A: obj.a B: obj()a 答案 A选项正确 哪个赋值会让浏览器解析成标签显示? let ul document.querySelector(#ul) let str <span>我是span标签</span>A: ul.innerText str B: ul…

HTML+CSS+JavaScript实战(一个简易的视频播放器)

效果如下&#xff1a; 思路很常规&#xff0c;无需注释即可看懂&#xff08;其实是懒得敲 bushi&#xff09; 没有注释也能跑&#xff0c;so直接上源码~ 感谢 夏柔站长 提供的免费API index.html <!DOCTYPE html> <html lang"en"> <head><meta …

UE4动作游戏实例RPG Action解析三:实现效果,三连击Combo,射线检测,显示血条,火球术

一、三连Combo 实现武器三连击,要求: 1.下一段Combo可以随机选择, 2.在一定的时机才能再次检测输入 3. 等当前片段播放完才播放下一片段 1.1、蒙太奇设置 通过右键-新建蒙太奇片段,在蒙太奇里创建三个片段,并且移除相关连接,这样默认只会播放第一个片段 不同片段播…

一分钟搞懂什么是this指针(未涉及静态成员和函数)

前言 我们在学习类的过程中&#xff0c;一定听说过this指针&#xff0c;但是并不知道它跟谁相似&#xff0c;又有什么用途&#xff0c;所以接下来&#xff0c;让我们一起去学习this指针吧&#xff01; 一、this指针的引入 我们先来看下面两段代码&#xff0c;它们输出的是什么&…

Rust实战教程:构建您的第一个应用

大家好&#xff01;我是lincyang。 今天&#xff0c;我们将一起动手实践&#xff0c;通过构建一个简单的Rust应用来深入理解这门语言。 我们的项目是一个命令行文本文件分析器&#xff0c;它不仅能读取和显示文件内容&#xff0c;还会提供一些基础的文本分析&#xff0c;如计算…

C# Onnx 轻量实时的M-LSD直线检测

目录 介绍 效果 效果1 效果2 效果3 效果4 模型信息 项目 代码 下载 其他 介绍 github地址&#xff1a;https://github.com/navervision/mlsd M-LSD: Towards Light-weight and Real-time Line Segment Detection Official Tensorflow implementation of "M-…

什么是Vue.js中的单向数据流(one-way data flow)?为什么它重要?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

【QT系列教程】之二创建项目和helloworld案例

文章目录 一、QT创建项目1.1、创建项目1.2、选择创建项目属性1.3、选择路径和项目名称1.4、选择构建项目类型1.5、布局方式1.6、翻译文件&#xff0c;根据自己需求选择1.7、选择套件1.8、项目管理&#xff0c;自行配置1.9、配置完成&#xff0c;系统自动更新配置 二、QT界面介绍…

图论16-拓扑排序

文章目录 1 拓扑排序2 拓扑排序的普通实现2.1 算法实现 - 度数为0入队列2.2 拓扑排序中的环检测 3 深度优先遍历的后续遍历3.1 使用环检测类先判断是否有环3.2 调用无向图的深度优先后续遍历方法&#xff0c;进行DFS 1 拓扑排序 对一个有向无环图G进行拓扑排序&#xff0c;是将…

守护 C 盘,Python 相关库设置

前言 pip 安装依赖和 conda 创建环境有多方便&#xff0c;那 C 盘就塞得就有多满。以前我不管使用什么工具&#xff0c;最多就设置个安装位置&#xff0c;其他都是默认。直到最近 C 盘飙红了&#xff0c;我去盘符里的 AppData 里一看&#xff0c;pip 的缓存和 conda 以前创建的…

2023年咨询实务速记突破【专题总结】

需要完整资料的可以联系我获取

matlab语言的由来与发展历程

MATLAB语言的由来可以追溯到1970年代后期。当时&#xff0c;Cleve Moler教授在New Mexico大学计算机系担任系主任&#xff0c;他为了LINPACK和EISPACK两个FORTRAN程序集开发项目提供易学、易用、易改且易交互的矩阵软件而形成了最初的MATLAB。 1984年&#xff0c;MATLAB推出了…

模拟接口数据之使用Mock方法实现(vite)

文章目录 前言一、安装依赖mockjs 安装vite-plugin-mock 安装新增mock脚本 二、vite插件配置vite-plugin-mockvite.config.ts 引入vite-plugin-mock 三、新建mock数据新建mock目录env目录新建.env.mock文件 四、使用mock数据定义接口调用接口 如有启发&#xff0c;可点赞收藏哟…

java 中arrayList 中去除重复项

ArrayList 中去除重复对象 Testpublic void removeRepeatItem() {ArrayList<String> arrayList new ArrayList<>();arrayList.add("apple");arrayList.add("banbana");arrayList.add("apple");arrayList.add("apple");S…