将 React 客户端连接到 Netty SocketIO Spring Boot 后端会导致核心问题

问题描述 投票:0回答:1

我正在尝试将我的

Next.js
前端连接到我正在使用
Spring boot
服务器的
netty socketio
后端。

我在浏览器控制台中收到 404 错误。

这是我的后端代码:

@Configuration
public class SocketIOConfig {
    @Bean
    public SocketIOServer socketIOServer() {
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        config.setPort(8081);
        config.setOrigin("*");
        return new SocketIOServer(config);
    }
}

我还在我的主应用程序类中添加了

cors

@Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        source.registerCorsConfiguration("/**", config);
        registrationBean.setFilter(new CorsFilter(source));
        registrationBean.setOrder(0);
        return registrationBean;
    }

@Component
public class SocketIOServerRunner implements CommandLineRunner {
    private final SocketIOEvents socketIOEvents;

    @Autowired
    public SocketIOServerRunner(SocketIOEvents socketIOEvents) {
        this.socketIOEvents = socketIOEvents;
    }

    @Override
    public void run(String... args) {
        socketIOEvents.init();
    }
}

@Component
public class SocketIOEvents {
    private final SocketIOServer server;

    @Autowired
    public SocketIOEvents(SocketIOServer server) {
        this.server = server;
    }

    public void init() {
        server.addConnectListener(client -> {
            System.out.println("Client connected: " + client.getSessionId());
            server.getBroadcastOperations().sendEvent("messageFromServer", "Client connected: " + client.getSessionId());
        });

        server.addDisconnectListener(client -> {
            System.out.println("Client disconnected: " + client.getSessionId());
        });

        server.addEventListener("messageFromClient", String.class, (client, data, ackSender) -> {
            System.out.println("Received message: " + data);
            server.getBroadcastOperations().sendEvent("messageFromServer", data);
        });
    }
}

这是我的前端

Next.js
代码:

"use client";

import { useEffect, useState } from "react";
import { io } from "socket.io-client";

export default function Home() {
  const [input, setInput] = useState("");
  const [messages, setMessage] = useState<string[]>([]);

  const socket = io("http://localhost:8080");

  useEffect(() => {
    socket.on("connect", () => {
      console.log(socket.id);
    });

    socket.on("messageFromServer", (data) => {
      console.log(data);
      setMessage((oldArray) => [...oldArray, data.data]);
    });

    socket.io.on("reconnect", (data) => {
      console.log("reconnect event");
      console.log(data);
    });
  }, []);

  const onChangeHandler = (event: any) => {
    setInput(event.target.value);
  };

  return (
    <div style={{ display: "flex", flexDirection: "column" }}>
      <input type="text" onChange={onChangeHandler} value={input} />
      <button
        onClick={() => {
          console.log("here");
          socket.emit("messageFromClient", { data: input });
        }}>
        Submit
      </button>
      {messages.map((item, index) => {
        return <h5 key={`${index}`}>{item}</h5>;
      })}
    </div>
  );
}

完整源代码这里

尝试使用

Next.js
服务器将
Spring Boot
前端连接到
Netty Socket.IO
后端时,在浏览器控制台中遇到 404 错误。

java spring-boot next.js socket.io netty-socketio
1个回答
0
投票

在进入代码之前,我必须说,websocket-webflux必须有更好的解决方案,因为在这个项目中,您将 Tomcat 与 Netty 一起使用,这可能会在生产中产生线程问题。在 tomcat 上配置 CORS 是不必要的,因为 Netty 应该在该项目的不同端口上工作。我们不能在同一端口上运行 Tomcat 和 Netty。

关于前端代码,我们不应该使用这样的Effect,因为它会将套接字放入重新连接的循环中。为了防止这种情况,最好直接打电话给

connect
并关闭
autoConnect

const chatSocket = io("http://192.168.0.11:18085", {
    autoConnect: false
});

对于页面本身

    useEffect(() => {
        chatSocket.connect();
    }, []);

这将使客户端仅连接一次。对于整页

"use client"

import React, {useEffect, useState} from 'react';
import chatSocket from "@/app/socket";

export default function Home() {
    const [input, setInput] = useState("");
    const [messages, setMessage] = useState<string[]>([]);

    let onConnect = () => {
        console.log("connected:" + chatSocket.id);
    };
    let onDisconnect = () => {
        console.log("disconnected");
    };

    let onMessageEvent = (data: string) => {
        setMessage([...messages, data]);
    };
    chatSocket.on("connect", onConnect);
    chatSocket.on("disconnect", onDisconnect);
    chatSocket.on("messageFromServer", onMessageEvent);
    useEffect(() => {
        chatSocket.connect();
    }, []);
    const onChangeHandler = (event: any) => {
        setInput(event.target.value);
    };

    const onClickHandler = () => {
        console.log("here" + input);
        chatSocket.emit("send_message", {chatMessage: input, id: chatSocket.id, timestamp: Date.now()});
    };

    return (
        <div style={{display: "flex", flexDirection: "column"}}>
            <input type="text" onChange={onChangeHandler} value={input}/>
            <button onClick={onClickHandler}>Submit {messages.length}</button>
            {messages.map((item, index) => {
                return <h5 key={`${index}`}>{item}</h5>;
            })}
        </div>
    );
}

对于后端SocketIOServerRunner已删除,其他文件如下更改

@Configuration
public class SocketIOConfig {

    @Value("${socket-server.host}")
    private String host;

    @Value("${socket-server.port}")
    private Integer port;

    @Bean
    public SocketIOServer socketIOServer() {
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        config.setHostname(host);
        config.setPort(port);
        return new SocketIOServer(config);
    }
}
@Component
public class SocketIOEvents {
    public static final String MESSAGE_FROM_SERVER = "messageFromServer";
    private final SocketIOServer server;

    @Autowired
    public SocketIOEvents(SocketIOServer server) {
        this.server = server;
        server.addConnectListener(onConnected());
        server.addDisconnectListener(onDisconnected());
        server.addEventListener("send_message", Message.class, onChatReceived());
    }

    private DataListener<Message> onChatReceived() {
        return (client, message, ackSender) -> {
            System.out.println("Received message: " + message);
            server.getBroadcastOperations().sendEvent(MESSAGE_FROM_SERVER, message.chatMessage);
        };
    }

    private DisconnectListener onDisconnected() {
        return client -> {
            System.out.println("Client disconnected: " + client.getSessionId());
            server.getBroadcastOperations().sendEvent(MESSAGE_FROM_SERVER, "Client disconnected: " + client.getSessionId());
        };
    }

    private ConnectListener onConnected() {
        return client -> {
            System.out.println("Client connected: " + client.getSessionId());
            client.joinRoom("room");
            server.getBroadcastOperations().sendEvent(MESSAGE_FROM_SERVER, "Client connected: " + client.getSessionId());
        };
    }

    record Message(String id, String chatMessage, String timestamp) {
    }
}

应用程序.属性

socket-server.port=18085
socket-server.host=192.168.0.11

非常感谢转载者。

参考资料:

© www.soinside.com 2019 - 2024. All rights reserved.