前后端分离之使用websocket,springboot+vue

---前言提要---

在百度、谷歌、CSDN、博客园...几经折腾之后,终于达到了我想要的结果。springboot+vue,前后端分离项目,网上的大多不是前后端分离,所以排错怎么也排不出,说到底我产生了依赖,只想从网上寻找答案,然后简单的一了百了,而忘记了思考,为什么出错。

其实错误很简单,我是前后端分离,前后端项目的端口都不一样,一个是8080,一个是自定义的63000,在前端发起的请求到了前端,而前端没有启动websocket这个服务,所以连接超时,无关配置无关代码,只是请求错了而已。

这个教训告诉我们,遇到事先自己想一想,想不通的时候再抱着疑问 一边想一边去查资料。

---正确配置---

后端pom:(可参考网上其他教程pom导包)



    org.springframework.boot
    spring-boot-starter-web


    org.springframework.boot
    spring-boot-starter-test
    test
    

    org.springframework.boot
    spring-boot-starter-websocket
    1.3.5.RELEASE

后端websock配置文件:

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

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

 后端websock具体实现:

注意@ServerEndpoint("/websocket")是你连接时的url,如果后端为127.0.0.1:8080,那么前端websocket连接url写为: 127.0.0.1:8080/websocket

import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

import javax.websocket.*;

import lombok.extern.slf4j.Slf4j;

@Slf4j
// @ServerEndpoint("/websocket/{username}")
@ServerEndpoint("/websocket")
@Component // 此注解千万千万不要忘记,它的主要作用就是将这个监听器纳入到Spring容器中进行管理
public class WebSocketServer {
	//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();
 
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    
    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        log.info("有新连接加入!当前在线人数为" + getOnlineCount());
        try {
        	 sendMessage("有新连接加入!当前在线人数为" + getOnlineCount());
        } catch (IOException e) {
            log.error("websocket IO异常");
        }
    }
	//	//连接打开时执行
	//	@OnOpen
	//	public void onOpen(@PathParam("user") String user, Session session) {
	//		currentUser = user;
	//		System.out.println("Connected ... " + session.getId());
	//	}
 
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
    }
 
    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
    	log.info("来自客户端的消息:" + message);
 
        //群发消息
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
	/**
	 * 发生错误
	 * @param session
	 * @param error
	 */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
 
 
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
 
 
    /**
     * 群发自定义消息
     * */
    public static void sendInfo(String message) throws IOException {
    	log.info(message);
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                continue;
            }
        }
    }
 
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
 
    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }
 
    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}

这里要注意的是:

  1. 用onMessage()接收前端用户发来的消息。
  2. 用sendMessage()给前端用户发送消息。

 前端vue主要js:(实际使用可以将我的部分自定义方法去掉)

created() {
  this.webSocket(); // 连接WebSocket
},
destroyed :function() {
  this.websocketclose();
},
methods: {
    say() {
      if (this.websock == null) {
        alert("连接异常:null");
        return 'null'
      }
      if(this.userInput===""){
        this.tips('请输入聊天内容');
      }else{
        this.tips('');
      }
      this.websocketsend(this.userInput);
      this.userInput = '';
    },
    webSocket :function() {
      // 建立socket连接
      if ('WebSocket' in window) {//判断当前浏览器是否支持webSocket
          this.websock = new WebSocket("ws://localhost:63000/websocket");//与后端服务建立连接
      } else {
        alert('你的浏览器暂不支持websocket :(');
      }
      console.log(this.websock);
      this.websock.onopen = this.websocketonopen;
      this.websock.onerror = this.websocketonerror;
      this.websock.onmessage = this.websocketonmessage;
      this.websock.onclose = this.websocketclose;
    },
    websocketonopen :function() {
      console.log("WebSocket连接成功");
      // let data = {
      //   code: 0,
      //   msg: '这是client:初次连接'
      // }
      var data = '这是'+'user'+',加入了连接';
      this.websocketsend(data)
    },
    websocketonerror :function(e) {
      this.tips("WebSocket连接发生错误");
      // console.log("WebSocket连接发生错误");
    },
    websocketonmessage :function(e) { // 数据接收
      // 显示消息内容
      this.setMessageInnerHTML(e.data);
    },
    websocketsend :function (data) { // 数据发送
      // this.tips("数据发送中...");
      this.websock.send(this.niming+": "+data)
    },
    websocketclose :function(e) {
      this.websock.close();
      this.tips("WebSocket连接关闭");
      console.log("connection closed (" + e + ")");// e.code
    },
    //将消息显示在网页上
    setMessageInnerHTML(msg) {
      document.getElementById('message').innerHTML += msg + '
'; }, //提示信息显示在网页上 tips (msg) { document.getElementById('ts').innerHTML = msg ; } }

这里要注意的是:

  1. this.websock = new WebSocket("ws://localhost:63000/websocket");//建立连接,这里的63000是我后端自定义的端口号,请自行改成后端的端口。
  2. 页面created时建立连接,页面close时断开连接。

 

---写在最后---

可能遇到的错误及注意事项:

  • 检查new WebSocket("ws://localhost:8080/websocket");的路径是否正确、是否以ws://开头
  • url是否和后端配置的一致,单词是否拼写正确,导包是否正确
  • 前后端端口号是否重复占用
  • pom引包是否正确
  • tomcat是否使用7以上版本,建议使用tomcat8以及较新的springboot版本
  • 后端配置文件是否注入spring
  • 是否设置了拦截器

参考博文:https://blog.csdn.net/eieiei438/article/details/82879887

 

你可能感兴趣的:(错误以及解决方案,websocket,Vue)