这里写自定义目录标题
websocket简介websocket协议与http协议的区别项目实战前端部分(客户端)后端代码,集成springbootsocket配置文件websocket服务端代码
websocket提供了发送信息的方法encode代码decode代码
websocket简介
websocket协议与http协议的区别
HTTP协议介绍.
websocket介绍 首先,Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说。 简单的举个例子吧,用目前应用比较广泛的PHP生命周期来解释。
HTTP的生命周期通过Request来界定,也就是一个Request 一个Response,那么在HTTP1.0中,这次HTTP请求就结束了。 在HTTP1.1中进行了改进,使得有一个keep-alive,也就是说,在一个HTTP连接中,可以发送多个Request,接收多个Response。 但是请记住 Request = Response , 在HTTP中永远是这样,也就是说一个request只能有一个response。而且这个response也是被动的,不能主动发起。
项目实战
前端部分(客户端)
<!DOCTYPE html
>
<html lang
="en">
<head
>
<meta charset
="UTF-8">
<script src
="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script
>
<title
>Java后端WebSocket实现
</title
>
</head
>
<body
>
信息框
:<input id
="text" type
="text"/>
<button onclick
="send()">发送
</button
>
<hr
/>
<button onclick
="closeWebSocket()">关闭WebSocket连接
</button
>
<hr
/>
收到的信息如下
:</br
>
<div id
="message">
</div
>
</body
>
<script type
="text/javascript">
if(typeof(WebSocket
) == "undefined") {
alert("您的浏览器不支持WebSocket");
}
var webSocket
= new WebSocket("ws://localhost:8080/websocket");
webSocket
.onerror = function () {
setMessageInnerHTML("WebSocket连接发生错误");
};
webSocket
.onopen = function () {
alert(132)
setMessageInnerHTML("WebSocket连接成功");
}
webSocket
.onmessage = function (event
) {
setMessageInnerHTML(event
.data
);
}
webSocket
.onclose = function () {
setMessageInnerHTML("WebSocket连接关闭");
}
window
.onbeforeunload = function () {
closeWebSocket();
}
function closeWebSocket() {
webSocket
.close();
}
function send() {
var message
= $('#text').val();
webSocket
.send(message
);
$("#text").val("");
}
var val
= "";
function setMessageInnerHTML(innerHTML
) {
var temp
= '<br/>' + innerHTML
+ '<br/>';
val
= val
+ temp
;
$("#message").html(val
);
}
</script
>
</html
>
后端代码,集成springboot
websocket的依赖
<!-- springboot版本
-->
<parent>
<groupId>org
.springframework
.boot
</groupId
>
<artifactId>spring
-boot
-starter
-parent
</artifactId
>
<version>2.3.1.RELEASE
</version
>
<relativePath
/> <!-- lookup parent from repository
-->
</parent
>
<!--websocket依赖
-->
<dependency>
<groupId>org
.springframework
.boot
</groupId
>
<artifactId>spring
-boot
-starter
-websocket
</artifactId
>
</dependency
>
socket配置文件
package com
.example
.demo
.config
;
import org
.springframework
.context
.annotation
.Bean
;
import org
.springframework
.context
.annotation
.Configuration
;
import org
.springframework
.web
.socket
.config
.annotation
.EnableWebSocket
;
import org
.springframework
.web
.socket
.config
.annotation
.StompEndpointRegistry
;
import org
.springframework
.web
.socket
.config
.annotation
.WebSocketMessageBrokerConfigurer
;
import org
.springframework
.web
.socket
.server
.standard
.ServerEndpointExporter
;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Bean
public ServerEndpointExporter
serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry
) {
registry
.addEndpoint("/websocket").setAllowedOrigins("*").withSockJS();
}
}
websocket服务端代码
如果需要写的带参数的话可以选择使用使用restful风格每一个客户端连接带当前服务端时候,都会生成一个session对象,表示当前websocket长连接已经连接成功.服务端向客户端发送消息也是通过session对象提供的方法发送信息.
package com
.example
.demo
;
import com
.example
.demo
.util
.WebSocketMapUtil
;
import org
.springframework
.stereotype
.Component
;
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
.ServerEndpoint
;
@Component
@ServerEndpoint(value
= "/websocket")
public class MyWebSocket{
private Session session
=null
;
private static CopyOnWriteArraySet
<MyWebSocket> webSocketSet
= new CopyOnWriteArraySet<>();
@OnOpen
public void onOpen(Session session
) throws Exception
{
this.session
= session
;
System
.out
.println(this);
webSocketSet
.add(this);
}
@OnClose
public void onClose() throws Exception
{
webSocketSet
.remove(this);
}
@OnMessage
public void onMessage(String message
, Session session
) throws IOException
{
for(MyWebSocket item
: webSocketSet
){
item
.session
.getBasicRemote().sendText(message
);
}
}
@OnError
public void onError(Session session
, Throwable error
){
error
.printStackTrace();
}
public void sendMessage(String message
) throws IOException
{
this.session
.getBasicRemote().sendText(message
);
}
public void sendMessageAll(String message
) throws IOException
{
for(MyWebSocket myWebSocket
: WebSocketMapUtil
.getValues()){
myWebSocket
.sendMessage(message
);
}
}
}
websocket提供了发送信息的方法
this.session.getBasicRemote()对象的方法.
sendMessage(String message) 发送字符串数据sendObject(Object obj) 发送对象类型的数据,obj要求被encode才行,不然会报异常;
encode代码
本质 sendObject方法在调用时候,会先将参数obj进行encode,然后才会将encode后的数据发送给客户端. 其实就是将对象解析成字符串形式,再发送;
这里推荐使用sendMessage方法,手动将参数对象进行解析成json字符串(使用alibb的fastjson依赖和方法).
package com
.example
.demo
.websocket
;
import com
.alibaba
.fastjson
.JSON
;
import com
.example
.demo
.bean
.Per
;
import javax
.websocket
.EncodeException
;
import javax
.websocket
.EndpointConfig
;
public class WebSocketEncoder implements javax.websocket.Encoder.Text<Per> {
@Override
public void destroy() {
}
@Override
public void init(EndpointConfig arg0
) {
}
@Override
public String
encode(Per param
) throws EncodeException
{
return JSON
.toJSONString(param
);
}
}
decode代码
对客户端发送的数据(String)编码成指定对象格式本质依然是使用的alibb的fastjson方法;
package com
.example
.demo
.websocket
;
import com
.alibaba
.fastjson
.JSON
;
import com
.example
.demo
.bean
.Per
;
import javax
.websocket
.DecodeException
;
import javax
.websocket
.EndpointConfig
;
public class WebSocketDecoder implements javax.websocket.Decoder.Text<Per> {
@Override
public void destroy() {
}
@Override
public void init(EndpointConfig arg0
) {
}
@Override
public Per
decode(String user
) throws DecodeException
{
return JSON
.parseObject(user
, Per
.class);
}
@Override
public boolean willDecode(String arg0
) {
return true;
}
}