赞
踩
在我们配置websocket完成之后,测试时发现服务报404;
问题可以分为两个方向去找:
1、配置出现问题导致服务未能正确启动
2、链接地址输错
我是使用@ServerEndpoint注解的方式来实现websocket服务的,使用的框架时SpringMVC或者SpringBoot都可以。
SpringMVC POM文件和具体代码:
- <!--websocketconfig start-->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-websocket</artifactId>
- <version>{spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-messaging</artifactId>
- <version>{spring.version}</version>
- </dependency>
- <!--websocketconfig end-->
- package com.yz.robot.api.controller.websocket;
-
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import org.apache.commons.lang3.StringUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Component;
-
- import javax.websocket.*;
- import javax.websocket.server.PathParam;
- import javax.websocket.server.ServerEndpoint;
- import java.io.IOException;
- import java.util.Date;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
-
- /**
- * @author AlexZ
- */
- @ServerEndpoint(value = "/websocket/{userId}")
- @Component
- public class WebSocketServer {
-
- public static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
- //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
- private static int onlineCount = 0;
- //concurrent包的线程安全Map,用来存放每个客户端对应的MyWebSocket对象。
- private static ConcurrentHashMap<String,WebSocketServer> webSocketSet = new ConcurrentHashMap<String,WebSocketServer>();
- //与某个客户端的连接会话,需要通过它来给客户端发送数据
- private Session session;
- //当前发消息人员编号
- private String sid="";
- /**
- * 连接建立成功调用的方法*/
- @OnOpen
- public void onOpen(@PathParam("userId")String userId, Session session) throws IOException {
- this.session = session;
- this.sid = userId;
- boolean flag = true;
- for (Map.Entry<String, WebSocketServer> entry : webSocketSet.entrySet()) {//大容量时,性能最优方案
- if(entry.getKey().equals(sid)) {
- flag = false;
- }
- }
-
- if(flag == false) {//表示session已经存在该用户
- System.out.println("该用户已连接");
- }else {
- webSocketSet.put(userId,this); //加入set中
- addOnlineCount(); //在线数加1
- System.out.println("有新连接加入!当前在线人数为" + getOnlineCount() + ",当前登陆者为ID:" + this.session.getId() + ",当前登陆者为name:" + sid);
- }
- }
- /**
- * 连接关闭调用的方法
- */
- @OnClose
- public void onClose(@PathParam("userId")String userId) {
- webSocketSet.remove(userId); //从set中删除
- subOnlineCount(); //在线数减1
- log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
- }
-
- /**
- * 收到客户端消息后调用的方法
- *
- * @param message 客户端发送过来的消息
- * @throws IllegalAccessException
- * @throws */
- @OnMessage
- public void onMessage(String message, Session session) throws IOException, IllegalAccessException {
- log.info("收到来自窗口"+sid+"的信息:"+message);
- JSONObject jsonObject = JSON.parseObject(message);
-
- insert2Message(message);
-
- }
- /**
- * 自定义发送消息
- * @throws IllegalAccessException
- * @throws
- * */
- public void sendInfo(String message) throws IOException, IllegalAccessException {
- log.info("收到来自窗口的信息:"+message);
- insert2Message(message);
- }
- /**
- *
- * @param session
- * @param error
- */
- @OnError
- public void onError(Session session, Throwable error) {
- log.error("发生错误");
- error.printStackTrace();
- }
-
-
- public void sendMessage(String message) throws IOException {
- this.session.getBasicRemote().sendText(message);
- }
-
- public static synchronized int getOnlineCount() {
- return onlineCount;
- }
-
- public static synchronized void addOnlineCount() {
- WebSocketServer.onlineCount++;
- }
-
- public static synchronized void subOnlineCount() {
- WebSocketServer.onlineCount--;
- }
-
- private void insert2Message(String message) throws IOException, IllegalAccessException {
- //返回的信息
- JSONObject jsonObject = JSON.parseObject(message);
- String receiverId = jsonObject.getString("receiverId");
- try {
- if(webSocketSet.get(receiverId) != null) {//没有session则不做操作
- //发送
- webSocketSet.get(receiverId).sendMessage(message);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
- }
注意点:websocketserver相当于服务器,我们需要好将这个类放到controller层中,如果我们放到service层中还是会出现404问题。
SpringBoot 基本与上面一致,如果不行需要加一个配置文件代码如下:
- package com.hzys.config.webSocket;
-
- import com.hzys.core.service.webSocket.WebSocketServer;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.messaging.simp.config.MessageBrokerRegistry;
- import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
- import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
- import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
- import org.springframework.web.socket.server.standard.ServerEndpointExporter;
-
- /**
- * @author AlexZ
- *
- */
- @Configuration
- public class WebSocketConfig{
-
- @Bean
- public ServerEndpointExporter serverEndpointExporter()
- {
- return new ServerEndpointExporter();
- }
-
- }
注意点SpringMVC不需要这个配置,SpringBoot使用内置容器时使用。
按照以上配置第一点问题算是解决了。
一般在本地启动使用ws://localhost:8080/websocket/{userId}
都可以正常启动其中注意点是 端口号与tomcat一致,端口号8080与websocket之间是不是需要加项目名(和自己配置有关)
保证如上注意点正确,即可链接成功!
但是我们将项目部署到自己的linux或者阿里云上,又报404
这里我们检查的东西和上面说的是一样的,但是要特别注意端口号,因为有的项目会使用nginx将正真的tomcat端口号隐藏起来,这里我们是需要正真的tomcat端口号。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。