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());
        }
    
    }
    

      




  • 相关阅读:
    使用linux下的C操作SQLLITE
    s3c6410下移植sqlite3.7.8
    sqlite3在Linux下的安装和使用
    Linux下如何查看哪些进程占用的CPU内存资源最多
    查看LINUX进程内存占用情况
    ssh免密码登陆及其原理
    搭建zookeeper和Kafka集群
    HTTP 错误码
    time 命令
    Shell 运算相关
  • 原文地址:https://www.cnblogs.com/Sora-L/p/14271601.html
Copyright © 2011-2022 走看看