• Websocket @serverendpoint 404


    今天写一个前后端交互的websocket , 本来写着挺顺利的,但测试的时候蒙了,前端websocket发的连接请求竟然连接不上

    返回状态Status 报了个404 ,然后看后台onError方法也没触发

    只是报了下面几条警告信息

      WARN o.s.web.servlet.PageNotFound | No mapping for GET /websocket/***
      WARN o.s.web.servlet.PageNotFound | No mapping for GET /websocket/***
      WARN o.s.web.servlet.PageNotFound | No mapping for GET /websocket/***

    没头绪,就上网找了一下,

      有说 需要配置Websocket 注入ServerEndpointExporter 的 ;

      有说 需要添加websocket jar包的 

    但看这些操作的缘由,却和我的实际情况不太一样,

    不过也照着做试了一下,依然没有变化。。。

    不由地怀疑,我是在后端代码那边少写了什么???

    于是又仔细看了几遍 几个相关的博客,忽然发现有的加了 @Component 注解,有的没加,有可能问题出现在这里

    果然,在加了这个@Component 注解后,网页和后台的websocket 就连接成功了

    所以,很怀疑那些博客上没加这个注解的,是不是也能连接成功?觉得还是看官方解释好,坑能少踩点!

    后端代码

    HtmlSocketServer

    package com.cloud.simulator.controller;
    
    import java.io.IOException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
    
    import org.springframework.stereotype.Component;
    
    /**
     * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
     * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
     * 即 @ServerEndpoint 可以把当前类变成websocket服务类
     */
    //访问服务端的url地址
    @ServerEndpoint(value = "/websocket/simulator/{userNo}")
    @Component
    public class HtmlSocketServer {
        
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
         
        //concurrent包的线程安全Map,用来存放每个客户端对应的HtmlSocketServer对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
        private static Map<String, HtmlSocketServer> webSocketMap = new ConcurrentHashMap<String, HtmlSocketServer>() ;
    
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
        //当前发消息的客户端的编号
        private String userNo = "" ;
    
        public static Map<String, HtmlSocketServer> getWebSocketMap() {
            return webSocketMap ;
        }
        
        /**
         * 连接成功后调用的方法
         * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
         */
        @OnOpen
        public void onOpen(@PathParam(value = "userNo") String param, Session session) {       
            userNo = param ;
            this.session = session;
            webSocketMap.put(param, this) ;
            //在线数加1
            addOnlineCount();           
            System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
        }
    
        /**
         * 连接关闭调用方法
         */
        @OnClose
        public void onClose() {
            if ( !userNo.equals("") ) {
                webSocketMap.remove(userNo);  
                //在线数减1
                subOnlineCount();           
                System.out.println("关闭一个连接!当前在线人数为" + getOnlineCount());
            }
        }
    
        /**
         * 连接异常
         */
        @OnError
        public void onError(Throwable error) {
            System.out.println("连接异常  ---onError");
            error.printStackTrace();
        }
    
        /**
         * 接收到客户短消息
         */
        @OnMessage
        public void onMessage(String mess) {
            System.out.println("接收到客户端消息  --onMessage  =" + mess);
        }
    
        /**
         * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
         * @param message
         * @throws IOException
         */
        public void sendMessage(String message) throws IOException{
            this.session.getBasicRemote().sendText(message);
            //this.session.getAsyncRemote().sendText(message);
        }
        
        /**
         * 给指定的人发送消息
         * @param message
         */
        public void sendToUser(String toUserNo, String message) {
            String now = getNowTime();
            try {
                HtmlSocketServer htmlSocketServer = webSocketMap.get(toUserNo) ;
                if ( htmlSocketServer != null ) {
                    htmlSocketServer.sendMessage(now + "用户" + userNo + "发来消息:" + message);
                } else {
                    System.out.println("当前接收信息的用户不在线");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 给所有人发消息
         * @param message
         */
        public void sendToAll(String message) {
            String now = getNowTime();
            //遍历HashMap
            for (String key : webSocketMap.keySet()) {
                try {
                    //判断接收用户是否是当前发消息的用户
                    if ( !userNo.equals(key) ) {
                        webSocketMap.get(key).sendMessage(now + "用户" + userNo + "发来消息:" + message);
                     }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
        /**
         * 获取当前时间
         *
         * @return
         */
        private String getNowTime() {
            Date date = new Date();
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String time = format.format(date);
            return time;
        }
    
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
     
        public static synchronized void addOnlineCount() {
            HtmlSocketServer.onlineCount++;
        }
         
        public static synchronized void subOnlineCount() {
            HtmlSocketServer.onlineCount--;
        }
        
    }
    View Code

    WebMvcConfig

    package com.cloud.simulator.configuration;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    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;
    
    
    /**
     * Spring MVC 配置
     */
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        private final Logger logger = LoggerFactory.getLogger(WebMvcConfig.class);
    
        //服务器支持跨域
        @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();
        }
        
    }
    View Code

    共同学习,共同进步,若有补充,欢迎指出,谢谢!

  • 相关阅读:
    中国剩余定理
    hdu1808-Halloween treats(抽屉原理)
    快速幂算法
    因子和与因子个数
    乘性函数
    HDU 2669 Romantic (扩展欧几里得定理)
    扩展欧几里得算法
    Bi-shoe and Phi-shoe(欧拉函数)
    欧拉函数
    [51nod]1284 2 3 5 7的倍数(容斥原理)
  • 原文地址:https://www.cnblogs.com/dengguangxue/p/11497276.html
Copyright © 2020-2023  润新知