简体   繁体   中英

"jar:file" vs. only "file:" reference when retrieving resources in Java

This question is related to my question

Jetty 11.0.11 - 404 on html file in \src\main\webapp\static - maven embedded fat jar

What --EXACTLY-- does "jar:file" mean as a Java resource reference, vs. just "file:"?

And how is that influenced by the operating system ran under?

E. g. using this resource reference in Jetty webserver, in Windows with Oracle JDK 17, files are found as resources and parsed by Jetty webserver:

file:///D:/Projects/verdi_2/target/classes/static/,AVAILABLE}{file:/D:/Projects/verdi_2/target/classes/static}

Using this resource reference in Jetty webserver, in Ubuntu Linux 20.04 LTS with Oracle JDK 17, NO files are found and nothing can be parsed by Jetty webserver:

jar:file:/usr/src/verdi/verdi-12-JDK17-jar-with-dependencies.jar!/static

Is there a difference in how a Linux version of JDK interprets "jar:file" vs. how a Windows version of the JDK interprets "jar:file"?

EDIT : The related issue is the Jetty webserver apparently can no longer serve resources directly out of a JAR file it is itself embedded in. This is now a GitHub bug ticket at https://github.com/eclipse/jetty.project/issues/8549

file: is the beginning of a general file url. jar:file: is that for a jar file particularly, with a view to referring (usually) to a particular entry in a jar. Here's an example you can run (obviously with your own jar url) where you can save an entry as a file (given by the parameter to the app)

import java.nio.file.Paths;
import java.nio.file.Files;
import java.net.URL;

public class JarUrl {
    public static void main(String[] args) {
        try {
            URL url = new URL("jar:file:root.jar!/root/a/b.txt");
            Files.copy(url.openStream(), Paths.get(args[0]));
        }
        catch(Throwable t) {
            t.printStackTrace();
        }
    }
}

What --EXACTLY-- does "jar:file" mean as a Java resource reference, vs. just "file:"?

You're mischaracterising the URL a little bit. The string until the first: decides the 'scheme' of a URL, so, the pertinent question is: How does jar: work. The file: part is a smaller aspect of a sub-part of the jar bit.

How does jar: work

The format is jar:(URL-of-jar)!(path-inside-jar)

Where URL-of-jar is itself a valid URL (and file: is just one way to do that. So is http , for that matter), and path-inside-jar is not a URL but a path.

The meaning is: First, resolve the 'URL-of-jar' URL. This gets you a jar file. Then, open the jar file, and retrieve the resource at the stated path.

So, to pull this one apart:

jar:file:/usr/src/verdi/verdi-12-JDK17-jar-with-dependencies.jar!/static

The jar is located at URL file:/usr/src/verdi/verdi-12-JDK17-jar-with-dependencies.jar and the resource it is referring to is the /static resource inside the jar found at the given URL.

How does file: work

That's not java-specific; file: is a generally available URL scheme. You can even type it in a web browser. The more general URL formatting scheme is scheme://server/resource , but with file: , server doesn't apply (it is by definition local to the system you are on), so usually its put as file:///foo , ie - an empty 'server' part. Because 3 slashes is a drag to type, I guess, file:/resource is allowed by some 'URL parsers', including java's in this regard, so, file:/usr/... simply maps straight to a local folder: /usr/src/verdi/verdi-12-JDK-etc , as in, if you type ls /usr/src/verdi/verdi-12-JDK17-jar-with-dependencies.jar on the command line on your system, it would show a result (and if it does not, this URL would fail to find anything).

And how is that influenced by the operating system ran under?

It isn't. file URLs are a general concept that work on any platform. Of course, /usr/src/verdi/etc is never going to work correctly on a windows platform. Or on anybody else's machine. The problem isn't "Oh no. This won't run on another OS,", The problem with file URLs. especially absolute ones, is "Oh no! This will not run on any machine other than this one!".

file:///D:/Projects

I've explained the triple slashes earlier. This is the standard windows 'scheme' for how to stick paths in file URLs: Always forward slashes (even though windows normally uses backslashes), and treat the disk letter as if it is a 'drive' in the 'root': /D:/Project is URL-ese for:

D:
cd \Project

There is no difference in OS at all - file: URLs are handled by 'interpret this file URL the way any file URL would be interpreted on this machine'.

The answer to the related question

Jetty 11.0.11 - 404 on html file in \src\main\webapp\static - maven embedded fat jar

which prompted this post is in the long series of posts beneath this GitHub issue for jetty:

https://github.com/eclipse/jetty.project/issues/8549

In essence, eventually I had to first clean up my Maven pom.xml (see this thread for the discussion and for links to a pom.xml example that is compliant with Maven Shade plugin and Jetty 11.0.11 requirements and standards) then at the end of the day hardcode a link to the JAR file to find the HTML, JS, etc. resources Jetty was to serve out as a webpage. Also put in a conditional where, on compiling, I need to specify if the code will run "in-IDE" (in my case, Netbeans 14) or "in-JAR" - eg in a detached JRE elsewhere than the Netbeans 14 IDE.

Also dropped using the Jetty WebAppContext class and started rendering web content out of a normal ServletContextHandler.

Hopefully this may help someone upgrading Jetty from Jetty 9.xxx to 11 and finding that it all falls apart.

For details as to why they changed so much, see the GitHub link (the last few entries are apropos.)

The github discussion also contains full working source code (startJettyc method) that solved the issue of getting a 404 in a detached, non-IDE modality where the JAR was being run in an JRE separate from an IDE.

Stefan

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM