Spring中的ConversionService,为Spring提供数据转换服务

在Spring中经常需要各种数据类型之间进行转换,比如配置文件中的数据转换为代码所需要的数据类型,在使用SpringMvc的时候,将前台传来的参数自动转换为我们接收参数时定义的类型。

Spring中的ConversionService就是提供这种服务的

1.DefaultConversionService

DefaultConversionService是一种默认的实现,如果我们不定义,就是使用默认的
@Test
public void defaultConversionService(){ConversionService conversionService = new DefaultConversionService();//这里是校验这个DefaultConversionService是否支持将String转换为Integerboolean b = conversionService.canConvert(String.class, Integer.class);System.out.println(b);Long convert = conversionService.convert("123", Long.class);System.out.println(convert);String convert1 = conversionService.convert(new Date() , String.class);System.out.println(convert1);Date convert2 = conversionService.convert("Mon Nov 04 23:32:14 CST 2024" , Date.class);System.out.println(convert2);}运行结果:
true
123
Tue Nov 05 11:02:17 CST 2024
Tue Nov 05 13:32:14 CST 2024

我们可以看到这里DefaultConversionService 可以成功的将 String转换为Long,将Date转换为String,将String转换为Date

为什么DefaultConversionService能支持这么多数据类型之间的相互转换呢,我们看看他的源码就知道了,原来在DefaultConversionService构造方法中就调用addDefaultConverters()方法注册了我们常用的数据类型转换器Converter,如果我们需要转换的时候,它就会找一个能够完成转换的Converter进行转换

public class DefaultConversionService extends GenericConversionService {@Nullableprivate static volatile DefaultConversionService sharedInstance;/*** Create a new {@code DefaultConversionService} with the set of* {@linkplain DefaultConversionService#addDefaultConverters(ConverterRegistry) default converters}.*/public DefaultConversionService() {addDefaultConverters(this);}/*** Return a shared default {@code ConversionService} instance,* lazily building it once needed.* <p><b>NOTE:</b> We highly recommend constructing individual* {@code ConversionService} instances for customization purposes.* This accessor is only meant as a fallback for code paths which* need simple type coercion but cannot access a longer-lived* {@code ConversionService} instance any other way.* @return the shared {@code ConversionService} instance (never {@code null})* @since 4.3.5*/public static ConversionService getSharedInstance() {DefaultConversionService cs = sharedInstance;if (cs == null) {synchronized (DefaultConversionService.class) {cs = sharedInstance;if (cs == null) {cs = new DefaultConversionService();sharedInstance = cs;}}}return cs;}/*** Add converters appropriate for most environments.* @param converterRegistry the registry of converters to add to* (must also be castable to ConversionService, e.g. being a {@link ConfigurableConversionService})* @throws ClassCastException if the given ConverterRegistry could not be cast to a ConversionService*/public static void addDefaultConverters(ConverterRegistry converterRegistry) {addScalarConverters(converterRegistry);addCollectionConverters(converterRegistry);converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));converterRegistry.addConverter(new StringToTimeZoneConverter());converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());converterRegistry.addConverter(new ObjectToObjectConverter());converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));converterRegistry.addConverter(new FallbackObjectToStringConverter());converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));}/*** Add common collection converters.* @param converterRegistry the registry of converters to add to* (must also be castable to ConversionService, e.g. being a {@link ConfigurableConversionService})* @throws ClassCastException if the given ConverterRegistry could not be cast to a ConversionService* @since 4.2.3*/public static void addCollectionConverters(ConverterRegistry converterRegistry) {ConversionService conversionService = (ConversionService) converterRegistry;converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));converterRegistry.addConverter(new MapToMapConverter(conversionService));converterRegistry.addConverter(new ArrayToStringConverter(conversionService));converterRegistry.addConverter(new StringToArrayConverter(conversionService));converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));converterRegistry.addConverter(new CollectionToStringConverter(conversionService));converterRegistry.addConverter(new StringToCollectionConverter(conversionService));converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));converterRegistry.addConverter(new StreamConverter(conversionService));}private static void addScalarConverters(ConverterRegistry converterRegistry) {converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());converterRegistry.addConverterFactory(new StringToNumberConverterFactory());converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());converterRegistry.addConverter(new StringToCharacterConverter());converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());converterRegistry.addConverter(new NumberToCharacterConverter());converterRegistry.addConverterFactory(new CharacterToNumberFactory());converterRegistry.addConverter(new StringToBooleanConverter());converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());converterRegistry.addConverterFactory(new StringToEnumConverterFactory());converterRegistry.addConverter(new EnumToStringConverter((ConversionService) converterRegistry));converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService) converterRegistry));converterRegistry.addConverter(new StringToLocaleConverter());converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());converterRegistry.addConverter(new StringToCharsetConverter());converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());converterRegistry.addConverter(new StringToCurrencyConverter());converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());converterRegistry.addConverter(new StringToPropertiesConverter());converterRegistry.addConverter(new PropertiesToStringConverter());converterRegistry.addConverter(new StringToUUIDConverter());converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());}}

2.DefaultFormattingConversionService

有的时候我们需要将某一种数据类型转换为指定的字符串格式,也需要将指定格式的字符串转换为某一种数据类型,比如我们需要将Date转为为yyyy-MM-dd格式的字符串。我们在配置文件配置yyyy-MM-dd 格式的字符串,需要将其转换为Date类型的数据。在SpringMvc将数据返回给前端之前我们可能需要将Person类型的数据转换为JSON格式的字符串

这个时候我们就需要DefaultFormattingConversionService,它在完成数据类型转换的同时还支持将某种数据类型转换为指定格式的字符串,而且我们还可以自定义格式转换器来支持我们自定义的数据类型。

2.1 自定义Date和String之间转换的Formatter
@Test
public void defaultFormattingConversionService(){DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();conversionService.addFormatter(new Formatter<Date>() {@Overridepublic String print(Date object, Locale locale) {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(object);}@Overridepublic Date parse(String text, Locale locale) throws ParseException {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(text);}});String convert1 = conversionService.convert(new Date() , String.class);System.out.println(convert1);Date convert2 = conversionService.convert("2024-11-04 23:52:36" , Date.class);System.out.println(convert2);}运行结果:
2024-11-05 11:48:33
Mon Nov 04 23:52:36 CST 2024

上面的代码我们自定义了一个Date和String的Formatter,那么DefaultFormattingConversionService在进行Date和String之间的相互转换时,就会用我们自定义的Formatter 进行格式化和解析

@Test
public void defaultFormattingConversionService(){DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();conversionService.addFormatter(new Formatter<Date>() {@Overridepublic String print(Date object, Locale locale) {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(object);}@Overridepublic Date parse(String text, Locale locale) throws ParseException {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(text);}});String convert1 = conversionService.convert(new Date() , String.class);System.out.println(convert1);Date convert2 = conversionService.convert("Mon Nov 04 23:32:14 CST 2024" , Date.class);System.out.println(convert2);}运行结果:
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value 'Mon Nov 04 23:32:14 CST 2024'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [Mon Nov 04 23:32:14 CST 2024]

这里报错了,说明了我们添加了自定义的Formatter之后,不支持将Mon Nov 04 23:32:14 CST 2024格式的字符串转换为Date类型了,支持支将yyyy-MM-dd HH:mm:ss格式的字符串转换为Date类型,说明之前默认的支持Mon Nov 04 23:32:14 CST 2024格式的Formatter被我们自定义Formatter给覆盖了

2.2 自定义Person和String之间转换的Formatter
@Test
public void defaultFormattingConversionService1(){DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();conversionService.addFormatter(new Formatter<Person>() {@Overridepublic String print(Person object, Locale locale) {return JSON.toJSONString(object);}@Overridepublic Person parse(String text, Locale locale) throws ParseException {return JSON.parseObject(text , Person.class);}});Person person = new Person();person.setName("孙悟空");person.setAge(20);String convert1 = conversionService.convert(person , String.class);System.out.println(convert1);Person convert2 = conversionService.convert(convert1 , Person.class);System.out.println(convert2);}运行结果:
{"age":20,"name":"孙悟空"}
Person{name='孙悟空', age=20}

我们看到成功将Person对象转换为我们自定义的JSON格式,也可以成功将JSON格式的字符串转换为Person对象

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

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

相关文章

高亚科技签约酸动力,助力研发管理数字化升级

近日&#xff0c;中国企业管理软件资深服务商高亚科技与广东酸动力生物科技有限公司&#xff08;以下简称“酸动力”&#xff09;正式签署合作协议。借助高亚科技的8Manage PM项目管理软件&#xff0c;酸动力将进一步优化项目过程跟踪与节点监控&#xff0c;提升研发成果的高效…

CSRF与SSRF

csrf(跨站请求伪造)的原理: csrf全称是跨站请求伪造(cross-site request forgery)&#xff0c;也被称为one-click attack 或者 session riding scrf攻击利用网站对于用户网页浏览器的信任&#xff0c;劫持用户当前已登录的web应用程序&#xff0c;去执行分用户本意的操作。 利…

享元模式-实现大颗粒度对象缓存机制

详解 享元模式是一种结构型设计模式&#xff0c;其主要目的是通过共享尽可能多的相同部分来有效地支持大量细粒度的对象。它通过将对象的属性分为内在属性&#xff08;可以共享、不随环境变化的部分&#xff09;和外在属性&#xff08;根据场景变化、不能共享的部分&#xff0…

HTML 基础标签——结构化标签<html>、<head>、<body>

文章目录 1. <html> 标签2. <head> 标签3. <body> 标签4. <div> 标签5. <span> 标签小结 在 HTML 文档中&#xff0c;使用特定的结构标签可以有效地组织和管理网页内容。这些标签不仅有助于浏览器正确解析和渲染页面&#xff0c;还能提高网页的可…

新华三H3CNE网络工程师认证—VLAN的配置

VLAN&#xff08;虚拟局域网&#xff09;是一种在逻辑上划分网络的技术&#xff0c;它可以将一个物理网络分割成多个虚拟网络&#xff0c;从而实现不同组的设备之间的隔离。在配置VLAN时&#xff0c;通常涉及到三种端口类型&#xff1a;Access、Trunk和Hybrid。Access端口用于连…

R语言*号标识显著性差异判断组间差异是否具有统计意义

前言 该R代码用于对Iris数据集进行多组比较分析&#xff0c;探讨不同鸢尾花品种在不同测量变量&#xff08;花萼和花瓣长度与宽度&#xff09;上的显著性差异。通过将数据转换为长格式&#xff0c;并利用ANOVA和Tukey检验&#xff0c;代码生成了不同品种间的显著性标记&#x…

手边酒店多商户版V2源码独立部署_博纳软云

新版采用laraveluniapp开发&#xff0c;为更多平台小程序开发提供坚实可靠的底层架构基础。后台UI全部重写&#xff0c;兼容手机端管理。 全新架构、会员卡、钟点房、商城、点餐、商户独立管理

Multi Agents协作机制设计及实践

01 多智能体协作机制的背景概述 在前述博客中&#xff0c;我们利用LangChain、AutoGen等开发框架构建了一个数据多智能体的平台&#xff0c;并使用了LangChain的Multi-Agents框架。然而&#xff0c;在实施过程中&#xff0c;我们发现现有的框架存在一些局限性&#xff0c;这些…

ReactPress—基于React的免费开源博客CMS内容管理系统

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎提出宝贵的建议&#xff0c;感谢Star。 ![ReactPress](https://i-blog.csdnimg.cn/direct/0720f155edaa4eadba796f4d96d394d7.png#pic_center ReactPress 是使用React开发的开源发布平台&…

如何在一个 Docker 容器中运行多个进程 ?

在容器化的世界里&#xff0c;Docker 彻底改变了开发人员构建、发布和运行应用程序的方式。Docker 容器封装了运行应用程序所需的所有依赖项&#xff0c;使其易于跨不同环境一致地部署。然而&#xff0c;在单个 Docker 容器中管理多个进程可能具有挑战性&#xff0c;这就是 Sup…

【JavaEE初阶 — 多线程】线程安全问题 & synchronized

目录 1. 什么是线程安全问题 (1) 观察线程不安全 (2) 线程安全的概念 2. 造成线程安全的原因 (1)线程调度的随机性 问题描述 解决方案 (2)修改共享数据&#xff06;原子性问题 问题描述 解决方案 3.synchronized 关键字 1. synchronized 的特性 (1) …

产品经理的重要性

一直觉得产品经理很重要&#xff0c;这几年写了好几篇和产品经理相关的思考。2020年写过对产品经理的一些思考的文章&#xff0c;2021年&#xff0c;写了一篇对如何分析项目的思考&#xff0c;2024年写了如何与PM探讨项目。 今天还想再写一篇&#xff0c;主要是最近很有感慨。…

Hunyuan-Large:推动AI技术进步的下一代语言模型

腾讯近期推出了基于Transformer架构的混合专家&#xff08;MoE&#xff09;模型——Hunyuan-Large&#xff08;Hunyuan-MoE-A52B&#xff09;。该模型目前是业界开源的最大MoE模型之一&#xff0c;拥有3890亿总参数和520亿激活参数&#xff0c;展示了极强的计算能力和资源优化优…

【Linux系列】利用 CURL 发送 POST 请求

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

通义灵码实操—飞机大战游戏

通义灵码实操—飞机大战游戏 有没有想象过自己独立编写一个有趣的小游戏。在本实践课程中&#xff0c;你不仅可以实现这个想法&#xff0c;而且还将得到通义灵码智能编程助手的支持与指导。我们将携手步入编程的神奇世界&#xff0c;以一种简洁、高效且具有创造性的方式&#…

lora训练模型 打造个人IP

准备工作 下载秋叶炼丹器整理自己的照片下载底膜 https://rentry.org/lycoris-experiments 实操步骤 解压整合包 lora-scripts,先点击“更新” 训练图片收集 比如要训练一个自己头像的模型&#xff0c;就可以拍一些自己的照片&#xff08;20-50张&#xff0c;最少15张&…

Caffeine 手动策略缓存 put() 方法源码解析

BoundedLocalManualCache put() 方法源码解析 先看一下BoundedLocalManualCache的类图 com.github.benmanes.caffeine.cache.BoundedLocalCache中定义的BoundedLocalManualCache静态内部类。 static class BoundedLocalManualCache<K, V> implements LocalManualCache&…

Spring Boot框架下的教育导师匹配系统

第一章 绪论 1.1 选题背景 如今的信息时代&#xff0c;对信息的共享性&#xff0c;信息的流通性有着较高要求&#xff0c;尽管身边每时每刻都在产生大量信息&#xff0c;这些信息也都会在短时间内得到处理&#xff0c;并迅速传播。因为很多时候&#xff0c;管理层决策需要大量信…

Unity SRP学习笔记(二)

Unity SRP学习笔记&#xff08;二&#xff09; 主要参考&#xff1a; https://catlikecoding.com/unity/tutorials/custom-srp/ https://docs.unity.cn/cn/2022.3/ScriptReference/index.html 中文教程部分参考&#xff08;可选&#xff09;&#xff1a; https://tuncle.blog/c…

2024年10款超好用的企业防泄密软件|企业文件加密防泄密必备!

随着信息技术的迅速发展&#xff0c;企业面临的数据泄露风险越来越高。为了保护企业的敏感信息&#xff0c;防止数据泄露&#xff0c;企业防泄密软件应运而生。以下是2024年值得关注的10款企业防泄密软件&#xff0c;帮助企业有效保障数据安全。 1.安秉网盾 安秉网盾防泄密是一…