Springboot配置websocket,https使用 WebSocket 连接

Springboot配置websocket,https使用 WebSocket 连接


提示:本文简单介绍websocket与http的区别及如何在项目中使用websocket,以springboot项目为例

一、http协议与websocket协议区别

  1. WebSocket

一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

用于Web应用中需要实现动态刷新的场景,大量数据定时刷新,数据轮询等操作场景,例如在线聊天、网页游戏、实时数据分析等。支持双向通信,实时性更强,更好的二进制支持,更小的控制开销:协议包头较小。同时支持扩展。

  1. HTTP

一种单向的请求-响应协议,即客户端向服务器发送请求,服务器响应后连接关闭。这种模式限制了服务器主动向客户端推送信息的能力。用户想刷新一次数据就需要请求一次后台。

HTTP更适合于传输静态内容或简单的请求-响应场景,如网页浏览。

二、使用步骤

1.引入库

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2.配置websocket

代码如下(示例):创建WebSocketConfig

@Configuration
public class WebSocketConfig {

	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}
}

代码如下(示例):创建websocket

//注册成组件
@Component
//定义websocket服务器端,它的功能主要是将目前的类定义成一个websocket服务器端。注解的值将被用于监听用户连接的终端访问URL地址
@ServerEndpoint("/websocket")
public class WebSocket {
	private final static Logger log = LoggerFactory.getLogger(WebSocket.class);
	private Session session;
	// 前端请求时一个websocket时
	@OnOpen
	public void onOpen(Session session) {
		this.session = session;
		webSocketSet.add(this);
		log.info("【websocket消息】有新的连接, 总数:{}", webSocketSet.size());
	}
	// 前端关闭时一个websocket时
	@OnClose
	public void onClose() {
		webSocketSet.remove(this);
		log.info("【websocket消息】连接断开, 总数:{}", webSocketSet.size());
	}
	// 前端向后端发送消息
	@OnMessage
	public void onMessage(String message) {
		log.info("【websocket消息】收到客户端发来的消息:{}", message);
	}
	// 新增一个方法用于主动向客户端发送消息
	public static void sendMessage(String message) {
		for (WebSocket webSocket : webSocketSet) {
			log.info("【websocket消息】广播消息, message={}", message);
			try {
				webSocket.session.getBasicRemote().sendText(message);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

3.消息互发
例如:在前端有一个员工表查询页面,要求实现员工表新增数据时,自动刷新员工list页面。

3.1 后台通知

public Map<String, Object> addStaff(Staff staff, Map<String, Object> resultMap) {
		boolean success = staffDao.addStaff(staff);
		if (success) {
			WebSocket.sendMessage("add staff data"); //通知前端
			resultMap.put("data", 1);
		} else {
			resultMap.put("data", 0);
		}
		return resultMap;
	}

3.2 前端接收消息并处理

<script type="text/javascript">
	var websocket = null;
// 判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
	websocket = new WebSocket("ws://localhost:8082/websocket");
} else {
	alert('Not support websocket')
}
// 连接发生错误的回调方法
websocket.onerror = function() {
	console.log("发生错误")
};
// 连接成功建立的回调方法
websocket.onopen = function(event) {
	console.log("建立连接")
}
// 接收到消息的回调方法
websocket.onmessage = function(event) {
	console.log(event.data)
	//此处编写回调成功你要做的事情,例如刷新页面
	window.location.href ="/staff/staffPage";
}
// 连接关闭的回调方法
websocket.onclose = function() {
	console.log("关闭连接")
}

// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
	alert("已关闭连接");
	websocket.close();
}
// 关闭连接
function closeWebSocket() {
	alert("已关闭连接");
	websocket.close();
}
</script>

到这里基本上项目使用websocket动态刷新就完成了,但是这也是基于本地的项目。如果是部署到linux,使用ssl连接的情况下,这种配置又会失效,原因是在默认情况下,Websocket 的 ws 协议使用 80 端口,运行在TLS之上时,wss 协议默认使用 443 端口。其实说白了,wss 就是 ws 基于 SSL 的安全传输。

4.配置服务器https域名
nginx配置域名证书的过程不做介绍,可以参考前面的文章Nginx配置多个ssl域名项目
按照上面的理论,是不是只要将路径的ws替换成wss,路径改为域名即可呢?

websocket = new WebSocket("ws://localhost:8082/websocket");//替换前

websocket = new WebSocket("wss://www.abc.com/websocket");//替换后

替换后发现报错了 This request has been blocked; this endpoint must be available over wss.
wss协议实际是websocket+ssl,是在websocket协议上加入ssl层,类似https(http+ssl),这个时候就需要检查配置的域名证书是否有效,如果证书确认没问题,还需要配置nginx

解决办法:nginx配置websocket,配置完成一定要重启nginx

server{
        listen       80; 
        server_name  www.abc.com;
        rewrite ^(.*) https://$server_name$1 permanent; //配置带不带www都可以访问通
    }
server {
        listen       443 ssl;
        server_name  www.abc.com;

        ssl_certificate      certificate_ssl/abc.com.pem; //自己存放证书的位置
        ssl_certificate_key  certificate_ssl/abc.com.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

		client_max_body_size 50m;
        location / {
            root   html;
            index  index.html index.htm;
	    proxy_set_header x-forwarded-for  $remote_addr;
            proxy_pass http://127.0.0.1:8082/;
			
			#以下为websocket配置关键步骤
			proxy_http_version 1.1;
        	proxy_set_header Upgrade $http_upgrade;
        	proxy_set_header Connection "upgrade";
        	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        	proxy_set_header X-Real-IP $remote_addr;
        }
        error_page   500 502 503 504  /upgrade.html;
        location = /upgrade.html {
            root   html;
        }
    }

不出意外应该大功告成了,如果期间还有不同报错,根据报错内容解决相关问题。


  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值