热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

springboot+websocket+语音交互(互相交互使用)

我提倡的是用白话文,和经验去传承分享程序,让程序更加开源话,共享化,让后来者,初学者,遇到此类困

我提倡的是用白话文,和经验去传承分享程序,让程序更加开源话,共享化,让后来者,初学者,遇到此类困难者等,少走弯路,提高效率,不喜勿喷。有更好的建议,可以留言探讨。。。。


首先说下此案例当时做的时候有点复杂,最后还是克服完成。拿出来广大网友分享,但愿能帮助你在java程序的道路上越走越远。。。
背景:
客户通过网页,在通过websocket协议,和Java后端创建连接,在通过Java后端和语音交互接口创建连接,接收到的返回数据,返回给前端在页面展示出来。Java就是做了一个中间件的作用。即是服务端又是客户端。



  1. 说完背景,直接上干货

  • maven依赖

org.java-websocketJava-WebSocket1.4.0org.springframework.bootspring-boot-starter-websocket

  • 代码

  • Java后端接口与前端交互(服务端)

package com.datago.robot.common.utils;import com.datago.robot.entity.DatagoApiWithBLOBs;
import com.datago.robot.service.DatagoApiService;
import org.java_websocket.client.WebSocketClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;/****/
@ServerEndpoint("/serverVue/{apiCode}")
@Component
public class SocketServerUtils {private Logger log = LoggerFactory.getLogger(SocketServerUtils.class);private Session session;private WebSocketClient client;private String apiCode;/*** 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/private static int OnlineCount= 0;/*** concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。* 在外部可以获取此连接的所有websocket对象,并能对其触发消息发送功能,我们的定时发送核心功能的实现在与此变量*/private static CopyOnWriteArraySet webSocketMap = new CopyOnWriteArraySet();private static DatagoApiService datagoApiService;@Autowiredpublic void setDatagoApiService(DatagoApiService datagoApiService) {SocketServerUtils.datagoApiService = datagoApiService;}/*** 建立连接** @param apiCode* @param session*/@OnOpenpublic void onOpen(@PathParam(value = "apiCode") String apiCode, Session session) {this.session = session;addOnlineCount();webSocketMap.add(this);//连接调用第三方服务client = SocketResultUtils.getClient("ws://192.168.0.109:8013/websocket");}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的音频数据*/@OnMessagepublic void onMessage(@PathParam(value = "apiCode") String apiCode, byte[] message) {log.info("音频数据报文:" + message);try {//在线client.send(message);ExceptionLog.isSuccess(apiCode, null,null);} catch (Exception e) {//离线isconnct(apiCode);client.send(message);ExceptionLog.isSuccess(apiCode, null,null);}}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的字符数据*/@OnMessagepublic void onMessage(@PathParam(value = "apiCode") String apiCode, String message) {log.info("字符数据报文:" + message);try {//在线client.send(message);ExceptionLog.isSuccess(apiCode, message,null);} catch (Exception e) {//离线isconnct(apiCode);client.send(message);ExceptionLog.isSuccess(apiCode, message,null);}}/*** 连接关闭调用的方法*/@OnClosepublic void onClose(@PathParam(value = "apiCode") String apiCode) {//请求第三方关闭连接webSocketMap.remove(this);subOnlineCount();log.info("有一连接关闭!当前在线人数为" + getOnlineCount());}/*** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error, @PathParam(value = "apiCode") String apiCode) {log.error("错误原因:" + error.getMessage());}/*** 新加* 判断连接(在线,离线)** @param apiCode*/private void isconnct(String apiCode) {DatagoApiWithBLOBs datagoApi = datagoApiService.selectByApiCode(apiCode);if (Utils.isNotEmpty(datagoApi)) {//判断在线(true),离线(false)// 在线String apiUrl = datagoApi.getApiUrl();if (apiUrl.startsWith("ws")) {client = SocketResultUtils.getClient(apiUrl);if (Utils.isEmpty(client)) {//离线String apiOffUrl = datagoApi.getApiOffUrl();if (apiOffUrl.startsWith("ws")) {client = SocketResultUtils.getClient(apiOffUrl);if (Utils.isEmpty(client)) {ExceptionLog.isConnect(apiCode, null);}} else {ExceptionLog.isUrl(apiCode, null);}}} else {ExceptionLog.isUrl(apiCode, null);}}}/*** 实现服务器主动推送** @param message*/public void sendMessage(String message) {try {this.session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();}}public static synchronized int getOnlineCount() {return onlineCount;}public static synchronized void addOnlineCount() {SocketServerUtils.onlineCount++;}public static synchronized void subOnlineCount() {SocketServerUtils.onlineCount--;}public static CopyOnWriteArraySet getWebSocketSet() {return webSocketMap;}public static void setWebSocketSet(CopyOnWriteArraySet webSocketSet) {SocketServerUtils.webSocketMap = webSocketSet;}}

  • Java与第三方服务交互代码(客户端),接收第三方服务的返回数据

package com.datago.robot.common.utils;import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;import java.net.*;import java.util.concurrent.CopyOnWriteArraySet;@Slf4j
@Component
public class SocketResultUtils {public static Logger log = LoggerFactory.getLogger(SocketResultUtils.class);/*** 获取客户端连接实例** @param uri* @return*/public static WebSocketClient getClient(String uri) {try {//创建客户端连接对象WebSocketClient client = new WebSocketClient(new URI(uri), new Draft_6455()) {/*** 建立连接调用* @param serverHandshake*/@Overridepublic void onOpen(ServerHandshake serverHandshake) {log.info("建立连接");}/*** 收到服务端消息调用* @param s*/@Overridepublic void onMessage(String s) {log.info("处理结束返回消息:" + s);//接收第三方websocket服务发送数据CopyOnWriteArraySet webSocketSet =SocketServerUtils.getWebSocketSet();if (Utils.isNotEmpty(webSocketSet)) {int i = 0;synchronized (webSocketSet) {webSocketSet.forEach(c -> {//返回前端数据log.info("返回结果数据, data = {}", s);for (int j = 0; j <10; j++) {c.sendMessage(s);}});log.info("收到来自服务端的消息:::" + s);}}}/*** 断开连接调用* @param i* @param s* @param b*/@Overridepublic void onClose(int i, String s, boolean b) {log.info("关闭连接:::" + "i = " + i + ":::s = " + s + ":::b = " + b);}/*** 连接报错调用* @param e*/@Overridepublic void onError(Exception e) {log.error("报错了:::" + e.getMessage());}};//请求与服务端建立连接client.connect();//判断连接状态,0为请求中 1为已建立 其它值都是建立失败while (client.getReadyState().ordinal() == 0) {try {Thread.sleep(200);} catch (Exception e) {log.warn("延迟操作出现问题,但并不影响功能");}log.info("连接中。。。");break;}//连接状态不再是0请求中,判断建立结果是不是1已建立if (client.getReadyState().ordinal() == 1) {return client;}} catch (URISyntaxException e) {log.error(e.getMessage());}return null;}
}

推荐阅读
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • Python实现变声器功能(萝莉音御姐音)的方法及步骤
    本文介绍了使用Python实现变声器功能(萝莉音御姐音)的方法及步骤。首先登录百度AL开发平台,选择语音合成,创建应用并填写应用信息,获取Appid、API Key和Secret Key。然后安装pythonsdk,可以通过pip install baidu-aip或python setup.py install进行安装。最后,书写代码实现变声器功能,使用AipSpeech库进行语音合成,可以设置音量等参数。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
  • 一、路由首先需要配置路由,就是点击good组件进入goodDetail组件配置路由如下{path:goodDetail,component:goodDetail}同时在good组件中写入如下点击事件,路由中加入 ... [详细]
  • Allegro总结:1.防焊层(SolderMask):又称绿油层,PCB非布线层,用于制成丝网印板,将不需要焊接的地方涂上防焊剂.在防焊层上预留的焊盘大小要比实际的焊盘大一些,其差值一般 ... [详细]
author-avatar
o.o
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有