当前位置: 首页 > news >正文

织梦 网站地图 样式网站不推广如何排名

织梦 网站地图 样式,网站不推广如何排名,高阳县做企业网站,优区生活app官方下载在 Spring MVC 开发中#xff0c;“前端请求数据” 与 “后端 Java 对象” 的格式差异是高频痛点 —— 比如前端传的String类型日期#xff08;2025-09-08#xff09;要转成后端的LocalDate#xff0c;或者字符串male要转成GenderEnum.MALE枚举。Spring 并非通过零散工具解…在 Spring MVC 开发中“前端请求数据” 与 “后端 Java 对象” 的格式差异是高频痛点 —— 比如前端传的String类型日期2025-09-08要转成后端的LocalDate或者字符串male要转成GenderEnum.MALE枚举。Spring 并非通过零散工具解决此问题而是构建了一套分工明确的转换体系核心是 “ConversionService统筹 多组件协作 按需适配老系统”。 本文将结合完整代码案例从 “组件架构→注册流程→绑定逻辑→新老适配” 四个维度用流程图和通俗比喻拆解底层原理帮你彻底掌握这一核心机制。 完整代码地址 一、先搞懂Spring 转换体系的核心组件 Spring 转换体系的本质是 “翻译团队”不同组件承担不同翻译角色共同完成 “前端数据→后端对象” 的转换。 1.1 组件架构图类关系可视化 #mermaid-svg-S5FneyJxHFxO1ZKv {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-S5FneyJxHFxO1ZKv .error-icon{fill:#552222;}#mermaid-svg-S5FneyJxHFxO1ZKv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-S5FneyJxHFxO1ZKv .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-S5FneyJxHFxO1ZKv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-S5FneyJxHFxO1ZKv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-S5FneyJxHFxO1ZKv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-S5FneyJxHFxO1ZKv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-S5FneyJxHFxO1ZKv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-S5FneyJxHFxO1ZKv .marker.cross{stroke:#333333;}#mermaid-svg-S5FneyJxHFxO1ZKv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-S5FneyJxHFxO1ZKv g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-S5FneyJxHFxO1ZKv g.classGroup text .title{font-weight:bolder;}#mermaid-svg-S5FneyJxHFxO1ZKv .nodeLabel,#mermaid-svg-S5FneyJxHFxO1ZKv .edgeLabel{color:#131300;}#mermaid-svg-S5FneyJxHFxO1ZKv .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-S5FneyJxHFxO1ZKv .label text{fill:#131300;}#mermaid-svg-S5FneyJxHFxO1ZKv .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-S5FneyJxHFxO1ZKv .classTitle{font-weight:bolder;}#mermaid-svg-S5FneyJxHFxO1ZKv .node rect,#mermaid-svg-S5FneyJxHFxO1ZKv .node circle,#mermaid-svg-S5FneyJxHFxO1ZKv .node ellipse,#mermaid-svg-S5FneyJxHFxO1ZKv .node polygon,#mermaid-svg-S5FneyJxHFxO1ZKv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-S5FneyJxHFxO1ZKv .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-S5FneyJxHFxO1ZKv g.clickable{cursor:pointer;}#mermaid-svg-S5FneyJxHFxO1ZKv g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-S5FneyJxHFxO1ZKv g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-S5FneyJxHFxO1ZKv .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-S5FneyJxHFxO1ZKv .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-S5FneyJxHFxO1ZKv .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-S5FneyJxHFxO1ZKv .dashed-line{stroke-dasharray:3;}#mermaid-svg-S5FneyJxHFxO1ZKv #compositionStart,#mermaid-svg-S5FneyJxHFxO1ZKv .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S5FneyJxHFxO1ZKv #compositionEnd,#mermaid-svg-S5FneyJxHFxO1ZKv .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S5FneyJxHFxO1ZKv #dependencyStart,#mermaid-svg-S5FneyJxHFxO1ZKv .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S5FneyJxHFxO1ZKv #dependencyStart,#mermaid-svg-S5FneyJxHFxO1ZKv .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S5FneyJxHFxO1ZKv #extensionStart,#mermaid-svg-S5FneyJxHFxO1ZKv .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S5FneyJxHFxO1ZKv #extensionEnd,#mermaid-svg-S5FneyJxHFxO1ZKv .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S5FneyJxHFxO1ZKv #aggregationStart,#mermaid-svg-S5FneyJxHFxO1ZKv .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S5FneyJxHFxO1ZKv #aggregationEnd,#mermaid-svg-S5FneyJxHFxO1ZKv .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S5FneyJxHFxO1ZKv .edgeTerminals{font-size:11px;}#mermaid-svg-S5FneyJxHFxO1ZKv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}管理单向转换1*管理双向格式化1*被适配11实现兼容老接口«核心接口»ConversionServicecanConvert(sourceType: TypeDescriptor, targetType: TypeDescriptor)convert(source: Object, targetType: Class)«实现类核心»FormattingConversionServiceaddConverter(Converter)addFormatter(Formatter)«接口单向翻译员»Converterconvert(source: S)«接口双向翻译排版员»Formatterparse(text: String, locale: Locale)print(object: T, locale: Locale)«老接口兼容旧系统的翻译员»PropertyEditorsetAsText(text: String)getAsText()«适配器新老衔接助手»FormatterPropertyEditorAdapter- formatter: FormattersetAsText(text: String)getAsText()1.2 组件通俗解释类比 “翻译团队” 组件角色定位核心能力代码案例来自提供的代码库ConversionService翻译团队负责人统筹所有转换逻辑对外提供 “翻译服务”FormattingConversionService全局注册入口Converter单向翻译员如中译英仅支持「A 类型→B 类型」无格式控制StringToGenderEnumConverterString→GenderEnum、StringToUserConverterString→ConverterUserFormatter双向翻译 排版员支持「String↔目标类型」 格式控制LocalDateFormatter指定日期格式yyyy-MM-ddPropertyEditor老版翻译员兼容旧系统仅支持「String↔Bean 属性」UserPropertyEditor在UserController中通过InitBinder注册适配器FormatterPropertyEditorAdapter转接头新老衔接让现代Formatter兼容老PropertyEditor场景FormatterToPropertyEditorBridgeDemo中用适配器包装UserFormatter适配旧系统 二、流程 1转换组件的 “全局注册”从启动到生效 所有自定义 Converter/Formatter 需先注册到FormattingConversionService才能被 Spring MVC 全局调用。这一过程由WebAppInitializerServlet 容器初始化和ConversionConfigMVC 配置协同完成。 2.1 注册流程图 2.2 代码对应与关键细节 1WebAppInitializerServlet 容器初始化替代 web.xml Slf4j public class WebAppInitializer implements WebApplicationInitializer {Overridepublic void onStartup(ServletContext servletContext) throws ServletException {// 1. 创建Spring上下文注解式AnnotationConfigWebApplicationContext springContext new AnnotationConfigWebApplicationContext();// 2. 注册核心配置类ConversionConfigspringContext.register(ConversionConfig.class);// 3. 刷新上下文触发Bean初始化包括FormattingConversionServicespringContext.refresh();// 4. 注册DispatcherServlet前端控制器关联Spring上下文DispatcherServlet dispatcherServlet new DispatcherServlet(springContext);ServletRegistration.Dynamic registration servletContext.addServlet(dispatcher, dispatcherServlet);registration.setLoadOnStartup(1); // 容器启动时初始化registration.addMapping(/); // 接收所有非.jsp请求} }关键作用Servlet 容器启动时通过该类完成 Spring 上下文初始化和DispatcherServlet注册为后续组件注册铺路。 2ConversionConfig注册 Converter/Formatter Slf4j Configuration ComponentScan(com.dwl.mvc.object_bind_and_type_converter) EnableWebMvc // 必须保留激活MVC功能 public class ConversionConfig implements WebMvcConfigurer {// 注册全局转换服务替代Spring默认的ConversionServiceBeanpublic FormattingConversionService formattingConversionService() {log.info(初始化FormattingConversionService注册自定义组件);FormattingConversionService service new FormattingConversionService();// 1. 注册Formatter日期格式化LocalDateFormatter dateFormatter new LocalDateFormatter();service.addFormatter(dateFormatter);log.info(已注册Formatter{}支持yyyy-MM-dd, dateFormatter.getClass().getSimpleName());// 2. 注册Converter单向转换service.addConverter(new StringToGenderEnumConverter()); // String→GenderEnumservice.addConverter(new StringToUserConverter()); // String→ConverterUserservice.addConverter(new GenderEnumToStringConverter()); // GenderEnum→Stringlog.info(FormattingConversionService初始化完成);return service;}// 解决中文响应乱码替换默认的StringHttpMessageConverterOverridepublic void configureMessageConverters(ListHttpMessageConverter? converters) {WebMvcConfigurer.super.configureMessageConverters(converters);// 删除默认ISO-8859-1编码的转换器converters.removeIf(c - c instanceof StringHttpMessageConverter);// 添加UTF-8编码的转换器优先使用converters.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));} }关键作用 通过Bean定义FormattingConversionService将自定义 Converter/Formatter 注入其中配置StringHttpMessageConverter解决中文乱码默认编码会导致响应中文乱码。 三、流程 2请求参数的 “转换绑定”从前端到后端 当用户发送请求如/user/enum?gendermaleSpring MVC 会自动触发转换体系将前端 String 参数转为后端所需的 Java 类型如GenderEnum.MALE。我们以UserController的枚举绑定和实体绑定为例拆解完整流程。 3.1 枚举绑定流程String→GenderEnum 流程图 #mermaid-svg-frKbAeedwk8RO6W1 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-frKbAeedwk8RO6W1 .error-icon{fill:#552222;}#mermaid-svg-frKbAeedwk8RO6W1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-frKbAeedwk8RO6W1 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-frKbAeedwk8RO6W1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-frKbAeedwk8RO6W1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-frKbAeedwk8RO6W1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-frKbAeedwk8RO6W1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-frKbAeedwk8RO6W1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-frKbAeedwk8RO6W1 .marker.cross{stroke:#333333;}#mermaid-svg-frKbAeedwk8RO6W1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-frKbAeedwk8RO6W1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-frKbAeedwk8RO6W1 .cluster-label text{fill:#333;}#mermaid-svg-frKbAeedwk8RO6W1 .cluster-label span{color:#333;}#mermaid-svg-frKbAeedwk8RO6W1 .label text,#mermaid-svg-frKbAeedwk8RO6W1 span{fill:#333;color:#333;}#mermaid-svg-frKbAeedwk8RO6W1 .node rect,#mermaid-svg-frKbAeedwk8RO6W1 .node circle,#mermaid-svg-frKbAeedwk8RO6W1 .node ellipse,#mermaid-svg-frKbAeedwk8RO6W1 .node polygon,#mermaid-svg-frKbAeedwk8RO6W1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-frKbAeedwk8RO6W1 .node .label{text-align:center;}#mermaid-svg-frKbAeedwk8RO6W1 .node.clickable{cursor:pointer;}#mermaid-svg-frKbAeedwk8RO6W1 .arrowheadPath{fill:#333333;}#mermaid-svg-frKbAeedwk8RO6W1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-frKbAeedwk8RO6W1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-frKbAeedwk8RO6W1 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-frKbAeedwk8RO6W1 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-frKbAeedwk8RO6W1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-frKbAeedwk8RO6W1 .cluster text{fill:#333;}#mermaid-svg-frKbAeedwk8RO6W1 .cluster span{color:#333;}#mermaid-svg-frKbAeedwk8RO6W1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-frKbAeedwk8RO6W1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}用户发送请求/user/enum?gendermaleDispatcherServlet接收请求通过HandlerMapping找到匹配的Controller方法enumBind(GenderEnum gender)参数解析过程HandlerAdapter协调调用全局FormattingConversionService查找匹配的ConverterString → GenderEnum匹配到StringToGenderEnumConverter执行convert()逻辑male → MALE → GenderEnum.MALE将转换后的枚举值传入Controller方法Controller处理并返回结果如“枚举绑定MALE”注HandlerMethodArgumentResolver可能参与此过程代码对应与核心逻辑 1Converter 实现String→GenderEnum Slf4j public class StringToGenderEnumConverter implements ConverterString, GenderEnum {Overridepublic GenderEnum convert(String source) {log.debug(开始转换String[{}]→GenderEnum, source);if (source.trim().isEmpty()) {throw new IllegalArgumentException(空字符串无法转换为GenderEnum);}// 核心逻辑字符串转大写后匹配枚举String processed source.trim().toUpperCase();return GenderEnum.valueOf(processed); // male→MALE→GenderEnum.MALE} }2Controller 接口 Controller RequestMapping(/object_bind_and_type_converter/user) public class UserController {// 枚举绑定接口GetMapping(/enum)ResponseBody // 必须加否则返回值会被当作“视图名”导致404public String enumBind(RequestParam(gender) GenderEnum gender) {log.info(接收枚举参数{}, gender);return 枚举绑定 gender 枚举值 gender.name() ;} }3.2 实体绑定流程String→ConverterUser 若请求参数是复合格式如user1,张三,20StringToUserConverter会将其解析为ConverterUser对象流程与枚举绑定类似核心差异在 Converter 的解析逻辑。 核心 Converter 代码 Slf4j public class StringToUserConverter implements ConverterString, ConverterUser {private static final String FORMAT id,name,age如1,张三,20;Overridepublic ConverterUser convert(String source) {log.debug(开始转换String[{}]→ConverterUser, source);if (!StringUtils.hasText(source)) {return null;}String[] parts source.split(,);if (parts.length ! 3) { // 校验格式必须包含id、name、age三部分throw new IllegalArgumentException(格式错误需符合 FORMAT);}// 解析各字段并构建对象Long id Long.parseLong(parts[0].trim());String name parts[1].trim();Integer age Integer.parseInt(parts[2].trim());return new ConverterUser(id, name, age);} }3.3 局部转换优先级InitBinder 的作用 若在 Controller 中通过InitBinder注册PropertyEditor其优先级会高于全局 Converter/Formatter类比 “局部规则覆盖全局规则”。 代码示例UserController 中注册 PropertyEditor InitBinder public void registerUserPropertyEditor(WebDataBinder binder) {// 注册UserPropertyEditor处理String↔ConverterUserUserPropertyEditor userEditor new UserPropertyEditor();binder.registerCustomEditor(ConverterUser.class, userEditor);log.info(【局部】注册UserPropertyEditor); }逻辑当请求绑定ConverterUser类型时Spring 会优先使用UserPropertyEditor而非全局的StringToUserConverter。 四、流程 3新老组件适配Formatter→PropertyEditor 部分老系统依赖PropertyEditor如基于BeanWrapper的旧代码而现代开发更倾向用Formatter支持格式控制。Spring 通过FormatterPropertyEditorAdapter实现 “新老兼容”本质是适配器模式。 4.1 适配流程图 4.2 代码案例FormatterToPropertyEditorBridgeDemo Slf4j public class FormatterToPropertyEditorBridgeDemo {// 测试Bean用于演示属性绑定public static class TestBean { private ConverterUser user; /* getter/setter */ }public static void main(String[] args) {// 1. 创建属性编辑器注册器管理适配器PropertyEditorRegistrar registrar registry - {// 现代组件UserFormatterFormatterConverterUser userFormatter new UserFormatter();// 适配器将Formatter转为PropertyEditorFormatterPropertyEditorAdapter adapter new FormatterPropertyEditorAdapter(userFormatter);// 注册适配器关联ConverterUser类型registry.registerCustomEditor(ConverterUser.class, adapter);};// 2. 包装TestBean并注册适配器TestBean testBean new TestBean();BeanWrapperImpl beanWrapper new BeanWrapperImpl(testBean);registrar.registerCustomEditors(beanWrapper);// 3. 测试String→User触发parseString userStr 2001,Charlie;beanWrapper.setPropertyValue(user, userStr);log.info(转换结果{}, testBean.getUser()); // 输出ConverterUser(2001,Charlie)// 4. 测试User→String触发printConverterUser user new ConverterUser(2002, David);beanWrapper.setPropertyValue(user, user);log.info(格式化结果{}, beanWrapper.getPropertyValue(user)); // 输出2002,David} }通俗理解FormatterPropertyEditorAdapter就像 “新手机转接头”—— 让支持双向格式化的Formatter新手机能插入依赖PropertyEditor的老系统旧耳机接口。 五、关键区别Converter vs Formatter vs PropertyEditor 很多开发者混淆这三个组件用下表明确差异避免误用 维度ConverterFormatterPropertyEditor转换方向单向A→B如 Enum→String双向String↔B如 LocalDate↔String双向String↔Bean 属性格式控制无仅类型转换支持如日期格式yyyy-MM-dd无适用场景通用类型转换枚举、实体需格式化的类型日期、数字老系统兼容、局部 Controller 转换注册方式全局FormattingConversionService.addConverter()全局FormattingConversionService.addFormatter()局部InitBinder全局CustomEditorConfigurer代码案例StringToUserConverterLocalDateFormatterUserPropertyEditor 六、实战避坑指南结合代码常见问题 1. 为什么 Controller 方法必须加ResponseBody 若不加ResponseBodySpring 会将返回的字符串如 “枚举绑定MALE”当作 “视图名”去查找对应的 JSP 页面如/WEB-INF/views/枚举绑定MALE.jsp导致 404。 代码示例UserController的enumBind方法必须保留ResponseBody。 2. 中文响应乱码怎么解决 Spring 默认的StringHttpMessageConverter用ISO-8859-1编码会导致中文乱码。需在ConversionConfig中删除默认转换器替换为UTF-8编码的实例 // 来自ConversionConfig.java Override public void configureMessageConverters(ListHttpMessageConverter? converters) {WebMvcConfigurer.super.configureMessageConverters(converters);converters.removeIf(c - c instanceof StringHttpMessageConverter); // 删除默认converters.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); // 添加UTF-8 }3. 日志中 “注册 3 个组件” 是怎么算的 ConversionConfig的日志中 “共注册 3 个组件”实际是1 个 FormatterLocalDateFormatter 2 个核心 ConverterStringToGenderEnumConverter、StringToUserConverter而GenderEnumToStringConverter是反向转换不单独计入核心业务组件。 七、总结 Spring MVC 类型转换与参数绑定的核心逻辑可概括为三句话 统筹者FormattingConversionService是全局转换入口管理所有 Converter 和 Formatter分工者Converter 负责单向类型转换Formatter 负责双向格式化PropertyEditor 兼容老系统优先级局部InitBinder注册的组件 全局FormattingConversionService注册的组件。 掌握这套体系后无论面对简单的枚举转换、复杂的实体解析还是老系统兼容需求都能找到清晰的解决方案避免重复造轮子。
http://www.zqtcl.cn/news/272373/

相关文章:

  • 郑州企业建站系统模板兰州需要做网站的公司有哪些
  • 怎样做网站卖东西 自己有货句容网络公司
  • 网站建设协议书 保密条款免费发布推广的网站
  • 网站首页外链上海网站建设联系方式
  • 陕西网站建设优化技术2023年1月热点新闻事件
  • 广东省建设银行招聘网站免费搭建个人网站
  • 知名商城网站建设公司wordpress主题 汉化
  • 网站上线做什么pc网站如何做移动适配
  • wap网站搭建北京北京网站建设
  • 放心的网站设计制作免费做logo设计的网站
  • 温州专业手机网站制作多少钱移动商城 网站建设方法方式
  • 周口网站开发wordpress
  • 如何查网站的备案号玉环在哪里做网站
  • 网站开发什么叫前端后端seo研究中心晴天
  • 邢台建筑类的建设网站代刷网站只做软件下载
  • 关于旅游的网站建设目的食品网站建设的目的
  • 开发php网站开发太湖网站建设推荐秒搜科技
  • 90设计网站怎么绑定手机号淘宝搜索排名
  • 无锡自助做网站哪些编程语言适合网站开发
  • 蒲城网站建设wzjseo北京专业推广公司
  • 阳春做网站外贸建站推广公司
  • 哪个网站的课件做的好源码之家关闭了
  • 各大网站热搜榜排名嵊州网站
  • 在哪找做网站的镇江网页设计工作室
  • 做网站的是干嘛的百度推广的几种方式
  • 临沧网站建设用eclipse做jsp网站
  • 做物流运输网站电话做网站看
  • 山东公司网站推广优化什么网站做宣传好
  • 企业网站模板设计外网vp(永久免费)加速器下载
  • 消费者联盟网站怎么做中山网站建设案例