- Notifications
You must be signed in to change notification settings - Fork562
🚀 lightweight high-performance WebSocket framework ( 轻量级、高性能的WebSocket框架)
License
YeautyYE/netty-websocket-spring-boot-starter
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
中文文档 (Chinese Docs)
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
- jdk version 17
- add Dependencies:
<dependency><groupId>org.yeauty</groupId><artifactId>netty-websocket-spring-boot-starter</artifactId><version>0.13.0</version></dependency>
- annotate
@ServerEndpointon endpoint class,and annotate@BeforeHandshake,@OnOpen,@OnClose,@OnError,@OnMessage,@OnBinary,@OnEventon the method. e.g.
@ServerEndpoint(path ="/ws/{arg}")publicclassMyWebSocket {@BeforeHandshakepublicvoidhandshake(Sessionsession,HttpHeadersheaders,@RequestParamStringreq,@RequestParamMultiValueMapreqMap,@PathVariableStringarg,@PathVariableMappathMap){session.setSubprotocols("stomp");if (!"ok".equals(req)){System.out.println("Authentication failed!");session.close(); } }@OnOpenpublicvoidonOpen(Sessionsession,HttpHeadersheaders,@RequestParamStringreq,@RequestParamMultiValueMapreqMap,@PathVariableStringarg,@PathVariableMappathMap){System.out.println("new connection");System.out.println(req); }@OnClosepublicvoidonClose(Sessionsession)throwsIOException {System.out.println("one connection closed"); }@OnErrorpublicvoidonError(Sessionsession,Throwablethrowable) {throwable.printStackTrace(); }@OnMessagepublicvoidonMessage(Sessionsession,Stringmessage) {System.out.println(message);session.sendText("Hello Netty!"); }@OnBinarypublicvoidonBinary(Sessionsession,byte[]bytes) {for (byteb :bytes) {System.out.println(b); }session.sendBinary(bytes); }@OnEventpublicvoidonEvent(Sessionsession,Objectevt) {if (evtinstanceofIdleStateEvent) {IdleStateEventidleStateEvent = (IdleStateEvent)evt;switch (idleStateEvent.state()) {caseREADER_IDLE:System.out.println("read idle");break;caseWRITER_IDLE:System.out.println("write idle");break;caseALL_IDLE:System.out.println("all idle");break;default:break; } } }}
- use Websocket client to connect
ws://127.0.0.1:80/ws/xxx
declaring
ServerEndpointExporterin Spring configuration,it will scan for WebSocket endpoints that be annotated withServerEndpoint.beans that be annotated withServerEndpointwill be registered as a WebSocket endpoint.allconfigurations are inside this annotation ( e.g.@ServerEndpoint("/ws"))
when there is a connection accepted,the method annotated with
@BeforeHandshakewill be called
classes which be injected to the method are:Session,HttpHeaders...
when there is a WebSocket connection completed,the method annotated with
@OnOpenwill be called
classes which be injected to the method are:Session,HttpHeaders...
when a WebSocket connection closed,the method annotated with
@OnClosewill be calledclasses which be injected to the method are:Session
when a WebSocket connection throw Throwable, the method annotated with
@OnErrorwill be calledclasses which be injected to the method are:Session,Throwable
when a WebSocket connection received a message,the method annotated with
@OnMessagewill be calledclasses which be injected to the method are:Session,String
when a WebSocket connection received the binary,the method annotated with
@OnBinarywill be calledclasses which be injected to the method are:Session,byte[]
when a WebSocket connection received the event of Netty,the method annotated with
@OnEventwill be calledclasses which be injected to the method are:Session,Object
all configurations are configured in
@ServerEndpoint's property
| property | default | description |
|---|---|---|
| path | "/" | path of WebSocket can be aliased forvalue |
| 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 portMulti-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 asChannelOption.CONNECT_TIMEOUT_MILLIS in Netty |
| optionSoBacklog | 128 | the same asChannelOption.SO_BACKLOG in Netty |
| childOptionWriteSpinCount | 16 | the same asChannelOption.WRITE_SPIN_COUNT in Netty |
| childOptionWriteBufferHighWaterMark | 64*1024 | the same asChannelOption.WRITE_BUFFER_HIGH_WATER_MARK in Netty,but useChannelOption.WRITE_BUFFER_WATER_MARK in fact. |
| childOptionWriteBufferLowWaterMark | 32*1024 | the same asChannelOption.WRITE_BUFFER_LOW_WATER_MARK in Netty,but useChannelOption.WRITE_BUFFER_WATER_MARK in fact. |
| childOptionSoRcvbuf | -1(mean not set) | the same asChannelOption.SO_RCVBUF in Netty |
| childOptionSoSndbuf | -1(mean not set) | the same asChannelOption.SO_SNDBUF in Netty |
| childOptionTcpNodelay | true | the same asChannelOption.TCP_NODELAY in Netty |
| childOptionSoKeepalive | false | the same asChannelOption.SO_KEEPALIVE in Netty |
| childOptionSoLinger | -1 | the same asChannelOption.SO_LINGER in Netty |
| childOptionAllowHalfClosure | false | the same asChannelOption.ALLOW_HALF_CLOSURE in Netty |
| readerIdleTimeSeconds | 0 | the same asreaderIdleTimeSeconds inIdleStateHandler and addIdleStateHandler topipeline when it is not 0 |
| writerIdleTimeSeconds | 0 | the same aswriterIdleTimeSeconds inIdleStateHandler and addIdleStateHandler topipeline when it is not 0 |
| allIdleTimeSeconds | 0 | the same asallIdleTimeSeconds inIdleStateHandler and addIdleStateHandler topipeline 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 asserver.ssl.key-password in spring-boot |
| sslKeyStore | ""(mean not set) | the same asserver.ssl.key-store in spring-boot |
| sslKeyStorePassword | ""(mean not set) | the same asserver.ssl.key-store-password in spring-boot |
| sslKeyStoreType | ""(mean not set) | the same asserver.ssl.key-store-type in spring-boot |
| sslTrustStore | ""(mean not set) | the same asserver.ssl.trust-store in spring-boot |
| sslTrustStorePassword | ""(mean not set) | the same asserver.ssl.trust-store-password in spring-boot |
| sslTrustStoreType | ""(mean not set) | the same asserver.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 |
You can get the configurate of
application.propertiesby using${...}placeholders. for example:
- first,use
${...}in@ServerEndpoint
@ServerEndpoint(host ="${ws.host}",port ="${ws.port}")publicclassMyWebSocket { ...}
- then configurate in
application.properties
ws.host=0.0.0.0ws.port=80The way of configure favicon is the same as spring-boot.Iffavicon.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/ | + <source code> +- resources/ +- favicon.icoThe way of configure favicon is the same as spring-boot.you can add a file to an/public/errorfolder.The name of the error page should be the exact status code or a series mask.the example is following:
src/ +- main/ +- java/ | + <source code> +- resources/ +- public/ +- error/ | +- 404.html | +- 5xx.html +- <other public assets>- base onQuick-Start,use annotation
@ServerEndpointand@Componentin 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
ServerBootstrapinstance. - when the addresses are the same,but path is different,they will use the same
ServerBootstrapinstance. - 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
- Auto-Configuration
- Support RESTful by
@PathVariable - Get param by
@RequestParamfrom query - Remove
ParameterMap,instead of@RequestParam MultiValueMap - Add
@BeforeHandshakeannotation,you can close the connect before handshake - Set sub-protocol in
@BeforeHandshakeevent - Remove the
@Componenton endpoint class - Update
Nettyversion to4.1.44.Final
- Bug fixed : it was null when using
@RequestParam MultiValueMapto get value - Update
Nettyversion to4.1.45.Final
- There are compatibility version under 0.8.0 that can configure the
ServerEndpointExportermanully
- Bug fixed :when there is no
@BeforeHandshake, NullPointerException will appear
- Bug fixed :when there is no
@BeforeHandshake,SessioninOnOpenis null
- Bug fixed :
ThrowableinOnErrorevent is null
- Modified the default value of
bossLoopGroupThreadsto 1 - Supports configuring
useEventExecutorGroupto 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
Nettyversion to4.1.49.Final
- When the
ServerEndpointclass is proxied by CGLIB (as with AOP enhancement), it still works
@enableWebSocketadds thescanBasePackagesattribute@serverEndpointno longer depends on@Component- Update
Nettyversion to4.1.67.Final
- Fixed the issue where WebSocket compression was not working.
- Upgraded support for Spring Boot 3.
- Included the client's
Sec-WebSocket-Protocolin the response header. - When closing the connection, sends a
byecommand first instead of directly closing. - Updated
Nettyversion to4.1.118.Final.
About
🚀 lightweight high-performance WebSocket framework ( 轻量级、高性能的WebSocket框架)
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Contributors7
Uh oh!
There was an error while loading.Please reload this page.