JVM生态下Web开发框架:SparkJava、Javalin、Micronaut、SparkKotlin

概述

对Java开发者,或更宽泛意义上的JVM生态开发者而言,首屈一指、人气最高、闭着眼睛选择、人人必会、面试必问、企业必用......Web开发框架,自然就是Spring系列:Spring WebMVC、Spring Web、Spring Boot、Spring Cloud。

但除了Spring之外,开发者还有很多选择,本文对这些框架进行简单汇总,并辅以入门实战案例。

Quarkus

另起一篇,参考Quarkus:简介、原理、实战。

SparkJava

官网,受Ruby的Sinatra框架启发、纯Java实现、用于快速开发Java Web应用的开源(GitHub,9.6K Star,1.6K Fork)框架,其核心设计围绕Java 8 Lambda表达式理念,相比其他Java框架更加简洁。

Web服务基于路由及其处理器构建。路由是核心要素,包含三部分:

  • 动词:对应HTTP方法,包括:get、post、put、delete、head、trace、connect、options
  • 路径(路由模式):决定路由监听的URI
  • 回调:处理函数,针对特定动词和路径生成响应。回调接收请求和响应对象作为参数

示例:

java 复制代码
get("/user/{id}", (req, resp) -> {
	// 回调代码
});

注意事项:项目功能已趋于稳定,不再添加新特性,最后一次提交停留于22年7月10号,更新README文档;Maven最后一个版本2.9.4也是发布于该天。

实战

Maven项目添加如下依赖:

xml 复制代码
<dependency>
	<groupId>com.sparkjava</groupId>
	<artifactId>spark-core</artifactId>
	<version>2.9.4</version>
</dependency>

Hello World:

java 复制代码
import static spark.Spark.*;

public class HelloWorldService {
	public static void main(String[] args) {
		get("/hello", (req, res) -> "Hello, world");
		
		get("/hello/:name", (req,res) -> {
			return "Hello, " + req.params(":name");
		});
	}
}

运行成功后,浏览器访问http://localhost:4567/hello,即可看到经典的Hello, world输出。

更多示例:

java 复制代码
import static spark.Spark.*;

public class SimpleExample {
	
	public static void main(String[] args) {
		//port(5678); 默认使用(监听)4567端口,自定义端口
		get("/hello", (req, resp) -> "Hello World!");
		
		post("/hello", (req, resp) ->
			"Hello World: " + req.body()
		);
		
		get("/private", (req, resp) -> {
			resp.status(401);
			return "Go Away!!!";
		});
		
		get("/users/:name", (req, resp) -> "Selected user: " + req.params(":name"));
		
		get("/news/:section", (req, resp) -> {
			resp.type("text/xml");
			return "<?xml version=\"1.0\" encoding=\"UTF-8\"?><news>" + req.params("section") + "</news>";
		});
		
		get("/protected", (req, resp) -> {
			halt(403, "I don't think so!!!");
			return null;
		});
		
		get("/redirect", (req, resp) -> {
			resp.redirect("/news/world");
			return null;
		});
		
		get("/", (req, resp) -> "root");
	}
}

带CRUD的示例:

java 复制代码
import static spark.Spark.*;

public class Books {
	private static Map<String, Book> books = new HashMap<String, Book>();
	
	public static void main(String[] args) {
		final Random random = new Random();
		// 新增:author=Foo&title=Bar
		post("/books", (req, resp) -> {
			String author = req.queryParams("author");
			String title = req.queryParams("title");
			Book book = new Book(author, title);
			int id = random.nextInt(Integer.MAX_VALUE);
			books.put(String.valueOf(id), book);
			resp.status(201); // HTTP状态码
			return id;
		});
		// 查询
		get("/books/:id", (req, resp) -> {
			Book book = books.get(req.params(":id"));
			if (book != null) {
				return "Title: " + book.getTitle() + ", Author: " + book.getAuthor();
			} else {
				resp.status(404);
				return "Book not found";
			}
		});
		// 更新:author=Foo&title=Bar
		put("/books/:id", (req, resp) -> {
			String id = req.params(":id");
			Book book = books.get(id);
			if (book != null) {
				String newAuthor = req.queryParams("author");
				String newTitle = req.queryParams("title");
				if (newAuthor != null) {
					book.setAuthor(newAuthor);
				}
				if (newTitle != null) {
					book.setTitle(newTitle);
				}
				return "Book with id '" + id + "' updated";
			} else {
				resp.status(404);
				return "Book not found";
			}
		});
		// 删除
		delete("/books/:id", (req, resp) -> {
			String id = req.params(":id");
			Book book = books.remove(id);
			if (book != null) {
				return "Book with id '" + id + "' deleted";
			} else {
				resp.status(404);
				return "Book not found";
			}
		});
		// 查询全部
		get("/books", (req, resp) -> {
			String ids = "";
			for (String id : books.keySet()) {
				ids += id + " ";
			}
			return ids;
		});
	}
	@Data
	public static class Book {
		public String author, title;
	}
}
java 复制代码
java 复制代码

模版引擎

Web开发,大多数情况下是CRUD页面,此时就可考虑引入模版引擎。

可选项:

  • spark-template-velocity:基于Apache Velocity的模板引擎,语法简洁,适合快速渲染简单页面
  • spark-template-freemarker:基于FreeMarker的模板引擎,支持逻辑控制与宏定义,适合复杂页面渲染
  • spark-template-thymeleaf:基于Thymeleaf的模板引擎,语法贴近HTML,支持自然模板,适合前后端协作

以Thymeleaf为例,Maven依赖如下:

xml 复制代码
<dependency>
	<groupId>com.sparkjava</groupId>
	<artifactId>spark-template-thymeleaf</artifactId>
	<version>2.7.1</version>
</dependency>

完整示例:

java 复制代码
import spark.ModelAndView;
import spark.template.thymeleaf.ThymeleafTemplateEngine;

import static spark.Spark.get;

public class ThymeleafExample {
	public static void main(String[] args) {
		get("/hello", (req, res) -> {
			Map<String, Object> model = new HashMap<>();
			model.put("name", "World");
			return new ModelAndView(model, "hello.html");
		}, new ThymeleafTemplateEngine());
	}
}

对应的模板文件 resources/templates/hello.html:

html 复制代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>Hello</title>
</head>
<body>
	<p th:text="'Hello, ' + ${name} + '!'">Hello, World!</p>
</body>
</html>

运行后访问http://localhost:4567/hello,即可看到渲染后的Hello, World!页面。

使用Velocity需引入的Maven依赖:

xml 复制代码
<dependency>
	<groupId>com.sparkjava</groupId>
	<artifactId>spark-template-velocity</artifactId>
	<version>2.7.1</version>
</dependency>

使用Freemarker需引入的Maven依赖:

xml 复制代码
<dependency>
	<groupId>com.sparkjava</groupId>
	<artifactId>spark-template-freemarker</artifactId>
	<version>2.7.1</version>
</dependency>

代码示例,略,不难。

spark-debug-tools

官方提供、Java+FreeMarker+CSS实现、开源(GitHub,70 Star,17 Fork)调试工具。

添加依赖:

xml 复制代码
<dependency>
	<groupId>com.sparkjava</groupId>
	<artifactId>spark-debug-tools</artifactId>
	<version>0.5</version>
</dependency>

基本使用,只需添加2行代码:

java 复制代码
import static spark.debug.DebugScreen.enableDebugScreen;
	// main方法里添加
	enableDebugScreen();

Javalin

官网,开源(GitHub,8.4K Star,648 Fork)、Kotlin+Java实现、为Java和Kotlin开发者设计、轻量级Web框架;基于Jetty构建,性能表现非常出色。

最初是SparkJava的分支,设计灵感源自koa.js,从零开始就追求简洁易懂,API设计直观,上手成本极低。

特性:

  • 支持WebSocket、HTTP2和异步请求
  • 默认包含Jackson、Jetty、等依赖

源码目录分析

典型的Maven多模块化设计。

实战

添加Maven依赖:

xml 复制代码
<dependency>
	<groupId>io.javalin</groupId>
	<artifactId>javalin</artifactId>
	<version>7.2.3</version>
</dependency>

Gradle项目添加依赖:

groovy 复制代码
implementation("io.javalin:javalin:7.2.3")

Hello World示例:

java 复制代码
import io.javalin.Javalin;
public class HelloWorld {
	public static void main(String[] args) {
		var app = Javalin.create(config -> {
			config.routes.get("/", ctx -> ctx.result("Hello World"));
		}).start(7070);
	}
}

运行成功后,在浏览器输入http://localhost:7070。

Micronaut

官网,Java+Groovy+Kotlin实现、开源(GitHub,6.4K Star,1.2K Fork)、面向JVM生态开发者的、Web开发框架,中文文档。

为云原生和微服务架构打造,通过编译时依赖注入和AOT(Ahead-of-Time)友好设计,实现亚秒级的启动速度和极低的内存占用,让Java应用在Serverless和边缘计算等场景中焕发新生。

适用场景:

  • 高并发、低延迟的微服务,如API网关、实时数据处理
  • Serverless环境,如AWS Lambda、Azure Functions
  • 资源受限的边缘计算设备

由Grails框架的创建者开发,旨在提供构建JVM应用程序所需的所有工具:

  • 依赖注入和控制反转(IoC)
  • 面向方面编程(AOP)
  • 敏感默认值和自动配置

模块:

  • Micronaut Data
  • Test
  • Redis
  • Servlet
  • MicorStream
  • GraphQL
  • Spring
  • R2DBC
  • MongoDB
  • Nats
  • RabbitMQ
  • Neo4j
  • JMX
  • Mail
  • Groovy
  • ACME
  • AOT
  • TOML
  • Reactor
  • Azure
  • Liquibase
  • Picocli
  • Tracing

对比Spring Boot

特性 Micronaut SpringBoot
依赖注入机制 编译时DI,无反射,启动快 运行时DI,依赖反射,启动较慢
启动时间(JVM) 极快(通常<1s) 较慢(通常2-5s+)
内存占用(RSS) 极低(JVM模式下~50-100MB) 较高(通常200MB+)
GraalVM原生支持 一流,官方深度集成,开箱即用 有限支持,需额外配置,Spring Native仍在发展中
响应式编程 原生支持Project Reactor 支持WebFlux,但不如前者集成紧密
原生镜像启动 毫秒级(<50ms) 秒级
原生镜像内存 10-30MB 50-100MB+
学习曲线 对Spring/Grails用户平滑 对Java开发者普遍友好
生态系统成熟度 快速成长,核心微服务功能完善 极其成熟,拥有最庞大的社区和第三方库
适用场景 云原生、微服务、Serverless、边缘计算 通用,尤其适合传统企业级单体/微服务

实战

Hello World应用:

java 复制代码
import io.micronaut.http.annotation.*;

@Controller("/hello")
class HelloController {
	@Get
	Map<String, String> index() {
		return Collections.singletonMap("message", "Hello World");
	}
}

运行成功,浏览器打开http://localhost:8080,即可看到经典的Hello World输出。

CLI

官方提供CLI,可通过SDKMAN安装:

bash 复制代码
sdk install micronaut
mn create-app com.johnny.demo
cd demo && ./gradlew run
# Startup completed in 235ms.
./gradlew nativeRun
# Startup completed in 15ms.

浏览器打开http://localhost:8080。

通过GraalVM将应用编译为原生二进制文件,./gradlew nativeRun可进一步减少启动时间。

进阶命令行:

bash 复制代码
mn create-app book-service --features=hibernate-jpa,h2,openapi,redis-lettuce
bash 复制代码
bash 复制代码

SparkKotlin

和上面的SparkJava同属一个开发者、几乎纯Kotlin实现、开源(GitHub,983 Star,42 Fork)Web开发框架。

注意:官方发布的Maven依赖还处于alpha版本,项目已无人维护,最后一次提交停留于18年2月20号。

实战

Kotlin项目添加如下唯一一个依赖:

xml 复制代码
<dependency>
	<groupId>com.sparkjava</groupId>
	<artifactId>spark-kotlin</artifactId>
	<version>1.0.0-alpha</version>
</dependency>

总结与选型建议

框架对比

框架 适用场景 性能 维护状态 推荐指数
Spring 企业级单体/微服务、大型项目、生态丰富 中等(运行时DI,启动较慢) 极其活跃,社区庞大 ⭐⭐⭐⭐⭐
Quarkus 云原生、Serverless、微服务、GraalVM原生镜像 极快(编译时DI,启动<1s) 活跃,RedHat主导 ⭐⭐⭐⭐⭐
SparkJava 小型API、原型验证、快速Demo 轻量、启动快 已停止维护(22年7月) ⭐⭐⭐
Javalin 轻量级Web服务、WebSocket、Kotlin/Java混合项目 优秀(基于Jetty) 活跃,持续迭代 ⭐⭐⭐⭐
Micronaut 云原生、微服务、Serverless、边缘计算 极快(编译时DI,启动<1s) 活跃,Grails团队维护 ⭐⭐⭐⭐⭐
SparkKotlin Kotlin快速原型、小型API 轻量 已停止维护(18年2月) ⭐⭐

选型建议

  • 企业级大型项目:优先选择Spring,生态最成熟、社区最庞大、招聘需求最多,适合长期维护。
  • 云原生/Serverless:优先选择Quarkus或Micronaut,两者都支持编译时DI和GraalVM原生镜像,启动快、内存占用低,非常适合微服务和边缘计算场景。
  • 轻量级API/原型验证:选择Javalin,API简洁直观、上手成本低,且仍在活跃维护;SparkJava:虽然轻量但已停止维护,不建议新项目使用。
  • Kotlin项目:Javalin对Kotlin支持良好,是比已停止维护的SparkKotlin更稳妥的选择。

总体而言,若追求生态与稳定选Spring,追求极致启动速度与云原生选Quarkus/Micronaut,追求轻量简洁选Javalin。

相关推荐
晨小安11 小时前
ThreadLocal及其内存泄漏问题深度解析
java·jvm·tomcat·哈希表
jingli918 小时前
一个测试用例把连接池卡死 30 秒:SQLite 连接池 max_size=1 下的重入自锁复盘
jvm·sqlite·测试用例
imDwAaY1 天前
Java中垃圾回收器 G1 和 CMS 有什么区别?
jvm·后端
xiaoqiMikko1 天前
JVM 线上排查实战(五):升 JDK 17 后进程起不来,十几个老 GC 参数挨个实测(完结)
java·jvm
Flynt1 天前
Java 27 悄悄改了 3 个默认值,我在 1 核小机器上逐个验证了一遍
java·jvm·性能优化
xiaoqiMikko1 天前
JVM 线上排查实战(三):grep BLOCKED 找不到的死锁,和 jstack 根本不报的死锁
java·jvm
此时不提桶,更待何时7 天前
01-06-A-JVM排查实战详解
java·jvm
wuminyu7 天前
HotSpot的轻量锁与膨胀后的ObjectMonitor状态重建原理
java·linux·c语言·jvm·c++
需要8267 天前
JVM 内存区域与对象创建:一次 GC 从哪来
java·jvm·spring boot·spring·servlet·tomcat