【Spring】Spring哪些源码解决了哪些问题P1

欢迎来到啾啾的博客🐱。
记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。
有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。

目录

  • Spring是怎么处理请求的?
    • Spring请求方法参数与返回怎么处理?
    • Spring如何自定义 JSON 的序列化/反序列化行为
  • Spring是怎么处理事务的?
  • Spring Boot的“约定大于配置”是如何实现的?
  • Spring Boot的自动配置是如何发生的?

Spring是怎么处理请求的?

对处理请求感兴趣的可以看之前的这篇Spring的请求处理

Spring请求方法参数与返回怎么处理?

请求方法中的参数,特别是 @RequestBody 标记的对象是怎么处理的呢?之前的请求篇有提及请求处理,但是没有提及参数,这里补充一下。
在RequestMappingHandlerAdapter调用方法前,它会遍历方法的参数,为每个参数找到合适的HandlerMethodArgumentResolver来解析参数值。
对于标记了@RequestBody的参数,则使用RequestResponseBodyMethodProcessor
RequestResponseBodyMethodProcessor在解析@RequestBody参数时,会从HttpServletRequest中获取输入流,然后遍历注册的HttpMessageConverter列表,找到一个能处理请求Content-Type(如application/json)并且能将输入流转换为目标参数类型的转换器。MappingJackson2HttpMessageConverter就是利用Jackson库将JSON字符串反序列化为Java对象。
![[【Spring】Spring哪些源码解决了哪些问题.png]]

Spring如何自定义 JSON 的序列化/反序列化行为

所以,如果需要自定义 JSON 的序列化/反序列化行为(比如日期格式、null值的处理),我们可以从Jackson2ObjectMapperBuilder / ObjectMapper入手。
Spring Boot 自动配置MappingJackson2HttpMessageConverter时,会使用Jackson2ObjectMapperBuilder来构建底层的ObjectMapper。
可以自定义一个Jackson2ObjectMapperBuilderCustomizer Bean,从而可以对Spring Boot创建的ObjectMapper进行细粒度调整,而不用完全替换它。


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; // 如果需要排序import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;@Configuration
public class JacksonCustomizerConfig {private static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";private static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";@Beanpublic Jackson2ObjectMapperBuilderCustomizer customJackson() {return builder -> {// --- 通用配置 ---// 1. 时区配置:序列化和反序列化日期时都使用指定时区//   注意:更推荐在Java对象中使用带时区的类型(如ZonedDateTime),或在DTO转换时处理builder.timeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 或 TimeZone.getDefault()// 2. Null值处理:序列化时,null值的字段不参与序列化builder.serializationInclusion(JsonInclude.Include.NON_NULL);// 其他选项:// JsonInclude.Include.ALWAYS (默认)// JsonInclude.Include.NON_EMPTY (null或空集合、空字符串等不序列化)// JsonInclude.Include.NON_DEFAULT (如果字段值等于其默认值,则不序列化)// 3. 反序列化特性:JSON中有多余的未知字段时,不报错,而是忽略builder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);// 如果想开启,则用 featuresToEnable// 4. 序列化特性:对于只有一个元素的数组,序列化时不作为数组,而是作为单个对象(谨慎使用)// builder.featuresToEnable(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED);// 反之,如果想禁用,则用 featuresToDisable// 5. 序列化特性:日期序列化为时间戳(ms)还是ISO 8601格式字符串//   Spring Boot 默认对于Java 8 Date/Time API是序列化为ISO字符串,//   对于 java.util.Date 是序列化为时间戳。//   禁用时间戳,强制使用ISO格式(或你自定义的格式)builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);// 6. 序列化特性:对于空对象(没有任何字段或getter),序列化时不抛出异常builder.featuresToDisable(SerializationFeature.FAIL_ON_EMPTY_BEANS);// 7. Mapper特性:枚举值使用toString()方法进行序列化/反序列化// builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);// builder.featuresToEnable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);// 8. Mapper特性:反序列化枚举时忽略大小写builder.featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);// --- Java 8 日期时间 API (java.time.*) 格式化 ---// Spring Boot 默认会通过 jackson-datatype-jsr310 模块支持Java 8日期时间类型// 以下是更细致的格式化配置JavaTimeModule javaTimeModule = new JavaTimeModule();// LocalDateTimejavaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));// LocalDatejavaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));// LocalTimejavaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));builder.modulesToInstall(javaTimeModule); // 注册自定义配置的JavaTimeModule// 或者 builder.modules(javaTimeModule); 效果类似,modules会替换现有模块,modulesToInstall会添加// --- 传统日期 (java.util.Date) 格式化 ---// 如果你还在使用 java.util.Date,可以这样配置builder.simpleDateFormat(DEFAULT_DATE_TIME_FORMAT);// --- 其他类型的自定义序列化器/反序列化器 ---// 例如,将Long、BigInteger序列化为字符串,以防止前端JS精度丢失问题builder.serializerByType(Long.class, ToStringSerializer.instance);builder.serializerByType(Long.TYPE, ToStringSerializer.instance); // long基本类型builder.serializerByType(BigInteger.class, ToStringSerializer.instance);// 你还可以添加自定义的序列化器和反序列化器// builder.serializerByType(YourCustomClass.class, new YourCustomSerializer());// builder.deserializerByType(YourCustomClass.class, new YourCustomDeserializer());};}// 如果有多个Customizer,可以使用@Order指定顺序// @Bean// @Order(Ordered.HIGHEST_PRECEDENCE)// public Jackson2ObjectMapperBuilderCustomizer anotherCustomJackson() {//     return builder -> {//         // ...//     };// }
}

Spring是怎么处理事务的?

可以看这篇Spring事务全面解析。

Spring Boot的“约定大于配置”是如何实现的?

Spring Boot 的“约定大于配置”(Convention over Configuration)是一种设计理念,旨在减少开发人员需要做出的决策数量,从而简化开发流程、提高开发效率。

其通过Starters引入一组完成特定功能所需的经过测试和版本兼容的依赖,Starters里面会包含默认bean。

通过自动配置,Spring Boot 会在 classpath 中查找特定的库,并根据找到的库来自动配置你的应用程序。条件化配置@ConditionalOn…在其中发挥了重要作用。
SPI 机制 (通过 spring.factories 或Spring Boot 2.7+ 及 3.x+开始的新的 .imports 文件) 是自动配置用来发现和加载候选配置类的重要手段。Spring Boot 读取这些文件,找到所有潜在的自动配置类,然后通过条件注解(@ConditionalOn…)来决定哪些配置实际生效。

还有就是配置项的合理默认值。Spring Boot 为许多配置项提供了合理的默认值。例如:

  • 内嵌 Tomcat 服务器默认监听 8080 端口。
  • 静态资源默认从 classpath:/static/, classpath:/public/, classpath:/resources/, classpath:/META-INF/resources/ 等路径提供。
  • 日志默认使用 Logback,并配置了控制台输出。

Spring Boot的自动配置是如何发生的?

SpringBoot的启动注解@SpringBootApplication是一个复合注解,其包含@EnableAutoConfiguration。
@EnableAutoConfiguration它通过 @Import(AutoConfigurationImportSelector.class) 导入了一个特殊的 ImportSelector。
![[【Spring】Spring哪些源码解决了哪些问题-2.png]]

AutoConfigurationImportSelector的核心方法是selectImports。selectImports的主要职责是:

  • 收集候选的自动配置类 (Candidate Configurations):
    • 它会去扫描classpath下所有jar包中的 META-INF/spring.factories 文件 (Spring Boot 2.7以前) 或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件 (Spring Boot 2.7+及3.x)。
    • 这些文件列出了所有可用的自动配置类的全限定名,以 org.springframework.boot.autoconfigure.EnableAutoConfiguration 为key。
    • 例如,spring-boot-autoconfigure.jar 中的 spring.factories 文件包含了大量的自动配置类,如 DataSourceAutoConfiguration, WebMvcAutoConfiguration, JacksonAutoConfiguration 等。

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

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

相关文章

坚持每日Codeforces三题挑战:Day 4 - 题目详解(2025-06-07,难度:1000, 1100, 1400)

前言: 此文章主要是记录每天的codeforces刷题,还有就是给其他打算法竞赛的人一点点点点小小的帮助(毕竟现在实力比较菜,题目比较简单,但我还是会认真写题解)。 之前忙学校事情,懈怠了一段时间…

6.7本日总结

一、英语 复习默写list10list19,07年第3篇阅读 二、数学 学习线代第一讲,写15讲课后题 三、408 学习计组第二章,写计组习题 四、总结 本周结束线代第一讲和计组第二章,之后学习计网4.4,学完计网4.4之后开操作系…

PGSR : 基于平面的高斯溅射高保真表面重建【全流程分析与测试!】【2025最新版!!】

【PGSR】: 基于平面的高斯溅射高保真表面重建 前言 三维表面重建是计算机视觉和计算机图形学领域的核心问题之一。随着Neural Radiance Fields (NeRF)和3D Gaussian Splatting (3DGS)技术的发展,从多视角RGB图像重建高质量三维表面成为了研究热点。今天我们要深入…

从认识AI开始-----AutoEncoder:生成模型的起点

前言 从15年开始,在深度学习的重要模型中,AutoEncoder(自编码器)可以说是打开生成模型世界的起点。它不仅是压缩与重建的工具,更是VAE、GAN、DIffusion等复杂生成模型的思想起源。其实AutoEncoder并不复杂,…

解决MySQL8.4报错ERROR 1524 (HY000): Plugin ‘mysql_native_password‘ is not loaded

最近使用了MySQL8.4 , 服务启动成功,但是就是无法登陆,并且报错: ERROR 1524 (HY000): Plugin mysql_native_password is not loaded 使用如下的命令也报错 mysql -u root -p -P 3306 问题分析: 在MySQL 8.0版本中,默认的认证插件从mysql_native_password变更为cachi…

TDengine 开发指南——无模式写入

简介 在物联网应用中,为了实现自动化管理、业务分析和设备监控等多种功能,通常需要采集大量的数据项。然而,由于应用逻辑的版本升级和设备自身的硬件调整等原因,数据采集项可能会频繁发生变化。为了应对这种挑战,TDen…

嵌入式面试高频(5)!!!C++语言(嵌入式八股文,嵌入式面经)

一、C有几种传值方式之间的区别 一、值传递(Pass by Value) 机制:创建参数的副本,函数内操作不影响原始数据语法:void func(int x)特点: 数据安全:原始数据不受影响性能开销:需要复…

Spark 之 AQE

个人其他链接 AQE 执行顺序https://blog.csdn.net/zhixingheyi_tian/article/details/125112793 AQE 产生 AQE 的 循环触发点 src/main/scala/org/apache/spark/sql/execution/adaptive/AdaptiveSparkPlanExec.scala override def doExecute(): RDD[InternalRow] = {withFin…

FSMC扩展外部SRAM

提示:文章 文章目录 前言一、背景二、2.12.2 三、3.1 总结 前言 前期疑问: 本文目标: 一、背景 2025年6月7日 19:34:48 今天看了FSMC扩展外部SRAM的文章,大概理解到stm32除了内部存储器,还可以扩展外部存储器。其中s…

【CSS-6】深入理解CSS复合选择器:提升样式表的精确性与效率

CSS选择器是前端开发的基石,而复合选择器则是其中最强大且实用的工具之一。本文将全面解析CSS复合选择器的类型、用法、优先级规则以及最佳实践,帮助你编写更高效、更精确的样式表。 1. 什么是复合选择器? 复合选择器是通过组合多个简单选择…

使用python实现奔跑的线条效果

效果,展示(视频效果展示): 奔跑的线条 from turtle import * import time t1Turtle() t2Turtle() t3Turtle() t1.hideturtle() t2.hideturtle() t3.hideturtle() t1.pencolor("red") t2.pencolor("green") t3…

从零搭建uniapp项目

目录 创建uni-app项目 基础架构 安装 uni-ui 组件库 安装sass依赖 easycom配置组件自动导入 配置view等标签高亮声明 配置uni-ui组件类型声明 解决 标签 错误 关于tsconfig.json中提示报错 关于非原生标签错误(看运气) 安装 uview-plus 组件库…

Redis主从复制的原理一 之 概述

概述 本文概要性的介绍了Redis主从复制原理,及新旧版本主从复制的区别,优缺点。具体的主从复制过程可详见「Redis主从复制原理二 之 主从复制工作流程」 旧版主从复制的实现 Redis的复制功能分为 同步(sync)和 命令传播&#xff…

网络原理 4-TCP3

上篇文章,我们讲了TCP协议的连接管理(”三次握手“和”四次挥手“的过程)。 4、滑动窗口 这个滑动窗口是TCP中非常有特点的机制。我们知道,TCP是通过前面讲的三个机制:确认应答,超时重传,连接…

【使用 Loki + Promtail + Grafana 搭建轻量级容器日志分析平台】

使用 Loki Promtail Grafana 搭建轻量级容器日志分析平台 摘要 本文介绍如何通过 Docker Compose 快速搭建 Loki 日志存储、Promtail 日志采集和 Grafana 日志可视化/告警的完整流程。用最小化示例演示核心配置、常见问题排查和告警规则设置,帮助读者快速上手。…

CRMEB 中 PHP 快递查询扩展实现:涵盖一号通、阿里云、腾讯云

目前已有一号通快递查询、阿里云快递查询扩展 扩展入口文件 文件目录 crmeb\services\express\Express.php 默认一号通快递查询 namespace crmeb\services\express;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use think\Container; use thi…

使用 Python 自动化 Word 文档样式复制与内容生成

在办公自动化领域,如何高效地处理 Word 文档的样式和内容复制是一个常见需求。本文将通过一个完整的代码示例,展示如何利用 Python 的 python-docx 库实现 Word 文档样式的深度复制 和 动态内容生成,并结合知识库中的最佳实践优化文档处理流程…

【MATLAB代码】基于MCC(最大相关熵)的EKF,一维滤波,用于解决观测噪声的异常|附完整代码,订阅专栏后可直接查看

本文所述的代码实现了一种基于最大相关熵准则(Maximum Correntropy Criterion, MCC)的鲁棒性卡尔曼滤波算法(MCC-KF),重点解决传统卡尔曼滤波在观测噪声存在异常值时估计精度下降的问题。通过引入高斯核函数对残差进行加权处理,有效降低了异常观测值对状态估计的干扰。订…

46、web实验-遍历数据与页面bug修改

46、web实验-遍历数据与页面bug修改 在Web开发中,遍历数据和修改页面bug是常见的任务。以下是关于这两个主题的讲解: ### 一、遍历数据 **目的**:在页面上动态展示数据,例如用户列表、商品信息等。 **常用方法**: ####…

华为云Flexus+DeepSeek征文|体验华为云ModelArts快速搭建Dify-LLM应用开发平台并创建自己的自定义聊天助手

华为云FlexusDeepSeek征文|体验华为云ModelArts快速搭建Dify-LLM应用开发平台并创建自己的自定义聊天助手 什么是华为云ModelArts 华为云ModelArts ModelArts是华为云提供的全流程AI开发平台,覆盖从数据准备到模型部署的全生命周期管理,帮助…