SpringBoot+WebSocket+VUE实现一个简单的聊天机器人

news2024/11/15 9:11:23

文章目录

    • 前言
    • SpringBoot+websocket
      • 引入jar包
      • 在Spring Boot的配置类中添加WebSocket配置
      • 创建聊天机器人处理器
      • 创建WebSocket处理器
    • 服务端测试
      • 启动springboot服务
      • 调用测试方法,能收到消息
    • vue websocket使用
    • 代码地址

前言

要实现一个简单的聊天机器人,可以使用Spring Boot框架作为后端,使用WebSocket协议实现实时通信,使用VUE作为前端实现聊天界面。

SpringBoot+websocket

引入jar包

<!--websocket-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
<!--        junit测试会用到,创建了一个client,连接springboot websocket服务-->
        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.5.1</version>
            <scope>test</scope>
        </dependency>

在Spring Boot的配置类中添加WebSocket配置

这里的WebSocketHandler是自定义的WebSocket处理器,用于处理WebSocket消息。

@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
	//拦截器,做了一些权限揽件
    @Bean
    public MyWebSocketInterceptor webSocketInterceptor() {
        return new MyWebSocketInterceptor();
    }

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
    @Autowired
    private MyWebsocketHandler myWebsocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        webSocketHandlerRegistry
                .addHandler(myWebsocketHandler, "/websocket")
                .setAllowedOrigins("*")
                .addInterceptors(webSocketInterceptor());
    }
}

做了一个简单的拦截器,实现了token校验

public class MyWebSocketInterceptor extends HttpSessionHandshakeInterceptor {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        logger.info("[MyWebSocketInterceptor#BeforeHandshake] Request from " + request.getRemoteAddress().getHostString());
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
            String token = serverHttpRequest.getServletRequest().getHeader("token");
            if (StrUtil.isEmpty(token)) {
                token = serverHttpRequest.getServletRequest().getParameter("token");
            }
            //这里做一个简单的鉴权,只有符合条件的鉴权才能握手成功
            if ("token-123456".equals(token)) {
                return super.beforeHandshake(request, response, wsHandler, attributes);
            } else {
                return false;
            }
        }
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        logger.info("[MyWebSocketInterceptor#afterHandshake] Request from " + request.getRemoteAddress().getHostString());
    }
}

创建聊天机器人处理器

在项目中创建聊天机器人处理器,用于处理聊天机器人的逻辑。这里可以使用机器人框架,例如ChatterBot,实现聊天机器人的功能。

@Component
public class ChatBotHandler {

    private ChatterBot bot;

    public ChatBotHandler() throws Exception {
        bot = new ChatterBotFactory().create(ChatterBotType.CLEVERBOT).createSession();
    }

    public String getResponse(String message) throws Exception {
        return bot.think(message);
    }
}

在构造函数中创建ChatterBot实例,然后实现一个getResponse方法,用于获取聊天机器人的回复。

创建WebSocket处理器

在项目中创建WebSocket处理器,用于处理WebSocket消息。

@Component
public class WebSocketHandler extends TextWebSocketHandler {

    @Autowired
    private ChatBotHandler chatBotHandler;

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String response = chatBotHandler.getResponse(message.getPayload());
        session.sendMessage(new TextMessage(response));
    }
}

这里的WebSocketHandler继承自TextWebSocketHandler,处理文本消息。在handleTextMessage方法中,通过ChatBotHandler获取聊天机器人的回复,然后将回复发送给客户端。

服务端测试

启动springboot服务

调用测试方法,能收到消息

public class WebSocketTest {
    private static final AtomicInteger count = new AtomicInteger(0);

    @Test
    public void test() {
        URI uri = URI.create("ws://127.0.0.1:8081/websocket");  //注意协议号为ws
        MyWebSocketClient client = new MyWebSocketClient(uri);
        client.addHeader("token", "token-123456");              //这里为header添加了token,实现简单的校验
        try {
            client.connectBlocking();   //在连接成功之前会一直阻塞

            while (true) {
                if (client.isOpen()) {
                    client.send("先有鸡还是先有蛋?");
                }
                Thread.sleep(1000000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

服务端收到了消息:
在这里插入图片描述
客户端也收到了消息的返回:
在这里插入图片描述

vue websocket使用

<template>
  <div class="test">

  </div>
</template>

<script>
  export default {
    name : 'test',
    data() {
      return {
        websock: null,
      }
    },
    created() {
      this.initWebSocket();
    },
    destroyed() {
      this.websock.close() //离开路由之后断开websocket连接
    },
    methods: {
      initWebSocket() {
      //初始化weosocket
      const wsuri = 'ws://127.0.0.1:8081/websocket?token=token-123456'//做了一个简单的授权认证
      this.websock = new WebSocket(wsuri)
      this.websock.onmessage = this.websocketonmessage
      this.websock.onopen = this.websocketonopen
      this.websock.onerror = this.websocketonerror
      this.websock.onclose = this.websocketclose
    },
    websocketonopen() {
      //此处不做任何处理
    },
    websocketonerror() {
      //连接建立失败重连
      this.initWebSocket()
    },
    websocketonmessage(e) {
      const redata = JSON.parse(e.data)
      //数据接收处理
      let chatGPT = {
        headImg: require('@/assets/img/head_portrait1.png'),
        name: 'ChatGPT',
        time: new Date().toLocaleTimeString(),
        msg: redata[0].text,
        chatType: 0, //信息类型,0文字,1图片
        uid: '1002' //uid
      }
      this.sendMsg(chatGPT)
      this.isSend = false
    },
    websocketsend(Data) {
      //数据发送
      this.websock.send(Data)
    },
    websocketclose(e) {
      //关闭
      console.log('断开连接', e)
    },
    sendText() {
      if (this.inputMsg) {
        let chatMsg = {
          headImg: require('@/assets/img/head_portrait.jpg'),
          name: '卧龙',
          time: new Date().toLocaleTimeString(),
          msg: this.inputMsg,
          chatType: 0, //信息类型,0文字,1图片
          uid: '1001' //uid
        }
        this.sendMsg(chatMsg)
        this.inputMsg = ''
        this.loading = true
        this.isSend = true
        this.websocketsend(chatMsg.msg)
      } else {
        this.$message({
          message: '消息不能为空哦~',
          type: 'warning'
        })
      }
    },
    //发送信息
    sendMsg(msgList) {
      this.chatList.push(msgList)
      this.scrollBottom()
    },
    //获取窗口高度并滚动至最底层
    scrollBottom() {
      this.$nextTick(() => {
        const scrollDom = this.$refs.chatContent
        animation(scrollDom, scrollDom.scrollHeight - scrollDom.offsetHeight)
      })
    }
    },
  }
</script>
<style lang='less'>
 
</style>

在这里插入图片描述

代码地址

点击查看gitee开源地址
点击查看github开源地址

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

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

相关文章

深入前端尾递归

在深入探讨前端尾递归前&#xff0c;我们先来了解递归和尾调用两个概念 递归 在函数内部调用自身&#xff0c;一般来说递归有两个状态 递归状态&#xff08;继续递归&#xff09;最终状态&#xff08;终止递归&#xff09; 递归式方法可以被用于解决很多的计算机科学问题&a…

QT学习记录(六)类对象属性

类对象属性用来描述类对象的一些信息和当前的状态。类对象属性可以由类的编写者在编写类的时候定义&#xff0c;也可以由类的使用者在使用对象的时候定义。 由类的编写者定义 QPROPERTY()宏就是用来定义一个对象属性。 以第二行属性举例 QPROPERTY(bool enabled READ isEnabl…

Makefile基础使用和实战详解

Makefile基础使用和实战详解一、基础1.1、简单的Makefile1.2、多文件编译1.3、伪对象.PHONY二、变量2.1、自动变量2.2、特殊变量2.3、变量的类别2.4、变量及其值的来源2.5、变量引用的高级功能2.6、override 指令三、模式四、函数4.1、addprefix 函数4.2、filter函数4.3、filte…

【JavaWeb】网络层协议——IP协议

目录 IP协议结构 IP地址管理 特殊IP 解决IP地址不够用 动态分配IP地址 NAT网络地址转换 IPV6 IP协议结构 版本&#xff1a;就是IP协议的版本号。目前只有 4 和 6。这里介绍的是IPV4 首部长度&#xff1a;单位是4字节。于TCP首部长度完全一致&#xff0c;也是可变的&…

python--pygame实现各级菜单栏目设置

随着学期的开始&#xff0c;同学们也即将进入计算机相关课程的课程设计了&#xff0c;对于python课程设计的小伙伴&#xff0c;可能有些是需要利用pygame来写应该小游戏的&#xff0c;因为最近很多小伙伴同学也在想我要一些基于python的pygame模块做的游戏项目&#xff0c;此外…

SpringBoot 2.x 实战专题——SpringBoot 2.6.X版本循环依赖(内含教学视频+源代码)

SpringBoot 2.x 实战专题——SpringBoot 2.6.X版本循环依赖&#xff08;内含教学视频源代码&#xff09; 教学视频源代码下载链接地址&#xff1a;https://download.csdn.net/download/weixin_46411355/87462754 目录SpringBoot 2.x 实战专题——SpringBoot 2.6.X版本循环依赖…

React SSR

ReactDOMServer 参考链接&#xff1a;https://zh-hans.reactjs.org/docs/react-dom-server.html ReactDOMServer 对象允许你将组件渲染成静态标记。通常&#xff0c;它被使用在 Node 服务端上 // ES modules import * as ReactDOMServer from react-dom/server; // CommonJS v…

全栈之路-前端篇 | 第二讲.基础前置知识【应用服务端与编程语言】学习笔记

欢迎关注「全栈工程师修炼指南」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; 涉及 企业运维、网络安全、应用开发、物联网、人工智能、大数据 学习知识 “ 花开堪折直须折&#xff0c;莫待无花…

谓词exsits用法及与in的使用区别

exists用法 大白话的说&#xff0c;exists的执行&#xff0c;是依次拿外层表的每条记录&#xff0c;去和exsits后的子查询表按你所定义的运算规则&#xff08;如果有的话&#xff09;做运算&#xff0c;如果存在结果&#xff0c;也就是有返回数据&#xff0c;无论这部分数据有…

MySQL中使用索引优化

目录 一.使用索引优化 数据准备 避免索引失效应用-全值匹配 避免索引失效应用-最左前缀法则 避免索引失效应用-其他匹配原则 1、 2、 3、 4、 5、 一.使用索引优化 索引是数据库优化最常用也是最重要的手段之一,通过索引通常可以帮助用户解决大多数的MySQL的性能优化…

Pandas库入门仅需10分钟

数据处理的时候经常性需要整理出表格&#xff0c;在这里介绍pandas常见使用&#xff0c;目录如下&#xff1a; 数据结构导入导出文件对数据进行操作 – 增加数据&#xff08;创建数据&#xff09; – 删除数据 – 改动数据 – 查找数据 – 常用操作&#xff08;转置&#xff0…

Linux 配置RAID组

目录 配置RAID&#xff08;软件RAID&#xff09; 创建RAID组 RAID中出现坏盘如何操作 RAID 添加热备盘 删除RAID组 RAID所解决的问题 提升硬盘的I/O吞吐率 提高硬盘的读写能力 提高硬盘的安全性 进行备份 减少硬盘成本 RAID级别 存储RAID——RAID级别_静下心来敲木鱼的博…

Spring Boot中使用@Autowire装配接口是怎么回事?

在学习使用Spring Boot框架时候&#xff0c;发现了一个特别的现象UserMapper是一个接口&#xff0c;在另一个类中好像直接使用Autowired装配了一个UserMapper对象&#xff1f;&#xff1f;&#xff1f;我纳闷了一会儿&#xff0c;接口居然可以直接实例对象吗&#xff1f;根据我…

测试开发之Django实战示例 第十三章 上线

在上一章&#xff0c;为其他程序与我们的Web应用交互创建了RESTful API。本章将学习如何创建生产环境让我们的网站正式上线&#xff0c;主要内容有&#xff1a;配置生产环境创建自定义中间件实现自定义管理命令1创建生产环境现在该将Django项目正式部署到生产环境中了。我们将按…

深度解读依赖注入DI源码

spring-framework-5.3.10 版本依赖注入代码的入口在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean 。如果想搞清楚为什么是这里需要去学习下Bean的生命周期&#xff0c;这里就不介绍了。AutowiredAutowired private OrderServic…

电子科技大学操作系统期末复习笔记(五):文件管理

目录 前言 文件管理&#xff1a;基础 基本概念 文件 文件系统 文件系统的实现模型 文件的组成 文件名 文件分类 文件结构 逻辑结构 物理结构 练习题 文件管理&#xff1a;目录 文件控制块FCB FCB&#xff1a;File Control Block FCB信息 目录 基本概念 目…

CAN通信笔记-位时间、Tq及采样点同步

本文框架1.前言2. 位时间2.1 位时间定义2.2 位时间计算3. Tq3.1 Tq的计算3.1.1 举个例子3.2 位时间与Tq的换算4. 采样点同步4.1 硬同步4.2 重同步4.2.1 延长PBS1的重同步4.2.2 缩短PBS2的重同步1.前言 本篇记录些关于CAN的一些学习笔记&#xff0c;说实话CAN协议发展的已经非常…

【项目设计】—— 负载均衡式在线OJ平台

目录 一、项目的相关背景 二、所用技术栈和开发环境 三、项目的宏观结构 四、compile_server模块设计 1. 编译服务&#xff08;compiler模块&#xff09; 2. 运行服务&#xff08;runner模块&#xff09; 3. 编译并运行服务&#xff08;compile_run模块&#xff09; 4…

MicroBlaze系列教程(6):AXI_IIC的使用(24C04 EEPROM)

文章目录 @[toc]AXI_IIC简介MicroBlaze硬件配置常用函数使用示例波形实测参考资料工程下载本文是Xilinx MicroBlaze系列教程的第6篇文章。 AXI_IIC简介 一般情况下,使用FPGA实现I2C协议主要有两种方式:一种是基于Verilog实现起始位、停止位、ACK产生和判断、数据的发送和接收…

1.HTTP及Template介绍

目录 来源 介绍 模板与渲染 Go语言的模板引擎 模板引擎的使用 定义模板文件 解析模板文件 模板渲染 基本示例 模板语法 {{.}} 注释 pipeline 变量 移除空格 条件判断 range with 预定义函数 比较函数 自定义函数 模板的嵌套template block 修改默认的标…