【SpringBoot】集成 Web Flux

本文介绍如何在SpringBoot项目中集成WebFlux,包括创建项目、配置依赖、实现User实体类、Repository、Controller及使用WebFlux进行数据处理的过程。通过PostMan测试接口,演示了WebFlux在Spring 5.0后的NIO优势。

前言:

必需学会SpringBoot基础知识

简介:

Takes an opinionated view of building production-ready Spring applications. Spring Boot favors convention over configuration and is designed to get you up and running as quickly as possible.

工具:

JDK8

apache-maven-3.5.2

IntelliJ IDEA 2018.1.3 x64

 

(1)新建一个springboot工程

(2)pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
 

(3)建立实体 User (简化不写了)

(4)建立 repository

package com.lwc.repository;

import com.lwc.pojo.User;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author eddie.lee
 * @Package com.lwc.repository
 * @ClassName UserRepository
 * @description this is dao
 * @date created in 2018-06-07 21:36
 * @modified by
 */
@Repository
public class UserRespository {

    /**
     * 使用内存方式存储 ===》 Map
     */
    private ConcurrentMap<Integer, User> repository = new ConcurrentHashMap<>();

    /**
     * id生成
     */
    private final static AtomicInteger idGenerator = new AtomicInteger();

    /**
     * 保护用户对象
     *
     * @param user
     * @return 如果保存成功,返回true,否则,返回false
     */
    public boolean save(User user) {
        // id 从 1 开始
        Integer id = idGenerator.incrementAndGet();
        // 设置主键
        user.setId(id);

        return repository.put(id, user) == null;
    }

    /**
     * 返回所有用户列表
     *
     * @return
     */
    public Collection<User> findAll(){
        return  repository.values();
    }

}
 

(5)建立控制层

package com.lwc.controller;

import com.lwc.pojo.User;
import com.lwc.repository.UserRespository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author eddie.lee
 * @Package com.lwc.controller
 * @ClassName UserController
 * @description
 * @date created in 2018-06-07 21:44
 * @modified by
 */
@RestController
public class UserController {

    private final UserRespository userRespository;

    @Autowired
    public UserController(UserRespository userRespository) {
        this.userRespository = userRespository;
    }

    @PostMapping("/person/save")
    public User save(@RequestParam("name") String name) {
        User user = new User();
        user.setName(name);
        if (userRespository.save(user)) {
            System.out.printf("用户对象: %s 保存成功! ", user);
            System.out.println(" ");
        }
        return user;
    }

}
 

(6)PostMan测试,插入接口。

http://localhost:8080/person/save?name=zhangsan2

 

{
     "id": 1,
     "name": "zhangsan2"
}

 

(7)使用 Web Flux , Spring  5.0 后提出,优点是NIO

package com.lwc.config;

import com.lwc.pojo.User;
import com.lwc.repository.UserRespository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Collection;

/**
 * @author eddie.lee
 * @Package com.lwc.config
 * @ClassName RouterFunctionConfiguration
 * @description 路由器函数配置
 * @date created in 2018-06-07 22:33
 * @modified by
 */
@Configuration
public class RouterFunctionConfiguration {

//    @Autowired
//    private UserRespository userRepository;

    @Bean
    @Autowired
    public RouterFunction<ServerResponse> personFindAll(UserRespository userRepository) {
        return RouterFunctions.route(RequestPredicates.GET("/person/find/all"),
                request -> {
                    Collection<User> users = userRepository.findAll();
                    Flux<User> userFlux = Flux.fromIterable(users);
                    Mono<ServerResponse> body = ServerResponse.ok().body(userFlux, User.class);
                    return body;
                });
    }

}

【SpringBoot】集成 Web Flux

标签:cto   hash   用户   san   接口   pid   ctr   .post   mic   

原文地址:https://www.cnblogs.com/EddieBlog/p/9157496.html

<think> 我们被要求回答关于SpringBoot集成AnythingLLM的实现方法。根据提供的引用,我们可以总结出以下几个关键点: 1. 引用[1]提到需要获取AnythingLLM工作区的API密钥,这通常在设置界面中生成。 2. 引用[2]展示了一个SpringBoot中通过Controller实现流式问答的示例,使用了Flux和MediaType.TEXT_EVENT_STREAM_VALUE。 3. 引用[3]展示了如何使用Spring AI中的OllamaChatClient进行问答,包括普通问答和流式问答。 虽然引用[3]是关于Ollama的,但我们可以借鉴其流式处理的方式,因为AnythingLLM也支持流式API(如引用[2]所示)。 因此,集成AnythingLLM到SpringBoot的步骤大致如下: 1. 在AnythingLLM中生成API密钥。 2. 在SpringBoot项目中,创建一个Service来调用AnythingLLM的API。 3. 在Controller中提供接口,支持流式和非流式问答。 具体实现步骤: ### 步骤1:获取AnythingLLM的API密钥 - 登录AnythingLLM,进入工作区的设置界面,生成API密钥(如引用[1]所述)。 ### 步骤2:添加依赖 - 在SpringBoot项目中,确保有WebFlux依赖以支持响应式编程(用于流式传输)和Web客户端。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> ``` ### 步骤3:创建AnythingLLM服务类 - 创建一个Service,使用WebClient调用AnythingLLM的API。AnythingLLM的API文档中会有具体的端点(endpoint)和请求格式。 假设AnythingLLM的API端点为:`https://your-anythingllm-instance.com/api/v1/workspace/{workspaceSlug}/chat` 请求体可能包含问题、会话ID等。 示例Service类: ```java import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Flux; @Service public class AnythingLLMService { private final WebClient webClient; public AnythingLLMService() { this.webClient = WebClient.builder() .baseUrl("https://your-anythingllm-instance.com/api/v1") // 替换为实际地址 .defaultHeader("Authorization", "Bearer YOUR_API_KEY") // 替换为你的API密钥 .build(); } public Flux<String> askAnythingllm(String question, String sessionId, String workspaceSlug) { // 构建请求体 // 根据AnythingLLM的API要求,可能需要一个JSON对象 // 这里假设请求体为:{"message": question, "sessionId": sessionId} // 实际请参考AnythingLLM的API文档 return webClient.post() .uri("/workspace/" + workspaceSlug + "/chat") .contentType(MediaType.APPLICATION_JSON) .bodyValue(new ChatRequest(question, sessionId)) .retrieve() .bodyToFlux(String.class); // 这里假设返回的是字符串流,实际可能是特定对象 } // 定义请求体内部类 private static class ChatRequest { private String message; private String sessionId; public ChatRequest(String message, String sessionId) { this.message = message; this.sessionId = sessionId; } // getters and setters } } ``` 注意:实际请求体结构请参考AnythingLLM的API文档。上述代码仅为示例。 ### 步骤4:创建Controller - 创建Controller,提供流式问答接口(如引用[2]所示)和非流式接口(可选)。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; @RestController public class AnythingLLMController { @Autowired private AnythingLLMService anythingLLMService; // 流式问答 @GetMapping(value = "/ask", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> askQuestion(@RequestParam String question, @RequestParam String sessionId, @RequestParam String workspaceSlug) { return anythingLLMService.askAnythingllm(question, sessionId, workspaceSlug); } // 非流式问答(可选) // 可以收集所有流式结果然后一次性返回,或者AnythingLLM可能有非流式API // 这里省略非流式实现,因为引用中未提供 } ``` ### 注意事项 1. **API密钥安全**:不要将API密钥硬编码在代码中,建议使用配置文件或环境变量。 2. **错误处理**:在实际代码中,应该添加错误处理机制。 3. **API文档**:具体请求和响应格式请参考AnythingLLM的官方API文档。 ### 引用说明 - 获取API密钥的方法来自引用[^1]。 - Controller层的流式接口写法参考了引用[^2]。 - 流式处理使用了响应式编程(Flux),类似引用[^3]中的方式。 §§相关问题§§ 1. 如何保护AnythingLLM的API密钥不被泄露? 2. SpringBoot中如何处理流式传输中的错误? 3. AnythingLLM的API调用有哪些限制? </think> ### SpringBoot集成AnythingLLM的实现方法 #### 1. **准备工作:获取API密钥** - 登录AnythingLLM控制台,进入目标工作区设置 - 在API密钥管理模块生成新密钥(需保存备用) - 示例路径:工作区设置 → API密钥 → 生成密钥[^1] #### 2. **项目依赖配置(pom.xml)** ```xml <dependencies> <!-- Spring WebFlux 支持流式响应 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <!-- HTTP客户端 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webflux</artifactId> </dependency> </dependencies> ``` #### 3. **Service层实现(核心通信逻辑)** ```java @Service public class AnythingLLMService { private final WebClient webClient; private final String API_URL = "https://your-anythingllm-instance/api/v1/chat"; private final String API_KEY = "your_generated_api_key"; // 替换为实际密钥[^1] public AnythingLLMService() { this.webClient = WebClient.builder() .baseUrl(API_URL) .defaultHeader("Authorization", "Bearer " + API_KEY) .build(); } public Flux<String> askAnythingllm(String question, String sessionId, String slug) { JSONObject body = new JSONObject(); body.put("message", question); body.put("sessionId", sessionId); body.put("workspace", slug); return webClient.post() .contentType(MediaType.APPLICATION_JSON) .bodyValue(body.toString()) .retrieve() .bodyToFlux(String.class); } } ``` #### 4. **Controller层实现(支持流式响应)** ```java @RestController public class AnythingLLMController { @Autowired private AnythingLLMService anythingLLMService; // 流式问答接口 @GetMapping(value = "/ask", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> askQuestion( @RequestParam String question, @RequestParam String sessionId, @RequestParam String slug) { return anythingLLMService.askAnythingllm(question, sessionId, slug); } // 同步问答接口(可选) @PostMapping("/ask/sync") public Mono<String> askSync(@RequestBody ChatRequest request) { return anythingLLMService.askAnythingllm( request.getQuestion(), request.getSessionId(), request.getSlug() ).collectList().map(list -> String.join("", list)); } } ``` #### 5. **请求参数DTO** ```java public class ChatRequest { private String question; private String sessionId; private String slug; // getters/setters省略 } ``` #### 6. **调用示例** - 流式调用: ```bash curl "http://localhost:8080/ask?question=SpringBoot集成步骤&sessionId=123&slug=workspace-abc" ``` - 同步调用: ```bash curl -X POST http://localhost:8080/ask/sync \ -H "Content-Type: application/json" \ -d '{"question":"如何优化API性能", "sessionId":"123", "slug":"workspace-abc"}' ``` ### 关键配置说明 1. **流式响应必需配置**: - `produces = MediaType.TEXT_EVENT_STREAM_VALUE` 声明SSE协议 - 使用`Flux<String>`返回增量响应[^2] 2. **认证机制**: - 需在HTTP头部添加`Authorization: Bearer <API_KEY>` - API密钥通过工作区设置获取[^1] 3. **会话管理**: - `sessionId`参数维持对话上下文 - 首次调用可生成随机UUID,后续请求传递相同ID 4. **工作区标识**: - `slug`参数指定目标工作区(在AnythingLLM中创建) > **注意事项**:生产环境应将API密钥存储在安全配置中(如Spring Cloud Config/Vault),避免硬编码[^1]。流式响应需前端支持SSE协议解析[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值