远程访问@HttpExchange

本文介绍了SpringBoot3.0中的新特性,包括webClient的异步非阻塞特性,以及如何通过接口声明式地定义和调用HTTP服务。文章详细解释了`@HttpExchange`注解的使用方法,展示了不同类型的HTTP请求方法,并提到了部分过时方法的替代方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提示:这是SpringBoot3以上的新特性。



  • 远程访问是开发的常用技术,一个应用能够访问其他应用的功能。Spring Boot 提供了多种远程访问技术。基于 HTTP 协议的远程访问是支持最广泛的。Spring Boot3 提供了新的 HTTP 访问能力,通过接口简化 HTTP 远程访问,类似 Feign 功能。Spring 包装了底层 HTTP 客户的访问细节
  • Spring Boot 中定义接口提供 HTTP 服务生成的代理对象实现此接口代理对象实现 HTTP 的远程访问。

一、webClient

  • 我们想要调用其他系统提供的 HTTP 服务,通常可以使用 Spring 提供的 RestTemplate 来访问,RestTemplate 是 Spring3 中引入的同步阻塞式 HTTP 客户端,因此存在一定性能瓶颈。Spring 官方在 Spring5 中引入了 WebClient 作为异步非阻塞式 HTTP 客户端。有如下的特点:
    • 非阻塞,异步请求
    • 它的响应式编程是基于 Reactor
    • 高并发,硬件资源少
    • 支持 Java8 lambda 函数式编程
  • 什么是同步和异步
    • 异步和同步针对调用者,调用者发送请求,如果等待对方回应之后才去做其他事情,就是同步,如果发送请求之后不等待对方回应就去做其他事情就是异步。
  • 什么是阻塞和非阻塞
    • 阻塞和非阻塞针对被调度者,被调度者收到请求后,做完请求任务之后才给出反馈就是阻塞,收到请求之后马上给出反馈然后去做其他事情,就是非阻塞。

二、Http 服务接口的方法定义

@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 {};
}
  • @HttpExchange 注解用于声明接口作为 HTTP 远程服务。在方法、类级别使用。通过注解属性以及方法的参数设置 HTTP 请求的细节。
    • @GetExchange 用于 HTTP GET 请求。一般用于获取数据。
    • @PostExchange 用于 HTTP POST 请求。一般用于提交数据。
    • @PutExchange 用于 HTTP PUT 请求。一般用于修改数据。
    • @PatchExchange 用于 HTTP PATCH 请求。
    • @DelectExchange 用于 HTTP DELETE 请求。一般用于删除数据。
  • 作为 HTTP 服务接口中的方法允许使用的参数
    参数说明
    URI设置请求的url,覆盖注解的url属性
    HttpMethod请求方式,覆盖注解的method属性
    @RequestHeader添加到请求中header。 参数类型可以为Map, MultiValueMap,单个值或者Collection
    @PathVariable添加一个变量以扩展请求 URL 中的占位符。参数可为Map<String, ?>带有多个变量的,也可以是单个值。非字符串值支持类型转换
    @RequestBody请求体,参数是对象
    @RequestParam请求参数,单个值或Map, MultiValueMap,Collection
    @RequestPart发送文件时使用
    @CookieValue向请求中添加cookie
  • 接口中方法返回值
    返回值类型说明
    void执行请求,无需解析应答
    HttpHeaders存储 response 应答的 header 信息
    对象解析应答结果,转为声明的类型对象
    ResponseEntity<void>执行给定的请求,释放响应内容,并返回 ResponseEntity带有状态和标头的 a。
    ResonseEntity<T>执行给定的请求,将响应内容解码为声明的返回类型,并返回 ResponseEntity 带有状态、标头和解码正文的 a。

三、声明式 HTTP 远程服务

  • 声明式 HTTP 接口可以让你像定义Java接口那样定义HTTP服务,用法和你平时写Controller中方法完全一致。
  • 使用一个免费的、24小时在线的 Rest Http 服务。===> https://jsonplaceholder.typicode.com/,其提供的 comments 服务。基于 RESTful 风格,添加新的 comments,修改 comments,查询某个具体的 comments。

1.组合使用注解

  • @HttpExchange,@GetExchange等注解可以组合使用。
  • 类级别的 url 和方法级别的 url 组合在一起就是最后请求的 url 地址。
  • ① 引入依赖
    • 声明性 HTTP 接口功能是spring-web依赖项的一部分,使用前必须引入如下依赖包:
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    
  • ② 编写 comment 数据类
    public class Comment {
        private Integer postId;
        private Integer id;
        private String name;
        private String email;
        private String body;
    //构造方法、setter和getter方法、toString方法
    }
    
  • ③ 声明HTTP服务接口
    //其中的一个方法就是一个远程服务调用
    @HttpExchange(url = "https://jsonplaceholder.typicode.com")
    public interface CommonService {
        @GetExchange("/comments/{id}") //设置请求的URI
        Comment getCommentById(@PathVariable("id") Integer id);
    }
    
  • ④ 创建 HTTP 服务代理对象
    @Configuration(proxyBeanMethods = false)
    public class HttpConfiguration {
        @Bean
        public CommonService requestService(){
            WebClient webClient =WebClient.builder().build();
            return HttpServiceProxyFactory.builderFor(WebClientAdapter.create(webClient)).build().createClient(CommonService.class);
        }
    }
    
  • ⑤ 编写测试代码
    	@SpringBootTest
    	class HttpExchangeApplicationTests {
    	    @Autowired
    	    private CommonService commonService;
    	    @Test
    	    public void test(){
    	        Comment comment = commonService.getCommentById(1);
    	        System.out.println(comment);
    	    }
    	}
    
  • ⑥ 结果展示
    在这里插入图片描述

2.使用单个注解

  • ① 引入依赖

  • ② 编写 comment 数据类

  • ③ 声明服务接口

    //其中的一个方法就是一个远程服务调用
    public interface CommonService {
        @PutExchange("/comments/{id}")
        ResponseEntity<Comment> modifyCommentById(@PathVariable("id") Integer modifyId, @RequestBody Comment comment);
    }
    
  • ④ 创建 HTTP 服务代理对象

    @Configuration(proxyBeanMethods = false)
    public class HttpConfiguration {
        @Bean
        public CommonService requestService(){
            WebClient webClient = WebClient.create("https://jsonplaceholder.typicode.com");
            //WebClient webClient = WebClient.builder().baseUrl("https://jsonplaceholder.typicode.com").build(); //也可以使用这种方式
            HttpServiceProxyFactory proxyFactory = HttpServiceProxyFactory.builderFor(WebClientAdapter.create(webClient)).build();
            return proxyFactory.createClient(CommonService.class);
        }
    }
    
  • ⑤ 编写测试代码

    @SpringBootTest
    class HttpExchangeApplicationTests {
        @Autowired
        private CommonService commonService;
        @Test
        public void test(){
            Comment comment = new Comment(123, 1, "gdb", "aaaaa", "bbbbbb");
            ResponseEntity<Comment> result = commonService.modifyCommentById(1, comment);
            System.out.println(result.getStatusCode());
            System.out.println(result.getHeaders());
            System.out.println(result.getBody());
        }
    }
    
  • ⑥ 结果展示
    在这里插入图片描述

3.定制 HTTP 请求服务


四、总结

1.部分方法过时

  • 动力节点王鹤Spring Boot3中代码的写法如下
    在这里插入图片描述
  • 由于新版的更新原来的方法已经过时了,大家可以按照如下的方式写
    在这里插入图片描述

2.过时的方法详解

  • Builder builder(HttpClientAdapter clientAdapter) ===> Builder builderFor(HttpExchangeAdapter)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • forCreate(WebClient webClient) ===> create(WebClient webClient)
    在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小宝945

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值