效果如图

部分源码如下
package top.yunp.jfxdemo
import com.sun.net.httpserver.HttpServer
import javafx.application.Application
import javafx.fxml.FXMLLoader
import javafx.scene.Scene
import javafx.stage.Stage
import java.net.InetSocketAddress
import java.net.URLConnection
import java.util.concurrent.CompletableFuture
fun startStaticServer(): CompletableFuture<Int> {
val future = CompletableFuture<Int>()
Thread.ofVirtual().start {
val server = HttpServer.create(InetSocketAddress("127.0.0.1", 0), 0)
server.createContext("/") { exchange ->
val uriPath = exchange.requestURI.path
val resourcePath = "/static${if (uriPath == "/") "/index.html" else uriPath}"
val resource = HelloApplication::class.java.getResource(resourcePath)
if (resource != null) {
val bytes = resource.readBytes()
exchange.responseHeaders.add("Content-Type", URLConnection.guessContentTypeFromName(resourcePath))
exchange.sendResponseHeaders(200, bytes.size.toLong())
exchange.responseBody.use { it.write(bytes) }
} else {
val notFound = "404 Not Found".toByteArray()
exchange.sendResponseHeaders(404, notFound.size.toLong())
exchange.responseBody.use { it.write(notFound) }
}
}
server.start()
future.complete(server.address.port)
}
return future
}
class HelloApplication : Application() {
override fun start(stage: Stage) {
Globals.internalServerPort = startStaticServer().get()
val fxmlLoader = FXMLLoader(HelloApplication::class.java.getResource("/jfx/views/hello-view.fxml"))
val scene = Scene(fxmlLoader.load(), 640.0, 480.0)
stage.title = "Hello!"
stage.scene = scene
stage.show()
}
}
fun main() {
Application.launch(HelloApplication::class.java)
}