Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/yeautyye/netty-websocket-spring-boot-starter

:rocket: lightweight high-performance WebSocket framework ( 轻量级、高性能的WebSocket框架)
https://github.com/yeautyye/netty-websocket-spring-boot-starter

annotation asynchronous chat im netty netty-spring-boot-starter spring-boot spring-boot-starter spring-boot-websocket websocket

Last synced: 6 days ago
JSON representation

:rocket: lightweight high-performance WebSocket framework ( 轻量级、高性能的WebSocket框架)

Awesome Lists containing this project

README

        

netty-websocket-spring-boot-starter [![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
===================================

[中文文档](https://github.com/YeautyYE/netty-websocket-spring-boot-starter/blob/master/README_zh.md) (Chinese Docs)

### About
netty-websocket-spring-boot-starter will help you develop WebSocket server by using Netty in spring-boot,it is easy to develop by using annotation like spring-websocket

### Requirement
- jdk version 1.8 or 1.8+

### Quick Start

- add Dependencies:

```xml

org.yeauty
netty-websocket-spring-boot-starter
0.12.0

```

- annotate `@ServerEndpoint` on endpoint class,and annotate `@BeforeHandshake`,`@OnOpen`,`@OnClose`,`@OnError`,`@OnMessage`,`@OnBinary`,`@OnEvent` on the method. e.g.

```java
@ServerEndpoint(path = "/ws/{arg}")
public class MyWebSocket {

@BeforeHandshake
public void handshake(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
session.setSubprotocols("stomp");
if (!"ok".equals(req)){
System.out.println("Authentication failed!");
session.close();
}
}

@OnOpen
public void onOpen(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
System.out.println("new connection");
System.out.println(req);
}

@OnClose
public void onClose(Session session) throws IOException {
System.out.println("one connection closed");
}

@OnError
public void onError(Session session, Throwable throwable) {
throwable.printStackTrace();
}

@OnMessage
public void onMessage(Session session, String message) {
System.out.println(message);
session.sendText("Hello Netty!");
}

@OnBinary
public void onBinary(Session session, byte[] bytes) {
for (byte b : bytes) {
System.out.println(b);
}
session.sendBinary(bytes);
}

@OnEvent
public void onEvent(Session session, Object evt) {
if (evt instanceof IdleStateEvent) {
IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
switch (idleStateEvent.state()) {
case READER_IDLE:
System.out.println("read idle");
break;
case WRITER_IDLE:
System.out.println("write idle");
break;
case ALL_IDLE:
System.out.println("all idle");
break;
default:
break;
}
}
}

}
```

- use Websocket client to connect `ws://127.0.0.1:80/ws/xxx`

### Annotation
###### @ServerEndpoint
> declaring `ServerEndpointExporter` in Spring configuration,it will scan for WebSocket endpoints that be annotated with `ServerEndpoint` .
> beans that be annotated with `ServerEndpoint` will be registered as a WebSocket endpoint.
> all [configurations](#configuration) are inside this annotation ( e.g. `@ServerEndpoint("/ws")` )

###### @BeforeHandshake
> when there is a connection accepted,the method annotated with `@BeforeHandshake` will be called
> classes which be injected to the method are:Session,HttpHeaders...

###### @OnOpen
> when there is a WebSocket connection completed,the method annotated with `@OnOpen` will be called
> classes which be injected to the method are:Session,HttpHeaders...

###### @OnClose
> when a WebSocket connection closed,the method annotated with `@OnClose` will be called
> classes which be injected to the method are:Session

###### @OnError
> when a WebSocket connection throw Throwable, the method annotated with `@OnError` will be called
> classes which be injected to the method are:Session,Throwable

###### @OnMessage
> when a WebSocket connection received a message,the method annotated with `@OnMessage` will be called
> classes which be injected to the method are:Session,String

###### @OnBinary
> when a WebSocket connection received the binary,the method annotated with `@OnBinary` will be called
> classes which be injected to the method are:Session,byte[]

###### @OnEvent
> when a WebSocket connection received the event of Netty,the method annotated with `@OnEvent` will be called
> classes which be injected to the method are:Session,Object

### Configuration
> all configurations are configured in `@ServerEndpoint`'s property

| property | default | description
|---|---|---
|path|"/"|path of WebSocket can be aliased for `value`
|host|"0.0.0.0"|host of WebSocket.`"0.0.0.0"` means all of local addresses
|port|80|port of WebSocket。if the port equals to 0,it will use a random and available port(to get the port [Multi-Endpoint](#multi-endpoint))
|bossLoopGroupThreads|0|num of threads in bossEventLoopGroup
|workerLoopGroupThreads|0|num of threads in workerEventLoopGroup
|useCompressionHandler|false|whether add WebSocketServerCompressionHandler to pipeline
|optionConnectTimeoutMillis|30000|the same as `ChannelOption.CONNECT_TIMEOUT_MILLIS` in Netty
|optionSoBacklog|128|the same as `ChannelOption.SO_BACKLOG` in Netty
|childOptionWriteSpinCount|16|the same as `ChannelOption.WRITE_SPIN_COUNT` in Netty
|childOptionWriteBufferHighWaterMark|64*1024|the same as `ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK` in Netty,but use `ChannelOption.WRITE_BUFFER_WATER_MARK` in fact.
|childOptionWriteBufferLowWaterMark|32*1024|the same as `ChannelOption.WRITE_BUFFER_LOW_WATER_MARK` in Netty,but use `ChannelOption.WRITE_BUFFER_WATER_MARK` in fact.
|childOptionSoRcvbuf|-1(mean not set)|the same as `ChannelOption.SO_RCVBUF` in Netty
|childOptionSoSndbuf|-1(mean not set)|the same as `ChannelOption.SO_SNDBUF` in Netty
|childOptionTcpNodelay|true|the same as `ChannelOption.TCP_NODELAY` in Netty
|childOptionSoKeepalive|false|the same as `ChannelOption.SO_KEEPALIVE` in Netty
|childOptionSoLinger|-1|the same as `ChannelOption.SO_LINGER` in Netty
|childOptionAllowHalfClosure|false|the same as `ChannelOption.ALLOW_HALF_CLOSURE` in Netty
|readerIdleTimeSeconds|0|the same as `readerIdleTimeSeconds` in `IdleStateHandler` and add `IdleStateHandler` to `pipeline` when it is not 0
|writerIdleTimeSeconds|0|the same as `writerIdleTimeSeconds` in `IdleStateHandler` and add `IdleStateHandler` to `pipeline` when it is not 0
|allIdleTimeSeconds|0|the same as `allIdleTimeSeconds` in `IdleStateHandler` and add `IdleStateHandler` to `pipeline` when it is not 0
|maxFramePayloadLength|65536|Maximum allowable frame payload length.
|useEventExecutorGroup|true|Whether to use another thread pool to perform time-consuming synchronous business logic
|eventExecutorGroupThreads|16|num of threads in bossEventLoopGroup
|sslKeyPassword|""(mean not set)|the same as `server.ssl.key-password` in spring-boot
|sslKeyStore|""(mean not set)|the same as `server.ssl.key-store` in spring-boot
|sslKeyStorePassword|""(mean not set)|the same as `server.ssl.key-store-password` in spring-boot
|sslKeyStoreType|""(mean not set)|the same as `server.ssl.key-store-type` in spring-boot
|sslTrustStore|""(mean not set)|the same as `server.ssl.trust-store` in spring-boot
|sslTrustStorePassword|""(mean not set)|the same as `server.ssl.trust-store-password` in spring-boot
|sslTrustStoreType|""(mean not set)|the same as `server.ssl.trust-store-type` in spring-boot
|corsOrigins|{}(mean not set)|the same as `@CrossOrigin#origins` in spring-boot
|corsAllowCredentials|""(mean not set)|the same as `@CrossOrigin#allowCredentials` in spring-boot

### Configuration by application.properties
> You can get the configurate of `application.properties` by using `${...}` placeholders. for example:

- first,use `${...}` in `@ServerEndpoint`
```java
@ServerEndpoint(host = "${ws.host}",port = "${ws.port}")
public class MyWebSocket {
...
}
```
- then configurate in `application.properties`
```
ws.host=0.0.0.0
ws.port=80
```

### Custom Favicon
The way of configure favicon is the same as spring-boot.If `favicon.ico` is presented in the root of the classpath,it will be automatically used as the favicon of the application.the example is following:
```
src/
+- main/
+- java/
| +
+- resources/
+- favicon.ico
```

### Custom Error Pages
The way of configure favicon is the same as spring-boot.you can add a file to an `/public/error`
folder.The name of the error page should be the exact status code or a series mask.the example is following:
```
src/
+- main/
+- java/
| +
+- resources/
+- public/
+- error/
| +- 404.html
| +- 5xx.html
+-
```

### Multi Endpoint
- base on [Quick-Start](#quick-start),use annotation `@ServerEndpoint` and `@Component` in classes which hope to become a endpoint.
- you can get all socket addresses in `ServerEndpointExporter.getInetSocketAddressSet()`.
- when there are different addresses(different host or different port) in WebSocket,they will use different `ServerBootstrap` instance.
- when the addresses are the same,but path is different,they will use the same `ServerBootstrap` instance.
- when multiple port of endpoint is 0 ,they will use the same random port
- when multiple port of endpoint is the same as the path,host can't be set as "0.0.0.0",because it means it binds all of the addresses

---
### Change Log

#### 0.8.0

- Auto-Configuration

#### 0.9.0

- Support RESTful by `@PathVariable`
- Get param by`@RequestParam` from query
- Remove `ParameterMap` ,instead of `@RequestParam MultiValueMap`
- Add `@BeforeHandshake` annotation,you can close the connect before handshake
- Set sub-protocol in `@BeforeHandshake` event
- Remove the `@Component` on endpoint class
- Update `Netty` version to `4.1.44.Final`

#### 0.9.1

- Bug fixed : it was null when using `@RequestParam MultiValueMap` to get value
- Update `Netty` version to `4.1.45.Final`

#### 0.9.2

- There are compatibility version under 0.8.0 that can configure the `ServerEndpointExporter` manully

#### 0.9.3

- Bug fixed :when there is no `@BeforeHandshake` , NullPointerException will appear

#### 0.9.4

- Bug fixed :when there is no `@BeforeHandshake` , `Session` in `OnOpen` is null

#### 0.9.5

- Bug fixed :`Throwable` in `OnError` event is null

#### 0.10.0

- Modified the default value of `bossLoopGroupThreads` to 1
- Supports configuring `useEventExecutorGroup` to run synchronous and time-consuming business logic in EventExecutorGroup, so that the I/O thread is not blocked by a time-consuming task
- SSL supported
- CORS supported
- Update `Netty` version to `4.1.49.Final`

#### 0.11.0

- When the `ServerEndpoint` class is proxied by CGLIB (as with AOP enhancement), it still works

#### 0.12.0

- `@enableWebSocket` adds the `scanBasePackages` attribute
- `@serverEndpoint` no longer depends on `@Component`
- Update `Netty` version to `4.1.67.Final`