客戶端請(qǐng)求websocket接口,連接通道=》我這邊業(yè)務(wù)成功客戶端發(fā)消息=》客戶端自動(dòng)刷新。
接口:ws://localhost:8080/websocket/xx
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @author Administrator
*/
@Configuration
public class WebSocketConfig implements WebSocketConfigurer {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
package com.xx.framework.web.service;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
@Component
@Slf4j
@ServerEndpoint("/websocket/{key}")
public class WebSocketService {
//與某個(gè)客戶端的連接會(huì)話,需要通過(guò)它來(lái)給客戶端發(fā)送數(shù)據(jù)
private Session session;
private static CopyOnWriteArraySet<WebSocketService> webSockets = new CopyOnWriteArraySet<>();
private static WebSocketService webSocketService;
@PostConstruct
public void init(){
webSocketService = this;
}
/**
* 連接成功后調(diào)用的方法
* @param session
* @param key
*/
@OnOpen
public void onOpen(Session session,@PathParam("key") String key){
//key作為前端傳給后端的參數(shù)值
this.session = session;
webSockets.add(this);
log.info("websocket連接成功");
log.info("websocket有新的連接,連接總數(shù)為"+webSockets.size());
}
/**
* 連接關(guān)閉調(diào)用的方法
*/
@OnClose
public void onClose(){
this.session = null;
webSockets.remove(this);
log.info("websocket連接關(guān)閉");
}
/**
* 收到客戶端消息后調(diào)用的方法,根據(jù)業(yè)務(wù)要求進(jìn)行處理,這里就簡(jiǎn)單地將收到的消息直接群發(fā)推送出去
* @param message 客戶端發(fā)送過(guò)來(lái)的消息
*/
@OnMessage
public void onMessage(Session session,String message){
if (StrUtil.isNotBlank(message)){
if(message.equals("heartbeat")){
sendTextMessage(session,"已連接");
}
}
log.info("WebSocket收到客戶端消息:"+message);
}
/**
* 實(shí)現(xiàn)服務(wù)器主動(dòng)推送消息
* @param session = sessionPool.get(key);
* @param message
*/
private void sendTextMessage(Session session, String message) {
if (session != null){
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendAllMessage(String message){
log.info("websocket消息全部人員消息:"+message);
for (WebSocketService apiWebSocketService:webSockets){
try{
if (apiWebSocketService.session.isOpen()){
apiWebSocketService.session.getAsyncRemote().sendText(message);
}
}catch (Exception e){
e.printStackTrace();
log.error("全部人員發(fā)送消息失敗:",e.getMessage());
}
}
}
/**
* 發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)
* @param session
* @param error
*/
@OnError
public void onError(Session session,Throwable error){
log.error("發(fā)生錯(cuò)誤");
error.printStackTrace();
}
}
經(jīng)測(cè)試,成功
如果是線上服務(wù)器連接,則需要在nginx里配置websocket相關(guān)內(nèi)容,再重啟nginx,代碼如下
server {
listen 443 ssl;
server_name api.kadecard.com;
ssl_certificate cert.pem;
ssl_certificate_key cert.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://xx:7878/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
#websocket 這里的websocket是后端websocket接口的接口名稱
location /websocket {
? ? ? ? ? ? rewrite ^/ws$ / break;
rewrite ^/ws(.*)$ $1 break;
proxy_pass http://127.0.0.1:7878;
proxy_http_version 1.1; #websoket必須要使用的協(xié)議,http 1.1
proxy_set_header Upgrade $http_upgrade; #要使用websocket協(xié)議時(shí),響應(yīng)http升級(jí)請(qǐng)求
proxy_set_header Connection "upgrade";
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_read_timeout 600s;
}
}
本地連接的時(shí)候用的是ws://,因?yàn)槭莌ttp鏈接,但是如果是服務(wù)器連接,且支持https連接方式,則就需要用wss://的連接方式。
如果是在 寶塔配置,則如下:
location /websocket {
##后臺(tái)服務(wù)器地址加上websocket的接口名稱
proxy_pass http://localhost:8084/websocket/; #這里是http不是ws,不用懷疑,代理的ip和port寫ws訪問(wèn)的實(shí)際地址
proxy_http_version 1.1; #這里必須使用http 1.1
#下面兩個(gè)必須設(shè)置,請(qǐng)求頭設(shè)置為ws請(qǐng)求方式
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
還要檢查接口權(quán)限是否開(kāi)放:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-567717.html
類型:SecurityConfig
.antMatchers("/login", "/register", "/captchaImage","/rinter/**","/websocket/**").permitAll()
前端vue:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-567717.html
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<el-input type="text" v-model="msgNew" label="新值"></el-input>
<el-button type="primary" @click="change()">改變值</el-button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data () {
return {
path:"ws://127.0.0.1:8088/websocket/"+this.algorithm(),
socket:"",
msgNew:'',
}
},
mounted () {
// 初始化
this.init()
},
methods: {
algorithm:function(){
let abc=['a','b','c','d','e','f','g','h','i','g','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
let [max,min]=[Math.floor(Math.random()*(10-7+1)+1),Math.floor(Math.random()*(17-10+1)+17)];
abc=abc.sort(()=>0.4-Math.random()).slice(max,min).slice(0,8).join("");
var a=new Date().getTime()+abc;
return a
},
change(){
this.msg=this.msgNew;
this.socket.send(this.msgNew);
},
init: function () {
if(typeof(WebSocket) === "undefined"){
alert("您的瀏覽器不支持socket")
}else{
// 實(shí)例化socket
this.socket = new WebSocket(this.path)
// 監(jiān)聽(tīng)socket連接
this.socket.onopen = this.open
// 監(jiān)聽(tīng)socket錯(cuò)誤信息
this.socket.onerror = this.error
// 監(jiān)聽(tīng)socket消息
this.socket.onmessage = this.getMessage
}
},
open: function () {
console.log("socket連接成功")
this.socket.send("heartbeat");
},
error: function () {
console.log("連接錯(cuò)誤")
this.init()
},
getMessage: function (msg) {
console.log("數(shù)據(jù)接收:"+msg.data)
this.msg=msg.data
},
// 發(fā)送消息給被連接的服務(wù)端
send: function (params) {
console.log("發(fā)送消息給服務(wù)端")
this.socket.send(params)
},
close: function () {
console.log("socket已經(jīng)關(guān)閉")
}
},
destroyed () {
// 銷毀監(jiān)聽(tīng)
this.socket.onclose = this.close
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
main.js文件配置:
import global from '@/utils/wsGlobal.js'
Vue.prototype.$global=global;
初始化的時(shí)候設(shè)置:
this.socket = new WebSocket(this.path+this.token)
this.$global.setWs(this.socket)
其他頁(yè)面引用:
例如消息獲?。?mounted() {
this.$global.ws.onmessage=this.websocketonmessage
},
methods: {
websocketonmessage(e){
console.log("數(shù)據(jù)接收"+e.data);
}
}
到了這里,關(guān)于java后端使用websocket實(shí)現(xiàn)與客戶端之間接收及發(fā)送消息的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!