惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official blog

博客园_首页

Agent工厂与A2A网络——AgentMesh设计思路 - 锅总的程序人生 [Python]标准库argparse解析命令行参数使用介绍 [开源] 全屏时钟 / Full Clock:放弃 time.is,用 Svelte 5 写了一个极致纯净的全屏时钟,解决秒数焦虑 AT_abc460_f 解题报告 三、Linux 文件管理+用户管理 XGBoost + SHAP 一键生成 10 张出版级模型解释图 【Azure App Service】App Service 里的 SNAT 端口 vs 出站连接数:到底是谁限制了谁? 2026御网杯线上挑战赛Pwn的wp WEB-2026DASCTF夏季赛-CorpGate 为什么你用光模块测试FPGA IBERT不通 面试官:Workflow 和 Agent 有什么区别?如何选型? 从失忆到记住一切:Spring AI AutoMemoryTools 与 Session API 实战 2026 年 5 个最佳 Agent Skills 平台推荐 15天学会AI应用开发(三)把历史对话作为提示词会怎样 如何在Reaonix中使用CodeGraph以及CodeGraph效果实测经验分享 架构师必备:分布式事务方案选型 Agent的诞生(二):让模型开始调用工具 OpenDeepWiki 导出仓库 Skill:把代码知识沉淀成企业可复用的 AI 资产 [python]argparse 包在聊天机器人中的应用 LazyVim安装snacks.nvim报错“Process was killed because it reached the timeout” 一、红帽RHCSA+RHCE课前说明与Linux系统安装学习笔记 洛谷-P11240 [KTSC 2024 R2] 回文判定 题解 告别深夜夺命Call:如何利用 AI Agent Skills 自动自愈生产环境故障 从机器翻译到智驾:规则派的黄昏与数据革命的终局 Google 开源了啥,让 AI Agent 碰数据库不再是定时炸弹 P3550 [POI 2013] TAK-Taxis FastAPI 【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (4)--- 架构 - 罗西的思考 CentOS服务器上搭建Jenkins+maven+GitLab k8s gateway agentgo 运行时架构深度解析:一个 Go AI 编程助手的核心引擎设计 免费可商用 PHP 管理后台 CatchAdmin V5.3.1 发布 后台打包直降 5s 内 PPO算法 基础讲解 从 Agent 到代码:Claude Code 编排模型的演进 15天学会AI应用开发(二)为什么编写提示词这么重要 记一次GIS专业职称水平能力测试考试 在CubeMX生成项目中,手动移植FreeRTOS Kernel V11.3.0 LTS,HardFault 启动崩溃问题日志 [MAF的Agent管道详解-05]对话历史的持久化和输入输出的增强 从跑通到放弃:我的 Cloud Agent V1开发历程 Avalonia 制作复杂布局动画 Claude Code + 通义千问,从零搭出生产级 RAG 要花多少钱? Flutter 复杂拖拽排序实战:同源排序 + 跨容器拖拽完整落地 语言开发笔记3 Keepalived 学习总结 企智栾生 ETA (企智孪生(ETA)vs 传统数字孪生:有本质区别)【浙江联保网络 卢伟舜】 [数学-导数隐零点] 看起来简单?求过定点 (0, √e) 的直线与 y=e^x 交点横坐标差最小时的斜率 深度学习进阶(二十五)RoPE:现代 NLP 的位置编码范式 GMSL + 硬件PTP方案,真能让ADAS路测告别“数十毫秒偏差”吗? 【学习笔记】《Python编程 从入门到实践》第4章:for循环、range()、切片与元组 AI Agent 框架接金融行情数据前,先检查这 7 个工程风险 Dify — Workflow - 数据可视化 高性能服务器的基石:从并发模型到状态机 我用了 8 个月 Codex CLI,总结出这套 AI 编程工作流 重建 AI 认知第 3 篇:Prompt Engineering——怎么让 AI 听懂你的话 使用typedef封装函数指针新类型 只有踩过坑才懂:前端生成唯一 ID,别用 Date.now ()了!试试它crypto.randomUUID() ClickHouse Kubernetes集群部署与维护文档 c#一行代码免写登录页:PicoServer 的 AddBasicAuth 中间件实战 南京办公室装修避坑|21 年只做公装,闭口合同零增项 共绩科技:跨云弹性推理场景下,模型分发如何跟上算力调度 薄雾之上的上界:高概率复杂度的分析 TopBeeAI基金申请助手:使用AI提升基金申请效率的实践指南 高管的 AI 精神病 【译】构建前先计划:带你了解 Visual Studio 中的 Plan Agent 一行代码干翻 Java 反射?EggG 流式反射调用让反射优雅到不可思议 RAG 负责召回,LLM Wiki 负责沉淀:团队知识系统为什么不能只做检索 做一款企业真正敢用的AI测试应用,到底有多难?究竟难在哪? JaVers 版本历史功能完整实现指南 Github Project-AI Agentic Framework (.NET) [MAF的Agent管道详解-04]如何让LLM按照要求的结构输出数据? 随机过程WebApp实验室:从随机动力学到 AI 洞察的概率世界 有关使用python爬虫的一些心得 前端视角下的 C# 《GIS基础原理与技术实践》配套案例(Python版) GoF设计模式——代理模式 上位机程序集的反编译与加壳保护 基于 Blazor 实现的电梯运行监测系统 - known 【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (3)--- 总体思考 用 ESP32 做了一个 AI Agent 桌面状态核心,科技感直接拉满 马能否走遍棋盘的可达性证明 PortSwigger SQL注入LAB10 从 Harness Engineering 到 Trellis:AI 编程助手的工程化落地实践 信息化运维项目费用测算全指南:政策边界、三大方法与实操要点 Claude Code 实战 400 万 Tokens:接入 DeepSeek V4,从$26降到$2 Docker--容器常用命令 Dify — Chatflow - 数据库 零基础认识大语言模型工作原理 不繁花 写页面时别再把 Element Plus 整个搬进来啦!Vue3按需加载的坑我帮你踩平了 一条命令让你这辈子彻底解决"LF will be replaced by CRLF"(建议收藏) Miller Rabin:概率之下,证据成群 - Ofnoname Nessus 2026.5.9 更新升级:企业级漏扫工具的全能进阶与实战应用 Agent Harness 架构真相:Prompt Cache 如何决定 Skill、MCP 与 SubAgent 设计 Claude Code 支持 LSP 指南(C#/JAVA等) [翻译] 为什么我要用 C# 构建数据库引擎 DeepSeek V4 + Claude Code thinking mode 400 错误修复方案 云原生 CI/CD 平台架构设计 模板方法模式实战:重构Agent工具审批,告别重复代码 Ubuntu修改主机名操作指南 [MAF的Agent管道详解-03]连接LLM的IChatClient对象
Solon Server 启动模式深度解析:从 0.3MB 内核到 10+ Server 插件
带刺的坐椅 · 2026-05-31 · via 博客园_首页

一、开篇:Server 插件化设计哲学

Java Web 开发中,应用框架与底层服务器通常是强绑定的。你选了一个框架,就绑定了它支持的服务器实现。切换?往往意味着大量适配工作。

Solon 的设计哲学不同:业务代码与底层容器完全解耦

在 Solon 中,你的 Controller、Service、Repository 等业务代码是"不变的",而底层服务器是"可插拔的"。只需要换一个 Maven 依赖,就能从 JDK 内置 HTTP 服务器(0.3MB)切换到 Jetty(2.7MB)、Undertow(4.6MB)或 Vert.x(6.3MB)——业务代码零修改

这就是 Solon Server 插件化设计的核心价值:

维度 传统方式 Solon 方式
框架与服务器关系 强绑定 可插拔
切换服务器 改代码/改配置 换一个 Maven 依赖
包大小 通常较大 按需选择,最小 0.3MB
协议支持 通常只有 HTTP HTTP + WebSocket + Socket.D

本文将带你深入解析 Solon 的 Server 启动模式体系。

二、应用启动入口与生命周期

2.1 标准启动方式

所有 Solon 应用的入口都是 Solon.start()

@SolonMain
public class App {
    public static void main(String[] args) {
        Solon.start(App.class, args);
    }
}

2.2 带初始化函数的启动

第三个参数是初始化函数,在应用初始化时机点执行:

@SolonMain
public class App {
    public static void main(String[] args) {
        Solon.start(App.class, args, app -> {
            // 控制信号启停、订阅早期事件等
            app.enableHttp(true);
            app.enableWebSocket(true);
        });
    }
}

2.3 应用生命周期全景

Solon 应用的生命周期包含四个层次的时机点:

① 一个初始化函数时机点

  • Solon.start() 的第三个参数回调

② 六个应用事件时机点

事件 说明 订阅方式
AppInitEndEvent 应用初始化完成 只支持手动订阅
AppPluginLoadEndEvent 插件加载完成 只支持手动订阅
AppBeanLoadEndEvent Bean 扫描完成 自动/手动
AppLoadEndEvent 应用启动完成 自动/手动
AppPrestopEndEvent 应用预停止 自动/手动
AppStopEndEvent 应用停止 自动/手动

③ 三个插件生命时机点

public interface Plugin {
    void start(AppContext context) throws Throwable;
    default void prestop() throws Throwable {}
    default void stop() throws Throwable {}
}

④ 两个容器生命时机点

  • AppContext::start() — 扫描完成后执行
  • AppContext::stop() — 插件 stop 后执行

AppBeanLoadEndEvent 之前的事件需要在启动前完成订阅,否则会错过时机。

三、启动参数体系

3.1 完整参数表

启动参数在应用启动后会被静态化(启动后不可修改)。

启动参数 对应配置 描述
--env solon.env 环境变量(配置切换)
--scanning 是否扫描(默认 1)
--debug solon.debug 调试模式(0 或 1)
--setup solon.setup 安装模式(0 或 1)
--white solon.white 白名单模式(0 或 1)
--drift solon.drift 漂移模式(k8s 部署设为 1)
--alone solon.alone 单体模式(0 或 1)
--extend solon.extend 扩展目录
--locale solon.locale 默认地区
--config.add solon.config.add 增加外部配置
--app.name solon.app.name 应用名
--app.group solon.app.group 应用分组
--app.title solon.app.title 应用标题
--stop.safe solon.stop.safe 安全停止(0 或 1)
--stop.delay solon.stop.delay 安全停止延时秒数(默认 10)

3.2 三种等价写法

所有带 . 的启动参数同时会成为应用配置,以下三种写法完全等价:

# 方式一:JVM 系统属性
java -Dsolon.env=dev -jar demo.jar

# 方式二:完整的命令行参数
java -jar demo.jar --solon.env=dev

# 方式三:简写命令行参数
java -jar demo.jar --env=dev

同理,server.port 也支持三种写法:

java -Dserver.port=8081 -jar demo.jar
java -jar demo.jar --server.port=8081

四、Server 插件全景矩阵

Solon Server 系列包含所有通讯"服务启动器"插件。切换 Boot 插件只需更换 Maven/Gradle 依赖。

4.1 HTTP 类 Server 插件

插件 框架版本 包大小 信号协议 JDK要求 开源协议
solon-server-jdkhttp JDK 0.3MB http 8+ Apache 2.0
solon-server-smarthttp [国产] 0.8MB http, ws 8+ Apache 2.0
solon-server-grizzly 1.8MB http, ws, http2 8+ EPL-2.0
solon-server-vertx 6.3MB http, ws, http2 8+ EPL-2.0
solon-server-jetty v9 2.7MB http, ws 8+ EPL-2.0
solon-server-jetty-jakarta v12 3.9MB http, ws, http2 17+ EPL-2.0
solon-server-undertow v2.2 4.6MB http, ws, http2 8+ Apache 2.0
solon-server-undertow-jakarta v2.3 http, ws, http2 17+ Apache 2.0
solon-server-tomcat v9 http, ws, http2 8+ Apache 2.0
solon-server-tomcat-jakarta v11 http, ws, http2 17+ Apache 2.0

4.2 WebSocket 类 Server 插件

插件 包大小 信号协议 JDK要求 开源协议
solon-server-websocket 0.4MB ws 8+ MIT
solon-server-websocket-netty 3.6MB ws 8+ Apache 2.0

4.3 Socket.D 类 Server 插件

插件 包大小 信号协议 JDK要求 开源协议
solon-server-socketd 0.4MB tcp, udp, ws 8+ Apache 2.0

4.4 插件切换方法

切换 Boot 插件只需更换依赖,业务代码无需任何修改:

<!-- 替换前:使用 JDK 内置 HTTP 服务器(0.3MB) -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-server-jdkhttp</artifactId>
</dependency>

<!-- 替换后:使用 Jetty(2.7MB,支持 WebSocket) -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-server-jetty</artifactId>
</dependency>

4.5 二级扩展插件

部分 Boot 插件有配套的二级插件,按需添加:

Boot 插件 二级插件 说明
solon-server-jetty solon-server-jetty-add-jsp 增加 JSP 视图
solon-server-jetty solon-server-jetty-add-websocket 增加 WebSocket
solon-server-tomcat solon-server-tomcat-add-jsp 增加 JSP 视图
solon-server-tomcat solon-server-tomcat-add-websocket 增加 WebSocket
solon-server-undertow solon-server-undertow-add-jsp 增加 JSP 视图

五、HTTP 模式详解

5.1 基础 Web 应用

以最轻量的 solon-server-jdkhttp(0.3MB)为例:

<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-server-jdkhttp</artifactId>
</dependency>
@SolonMain
public class DemoApp {
    public static void main(String[] args) {
        Solon.start(DemoApp.class, args);
    }
}

@Controller
public class DemoController {
    @Mapping("/hello")
    public String hello(@Param(defaultValue = "world") String name) {
        return "Hello " + name + "!";
    }
}

5.2 SSL/HTTPS 配置

方式一:配置文件

server:
  ssl:
    keyStore: "/data/_ca/demo.jks"    # 或 "demo.pfx"
    keyPassword: "demo"

方式二:自定义 SSLContext(v2.5.9+)

不走配置文件,完全代码控制:

@SolonMain
public class AppDemo {
    public static void main(String[] args) {
        Solon.start(AppDemo.class, args, app -> {
            SSLContext sslContext = buildSSLContext(); // 自行构建
            app.onEvent(HttpServerConfigure.class, e -> {
                e.enableSsl(true, sslContext);
            });
        });
    }
}

5.3 额外 HTTP 端口

启用 HTTPS 后仍需保留 HTTP 端口的场景(v2.2.18+):

@SolonMain
public class SeverDemo {
    public static void main(String[] args) {
        Solon.start(SeverDemo.class, args, app -> {
            app.onEvent(HttpServerConfigure.class, e -> {
                e.addHttpPort(8082);
            });
        });
    }
}

5.4 控制端口启停

// 关闭 HTTP 自动启动
@SolonMain
public class SeverDemo {
    public static void main(String[] args) {
        Solon.start(SeverDemo.class, args, app -> {
            app.enableHttp(false);
        });
    }
}

六、WebSocket 模式

6.1 启用 WebSocket

使用 Jetty 为例(需添加二级插件):

<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-server-jetty</artifactId>
</dependency>
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-server-jetty-add-websocket</artifactId>
</dependency>
@SolonMain
public class DemoApp {
    public static void main(String[] args) {
        Solon.start(DemoApp.class, args, app -> {
            app.enableWebSocket(true);  // 启用 WebSocket
        });
    }
}

6.2 WebSocket 端点

@ServerEndpoint("/ws/demo/{id}")
public class WebSocketDemo extends SimpleWebSocketListener {
    @Override
    public void onMessage(WebSocket socket, String text) throws IOException {
        socket.send("我收到了:" + text);
    }

    @Override
    public void onOpen(WebSocket socket) {
        System.out.println("连接建立:" + socket.param("id"));
    }
}

七、Socket.D 模式

7.1 依赖配置

<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-server-socketd</artifactId>
</dependency>
<!-- 按需选择传输协议包 -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>socketd-transport-netty</artifactId>
</dependency>

7.2 启用 Socket.D 服务

@SolonMain
public class DemoApp {
    public static void main(String[] args) {
        Solon.start(DemoApp.class, args, app -> {
            app.enableSocketD(true);
        });
    }
}

7.3 Socket.D 端点

@ServerEndpoint("/demo/{id}")
public class SocketDDemo extends SimpleListener {
    @Override
    public void onMessage(Session session, Message message) throws IOException {
        session.send("test", new StringEntity("我收到了:" + message));
        // session.param("id"); // 获取路径变量
    }
}

7.4 三种协议架构的端口分配

协议 端口计算 示例(server.socket.port=28080)
sd:tcp ${server.socket.port} 28080
sd:udp ${server.socket.port} + 1 28081
sd:ws ${server.socket.port} + 2 28082

7.5 Socket.D 配置项全表

server:
  socket:
    name: "waterapi.tcp"          # 信号名称
    port: 28080                   # 信号端口
    host: "0.0.0.0"               # 绑定主机
    wrapPort: 28080               # 包装端口(Docker + 注册时用)
    wrapHost: "0.0.0.0"           # 包装主机
    coreThreads: 0                # 最小线程(0=自动)
    maxThreads: 0                 # 最大线程(0=自动)
    idleTimeout: 0                # 闲置超时(0=自动,ms)
    ioBound: true                 # IO密集型

八、Server 配置体系

8.1 四大配置系列

系列 说明 备注
server.? 主配置 供信号配置继承
server.http.? HTTP 信号配置
server.socket.? Socket 信号配置
server.websocket.? WebSocket 信号配置

8.2 配置继承关系

  • 当没有"信号配置"时,使用"主配置"
  • 例如:没有 server.http.ssl 时,使用 server.ssl

端口默认值

信号 默认端口 说明
http server.port(默认 8080) 主端口
websocket 主端口 + 15000 23080
socket 主端口 + 20000 28080

8.3 完整配置模板

solon:
  app:
    name: "demo"
    group: "demo"
  env: "dev"
  stop:
    safe: 1
    delay: 10
  threads:
    virtual:
      enabled: false

server:
  port: 8080
  host: "0.0.0.0"
  
  # SSL 主配置(所有信号共享)
  ssl:
    keyStore: "/data/_ca/demo.jks"
    keyPassword: "demo"
  
  # HTTP 信号配置
  http:
    port: 8080
    coreThreads: 0
    maxThreads: 0
    idleTimeout: 0
    ioBound: true
  
  # WebSocket 信号配置
  websocket:
    port: 23080
  
  # Socket 信号配置
  socket:
    name: "demo.tcp"
    port: 28080
    host: "0.0.0.0"
    coreThreads: 0
    maxThreads: 0
    idleTimeout: 0
    ioBound: true

九、线程数配置

9.1 配置项

server:
  http:
    coreThreads: 0     # 最小线程(0=自动)
    maxThreads: 0      # 最大线程(0=自动)
    idleTimeout: 0     # 闲置超时(ms)
    ioBound: true      # IO密集型

# 虚拟线程池(v2.7.3+)
solon:
  threads:
    virtual:
      enabled: false

9.2 自动计算规则

IO 密集型(ioBound: true,默认)

配置项 计算公式 2c4g 实例
coreThreads CPU 内核数 × 2 4
maxThreads coreThreads × 32 128

CPU 密集型(ioBound: false

配置项 计算公式 2c4g 实例
coreThreads CPU 内核数 × 2 4
maxThreads coreThreads × 8 32

9.3 调优建议

  • coreThreads 一般不需要配置(BIO 太大不收缩,NIO 不能太大)
  • maxThreads 一般默认即可;单实例且流量大或请求慢时适当调大
  • 线程数不是越多越好(切换需要时间),也不是越少越好(会不够用)
  • Java 21+ 可考虑开启虚拟线程:solon.threads.virtual.enabled: true

十、嵌入式启动

Solon 的所有 Server 插件均支持嵌入式启动,可直接通过 Server 实现类手动控制生命周期:

// JDK HTTP Server
JdkHttpServer server = new JdkHttpServer();
server.start(null, 8080);
// ... 使用中
server.stop();

// Jetty Server
JettyServer server = new JettyServer();
server.start(null, 8080);

// Undertow Server
UndertowServer server = new UndertowServer();
server.start(null, 8080);

// Vert.x Server
VertxServer server = new VertxServer();
server.start(null, 8080);

这种模式适合:

  • 将 Solon 嵌入到已有 Java 应用中
  • 在单元测试中启动轻量级服务器
  • 构建自定义的启动流程

十一、实战案例:三种服务同时运行

一个应用同时提供 HTTP API + WebSocket + Socket.D 三种服务:

11.1 Maven 依赖

<!-- HTTP + WebSocket (通过 Jetty) -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-server-jetty</artifactId>
</dependency>
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-server-jetty-add-websocket</artifactId>
</dependency>

<!-- Socket.D -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-server-socketd</artifactId>
</dependency>
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>socketd-transport-netty</artifactId>
</dependency>

<!-- 其他基础依赖 -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-web</artifactId>
</dependency>

11.2 配置文件

server:
  port: 8080
  
  http:
    port: 8080
    coreThreads: 4
    maxThreads: 128
  
  websocket:
    port: 8080    # 与 http 共用端口
  
  socket:
    name: "demo.tcp"
    port: 28080
    coreThreads: 2
    maxThreads: 64

11.3 启动类

@SolonMain
public class App {
    public static void main(String[] args) {
        Solon.start(App.class, args, app -> {
            app.enableHttp(true);
            app.enableWebSocket(true);
            app.enableSocketD(true);
        });
    }
}

11.4 HTTP 控制器

@Controller
public class ApiGateway {
    @Inject
    OrderService orderService;
    
    @Mapping("/api/order/create")
    public OrderDTO createOrder(@Body OrderRequest req) {
        return orderService.create(req);
    }
    
    @Mapping("/api/order/{id}")
    public OrderDTO getOrder(int id) {
        return orderService.getById(id);
    }
}

11.5 WebSocket 端点

@ServerEndpoint("/ws/notify/{userId}")
public class NotifyWebSocket extends SimpleWebSocketListener {
    @Override
    public void onOpen(WebSocket socket) {
        String userId = socket.param("userId");
        SessionManager.register(userId, socket);
    }
    
    @Override
    public void onClose(WebSocket socket) {
        String userId = socket.param("userId");
        SessionManager.unregister(userId);
    }
    
    @Override
    public void onMessage(WebSocket socket, String text) {
        // 处理客户端推送的消息
    }
}

11.6 Socket.D 端点

@ServerEndpoint("/sd/rpc")
public class RpcSocketD extends SimpleListener {
    @Override
    public void onMessage(Session session, Message message) throws IOException {
        if ("order.query".equals(message.topic())) {
            String orderId = message.bodyAsString();
            // 处理 RPC 请求
            session.reply(message, new StringEntity("{\"status\":\"ok\"}"));
        }
    }
}

十二、总结与选型建议

选型决策表

场景 推荐 Server 插件 理由
微服务 API、RESTful solon-server-jdkhttp 0.3MB 极简,够用
需要 WebSocket solon-server-jettysolon-server-smarthttp 原生 WS 支持
高性能 HTTP/2 solon-server-undertowsolon-server-vertx HTTP/2 支持
传统 JSP 项目 solon-server-tomcat + JSP 二级插件 JSP 兼容
RPC 长连接 solon-server-socketd Socket.D 协议
最小化部署 solon-server-jdkhttp 0.3MB 包大小
国产化/信创 solon-server-smarthttp 国产 HTTP 服务器

核心要点

  1. 业务代码与 Server 完全解耦 — 只需换依赖,代码零修改
  2. 最小 0.3MB — jdkhttp 适合微服务和 Serverless
  3. 三种信号并存 — HTTP + WebSocket + Socket.D 可以同一应用运行
  4. 配置继承 — 信号配置缺省时自动使用主配置
  5. 线程数自适应 — 根据 CPU 内核数和 IO 类型自动计算
  6. 嵌入式支持 — 可以嵌入到已有 Java 应用中