java websocket 404_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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.cloud.simulator.controller;importjava.io.IOException;importjava.text.DateFormat;importjava.text.SimpleDateFormat;importjava.util.Date;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;importjavax.websocket.OnClose;importjavax.websocket.OnError;importjavax.websocket.OnMessage;importjavax.websocket.OnOpen;importjavax.websocket.Session;importjavax.websocket.server.PathParam;importjavax.websocket.server.ServerEndpoint;importorg.springframework.stereotype.Component;/*** @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,

* 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端

* 即 @ServerEndpoint 可以把当前类变成websocket服务类*/

//访问服务端的url地址

@ServerEndpoint(value = "/websocket/simulator/{userNo}")

@Componentpublic classHtmlSocketServer {//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。

private static int onlineCount = 0;//concurrent包的线程安全Map,用来存放每个客户端对应的HtmlSocketServer对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识

private static Map webSocketMap = new ConcurrentHashMap() ;//与某个客户端的连接会话,需要通过它来给客户端发送数据

privateSession session;//当前发消息的客户端的编号

private String userNo = "";public static MapgetWebSocketMap() {returnwebSocketMap ;

}/*** 连接成功后调用的方法

*@paramsession 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据*/@OnOpenpublic void onOpen(@PathParam(value = "userNo") String param, Session session) {

userNo=param ;this.session =session;

webSocketMap.put(param,this) ;//在线数加1

addOnlineCount();

System.out.println("有新连接加入!当前在线人数为" +getOnlineCount());

}/*** 连接关闭调用方法*/@OnClosepublic voidonClose() {if ( !userNo.equals("") ) {

webSocketMap.remove(userNo);//在线数减1

subOnlineCount();

System.out.println("关闭一个连接!当前在线人数为" +getOnlineCount());

}

}/*** 连接异常*/@OnErrorpublic voidonError(Throwable error) {

System.out.println("连接异常 ---onError");

error.printStackTrace();

}/*** 接收到客户短消息*/@OnMessagepublic voidonMessage(String mess) {

System.out.println("接收到客户端消息 --onMessage =" +mess);

}/*** 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。

*@parammessage

*@throwsIOException*/

public void sendMessage(String message) throwsIOException{this.session.getBasicRemote().sendText(message);//this.session.getAsyncRemote().sendText(message);

}/*** 给指定的人发送消息

*@parammessage*/

public voidsendToUser(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();

}

}/*** 给所有人发消息

*@parammessage*/

public voidsendToAll(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

*/

privateString getNowTime() {

Date date= newDate();

DateFormat format= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String time=format.format(date);returntime;

}public static synchronized intgetOnlineCount() {returnonlineCount;

}public static synchronized voidaddOnlineCount() {

HtmlSocketServer.onlineCount++;

}public static synchronized voidsubOnlineCount() {

HtmlSocketServer.onlineCount--;

}

}

View Code

WebMvcConfig

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.cloud.simulator.configuration;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;importorg.springframework.web.socket.server.standard.ServerEndpointExporter;/*** Spring MVC 配置*/@Configurationpublic class WebMvcConfig implementsWebMvcConfigurer {private final Logger logger = LoggerFactory.getLogger(WebMvcConfig.class);//服务器支持跨域

@Overridepublic voidaddCorsMappings(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,因为它将由容器自己提供和管理。*/@BeanpublicServerEndpointExporter serverEndpointExporter() {return newServerEndpointExporter();

}

}

View Code

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值