{"id":15014292,"url":"https://github.com/yeautyye/netty-websocket-spring-boot-starter","last_synced_at":"2025-05-14T18:07:32.455Z","repository":{"id":37397006,"uuid":"139380324","full_name":"YeautyYE/netty-websocket-spring-boot-starter","owner":"YeautyYE","description":":rocket: lightweight high-performance WebSocket framework     （ 轻量级、高性能的WebSocket框架）","archived":false,"fork":false,"pushed_at":"2025-04-24T07:55:35.000Z","size":154,"stargazers_count":1865,"open_issues_count":159,"forks_count":555,"subscribers_count":59,"default_branch":"master","last_synced_at":"2025-05-14T18:07:26.187Z","etag":null,"topics":["annotation","asynchronous","chat","im","netty","netty-spring-boot-starter","spring-boot","spring-boot-starter","spring-boot-websocket","websocket"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YeautyYE.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-02T02:17:43.000Z","updated_at":"2025-05-12T08:53:43.000Z","dependencies_parsed_at":"2024-06-21T17:50:50.874Z","dependency_job_id":"2fae6425-0cdb-4c8b-8908-8419ba367671","html_url":"https://github.com/YeautyYE/netty-websocket-spring-boot-starter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YeautyYE%2Fnetty-websocket-spring-boot-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YeautyYE%2Fnetty-websocket-spring-boot-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YeautyYE%2Fnetty-websocket-spring-boot-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YeautyYE%2Fnetty-websocket-spring-boot-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YeautyYE","download_url":"https://codeload.github.com/YeautyYE/netty-websocket-spring-boot-starter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198514,"owners_count":22030966,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["annotation","asynchronous","chat","im","netty","netty-spring-boot-starter","spring-boot","spring-boot-starter","spring-boot-websocket","websocket"],"created_at":"2024-09-24T19:45:25.687Z","updated_at":"2025-05-14T18:07:27.446Z","avatar_url":"https://github.com/YeautyYE.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"netty-websocket-spring-boot-starter [![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)\n===================================\n\n[中文文档](https://github.com/YeautyYE/netty-websocket-spring-boot-starter/blob/master/README_zh.md) (Chinese Docs)\n\n### About\nnetty-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 \n\n### Requirement\n- jdk version 1.8 or 1.8+\n\n\n### Quick Start\n\n- add Dependencies:\n\n```xml\n\t\u003cdependency\u003e\n\t\t\u003cgroupId\u003eorg.yeauty\u003c/groupId\u003e\n\t\t\u003cartifactId\u003enetty-websocket-spring-boot-starter\u003c/artifactId\u003e\n\t\t\u003cversion\u003e0.12.0\u003c/version\u003e\n\t\u003c/dependency\u003e\n```\n\n- annotate `@ServerEndpoint` on endpoint class，and annotate `@BeforeHandshake`,`@OnOpen`,`@OnClose`,`@OnError`,`@OnMessage`,`@OnBinary`,`@OnEvent` on the method. e.g.\n\n```java\n@ServerEndpoint(path = \"/ws/{arg}\")\npublic class MyWebSocket {\n\n    @BeforeHandshake\n    public void handshake(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){\n        session.setSubprotocols(\"stomp\");\n        if (!\"ok\".equals(req)){\n            System.out.println(\"Authentication failed!\");\n            session.close();\n        }\n    }\n    \n    @OnOpen\n    public void onOpen(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){\n        System.out.println(\"new connection\");\n        System.out.println(req);\n    }\n\n    @OnClose\n    public void onClose(Session session) throws IOException {\n       System.out.println(\"one connection closed\"); \n    }\n\n    @OnError\n    public void onError(Session session, Throwable throwable) {\n        throwable.printStackTrace();\n    }\n\n    @OnMessage\n    public void onMessage(Session session, String message) {\n        System.out.println(message);\n        session.sendText(\"Hello Netty!\");\n    }\n\n    @OnBinary\n    public void onBinary(Session session, byte[] bytes) {\n        for (byte b : bytes) {\n            System.out.println(b);\n        }\n        session.sendBinary(bytes); \n    }\n\n    @OnEvent\n    public void onEvent(Session session, Object evt) {\n        if (evt instanceof IdleStateEvent) {\n            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;\n            switch (idleStateEvent.state()) {\n                case READER_IDLE:\n                    System.out.println(\"read idle\");\n                    break;\n                case WRITER_IDLE:\n                    System.out.println(\"write idle\");\n                    break;\n                case ALL_IDLE:\n                    System.out.println(\"all idle\");\n                    break;\n                default:\n                    break;\n            }\n        }\n    }\n\n}\n```\n\n- use Websocket client to connect `ws://127.0.0.1:80/ws/xxx` \n\n\n### Annotation\n###### @ServerEndpoint \n\u003e declaring `ServerEndpointExporter` in Spring configuration,it will scan for WebSocket endpoints that be annotated  with `ServerEndpoint` .\n\u003e beans that be annotated with `ServerEndpoint` will be registered as a WebSocket endpoint.\n\u003e all [configurations](#configuration) are inside this annotation ( e.g. `@ServerEndpoint(\"/ws\")` )\n\n###### @BeforeHandshake \n\u003e when there is a connection accepted,the method annotated with `@BeforeHandshake` will be called  \n\u003e classes which be injected to the method are:Session,HttpHeaders...\n\n###### @OnOpen \n\u003e when there is a WebSocket connection completed,the method annotated with `@OnOpen` will be called  \n\u003e classes which be injected to the method are:Session,HttpHeaders...\n\n###### @OnClose\n\u003e when a WebSocket connection closed,the method annotated with `@OnClose` will be called\n\u003e classes which be injected to the method are:Session\n\n###### @OnError\n\u003e when a WebSocket connection throw Throwable, the method annotated with `@OnError` will be called\n\u003e classes which be injected to the method are:Session,Throwable\n\n###### @OnMessage\n\u003e when a WebSocket connection received a message,the method annotated with `@OnMessage` will be called\n\u003e classes which be injected to the method are:Session,String\n\n###### @OnBinary\n\u003e when a WebSocket connection received the binary,the method annotated with `@OnBinary` will be called\n\u003e classes which be injected to the method are:Session,byte[]\n\n###### @OnEvent\n\u003e when a WebSocket connection received the event of Netty,the method annotated with `@OnEvent` will be called\n\u003e classes which be injected to the method are:Session,Object\n\n### Configuration\n\u003e all configurations are configured in `@ServerEndpoint`'s property \n\n| property  | default | description \n|---|---|---\n|path|\"/\"|path of WebSocket can be aliased for `value`\n|host|\"0.0.0.0\"|host of WebSocket.`\"0.0.0.0\"` means all of local addresses\n|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))\n|bossLoopGroupThreads|0|num of threads in bossEventLoopGroup\n|workerLoopGroupThreads|0|num of threads in workerEventLoopGroup\n|useCompressionHandler|false|whether add WebSocketServerCompressionHandler to pipeline\n|optionConnectTimeoutMillis|30000|the same as `ChannelOption.CONNECT_TIMEOUT_MILLIS` in Netty\n|optionSoBacklog|128|the same as `ChannelOption.SO_BACKLOG` in Netty\n|childOptionWriteSpinCount|16|the same as `ChannelOption.WRITE_SPIN_COUNT` in Netty\n|childOptionWriteBufferHighWaterMark|64*1024|the same as `ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK` in Netty,but use `ChannelOption.WRITE_BUFFER_WATER_MARK` in fact.\n|childOptionWriteBufferLowWaterMark|32*1024|the same as `ChannelOption.WRITE_BUFFER_LOW_WATER_MARK` in Netty,but use `ChannelOption.WRITE_BUFFER_WATER_MARK` in fact.\n|childOptionSoRcvbuf|-1(mean not set)|the same as `ChannelOption.SO_RCVBUF` in Netty\n|childOptionSoSndbuf|-1(mean not set)|the same as `ChannelOption.SO_SNDBUF` in Netty\n|childOptionTcpNodelay|true|the same as `ChannelOption.TCP_NODELAY` in Netty\n|childOptionSoKeepalive|false|the same as `ChannelOption.SO_KEEPALIVE` in Netty\n|childOptionSoLinger|-1|the same as `ChannelOption.SO_LINGER` in Netty\n|childOptionAllowHalfClosure|false|the same as `ChannelOption.ALLOW_HALF_CLOSURE` in Netty\n|readerIdleTimeSeconds|0|the same as `readerIdleTimeSeconds` in `IdleStateHandler` and add `IdleStateHandler` to `pipeline` when it is not 0\n|writerIdleTimeSeconds|0|the same as `writerIdleTimeSeconds` in `IdleStateHandler` and add `IdleStateHandler` to `pipeline` when it is not 0\n|allIdleTimeSeconds|0|the same as `allIdleTimeSeconds` in `IdleStateHandler` and add `IdleStateHandler` to `pipeline` when it is not 0\n|maxFramePayloadLength|65536|Maximum allowable frame payload length.\n|useEventExecutorGroup|true|Whether to use another thread pool to perform time-consuming synchronous business logic\n|eventExecutorGroupThreads|16|num of threads in bossEventLoopGroup\n|sslKeyPassword|\"\"(mean not set)|the same as `server.ssl.key-password` in spring-boot\n|sslKeyStore|\"\"(mean not set)|the same as `server.ssl.key-store` in spring-boot\n|sslKeyStorePassword|\"\"(mean not set)|the same as `server.ssl.key-store-password` in spring-boot\n|sslKeyStoreType|\"\"(mean not set)|the same as `server.ssl.key-store-type` in spring-boot\n|sslTrustStore|\"\"(mean not set)|the same as `server.ssl.trust-store` in spring-boot\n|sslTrustStorePassword|\"\"(mean not set)|the same as `server.ssl.trust-store-password` in spring-boot\n|sslTrustStoreType|\"\"(mean not set)|the same as `server.ssl.trust-store-type` in spring-boot\n|corsOrigins|{}(mean not set)|the same as `@CrossOrigin#origins` in spring-boot\n|corsAllowCredentials|\"\"(mean not set)|the same as `@CrossOrigin#allowCredentials` in spring-boot\n\n### Configuration by application.properties\n\u003e You can get the configurate of `application.properties` by using `${...}` placeholders. for example：\n\n- first,use `${...}` in `@ServerEndpoint` \n```java\n@ServerEndpoint(host = \"${ws.host}\",port = \"${ws.port}\")\npublic class MyWebSocket {\n    ...\n}\n```\n- then configurate in `application.properties`\n```\nws.host=0.0.0.0\nws.port=80\n```\n\n### Custom Favicon\nThe 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:\n```\nsrc/\n  +- main/\n      +- java/\n      |   + \u003csource code\u003e\n      +- resources/\n          +- favicon.ico\n```\n\n### Custom Error Pages\nThe way of configure favicon is the same as spring-boot.you can add a file to an `/public/error`\nfolder.The name of the error page should be the exact status code or a series mask.the example is following:\n```\nsrc/\n  +- main/\n      +- java/\n      |   + \u003csource code\u003e\n      +- resources/\n          +- public/\n              +- error/\n              |   +- 404.html\n              |   +- 5xx.html\n              +- \u003cother public assets\u003e\n```\n\n### Multi Endpoint\n- base on [Quick-Start](#quick-start),use annotation `@ServerEndpoint` and `@Component` in classes which hope to become a endpoint.\n- you can get all socket addresses in `ServerEndpointExporter.getInetSocketAddressSet()`.\n- when there are different addresses(different host or different port) in WebSocket,they will use different `ServerBootstrap` instance.\n- when the addresses are the same,but path is different,they will use the same `ServerBootstrap` instance.\n- when multiple port of endpoint is 0 ,they will use the same random port\n- 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\n\n---\n### Change Log\n\n#### 0.8.0\n\n- Auto-Configuration\n\n#### 0.9.0\n\n- Support RESTful by `@PathVariable`\n- Get param by`@RequestParam` from query\n- Remove `ParameterMap` ,instead of `@RequestParam MultiValueMap`\n- Add `@BeforeHandshake` annotation，you can close the connect before handshake\n- Set sub-protocol in `@BeforeHandshake` event\n- Remove  the `@Component` on endpoint class\n- Update `Netty` version to `4.1.44.Final`\n\n#### 0.9.1\n\n- Bug fixed : it was null when using `@RequestParam MultiValueMap` to get value\n- Update `Netty` version to `4.1.45.Final`\n\n#### 0.9.2\n\n-  There are compatibility version under 0.8.0 that can configure the `ServerEndpointExporter` manully \n\n#### 0.9.3\n\n- Bug fixed ：when there is no  `@BeforeHandshake` , NullPointerException will appear\n\n#### 0.9.4\n\n- Bug fixed ：when there is no  `@BeforeHandshake` , `Session` in `OnOpen` is null\n\n#### 0.9.5\n\n- Bug fixed ：`Throwable` in `OnError` event  is null\n\n#### 0.10.0\n\n- Modified the default value of `bossLoopGroupThreads` to 1\n- 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\n- SSL supported\n- CORS supported\n- Update `Netty` version to `4.1.49.Final`\n\n#### 0.11.0\n\n- When the `ServerEndpoint` class is proxied by CGLIB (as with AOP enhancement), it still works\n\n#### 0.12.0\n\n- `@enableWebSocket` adds the `scanBasePackages` attribute\n- `@serverEndpoint` no longer depends on `@Component`\n- Update `Netty` version to `4.1.67.Final`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeautyye%2Fnetty-websocket-spring-boot-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyeautyye%2Fnetty-websocket-spring-boot-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeautyye%2Fnetty-websocket-spring-boot-starter/lists"}