正如马特在评论中所建议的那样,如果您为任一路径添加前缀,将会更加简洁。这样,您可以拥有/r/:id
(或/u/:id
使用“u”表示“URL”)并且静态文件不会妨碍您,或者您可以在静态文件前面加上 eg /static/
,甚至只是/s/
为了简洁,您的缩短 URL 不会妨碍你。
但是,如果您更喜欢坚持当前的方案,您可以简单地在处理程序中过滤掉 JavaScript 文件(或任何其他非 ID 请求)并提供文件(但是,如果您以前有自动生成的 ETag,您如果您不想自己处理,则会丢失缓存)。
后一种解决方案如下所示:
app.routes (() -> {
path ("", () -> {
get ("/:id", ctx -> {
String id = ctx.pathParam ("id");
if (id.endsWith (".js")) {
String resourcePath = "your/classpath/resources/folder/" + id;
try {
InputStream resultStream = Thread.currentThread ()
.getContextClassLoader ()
.getResourceAsStream (resourcePath);
if (resultStream == null)
throw new NullPointerException ("Script not found");
ctx.contentType ("application/javascript");
ctx.result (resultStream);
} catch (NullPointerException e) { // script does not exist
e.printStackTrace (); // for development only!
ctx.status (404);
}
return;
}
// do stuff
ctx.redirect ("somewhere.com");
});
});
});
根据您的偏好,您还可以处理resultStream == null
我的代码当前抛出 NPE 以被外部 try/catch 捕获并完全省略 try/catch 的情况。
设置Content-Type
是必不可少的,以便浏览器知道您实际上是在使用 JavaScript 代码进行响应。另外,我通常使用Thread.currentThread ().getContextClassLoader ()
的是因为我们希望根据当前的 HTTP 处理程序线程解析资源,从理论上讲,它可能具有与我们当前所在的类不同的类路径/类加载器。
请注意,如上所述,这将不支持客户端缓存,因为处理程序只是忽略ETag
随请求*发送的所有标头,而是使用完整的文件进行响应,该文件在短时间内有许多请求和大型脚本,肯定会给您的磁盘和 CPU 带来更大的压力。
因此,我实际上建议为静态文件路由添加前缀,让 Javalin/Jetty 处理所有缓存和文件魔法。
*其实If-None-Match
大部分时间都是客户端发送的header。服务器将响应ETag
以允许在浏览器中进行缓存。