java webSocket


测试网站:http://www.websocket-test.com/

前端代码

<template>
    <div class="app switchDisabledClass">
        <el-table  style="100%;" :data="tableData" highlight-current-row border fit>
            <el-table-column type="index" align="center" label="序号" width="60"></el-table-column>
            <el-table-column prop="goodsIdentityCode" align="center" label="识别码" width="210"></el-table-column>
            <el-table-column prop="productName" align="center" label="产品名称" width="210"></el-table-column>
            <el-table-column prop="specification" align="center"  label="规格型号" width="110"></el-table-column>
            <el-table-column prop="batchNumber" align="center" label="批号" width="180"></el-table-column>
            <el-table-column prop="expiryDate" align="center" label="有效期" width="180"></el-table-column>
            <el-table-column prop="productionDate" align="center" label="生产日期" width="180"></el-table-column>
            <el-table-column prop="manufacturerName" align="center" label="生产厂家" width="180"></el-table-column>
        </el-table>
        <br/>
        <el-button type="primary" @click="conSocket">连接WEBSOCKET</el-button>
    </div>
</template>
<script>
export default {
    name: "demo",
    data() {
        return {
            tableData:[],
            socket:''
        }
    },
    //计算属性
    computed: {
    },
    //监控data中的数据变化
    watch: {},
    //方法集合
    methods: {
        //websocket连接
        conSocket(){
            if ("WebSocket" in window){
                alert("您的浏览器支持 WebSocket!");
                // 创建一个 websocket
                this.socket  = new WebSocket("ws://192.168.1.107:8034/socket/00149733FABB");
                // 监听socket连接
                this.socket.onopen = this.onOpen
                // 监听socket消息
                this.socket.onmessage = this.onMessage
                this.socket.onclose  = this.onClose
            }
            else
            {
                // 浏览器不支持 WebSocket
                alert("您的浏览器不支持 WebSocket!");
            }
        },
        onOpen(){
            console.log("socket连接成功")
            this.socket.send('客户端连接成功')
        },
        onMessage(evt){
            this.tableData.push(JSON.parse(evt.data))
        },
        onClose(){
            console.log('socket关闭')
        }
    },
    //生命周期 - 创建完成(可以访问当前this实例)
    created() { },
    //生命周期 - 挂载完成(可以访问DOM元素)
    mounted() {
    },
    activated() { }, //如果页面有keep-alive缓存功能,这个函数会触发
}
</script>
<style lang='scss'>
    .app {
        height: 100%;
         100%;
        user-select: none;
        .item {
            padding: 30px 0;
        }
        .seamless-warp {
            height: 100%;
            overflow: hidden;
        }
    }
</style>

  


后端代码

--引入包

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

package com.example.datasourcedemo.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;


/**
 * @author luwl
 * @date 2021/11/26 17:38
 */
@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {


    //服务器支持跨域
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST","OPTIONS")
                .allowedHeaders("*")
                .exposedHeaders("Access-Control-Allow-Headers",
                        "Access-Control-Allow-Methods",
                        "Access-Control-Allow-Origin",
                        "Access-Control-Max-Age",
                        "X-Frame-Options")
                .allowCredentials(false)
                .maxAge(3600);
    }


    /**
     * The bean shown in the preceding example registers any @ServerEndpoint
     * annotated beans with the underlying WebSocket container. When deployed to a
     * standalone servlet container, this role is performed by a servlet container
     * initializer, and the ServerEndpointExporter bean is not required.
     *
     * @return
     * 在Spring中可以直接使用Java WebSocket API来提供服务,如果使用内置的web容器,需要做的仅仅是需要在下面添加
     */
    /** 注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint 。
     * 要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。*/
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

  

import cn.com.zhengya.framework.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.stereotype.Component;

import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;


/**
 * webSocket客户端
 * @author luwl
 * @date 2021/1/13 10:54
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 * {mac}是传递唯一标识的识别参数
 */
@Slf4j
@Component
@ServerEndpoint("/socket/{mac}")
public class WebSocketServer {

    /**
     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     */
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();

    /**
     * 存活的session集合(使用线程安全的map保存)
     */
    private static Map<String, Session> livingSessions = new ConcurrentHashMap<>();
    /**
     * 在线的连接对象
     */
    private static volatile int livingCount = 0;
    /**
     * 当前的session对象
     */
    private Session session;

    /**
     * 建立连接的回调方法
     *
     * @param session 与客户端的WebSocket连接会话
     * @param mac     硬件MAC地址 唯一
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("mac") String mac) {
        if (!livingSessions.containsKey(mac)) {
            webSocketSet.add(this);
            livingSessions.put(mac, session);
            this.session = session;
            addLivingCount();
            log.info(mac + " 进入连接,当前连接中数量为:" + getLivingCount());
        } else {
            log.info(mac + "重新连接,当前连接中数量为:" + getLivingCount());
        }
    }

    @OnMessage
    public void onMessage(String message, Session session, @PathParam("mac") String mac) {
        log.info(mac + " : " + message);
        sendMessageToAll(message);
    }


    @OnError
    public void onError(Session session, Throwable error) {
        log.info("发生错误");
        log.error(error.getStackTrace() + "");
    }


    @OnClose
    public void onClose(Session session, @PathParam("mac") String mac) {
        webSocketSet.remove(this);
        livingSessions.remove(mac);
        subLivingCount();
        log.info(mac + " 关闭连接,当前连接中数量为:" + getLivingCount());
    }

    /**
     * 单独发送消息到指定用户
     *
     * @param message
     */
    public void sendMessage(String mac, String message) {
        try {
            if (getLivingCount() != 0) {
                livingSessions.get(mac).getBasicRemote().sendText(message);
            } else {
                throw new ServiceException("当前无连接对象");
            }
        } catch (IOException e) {
            log.info("sendMessage error", e);
        }
    }

    /**
     * 单独发送消息到当前用户
     *
     * @param message
     */
    public void sendMessage(String message) {
        try {
            synchronized (this) {
                this.session.getBasicRemote().sendText(message);
            }
        } catch (IOException e) {
            log.info("sendMessage error", e);
        }
    }

    /**
     * 群发消息
     *
     * @param message
     */
    public void sendMessageToAll(String message) {
        if (getLivingCount() != 0) {
            for (WebSocketServer server : webSocketSet) {
                server.sendMessage(message);
            }
        } else {
            throw new ServiceException("当前无连接对象");
        }
    }


    public static synchronized int getLivingCount() {
        return livingCount;
    }

    public static synchronized void addLivingCount() {
        WebSocketServer.livingCount++;
    }

    public static synchronized void subLivingCount() {
        WebSocketServer.livingCount--;
    }

    /**
     * 获取所有连接中对象的标识
     *
     * @return
     */
    public List<String> getAllMac() {
        return new ArrayList<>(livingSessions.keySet());
    }


}

  

-发送消息

@Data
@ApiModel("发送消息给指定的对象")
public class SocketParam {
    @ApiModelProperty("发送对象标识(物理机器的MAC地址)")
    private String mac;
    @ApiModelProperty("消息")
    private String message;
}

  

@Slf4j
@RestController
@RequestMapping("/socket/api")
@Api(value = "socket服务", tags = "socket服务")
public class SocketController {

    @Autowired
    private WebSocketServer webSocketServer;

    @PostMapping("/sendMessageToOne")
    @ApiOperation(value = "发送消息给单个通道")
    public Result<?> sendMessageToOne(@RequestBody SocketParam socketParam){
        webSocketServer.sendMessage(socketParam.getMac(),socketParam.getMessage());
        return Result.success();
    }

    @PostMapping("/sendMessageToALL")
    @ApiOperation(value = "发送消息给所有通道")
    public Result<?> sendMessageToAll(@RequestParam String message){
        webSocketServer.sendMessageToAll(message);
        return Result.success();
    }

    @PostMapping("/getAllSession")
    @ApiOperation(value = "获取所有连接中通道")
    public Result<?> getAllSession(){
        return Result.success(webSocketServer.getAllMac());
    }

}

  




原文地址:https://www.cnblogs.com/Sora-L/p/14271601.html