我正在尝试将我的
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 错误。
在进入代码之前,我必须说,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
参考资料: