HTML 片段

HTMXHotwire Turbo 强调一种“通过线路传输 HTML”的方法,即客户端接收服务器以 HTML 格式而非 JSON 格式发送的更新。 这种方法可以在无需编写大量甚至完全不编写 JavaScript 的情况下,获得单页应用(SPA)的优势。如需全面了解并深入学习,请访问它们各自的官方网站。spring-doc.cadn.net.cn

在 Spring MVC 中,视图渲染通常涉及指定一个视图和一个模型。 然而,在 HTML-over-the-wire(通过网络传输 HTML)中,一种常见的能力是发送多个 HTML 片段, 浏览器可以使用这些片段来更新页面的不同部分。为此,控制器方法 可以返回 Collection<ModelAndView>。例如:spring-doc.cadn.net.cn

@GetMapping
List<ModelAndView> handle() {
	return List.of(new ModelAndView("posts"), new ModelAndView("comments"));
}
@GetMapping
fun handle(): List<ModelAndView> {
	return listOf(ModelAndView("posts"), ModelAndView("comments"))
}

也可以通过返回专用类型 FragmentsRendering 来实现相同的效果:spring-doc.cadn.net.cn

@GetMapping
FragmentsRendering handle() {
	return FragmentsRendering.fragment("posts").fragment("comments").build();
}
@GetMapping
fun handle(): FragmentsRendering {
	return FragmentsRendering.fragment("posts").fragment("comments").build()
}

每个片段都可以拥有一个独立的模型,并且该模型会从请求的共享模型中继承属性。spring-doc.cadn.net.cn

HTMX 和 Hotwire Turbo 支持通过 SSE(服务器发送事件)进行流式更新。 控制器可以使用 SseEmitter 发送 ModelAndView,以在每次事件中渲染一个片段:spring-doc.cadn.net.cn

@GetMapping
SseEmitter handle() {
	SseEmitter emitter = new SseEmitter();
	startWorkerThread(() -> {
		try {
			emitter.send(SseEmitter.event().data(new ModelAndView("posts")));
			emitter.send(SseEmitter.event().data(new ModelAndView("comments")));
			// ...
		}
		catch (IOException ex) {
			// Cancel sending
		}
	});
	return emitter;
}
@GetMapping
fun handle(): SseEmitter {
	val emitter = SseEmitter()
	startWorkerThread{
		try {
			emitter.send(SseEmitter.event().data(ModelAndView("posts")))
			emitter.send(SseEmitter.event().data(ModelAndView("comments")))
			// ...
		}
		catch (ex: IOException) {
			// Cancel sending
		}
	}
	return emitter
}

也可以通过返回 Flux<ModelAndView>,或任何其他可通过 Publisher 适配为 Reactive Streams ReactiveAdapterRegistry 的类型来实现相同的效果。spring-doc.cadn.net.cn