开篇: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"
  
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐