springboot+vue+websocket實現PC端消息實時推送

前端使用了vue框架,增加的代碼比較簡單如下:

//在方法裏調用 this.websocketsend()發送數據給服務器
    onConfirm () {
   		 //需要傳輸的數據
        let data = {
          code: 1,
          item: '傳輸數據'
        }
        this.websocketsend(JSON.stringify(data))
    },
    /*
    */
    initWebSocket () { // 初始化weosocket
      this.websock = new WebSocket('ws://localhost:9090/websocket/dhj')
      this.websock.onmessage = this.websocketonmessage
      this.websock.onerror = this.websocketonerror
      this.websock.onopen = this.websocketonopen
      this.websock.onclose = this.websocketclose
    },
    websocketonopen () { // 連接建立之後執行send方法發送數據
      let data = {
        code: 0,
        msg: '這是client:初次連接'
      }
      this.websocketsend(JSON.stringify(data))
    },
    websocketonerror () { 
    	console.log( 'WebSocket連接失敗')
    },
    websocketonmessage (e) { // 數據接收
      console.log('數據接收' + e.data)
      alert('你有新消息'+ e.data)
    },
    websocketsend (Data) { // 數據發送
      this.websock.send(Data)
    },
    websocketclose (e) {  // 關閉
      console.log('已關閉連接', e)
    }
  },
created () {
    console.log('created')
    this.initWebSocket()
  },
 data() {
return{
websocket: null
}
},
destroyed () {
    this.websock.close() // 離開路由之後斷開websocket連接
  },

前端就這麼多,沒什麼複雜的,不多說

下面是後臺服務:

 

 相關的就是這四個文件,全部將代碼分析,不需要你下載花積分,坑也都解決完畢

首先是pom.xml文件的內容,拿走不謝

<?xml version="1.0" encoding="UTF-8"?>
<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.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mi.msg</groupId>
    <artifactId>mi</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mi</name>
    <description>Msg project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- 添加JSON依賴-->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <!-- 必須添加JDK版本號-->
            <classifier>jdk15</classifier>
        </dependency>

        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.2</version>
        </dependency>

        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.5</version>
        </dependency>

        <dependency>
            <groupId>net.sf.ezmorph</groupId>
            <artifactId>ezmorph</artifactId>
            <version>1.0.3</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.28</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

能用到的依賴都全了,下面是MySpringConfigurator代碼

package com.mi.msg.base;


import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.websocket.server.ServerEndpointConfig;

public class MySpringConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware {

    private static volatile BeanFactory context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MySpringConfigurator.context = applicationContext;
    }

    @Override
    public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
        return context.getBean(clazz);
    }
}

 然後是WebSocketConfig代碼配合上一個來解決websocket初始化連接報404錯誤,其他人的解釋都沒解決,這個可以

package com.mi.msg.base;

import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
@ConditionalOnWebApplication
public class WebSocketConfig {
    //使用boot內置tomcat時需要注入此bean
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }


    @Bean
    public MySpringConfigurator mySpringConfigurator() {
        return new MySpringConfigurator();
    }
}

然後是WebSocket核心接受和發送消息的代碼

package com.mi.msg.base;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint(value = "/websocket/{username}")//, configurator = MySpringConfigurator.class這個地方經驗證不需用加上否則多設備連接回發現兩臺以上設備連接 回造成下面的session變爲同一個,造成其他設備推送失敗,所以不要盲目複製別人的,要注意此處
public class WebSocket {
    private static int onlineCount = 0;
    private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
    private Session session;
    private String username;

    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session) throws IOException {
        this.username = username;
        this.session = session;

        addOnlineCount();
        clients.put(username, this);
        System.out.println("已連接" + getOnlineCount());
    }

    @OnClose
    public void onClose() throws IOException {
        clients.remove(username);
        subOnlineCount();
        System.out.println("已連接" + getOnlineCount());
    }

    @OnMessage
    public void onMessage(String message) throws IOException {
       // DataWrapper res = new DataWrapper();
       // System.out.println("message:" + message);
       // JSONObject req = JSONObject.parseObject(message);


        // 發送數據給服務端
       // sendMessageAll(JSON.toJSONString(res));
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    public void sendMessageTo(String message, String To) throws IOException {
        // session.getBasicRemote().sendText(message);
        // session.getAsyncRemote().sendText(message);
        for (WebSocket item : clients.values()) {
            if (item.username.equals(To))
                item.session.getAsyncRemote().sendText(message);
        }
    }

    public void sendMessageAll(String message) throws IOException {
        for (WebSocket item : clients.values()) {
            item.session.getAsyncRemote().sendText(message);
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocket.onlineCount--;
    }

    public static synchronized Map<String, WebSocket> getClients() {
        return clients;
    }
}

 對點,對羣發送消息都可以,下面是後臺主動觸發,發送消息

@ApiOperation(value="獲取用戶信息",notes="username是唯一屬性,單個用戶可直接通過username獲取") //標註在方法:用以備註接口描述
@PostMapping(value="/user/query")
public String getUserInfo(@RequestBody String username){
    WebSocket ws = new WebSocket();
    try {
        //ws.sendMessageAll(JSON.toJSONString(username));
        ws.sendMessageTo("你有新訂單了",username);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return username;
}

 

指定的人就能收到了,花了一天時間纔打通,後面會實現圖文推送,移動設備推送等都要建立在這個基礎上

加油#######

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章