【代码小抄】如何使用WebClient开发响应式接口

在全民AI的大势下,很多类Chat GPT的聊天对话吐字形式的产品层出不穷,服务端与前端都需要对生成式Stream的技术方案进行了解,本篇内容简单Java工程师如何借助Spring WebClient开发响应式接口

首先引入依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webflux</artifactId>
  <version>2.7.16</version> # 修改为自己的版本
</dependency>

创建WebClient配置类

@Configuration
public class WebClientConfig {

    @Bean(name = "webClient") 
    WebClient webClient() { 
     ExchangeStrategies strategies = ExchangeStrategies.builder() // 创建一个ExchangeStrategies构建器,用于配置HTTP消息的编码和解码策略
             .codecs(configurer -> // 使用codecs方法来配置编解码器
                     configurer.defaultCodecs() // 获取默认的编解码器配置
                             .jackson2JsonDecoder(new Jackson2JsonDecoder()) // 使用Jackson 2 JSON解码器,并传入一个新的实例作为参数
             )
             .build(); // 构建ExchangeStrategies对象
     return WebClient.builder() // 创建一个WebClient构建器
             .exchangeStrategies(strategies) // 设置之前构建的ExchangeStrategies,用于处理消息编码和解码
             .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) // 为所有请求设置默认的HTTP头,这里设置Content-Type为application/json,并指定UTF-8编码
             .build(); // 构建WebClient实例
    }

}

GPT相关Entity

@Data
public class CompletionRequest {
    // 对话的消息列表
    private List<Message> messages;
    // 聊天完成中可以生成的最大令牌数
    @SerializedName("max_tokens")
    public int maxTokens;
    // temperature范围 0 - 2,值越高,响应结果越随机(What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.)
    private Double temperature;

    private String model;
}

@Data
@AllArgsConstructor
public class Message {
    private String role;
    private String content;
}

@Data
public class CompletionResponse {
    private Long created;
    private String model;
    private List<Choice> choices;
}

@Data
public class Choice {
    private Delta delta;
    private int index;
    private String finish_reason;
}

@Data
public class Delta {
    private String role;
    private String content;
}

创建Controller,这里与平时接口不同的是媒体类型不再是 application/json ,而是text/event-stream

@ApiOperation(value = "发送补全对话", notes = "wheelmouse", httpMethod = "POST",
            produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @PostMapping(value = "/completion", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<CompletionResponse>  completion(@RequestBody CompletionRequest request) {
        return gptService.completion(request);
    }

编写Service方法


@Autowired
WebClient webClient;

// 发起GET请求
Mono<String> response = webClient.get() // 指定GET请求
       .uri("/api/data") // 指定请求的路径
       .retrieve() // 获取响应
       .bodyToMono(String.class); // 将响应体转换为字符串

// 订阅并消费响应
response.subscribe(
       result -> System.out.println("GET请求结果:" + result), // 处理成功的结果
       error -> System.out.println("GET请求错误:" + error.getMessage()) // 处理错误
);


// 发起POST请求
public Flux<CompletionResponse> completion(CompletionRequest request) {
   return webClient
    .post() // 创建一个POST请求
    .uri("localhost:8080/stream/api") // 设置请求的URL为第三方接口的URL
    .body(BodyInserters.fromObject(JacksonUtils.objToJson(chatBotCompletion))) // 将请求体设置为chatBotCompletion对象转换为JSON字符串的结果
    .retrieve() // 触发实际的HTTP请求并获取响应
    .bodyToFlux(String.class) // 将响应体转换为字符串类型的Flux流,这意味着响应可以是多个字符串消息
    .onErrorResume(WebClientResponseException.class, ex -> { // 当发生WebClientResponseException异常时,执行以下操作
        HttpStatus status = ex.getStatusCode(); // 获取异常中的HTTP状态码
        String res = ex.getResponseBodyAsString(); // 获取异常中的响应体字符串
        logger.error("OpenAI API error: {} {}", status, res); // 使用日志记录器记录错误信息
        return Mono.just(""); // 返回一个空的Mono以继续处理流程
    })
    .map(eventStream -> { // 对流中的每个字符串元素应用map操作,将其转换为其他对象
        return processEventStream(eventStream); // 调用processEventStream方法处理事件流
    })
    .doOnNext(responseList::add) // 当流中有新的元素时,将其添加到responseList集合中
    .doOnComplete(() -> handleResponse(conversationId, responseList)) // 当流完成时,调用handleResponse方法处理最终的响应
    // 补充响应条数
    .concatWith(Flux.just(new CompletionResponse())); // 将这个新对象作为流的一部分,追加到现有的流中
}

private CompletionResponse processEventStream(String eventStream) {
   CompletionResponse response = JacksonUtils.jsonToPojo(eventStream,
           CompletionResponse.class);
   if (response == null) {
       response = new CompletionResponse();
   }
   return response;
}

private void handleResponse(Long conversationId, List<CompletionResponse> responseList) {
   // do anything
}

效果展示:
使用postman测试接口,可以看到是吐字的方式返回响应
在这里插入图片描述

总结

通过以上介绍,我们可以看到Spring中的WebClient是一个非常强大和灵活的工具,可以方便地与React接口进行交互。它支持各种HTTP方法,可以处理不同类型的请求和响应,同时还提供了错误处理的机制。希望这篇文章能够帮助您更好地理解如何使用Spring中的WebClient来调用React接口。

公众号推荐

  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Leetcode算法小抄是一份权威的算法手册,包含了Leetcode上常见的算法题目的解法和详细讲解。这个小抄对于想要提升自己算法能力的程序员来说非常有用。该小抄包括以下内容: 1.基础数据结构:包括数组、链表、栈、队列、树、哈希表等。 2.算法基础:包括排序算法、搜索算法、贪心算法、动态规划等。 3.高级算法:包括图论、字符串匹配、线性代数、计算几何等。 每个算法题目都附有详细的解析和代码实现,方便程序员进行学习和练习。此外,该小抄还提供了优秀的算法实现其他程序员的思路和解答,这对于新手来说尤为重要。 总之,Leetcode算法小抄是一份非常实用的算法手册,如果你想成为一名出色的程序员,学习和掌握其中的内容必不可少。 ### 回答2: LeetCode算法小抄是一份非常实用的算法指南,它包含了大量的算法问题和解答,而且所有的算法问题都是以LeetCode网站上的题目为蓝本的。这个小抄主要面向准备参加Google、Facebook、 Apple等知名科技公司的笔试或者面试的程序员,也适用于想要提高自己算法能力的人。这份小抄的编制者是Steven Halim和Felix Halim,也就是ACM竞赛的著名选手和教练。他们将自己多年的ACM竞赛经验倾囊相授,帮助大家提高算法能力。小抄中包含了高频出现的数据结构和算法,如树、图、排序、数组、动态规划等,每个算法都有详细的解释和代码实现。此外,小抄还包含了一些实用技巧,如测试用例设计、代码调试、复杂度分析等。总之,LeetCode算法小抄是一份非常实用、全面的算法指南,如果你想要提高自己的算法能力,相信它一定能为你带来帮助。 ### 回答3: LeetCode算法小抄是一个常用的算法学习工具,它主要是为了帮助程序员更加高效地学习和掌握LeetCode算法。LeetCode算法小抄中收录了大量经典的算法题目,并提供了详细的题解和代码示例,涵盖了各种数据结构、算法和编程技术。 LeetCode算法小抄的优点在于它的简便性和针对性。其内容结构清晰,难度逐渐增加,让读者能够逐步学习并掌握更加复杂的数据结构和算法。同时,小抄中提供了大量的代码示例和优化方法,可以帮助读者更加深入地理解和掌握算法。 另外,LeetCode算法小抄还提供了各种算法题目的分类、标签和解法推荐,让读者能够更加容易地找到自己需要的题目和解法。同时,小抄中还提供了一些常见的面试题目和解题思路,可以帮助读者更好地应对工作中和面试中的挑战。 总之,LeetCode算法小抄是一本非常实用的算法学习工具,它可以帮助程序员更加高效地学习和掌握算法知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值