zoukankan      html  css  js  c++  java
  • 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());
        }
    
    }
    

      




  • 相关阅读:
    Java实现 蓝桥杯 算法提高 特等奖学金(暴力)
    Java实现 蓝桥杯 算法提高 特等奖学金(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    第一届云原生应用大赛火热报名中! helm install “一键安装”应用触手可及!
    云原生时代,2个方案轻松加速百万级镜像
    Knative 基本功能深入剖析:Knative Serving 自动扩缩容 Autoscaler
  • 原文地址:https://www.cnblogs.com/Sora-L/p/14271601.html
Copyright © 2011-2022 走看看