其它篇章:
一:SpringBoot3-日志——日志原理&日志格式&日志级别&日志分组&文件输出&文件归档&滚动切割
二:SpringBoot3-Web开发-静态资源——WebMvcAutoConfiguration原理&资源映射&资源缓存&欢迎页&Favicon&自定义

一、多端内容适配

一套系统适配多端数据返回。

假设:
  • 主体:写好一个接口GET /person
  • 部署:部署到服务器,暴露给外界访问。
  • 外界
    1. 一个移动端应用:希望接口返回一个JSON文件;
    2. 一个第三方应用:希望接口返回一个XML文件;
    3. 一个IoT(物联网设备):希望接口返回一个自定义协议数据文件。
提问:
  • 以以上假设为例,如何让一个接口做到多端的数据反馈?
思考:
  • ,可以写三个请求路径,分别为/person.json/person.xml/person.diy(应用指定后缀),这三个不同应用分别访问指定的请求路径:
    • 缺点:这种方法只能用在内部接口少的情况下。如果,内部接口很多,那么每个接口都得拆分成三个接口,对应三个外部应用。若需要返回更多种类型数据文件,这个数量还得上升。
  • SpringBoot可以解决这个问题,详细看接下来的内容。

默认规则

a.主要内容

内容协商功能是SpringMVC自带的功能,SpringBoot对其进行了整合,快速实现一套系统适配多端数据返回。

SpringBoot多端内容适配
  1. 基于请求头内容协商(默认开启)
  • 客户端服务端 发送请求时,携带HTTP标准的Accept请求头。
    • 客户端:外界应用
    • 服务端:接口
    • accept:是http协议里规定的一个标准
  • 客户端服务端 发送请求时,带上Accept,让 服务端 知道该返回什么类型的数据,SpringBoot 就把数据自动格式化成对应类型,再返回。
    • 举例
      • Accept:application/json
      • Accept:text\xml
      • Accept:text\yaml
  1. 基于请求参数内容协商(需要手动开启)
  • 举例
    • ?format=json:
      • 发送请求: GET /projects/spring-boot?format=json
      • 匹配:匹配到 GetMapping("/projects/spring-boot")
      • 返回:根据参数协商,优先返回json类型数据
    • 同理,发送请求 GET /projects/spring-boot?format=xml,则优先返回xml类型数据

b.演示验证

  1. 创建一个接口,其内容如下:
    • 先绑定地址:@GetMapping("/person")
    • 再定义一个 Person类。
    • 创建的接口代码如下:
      package com.atwyb.web.controller;import com.atwyb.web.bean.Person;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RestController;@RestController
      public class HelloController {@GetMapping("/person")public Person person(){Person person = new Person();person.setId("1");person.setUserName("zhangsan");return person;}
      }
      
    • person的javabean如下:
      package com.atwyb.web.bean;public class Person {private String id;private String userName;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}
      }
      

点进@RestController,发现标注了@ResponseBody。说明@RestController返回的数据都标注了@ResponseBody,而所有标注了@ResponseBody的对象,都会以json传输。
在这里插入图片描述

  1. 启动项目,在浏览器中验证:

    • 浏览器中访问:http://localhost:8080/person
    • 发现数据的类型为json,如下图所示:在这里插入图片描述
  2. 思考:要想让数据适配xml,该怎么做?

    • SpringBoot默认支持把对象写为json。因为默认web场景导入了jackson处理json的包:jackson-core。
    • jackson是一个库,也支持把数据写为xml,但要导入xml相关依赖:
      • 引入支持xml内容依赖:
         <dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId>
        </dependency>
        
      • 标注xml注解:在Person这个JavaBean下标注xml注解
        @JacksonXmlRootElement
        public class person{(省略……)}
        
    • 开启基于请求参数的内容协商(默认关闭)
      • 开启基于请求参数的内容协商功能,默认参数名为format
        spring.mvc.contentnegotiation.favor-parameter=true
        
      • 指定内容协商时使用的参数名,默认为format
      • 在application.propertise中添加以下内容:
        在这里插入图片描述
  3. 验证:

    • 在浏览器中访问http://localhost:8080/person?format=xml
      在这里插入图片描述
    • 在浏览器中访问http://localhost:8080/person?type=json在这里插入图片描述

二、内容协商原理-HttpMessageConverter

学习逻辑链:

  1. 目的:想要自定义接口的返回内容
  2. 分析:要想自定义接口的返回内容,就要先理解内容协商的底层原理;而要理解内容协商的底层原理,只要知道HttpMessageConverter怎么工作,什么时候工作就行了;知道HttpMessageConverter工作原理后,就能通过定制HttpMessageConverter来实现多端内容协商,以达到自定义接口返回内容的目的。
  3. 步骤:
    a. 了解HttpMessageConverter怎么工作,什么时候工作。
    b. 这样就能,理解内容协商的底层原理
    c. 接下来就能,通过定制HttpMessageConverter来实现多端内容协商。
    d. 这样就,达到了想要自定义接口的返回内容的目的。
  4. 总结:要想知道怎么自定义接口的返回内容,其实就是要知道怎么通过定制HttpMessageConverter来实现多端内容协商。

WebMvcConfigurer接口里,能够配置很多底层的东西,其中就包含了一个configureMessageConverters,如下图。
在这里插入图片描述
只需要编写WebMvcConfigurer接口提供的configureMessageConverters底层,修改底层的MessageConverters就可以了。
思考:只要修改以上的MessageConverters就可以了,但为什么这样做就可以了?这就是接下来要说的内容了。

1、@ResponseBody由HttpMessageConverter处理

a.主要内容

在向浏览器返回内容的controller里,有一个@RestController注解,而这个注解里又包含一个@ResponseBody,而注解标注在类上面,就表示标注在每一个方法上。

  1. 如果controller方法的返回值标注了@ResponseBody注解,
    按照SpringMVC的原理,我们从DispatcherServlet.class开始,所有请求来到DispatcherServlet,都是从doDispatch()开始的。
    ctlr+n搜索DispatcherServlet.class,进入后继续ctlr+n搜索doDispatch(),在其内容第一行设置一个断点,找到以下界面:
    在这里插入图片描述
    往下翻找到HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
    在这里插入图片描述
  2. 如果根据/person这个请求路径找到了某个方法要处理,那就要找到这个适配器,最终利用这个适配器处理方法。往下翻找到mv = ha.handle(processedRequest, response, mappedHandler.getHandler());,如图。这是正真执行handler的语句。
    在这里插入图片描述
  3. 给person()第一行打个断点,并以debug启动,看看是怎么处理的。
    在这里插入图片描述
    浏览器访问http://localhost:8080/person?format=json,先来到doDispatch,它来接第一个请求。在这里插入图片描述
    放行。
    在这里插入图片描述
    再放行,来到正真执行handler的语句的位置。
    在这里插入图片描述
  4. 这个时候点击step into,进到这个目标执行方法,来到以下界面:
    在这里插入图片描述
    再点进handleInternal,往下翻,看到invokeHandlerMethod方法。
    在这里插入图片描述
    点进去,在第一行设置一个断点:
    在这里插入图片描述
    一直放行到这,目标方法还没进行到,只进行到invokeHandlerMethod
    RequestMappingHandlerAdapter.class中往下找到invocableMethod.invokeAndHandle,意思是执行并处理,把这一放行,就会去到person()并执行。在这里插入图片描述
    这样就会得到结论:
    RequestMappingHandlerAdapter.class里面的invokeAndHandle()才是正真执行目标方法的。

b. 总结:

  • 如果controller方法的返回值标注了@ResponseBody注解:
    1. 请求进来先来到DispatcherServletdoDispatch()进行处理
    2. 找到一个HandlerAdapter适配器,利用适配器执行目标方法
    3. RequestMappingHandlerAdapter来执行,调用invokeHandlerMethod()来执行目标方法
    4. 目标方法执行之前,准备好两个东西:
      • HandlerMethodArgumentResolver:参数解析器,确定目标方法每个参数值
      • HandlerMethodReturnValueHandler:返回值处理器,确定目标方法的返回值该怎么处理。
    5. 目标方法执行完成,会返回返回值对象
    6. 找到一个合适的返回值处理器
    7. 最终找到RequestResponseBodyMethodProcessor中能处理 标注了@ResponseBody注解 的方法
    8. RequestResponseBodyMethodReturnValueHandler调用writeWithMessageConverters,利用MessageConverter把返回值写出去。

看到@GetMapping,要知道这个注解都是由invokeHandlerMethod所在的RequestMappingHandlerAdapter.class

其它篇章:
一:SpringBoot3-日志——日志原理&日志格式&日志级别&日志分组&文件输出&文件归档&滚动切割
二:SpringBoot3-Web开发-静态资源——WebMvcAutoConfiguration原理&资源映射&资源缓存&欢迎页&Favicon&自定义

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

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

相关文章

Spring MVC 类型转换与参数绑定:从架构到实战

在 Spring MVC 开发中&#xff0c;“前端请求数据” 与 “后端 Java 对象” 的格式差异是高频痛点 —— 比如前端传的String类型日期&#xff08;2025-09-08&#xff09;要转成后端的LocalDate&#xff0c;或者字符串male要转成GenderEnum.MALE枚举。Spring 并非通过零散工具解…

Spark提交任务的资源配置和优化

Spark 提交任务时主要可调的资源配置参数包括 Driver 资源&#xff08;内存、CPU&#xff09;、Executor 资源&#xff08;数量、内存、CPU&#xff09;以及 集群管理相关参数。配置和优化时一般结合集群硬件资源、数据规模、作业类型和作业复杂度&#xff08;SQL / 机器学习&a…

机器学习06——支持向量机(SVM核心思想与求解、核函数、软间隔与正则化、支持向量回归、核方法)

上一章&#xff1a;机器学习05——多分类学习与类别不平衡 下一章&#xff1a;机器学习07——贝叶斯分类器 机器学习实战项目&#xff1a;【从 0 到 1 落地】机器学习实操项目目录&#xff1a;覆盖入门到进阶&#xff0c;大学生就业 / 竞赛必备 文章目录一、间隔与支持向量&…

AI集群全链路监控:从GPU微架构指标到业务Metric关联

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;H卡级别算力&#xff0c;80G大显存&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生更享专属优惠。 引言&#xff1a;AI算力时代的监控挑战 随着深度学习模型规模的指…

K8s Ingress Annotations参数使用指南

Kubernetes Ingress Annotations 是与特定 Ingress 控制器&#xff08;如 Nginx、Traefik、HAProxy 等&#xff09;配合使用&#xff0c;用于扩展和定制 Ingress 资源行为的关键配置项。它们通常以键值对的形式添加在 Ingress 资源的 metadata部分。Ingress Annotations参数速查…

CodeBuddy Code深度实战:从零构建智能电商推荐系统的完整开发历程

项目背景与挑战作为一名有着多年全栈开发经验的技术人员&#xff0c;我最近接手了一个具有挑战性的项目&#xff1a;为某中型服装电商平台开发一套智能商品推荐系统。该系统需要在2个月内完成&#xff0c;包含以下核心功能&#xff1a;前端&#xff1a;React TypeScript构建的…

Day 19: 算法基础与面试理论精通 - 从思想理解到策略掌握的完整体系

Day 19: 算法基础与面试理论精通 - 从思想理解到策略掌握的完整体系 🎯 课程概述 核心目标:深度理解算法设计思想和核心原理,掌握面试高频算法概念,建立完整的算法知识体系 学习重点: ✅ 核心数据结构的本质理解和应用场景分析 ✅ 经典算法设计模式的思想精髓和解题策…

AI与AR融合:重塑石化与能源巡检的未来

在石化企业和新能源电站的巡检工作中&#xff0c;传统模式正被一场技术革命所颠覆。AI与AR&#xff08; www.teamhelper.cn &#xff09;的深度融合&#xff0c;不仅提升了巡检效率&#xff0c;更将巡检工作从被动响应转变为预测预防&#xff0c;开启了智能运维的新篇章。一、透…

滴滴二面(准备二)

手写防抖函数并清晰阐述其价值&#xff0c;确实是前端面试的常见考点。下面我将为你直接呈现防抖函数的代码&#xff0c;并重点结合滴滴的业务场景进行解释&#xff0c;帮助你向面试官展示思考深度。 这是防抖函数的一个基本实现&#xff0c;附带注释以便理解&#xff1a; func…

Kubernetes(四):Service

目录 一、定义Service 1.1 typeClusterIP 1.2 typeNodePort 1.3 typeLoadBalancer 1.4 typeExternalName 1.5 无标签选择器的Service 1.6 Headless Service 二、Kubernetes的服务发现 2.1 环境变量方式 2.2 DNS方式 Kubernetes 中 Service 是 将运行在一个或一组 Pod 上的应用…

在 Python 中实现观察者模式的具体步骤是什么?

在 Python 中实现观察者模式可以遵循以下具体步骤&#xff0c;这些步骤清晰地划分了角色和交互流程&#xff1a; 步骤 1&#xff1a;定义主题&#xff08;Subject&#xff09;基类 主题是被观察的对象&#xff0c;负责管理观察者和发送通知。需实现以下核心方法&#xff1a; 存…

分布式方案 一 分布式锁的四大实现方式

Java分布式锁实现方式详解 什么是分布式锁 基于数据库的分布式锁基于Redis的分布式锁基于ZooKeeper的分布式锁基于Etcd的分布式锁 各种实现方式对比最佳实践建议多节点/线程调用结果展示 基于数据库的分布式锁 - 多线程测试基于Redis的分布式锁 - 多节点测试基于ZooKeeper的分…

基于Room+RESTful的双权限Android开机时间监控方案

概述 以下是使用Kotlin实现的商业级Android开机时间记录功能&#xff0c;包含现代Android开发最佳实践。 系统架构 组件设计 // BootReceiver - 接收开机广播 class BootReceiver : BroadcastReceiver() {override fun onReceive(context: Context, intent: Intent?) {if (int…

水库大坝安全监测系统的作用

水库大坝作为重要的水利基础设施&#xff0c;承担着防洪、供水、发电、灌溉等多重功能&#xff0c;其安全性直接关系到人民生命财产安全和社会经济发展。然而&#xff0c;由于自然环境变化、材料老化、荷载作用以及人为因素的影响&#xff0c;大坝在长期运行过程中可能出现裂缝…

《Kubernetes 构建 MySQL MGR 集群实战教程》

#### 一、前言 MySQL Group Replication (MGR) 是 MySQL 官方提供的高可用集群方案&#xff0c;基于 Paxos 协议实现多节点数据强一致性。本教程将指导如何在 Kubernetes 上部署 MySQL MGR 集群&#xff0c;适用于生产级高可用场景。---#### 二、环境准备 1. **Kubernetes 集…

影视APP源码 SK影视 安卓+苹果双端APP 反编译详细视频教程+源码

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 影视APP源码 SK影视 安卓苹果双端APP 反编译详细视频教程源码 自带对接优效SDK广告&#xff08;已失效&#xff09;。域名和IP都可以搭建。 自带一起看和短剧页面功能&#xff0c;三种…

pyqt+python之二进制生肖占卜

目录 一、引言 二、GUI界面设计 1.效果演示 2.相关提示 3.界面设计.py 三、主要程序详解 1.导入相关模块 2.初始化设置 3.组内判断 4.猜测过程 四、总程序代码 一、引言 在数字时代&#xff0c;传统文化与编程语言的碰撞总能迸发奇妙火花。本项目以PyQtPython为技术…

人工智能-python-深度学习-经典网络模型-LeNets5

文章目录LeNet-5&#xff08;详解&#xff09;—— 从原理到 PyTorch 实现&#xff08;含训练示例&#xff09;简介LeNet-5 的核心思想LeNet-5 逐层结构详解逐层计算举例&#x1f4cc; 输入层&#x1f4cc; C1 卷积层&#x1f4cc; S2 池化层&#x1f4cc; C3 卷积层&#x1f4…

机器视觉的手机柔性屏贴合应用

在智能手机制造领域&#xff0c;柔性屏逐渐成为智能手机的主流选择&#xff0c;柔性屏因其轻便、易于弯曲的特性&#xff0c;已成为现代电子设备的重要组成部分&#xff0c;但同时也带来了前所未有的制造挑战。柔性屏与传统刚性玻璃屏有本质区别&#xff0c;它容易形变&#xf…

贪心算法应用:数字孪生同步问题详解

Java中的贪心算法应用&#xff1a;数字孪生同步问题详解 贪心算法是一种在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望导致结果是全局最好或最优的算法。下面我将全面详细地讲解贪心算法在数字孪生同步问题中的应用。…