A Java server framework designed based on the Socket.IO protocol, built on top of the high-performance Netty network framework. This project is inspired by the netty-socketio open-source project and adds annotation-driven development and multi-endpoint support features.
- Features
- Quick Start
- Core Concepts
- Annotations
- Usage Examples
- Configuration
- Advanced Features
- Performance Optimization
- FAQ
- References
- π High Performance: Built on Netty asynchronous I/O framework, supporting high concurrent connections
- π‘ Socket.IO Compatible: Fully compatible with Socket.IO protocol, supporting WebSocket and HTTP long polling
- π― Annotation-Driven: Annotation-based event handling, simplifying development workflow
- π Multi-Endpoint Support: Support for multiple WebSocket endpoints with flexible routing configuration
- π Rooms & Namespaces: Complete room management and namespace isolation mechanism
- π’ Broadcast Operations: Support for global broadcast, room broadcast, and various message distribution methods
- π Interceptor Mechanism: Support for connection authentication, message interception, and middleware functionality
- π¦ Binary Data: Support for binary data transmission
- ποΈ Flexible Configuration: Rich configuration options to adapt to different business scenarios
- Java 8+
- Maven 3.6+
- Teambeit Cloud Microservices Framework 1.0+
<dependency>
<groupId>cloud.apposs</groupId>
<artifactId>teambeit-socketio</artifactId>
<version>1.0.0</version>
</dependency>import cloud.apposs.socketio.SocketIOSession;
import cloud.apposs.socketio.annotation.*;
@ServerEndpoint("/socket.io")
public class ChatEndpoint {
@OnConnect
public void onConnect(SocketIOSession session) {
System.out.println("Client connected: " + session.getSessionId());
}
@OnEvent("message")
public void onMessage(SocketIOSession session, String message) {
System.out.println("Received message: " + message);
// Reply with message
session.sendEvent("message", "Server reply: " + message);
}
@OnDisconnect
public void onDisconnect(SocketIOSession session) {
System.out.println("Client disconnected: " + session.getSessionId());
}
}import cloud.apposs.socketio.SocketIOApplication;
public class ChatApplication {
public static void main(String[] args) throws Exception {
SocketIOApplication.run(ChatApplication.class, args);
}
}const socket = io('http://localhost:9092');
socket.on('connect', () => {
console.log('Connected successfully');
socket.emit('message', 'Hello, server!');
});
socket.on('message', (data) => {
console.log('Received message:', data);
});The application context is the core container of the entire SocketIO service, responsible for managing the service lifecycle, configuration information, and component registration.
Namespaces provide logical isolation mechanisms where clients in different namespaces are independent of each other. The default namespace is /.
Rooms are a further grouping mechanism within namespaces, allowing clients to join or leave rooms for precise message broadcasting.
Each connected client corresponds to a Session object containing connection information, authentication status, etc.
Defines WebSocket server endpoints, supporting multi-path matching.
@ServerEndpoint({"/socket.io", "/ws"})
public class MultiPathEndpoint {
// Endpoint logic
}Attributes:
value: Path array, supporting multiple path mappings to the same endpointhost: Host matching rule, default is*(matches all hosts)
Marks callback methods for connection establishment.
@OnConnect
public void handleConnect(SocketIOSession session) {
// Connection establishment handling logic
}Marks event handling methods, supporting multiple parameter types.
@OnEvent("chat")
public void handleChat(SocketIOSession session, ChatMessage message) {
// Event handling logic
}
@OnEvent("multidata")
public void handleMultiData(SocketIOSession session, String text, Integer count, ChatObject obj) {
// Supports multiple parameters
}Marks callback methods for connection disconnection.
@OnDisconnect
public void handleDisconnect(SocketIOSession session) {
// Disconnection handling logic
}Marks error handling methods.
@OnError
public void handleError(Throwable error) {
// Error handling logic
}Controls the execution order of multiple handling methods for the same event.
@OnConnect
@Order(1)
public void firstHandler(SocketIOSession session) {
// Execute first
}
@OnConnect
@Order(2)
public void secondHandler(SocketIOSession session) {
// Execute second
}@ServerEndpoint("/chat")
public class ChatRoomEndpoint {
@OnConnect
public void onConnect(SocketIOSession session) {
// Join default room
session.joinRoom("lobby");
session.getRoomOperations("lobby").sendEvent("userJoin",
"User " + session.getSessionId() + " joined the chat room");
}
@OnEvent("sendMessage")
public void onSendMessage(SocketIOSession session, ChatMessage message) {
// Broadcast message to room
session.getRoomOperations("lobby").sendEvent("receiveMessage", message);
}
@OnEvent("joinRoom")
public void onJoinRoom(SocketIOSession session, String roomName) {
session.leaveRoom("lobby");
session.joinRoom(roomName);
session.sendEvent("roomChanged", roomName);
}
}@ServerEndpoint("/binary")
public class BinaryEndpoint {
@OnEvent("uploadFile")
public void onUploadFile(SocketIOSession session, byte[] fileData) {
// Handle binary file data
System.out.println("Received file, size: " + fileData.length + " bytes");
// Return processing result
session.sendEvent("uploadResult", "File upload successful");
}
}@Component
public class AuthInterceptor implements CommandarInterceptor {
@Override
public boolean isAuthorized(HandshakeData handshakeData) throws Exception {
// Pre-connection authentication
String token = handshakeData.getSingleUrlParam("token");
return validateToken(token);
}
@Override
public boolean onEvent(Commandar commandar, SocketIOSession session, List<Object> arguments) {
// Event interception
System.out.println("Intercepting event: " + commandar.getEventName());
return true;
}
@Override
public void afterCompletion(Commandar commandar, SocketIOSession session, Throwable throwable) {
// Post-completion handling
if (throwable != null) {
System.err.println("Event handling error: " + throwable.getMessage());
}
}
private boolean validateToken(String token) {
// Implement token validation logic
return token != null && !token.isEmpty();
}
}public class CustomApplication {
public static void main(String[] args) throws Exception {
SocketIOConfig config = new SocketIOConfig();
config.setPort(9092); // Port number
config.setHostname("0.0.0.0"); // Bind address
config.setMaxFramePayloadLength(65536); // Maximum frame size
config.setMaxHttpContentLength(65536); // Maximum HTTP content length
config.setWorkerThreads(0); // Worker thread count, 0 means auto
SocketIOApplication.run(CustomApplication.class, config, args);
}
}Supports configuration through configuration files:
<!-- application.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<socketio-config>
<!-- Basic configuration -->
<!-- Base package scan, must be configured, framework will automatically scan annotation classes -->
<property name="basePackage">cloud.apposs.socketio.sample</property>
<!-- Project input/output encoding -->
<property name="charset">utf-8</property>
<!-- Bind host and port -->
<property name="host">0.0.0.0</property>
<property name="port">9088</property>
<property name="keepAlive">true</property>
<!-- Log related configuration -->
<!-- Log output level, can be FATAL, ERROR, WARN, INFO, DEBUG, TRACE, OFF -->
<property name="logLevel">info</property>
</socketio-config>// Global broadcast
session.getBroadcastOperations().sendEvent("globalMessage", "Global message");
// Room broadcast
session.getRoomOperations("room1").sendEvent("roomMessage", "Room message");
// Namespace broadcast
session.getNamespace().getBroadcastOperations().sendEvent("namespaceMessage", "Namespace message");@ServerEndpoint("/admin")
public class AdminEndpoint {
// Admin endpoint
}
@ServerEndpoint("/user")
public class UserEndpoint {
// User endpoint
}public class ChatMessage {
private String username;
private String content;
private long timestamp;
// Must have default constructor
public ChatMessage() {}
// getter/setter methods
}
@OnEvent("chat")
public void handleChat(SocketIOSession session, ChatMessage message) {
// Automatically deserialized to ChatMessage object
}SocketIOConfig config = new SocketIOConfig();
config.setWorkerCount(Runtime.getRuntime().availableProcessors() * 2);// Set appropriate buffer sizes
config.setMaxFramePayloadLength(1024 * 64); // 64KB
config.setMaxHttpContentLength(1024 * 64); // 64KB@Component
public class PerformanceInterceptor implements CommandarInterceptor {
@Override
public void afterCompletion(Commandar commandar, SocketIOSession session, Throwable throwable) {
// Record performance metrics
long duration = System.currentTimeMillis() - startTime;
System.out.println("Event " + commandar.getEventName() + " took: " + duration + "ms");
}
}A: You can use reverse proxies like Nginx for load balancing.
A: All standard Socket.IO clients are supported, including:
- JavaScript (browser)
- Node.js
- Java
- Python
- Swift (iOS)
- Kotlin/Java (Android)
A: Enable debug logging:
config.setLogLevel(LogLevel.DEBUG);- Socket.IO Official Documentation
- Netty-SocketIO Project
- Socket.IO Protocol Details
- Netty Official Documentation
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
Issues and Pull Requests are welcome!
- Fork the project
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Create a Pull Request
If you have any questions or suggestions, please contact us through GitHub Issues.