【Spring】Spring 6 新特性一一HTTP Interface

news2024/9/22 21:33:34

简介

Spring 6 的第一个 GA 版本发布了,其中带来了一个新的特性——HTTP Interface。
这个新特性,可以让开发者将 HTTP 服务,定义成一个包含特定注解标记的方法的 Java 接口,然后通过对接口方法的调用,完成 HTTP 请求。下面我们参考官方文档来完成一个 Demo。

Http Demo

首先创建一个简单的 HTTP 服务,这一步可以创建一个简单的 Spring Boot 工程来完成。

先创建一个实体类:

public class User implements Serializable {

    private int id;
    private String name;
    // 省略构造方法、Getter和Setter
    @Override
    public String toString() {
        return id + ":" + name;
    }
}

再写一个简单的 Controller:

@GetMapping("/users")
public List<User> list() {
    return IntStream.rangeClosed(1, 10)
            .mapToObj(i -> new User(i, "User" + i))
            .collect(Collectors.toList());
}

确保启动服务之后,能够从http://localhost:8080/users地址获取到一个包含十个用户信息的用户列表。

下面我们新建一个 Spring Boot 工程。

在这里插入图片描述
这里需要注意,Spring Boot 的版本至少需要是 3.0.0,这样它以来的 Spring Framework 版本才是 6.0 的版本,才能够包含 HTTP Interface 特性,另外,Spring Framework 6.0 和 Spring Boot 3.0 开始支持的 Java 版本最低是 17,因此,需要选择至少是 17 的 Java 版本。

另外,需要依赖 Spring Web 和 Spring Reactive Web 依赖,原因下文中会提到。

创建好新的 Spring Boot 工程后,首先需要定义一个 HTTP Interface 接口。最简单的定义如下即可:

public interface UserApiService {
    @GetExchange("/users")
    List<User> getUsers();
}

然后,我们可以写一个测试方法。

@Test
void getUsers() {
   WebClient client = WebClient.builder().baseUrl("http://localhost:8080/").build();
   HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
   UserApiService service = factory.createClient(UserApiService.class);
   List<User> users = service.getUsers();
   for (User user : users) {
      System.out.println(user);
   }
}

最终回打印获取到的是个用户信息:

1:User1
2:User2

9:User9
10:User10

以上是一个最简单的示例,下面我们看看其中的一些细节。

GetExchange(HttpExchange)注解

上文例子中的 GetExchange 注解代表这个方法代替执行一个 HTTP Get 请求,与此对应,Spring 还包含了其他类似的注解:

在这里插入图片描述

这些注解定义在spring-web模块的org.springframework.web.service.annotation包下,除了 HttpExchange 之外,其他的几个都是 HttpExchange 的特殊形式,这一点与 Spring MVC 中的 RequestMapping/GetMapping 等注解非常相似。

以下是 HttpExchange 的源码:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
@Reflective(HttpExchangeReflectiveProcessor.class)
public @interface HttpExchange {

    @AliasFor("url")
    String value() default "";

    @AliasFor("value")
    String url() default "";

    String method() default "";

    String contentType() default "";

    String[] accept() default {};

}

在上面的例子中,我们只指定了请求的资源路径。

UserApiService 实例的创建

在上面例子中,我们定义的 HTTP Interface 接口是 UserApiService,在测试方法中,我们通过 HttpServiceProxyFactory 创建了 UserApiService 的实例,这是参考了 Spring 的官方文档的写法。

你也可以将创建的过程写到一个 @Bean 方法中,从而可以将创建好的实例注入到其他的组件中。

我们再定义 UserApiService 的时候,只是声明了一个接口,那具体的请求操作是怎么发出的呢,我们可以通过 DEBUG 模式看得出来,这里创建的 UserApiService 的实例,是一个代理对象:

在这里插入图片描述

目前,Spring 还没有提供更方便的方式来创建这些代理对象,不过,之后的版本肯定会提供,如果你感兴趣的话,可以从 HttpServiceProxyFactory 的createClient方法的源码中看到一些与创建 AOP 代理相似的代码,因此,我推测 Spring 之后可能会增加类似的注解来方便地创建代理对象。

其他特性

除了上述例子中的简单使用之外,添加了 HttpExchange 的方法还支持各种类型的参数,这一点也与 Spring MVC 的 Controller 方法类似,方法的返回值也可以是任意自定义的实体类型(就像上面的例子一样),此外,还支持自定义的异常处理。

为什么需要 Spring Reactive Web 的依赖

上文中创建工程的时候,引入了 Spring Reactive Web 的依赖,在创建代理的service对象的时候,使用了其中的 WebClient 类型。这是因为,HTTP Interface 目前只内置了 WebClient 的实现,它属于 Reactive Web 的范畴。Spring 在会在后续版本中推出基于 RestTemplate 的实现。

总结

本文带你对 HTTP Interface 特性进行了简单的了解,我之后会深入研究这个特性,也会追踪后续版本中的改进并与你分享,欢迎点赞加关注。

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

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

相关文章

硬盘损坏数据恢复怎么操作?恢复数据的常用方法

硬盘一般固定在电脑里面的存储装置&#xff0c;里面保存着我们大量的数据。随着电脑的使用越加广泛&#xff0c;有时不免出现一些问题&#xff0c;比如硬盘在使用过程中出现数据错误&#xff0c;或者是硬盘的内部零件出现故障。出现这些问题&#xff0c;硬盘损坏数据恢复怎么操…

Redis实现UV统计 | 黑马点评

一、HyperLogLog 1、为什么用HyperLogLog 先介绍两个概念&#xff1a; UV&#xff1a;全称 Unique Visitor&#xff0c;也叫独立访客量&#xff0c;是指通过互联网访问、浏览这个网页的自然人、1 天内同一个用户多次访问该网站&#xff0c;只记录 1 次。PV&#xff1a;全称 …

车载以太网 - SomeIP测试专栏 - 总纲

关于车载以太网中的SomeIP在网上也逐渐有越来越多的资料,讲的也是非常好;但是个人认为讲的泛,很难让初学者或者初入门者真正了解SomeIP到底是一个什么东西,以及它究竟在车载上有什么作用,本专栏会由浅入深的讲解SomeIP整个协议内容规范,并且对Tc8中SomeIP相关的协议测试用…

实习日记!

目录 http://localhost:5789实习第三天 接下来几天的target 实习第四天 Git的操作 实习第五天 12月5日-Mon 12月6日 12月9日 12月12日 12月15日 useState() hook 12月16日 useEffect() hook async 函数 异步编程 回调函数 12月17日 C#中的&#xff1f;&#x…

postgresql源码学习(54)—— HotStandby从库必须设置大于等于主库的参数

新的一篇本来计划研究lazy_scan_heap函数&#xff0c;但过于复杂还没研究出来… 下午做题遇到一个这样的问题&#xff0c;之前没太关注过&#xff0c;打算学习学习&#xff0c;避免主从配置踩坑。 题干搜一搜&#xff0c;没搜出啥有用的玩意…渣翻成英文搜一搜&#xff0c;搜出…

windows搭建go语言开发环境,IDEA安装go插件并运行Hello world代码

2023年1月27日1.Windows上安装Go语言开发包参考链接&#xff1a;http://c.biancheng.net/view/3992.html1.1.下载Go语言开发包可以在Go语言官网 &#xff08;https://golang.google.cn/dl/&#xff09; 下载Windows 系统下的Go语言开发包&#xff0c;如下图所示。这里我们下载的…

学习Docker就应该掌握的dockerfile语法与指令

在日常的工作中&#xff0c;常常需要制作自己的项目的镜像&#xff0c;一般通过以下两种方式制作镜像&#xff1a;Docker commit、Dockerfile。Docker commitDocker commit一般用做从一个运行状态的容器来创建一个新的镜像。定制镜像应该使用Dockerfile来完成。docker commit 容…

Git场景分析

当前的开发环境如下&#xff0c;我们每个人都对这个项目已经开发一段时间&#xff0c;接下来我们要切换成团队开发模式。 也就是我们由一个团队来完成这个项目实战的内容。团队有组长和若干组员组成(组长就是开发中的项目经理)。 练习场景如下&#xff1a; 1.由组长&#xff0…

LeetCode[1202]交换字符串中的元素

难度&#xff1a;中等题目&#xff1a;给你一个字符串 s&#xff0c;以及该字符串中的一些「索引对」数组 pairs&#xff0c;其中 pairs[i] [a, b]表示字符串中的两个索引&#xff08;编号从 0 开始&#xff09;。你可以 任意多次交换 在 pairs中任意一对索引处的字符。返回在…

java递归问题——汉诺塔

目录 &#x1f332;&#x1f332;什么是汉诺塔&#xff1f; &#x1f430; 当只有1个圆盘的时候&#xff1a; &#x1f430; 当只有2个圆盘的时候&#xff1a; &#x1f430; 当只有3个圆盘的时候&#xff1a; &#x1f332;&#x1f332;汉诺塔代码 &#x1f430;思路 &am…

电脑安全模式怎么进?3种方式教会你!

安全模式经常是电脑死机的时候&#xff0c;我们会选择的一种方式。因为安全模式可以帮助我们修复电脑系统里面的一些错误&#xff0c;电脑安全模式怎么进&#xff1f;其实很简单&#xff0c;主要有以下3种方式&#xff0c;你可以根据你的需要来选择其中一种&#xff01; 操作环…

剑指 Offer 第7天(中午睡起来都十二点了,今天摆了吧)

目录 剑指 Offer 26. 树的子结构 剑指 Offer 27. 二叉树的镜像 剑指 Offer 28. 对称的二叉树 剑指 Offer 26. 树的子结构 输入两棵二叉树A和B&#xff0c;判断B是不是A的子结构。(约定空树不是任意一个树的子结构) B是A的子结构&#xff0c; 即 A中有出现和B相同的结构和节点…

极光厂商通道集成指南

小米集成指南 1、使用JCenter自动化集成步骤 确认AndroidStudio的Project根目录的主gradle中配置了jcenter支持。(新建project默认配置就支持&#xff09; buildscript { repositories { jcenter() } } allprojects {repositories { jcenter() } } 在应用module的gr…

ffmpeg为mkv封装格式的音视频文件添加内挂字幕

现在好莱坞的电影&#xff0c;都是全球看&#xff0c;一个地区的人看电影时&#xff0c;电影屏幕上应该展示对应的本地区语言字幕。故电影画面在不同的地区&#xff0c;需要配置不同的语言字幕。故视频画面里面的字幕应该可以拆出来&#xff0c;不能像老版三国演义&#xff0c;…

数据中心Spine/Leaf+VXLAN的结构

大家过年好&#xff0c;我是技福的小咖老师。今天我们继续聊聊网络架构。 随着业务系统对IT基础设备灵活度要求的不断提升&#xff0c;云计算、大数据以及虚拟化等技术在新型数据中心的建设中发挥着重要作用。如何更好地满足数据中心计算资源灵活调配以及服务扩展&#xff0c;…

C语言块级变量

所谓代码块&#xff0c;就是由{ }包围起来的代码。代码块在C语言中随处可见&#xff0c;例如函数体、选择结构、循环结构等。不包含代码块的C语言程序根本不能运行&#xff0c;即使最简单的C语言程序&#xff08;上节已经进行了展示&#xff09;也要包含代码块。C语言允许在代码…

不就是Java吗之 认识异常

认识异常一、异常的概念与体系结构1.1 异常的概念1.2 异常的体系结构1.3 异常的分类1.3.1 编译时异常(受查异常)1.3.2 运行时异常(非受查异常)二、异常的处理2.1 防御型编程2.1.1 LBYL2.1.2 EAFP2.2 异常的抛出2.3 异常的捕获2.3.1 异常的声明2.3.2 try-catch捕获并处理2.3.3 f…

linux gui版本控制工具对比

linux gui版本控制工具对比qgitungitgitgsublime mergegitKrakengitAhead tkdiff之前一直用windows开发, 最近想用linux开发, 选版本控制工具的时候考察了以下几款可以在linux平台上使用的版本控制工具, 还是觉得tortoise好用. 记录下它们的优缺点. 想起以前一位同事说过的话,…

Elasticsearch:将数据从 Elasticsearch 和 Kibana 导出到 Pandas Dataframe

在这篇文章中&#xff0c;我们将看到如何从 Elasticsearch 索引和 Kibana 的 CSV 报告中导出数据 - post-url 到 pandas 数据帧。 数据的可视化可以在 Kibana 中完成&#xff0c;但如果你想对数据进行更精细的分析并创建更动态的可视化&#xff0c;将数据导出到 pandas datafra…

LeetCode 55. 跳跃游戏 45. 跳跃游戏 II 22. 括号生成 53. 最大子数组和

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 55. 跳跃游戏 一、力扣示例 二、解决办法 三、代码实现 45. 跳跃游戏 II 一、力扣示例 二、解决办法 三、代码实现 22. 括号生成 一、力扣示例 二、解决办法 三、代码实现 53. 最大子数组和 一、力扣示例 …