springboot与websocket之简单入门

1.什么是websocket协议?

WebSocket是HTML5中的协议, 他是为了解决客户端发起多个http请求到服务器资源浏览器必须要经过长时间的轮训问题而生的,他实现了多路复用,他是全双工通信。在webSocket协议下客服端和浏览器可以同时发送信息。

2.与http协议的不同

区别 http websocket
链接方式 http1.0即普通http请求,一般都是短链接,一次请求,三次握手,完毕之后立即断开 其实websocket是http协议的升级,http1.1版本默认长链接,长链接代表:一次链接,在一定限期内保持着链接,保持tcp不断开,双方都可以即时通讯,是一种全双工通信协议
场景 http协议更适合普通文件请求,不适合即时通讯,一般我们要得到及时信息,通过http方式,我们就需要不断的轮询,网络资源消耗大 websocket更适合做即及时通讯,不需要不断的轮询,一次链接,长时间有效

3.代码实现

3.1导入pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
	</parent>
	<groupId>com.liuhao.springboot</groupId>
	<artifactId>springboot-websocket</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springboot-websocket</name>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- websocket依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-websocket</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
	</dependencies>
</project>

3.2编写websocketCofig类

package com.liuhao.application.config;

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

@Configuration
public class WebSocketConfig {
    
    

	/**
	 * @return
	 */
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
    
    

		return new ServerEndpointExporter();
	}
}

3.3实现websocket协议类

package com.liuhao.application.pojo;

import java.io.IOException;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

@ServerEndpoint("/websocket/{sid}")
@Component
public class WebSocketServer {
    
    

	// session 会话集合
	private static ConcurrentHashMap<String, Session> map = new ConcurrentHashMap<String, Session>();

	// 当前会话
	private Session session;
	// sid
	private String sid = "";

	/**
	 * 连接
	 * 
	 * @param session 服务器与客户端建立建立连接,生成会话
	 * @param sid     客户端的唯一id
	 */
	@OnOpen
	public void onOpen(Session session, @PathParam("sid") String sid) {
    
    
		this.session = session;
		this.sid = sid;
		System.out.println("有一个连接sid:" + this.sid);
		this.map.put(this.sid, this.session);
	}

	/**
	 * 关闭当前会话
	 */
	@OnClose
	public void onClose() {
    
    
		try {
    
    
			// 从名单中清楚
			this.map.remove(this.sid);
			// 关闭会话
			this.session.close();

			System.out.println("sid:" + sid + "会话被关闭,移除");
		} catch (IOException e) {
    
    
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 接受消息
	 * 
	 * @param message 接受到的消息
	 */
	@OnMessage
	public void onMessage(String message) {
    
    
		try {
    
    
			System.out.println("message:" + message);

			// 广播消息
			for (Entry<String, Session> entry : map.entrySet()) {
    
    
				entry.getValue().getBasicRemote().sendText(message);
			}
		} catch (Exception e) {
    
    
			e.printStackTrace();
		}
	}

	/**
	 * 发送消息
	 * 
	 * @param massage 需要发送消息
	 */
	public void sendMassage(String massage) {
    
    
		try {
    
    
			this.session.getBasicRemote().sendText(massage);
		} catch (Exception e) {
    
    
			e.printStackTrace();
		}
	}
}

3.4前端页面

<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
		<title>Bootstrap 101 Template</title>
		<link rel="stylesheet" type="text/css" href="../css/bootstrap.css" />
		<script src="../js/Vue2.6.11.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<div class="container">
				<form action="" method="">
					<div class="row">
						<div class="form-group col-md-6">
							<label>信息展示:</label>
							<textarea class="form-control" rows="10" cols="" v-model="showContent"></textarea>
						</div>
						<div class="col-md-6">
							<div class="row">
								<div class="form-group col-md-12">
									<label>发送人ID:</label>
									<input type="text" class="form-control" name="" v-model="id" />
								</div>
							</div>
							<div class="row">
								<div class="form-group col-md-12">
									<label>发送信息:</label>
									<textarea class="form-control" rows="6" cols="" v-model="sendContent"></textarea>
								</div>
							</div>
							<div class="row">
								<div class="form-group col-md-6">
									<button type="button" class="btn btn-primary btn-block" @click="sendMsg()">点击发送</button>
								</div>
								<div class="form-group col-md-6">
									<button type="button" class="btn btn-danger btn-block" @click="connect()">连接</button>
								</div>
							</div>
						</div>
					</div>
				</form>
			</div>
		</div>

		<script type="text/javascript">
			var vm = new Vue({
     
     
				el: '#app',
				data: {
     
     
					id: '',
					showContent: '',
					sendContent: '',
					socket: null
				},
				methods: {
     
     
					connect: function() {
     
     
						var lsocket;
						if (typeof(WebSocket) == "undefined") {
     
     
							console.log("您的浏览器不支持WebSocket,请更换浏览器");
							return;
						} else {
     
     
							console.log("您的浏览器支持WebSocket");
							if (this.id.trim() == "") {
     
     
								alert('连接之前必须指定唯一ID')
								return
							}

							lsocket = new WebSocket("ws://localhost:8080/websocket/" + this.id)
							this.socket = lsocket

							this.socket.onopen = function() {
     
     
								console.log('连接已开放')
							}
							this.socket.onerror = function() {
     
     
								alert('websocket出现error')
							}
							this.socket.onmessage = function(msg) {
     
     
								console.log(msg)
								vm.showContent += msg.data
							}
						}
					},
					sendMsg: function() {
     
     
						if(this.sendContent.trim()==""||this.socket==null)
						{
     
     
							alert('不能发送空的信息哦,发送信息前,要先连接')
							return 
						}
						this.socket.send(this.sendContent)
						this.sendContent=''
					}
				},
				created: function() {
     
     

				}
			})
		</script>
	</body>
</html>

3.5App启动类

package com.liuhao.application;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    
    

	public static void main(String[] args) {
    
    
		SpringApplication.run(App.class, args);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42418169/article/details/109178412