首页 > 其他分享 >Springboot集成WebSocket实现智能聊天【Demo】

Springboot集成WebSocket实现智能聊天【Demo】

时间:2024-04-13 20:45:38浏览次数:19  
标签:username WebSocket String Demo session import message public Springboot

背景

openai 目前越来越流行,其他 ai 产业也随之而来,偶然翻到 openai接口文档,就想着可以调用接口实现智能聊天,接下来就写写我怎么接入 websocket 的过程,文笔不佳,谅解。


接入WebSocket

1. webSocket依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-websocket</artifactId>
  <version>${spring.boot.version}</version>  <!--填写springboot 版本 -->
</dependency>

2. 配置文件

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {

    /**
     * 注入ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint
     */
     @Bean
     public ServerEndpointExporter serverEndpointExporter() {
         return new ServerEndpointExporter();
     }

}

3. 编写Server


import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.handsometaoa.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@ServerEndpoint(value = "/aiChatServer/{username}/{password}")
public class WebSocketServer {

    @Value("${ai.chat.url}")
    private String aiChatUrl;
    @Value("${ai.chat.token}")
    private String aiChatToken;


    /**
     * 记录当前在线连接信息
     */
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<String, Session>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username,@PathParam("password") String password) {
        // 1. todo: 校验密码(由于AI接口是计费的,所以需要校验密码)
        // 2. 将用户session放入sessionMap中
        sessionMap.put(username, session);
    }
    
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("username") String username) {
        sessionMap.remove(username);
    }

    /**
     * 收到客户端消息后调用的方法
     * 用来处理接收到消息的逻辑
     */
    @OnMessage
    public void onMessage(String message, @PathParam("username") String username) {
        log.info("服务端收到用户username={}的消息:{}", username, message);
        // 调用AI接口获取回复
        HashMap<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Bearer " + aiChatToken);
        String requestBody = buildAiRequestBody(message);
        String post = HttpClientUtil.post(aiChatUrl, headers, requestBody);
        JSONObject response = JSONObject.parseObject(post);
        String aiResponseText = response.getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content");
        // 由于是机器人对话聊天,消息发给自己
        sessionMap.get(username).getAsyncRemote().sendText(aiResponseText);
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void one rror(Session session, Throwable error) {
        log.error("发生错误:{}",error.getMessage(),error);
    }

    /**
     * 服务端发送消息给客户端
     */
    private void sendMessage(String message, Session toSession) {
        try {
            log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }

    /**
     * 服务端发送消息给所有客户端
     */
    private void sendAllMessage(String message) {
        try {
            for (Session session : sessionMap.values()) {
                log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }


    /**
     * 封装构建OpenAi请求体
     */
    private static String buildAiRequestBody(String message) {
        JSONObject body = new JSONObject();
        body.put("model","gpt-3.5-turbo");
        JSONArray jsonArray = new JSONArray();
        JSONObject messages = new JSONObject();
        messages.put("role","user");
        messages.put("content", message);
        jsonArray.add(messages);
        body.put("messages",jsonArray);
        return body.toString();
    }
}


测试

webSocket 测试网站:http://www.websocket-test.com/


补充

OpenAi接口文档 : https://platform.openai.com/docs/api-reference/chat

标签:username,WebSocket,String,Demo,session,import,message,public,Springboot
From: https://www.cnblogs.com/handsometaoa/p/18133335

相关文章

  • C# NModbus 4 demo
    1.添加modbus程序包 2.创建 ModbusSerialMaster 实例对象 privatestaticModbusSerialMasterCreateModbusRtu(){SerialPortport=newSerialPort();port.PortName="COM11";port.BaudRate=9600;......
  • SpringBoot项目中对定义的多个Aspect类排序
    代码示例@ConfigurationpublicclassAspectConfig{@Aspect@Component@Order(Ordered.HIGHEST_PRECEDENCE)publicstaticclassLogAspect{@Pointcut("execution(public*com.imooc.spring.web..*.*(..))")publicvoidwe......
  • SpringBoot中的Jetty使用及分析
    前言和Tomcat类似,Jetty也是一个Web应用服务器,相对于Tomcat,Jetty更加轻量、更加简易、更加灵活。今天通过代码来简单分析下SpringBoot中是如何启动Jetty的。Jetty简介使用importjava.io.File;importjava.io.IOException;importjava.net.InetAddress;import......
  • SpringBoot使用 nacos 会默认加载项目名配置文件
    问题描述boostrap.yml配置如下spring:application:name:cnblogscloud:nacos:config:server-addr:http://ip:8848namespace:d8b0df04-aa58-4a5b-b582-7d133b9e8b2c#命名空间IDfile-extension:yamlusern......
  • vue 响应性代码demo
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device......
  • springboot集成redis
    首先引入依赖<!--redis坐标--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>在yml中引入redis数据库spring......
  • Springboot2+vue2整合项目
    前端https://blog.csdn.net/m0_37613503/article/details/128961447数据库1.用户表CREATETABLE`x_user`(`id`int(11)NOTNULLAUTO_INCREMENT,`username`varchar(50)NOTNULL,`password`varchar(100)DEFAULTNULL,`email`varchar(50)DEFAULTNULL,`......
  • 【Camunda】SpringBoot优雅集成Camunda 7工作流引擎,保姆级教程!
    From: https://mp.weixin.qq.com/s/lZmIucZYzqqwjBCtDAL9WA前言项目中需要用到工作流引擎来设计部分业务流程,框架选型最终选择了Camunda7,关于Camunda以及Activity等其他工作流引擎的介绍及对比不再介绍,这里只介绍与现有Springboot项目的集成以及具体使用及配置概念流程......
  • SpringBoot starter 原理及如何自定义 starter
     前言项目的开发要求是不断进化的,而随着时间以及技术的推移,在项目中除了基本的编程语言外,还需要进行大量的应用服务整合。例如,在项目中使用MySQL数据库进行持久化存储,同时会利用Redis作为缓存存储,以及使用RocketMQ实现异构系统整合服务等。但在早先使用Spring开发的......
  • 【Springboot】排除多余依赖与Bean实例
    一、背景:引入公共包之后,需要排除部分不需要的包和bean,给当前服务最大程度减重二、实现:1.在pom.xml排除依赖 2.在启动类上添加扫描排除项@ComponentScan(basePackages={"com.xxx"},excludeFilters={@ComponentScan.Filter(type......