Static Files

classpath:/public/* is served at the root without being asked for; staticFiles("/assets") names a different directory. Every response carries an ETag and Last-Modified derived from the resource, so a reload comes back as a bodyless 304 instead of the file again. The default Cache-Control: no-cache means "cache it, but check with me first", which is right for names that never change. For fingerprinted names, say so:

app.staticFiles(new StaticFiles("/public")
        .hostedPath("/assets")              // classpath:/public/* at /assets/*
        .maxAge(Duration.ofDays(365)));     // only when the name carries a content hash

Routes are matched first, so a route can shadow a file. Directories are never served.