1、SpringBoot整合WebSocket
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.mmt</groupId>
<artifactId>SpringBootWeb</artifactId>
<version>0.01</version>
<name>SpringBootWeb</name>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- springboot 整合 log4j -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
<!--end springboot 整合 log4j -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!--jsp支持 -->
<!-- servlet 依赖. -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- tomcat 的支持. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
#====================================================
spring.application.name: SpringBootWeb
#server
server.port=80
server.servlet.context-path=/#====================================================
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
2、后端代码:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 开启WebSocket支持
*
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
/**
* @author 008
* WebSocket
*/
@ServerEndpoint("/websocket/{id}")
@Component
public class WebSocketServer {
private static Log log = LogFactory.getLog(WebSocketServer.class);
// 当前在线连接数,要求线程安全。
private static int count = 0;
// concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
// 与某个客户端的连接会话通过它来给客户端发送数据,
private Session session;
// 每个连接的连接标识
private String id = "";
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("id") String id) {
this.session = session;
webSocketSet.add(this);
addcount();
this.id = id;
log.info("有一连接打开!当前连接数为" + getcount());
try {
sendMessage("connect success");
} catch (IOException e) {
log.error("websocket exception: " , e);
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this);
subcount();
log.info("有一连接关闭!当前连接数为" + getcount());
}
/**
* 收到客户端(前端)消息后调用的方法
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info(id + " , message:" + message);
// 群发消息
for (WebSocketServer socket : webSocketSet) {
try {
socket.sendMessage(message);
} catch (IOException e) {
log.error("websocket exception: " , e);
}
}
}
/**
* 异常
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("websocket exception: " , error);
}
/**
* 服务器端主动推送信息到前端
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public static void sendMessage(String id , String message) throws IOException {
log.info(id + " , message:" + message);
for (WebSocketServer socket : webSocketSet) {
if (socket.id.equals(id)) {
socket.sendMessage(message);
}
}
}
public static synchronized int getcount() {
return count;
}
public static synchronized void addcount() {
WebSocketServer.count++;
}
public static synchronized void subcount() {
WebSocketServer.count--;
}
}
@RestController
public class PushController {
//触发WebSocket,向前端发送数据
@RequestMapping("/push/{id}")
public String push(@PathVariable String id, String message) {
try {
WebSocketServer.sendMessage(id , message);
return "success" ;
} catch (IOException e) {
e.printStackTrace();
}
return "failed" ;
}
}
3、页面代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
</head>
<body>
<audio controls="controls" id="my_audio" src="audio/Kalimba.mp3" style="disylay:none;">
your browser dose not support the audio element
</audio>
<span id="msg"></span>
<script type="text/javascript">
var socket;
if(typeof(WebSocket) == "undefined") {
$("#msg").html("您的浏览器不支持WebSocket") ;
console.log("您的浏览器不支持WebSocket");
}else{
$("#msg").html("") ;
console.log("您的浏览器支持WebSocket");
//实现化WebSocket对象,指定要连接的服务器地址与端口 建立连接
socket = new WebSocket("ws://localhost:80/websocket/10");
//打开事件
socket.onopen = function() {
console.log("Socket 已打开");
};
//获得消息事件
socket.onmessage = function(msg) {
console.log("msg : " + msg.data);
//发现消息进入 开始处理前端触发逻辑
if(msg.data == "OK"){
console.log("start play ...");
var my_audio = document.getElementById("my_audio");
my_audio.play();
send() ;
}
};
//关闭事件
socket.onclose = function() {
console.log("Socket已关闭");
};
// 异常
socket.onerror = function() {
alert("Socket发生了错误");
} ;
//发送消息到后端
function send(){
socket.send("已经接收到消息。。。");
}
}
</script>
</body>
</html>
4、测试
打开音频页面: http://localhost/audio.html , 此时不会自动播放音频。
触发WebSocket: http://localhost/push/10?message=OK , websocket给前端发送"OK" , 调用my_audio.play(); 播放音频。
可能会遇到问题: my_audio.play(); 播放音频时可能会遇到浏览器报错:Uncaught (in promise) DOMException ,
谷歌浏览器解决: 谷歌浏览器输入 chrome://flags , 搜索 autoplay-policy , 选择 no user gesture is required , 然后重启浏览器即可。
火狐浏览器:在URL地址栏左边点击开启即可。