Precisely. As I've been known to point out occasionally, a WEB server is NOT a FILE server. A URL is a resource locator
string, not something that has an inherent meaning the way a filesystem path does.
The confusion arrives because A) URLs are normally constructed with a syntax that closely resembles that used by Unix filesystems and because B) the most common way of resolving a resource is for the web server (or web application server) is for it to break the URL into components and use the components as the names of directories and files.
However, in J(2)EE, this default resolution is overridden when you pass the URL to a servlet (or a JSP - which is compiled to produce a servlet, so same difference). The servlet is free to deconstruct a URL in any way it desires, and return any type of data it wishes to. Or, in the case of MVC-style servlet frameworks such as JSF and Struts, to dispatch work to an action process, then bounce the results to a second servlet - the JSF or Struts view JSP. Which view JSP is targeted, of course, determined by the navigation rules and directives defined by the application developer in the struts-config.xml or its JSF equivalent.
If a URL is
not routed to a servlet - meaning that it doesn't match any of the routing
patterns defined in the webapp's WEB-INF/web.xml resource then the default action kicks in, which is to strip the host and context parts out of the URL and use the rest as a filename path, PROVIDED that the root of said filename path is not /WEB-INF. For those exceptions, the proper response is a 404 error.
Notice I didn't say WEB-INF/web.xml FILE, I said RESOURCE. That's because WARs in their purest forms are in zipfile format, so the WEB-INF/web.xml "file" isn't actually a discrete filesystem object, thus not a file in the literal sense. And within the context of a deployed webserver the same can be said of the WAR itself, but that's another matter.
So, since the appserver client isn't allowed to see WEB-INF or its subordinates via URLs, it's an ideal place to hide things. And, since the components of the webapp
can see WEB-INF and its subordinates (as web app resources), they can pull that information out and do anything they want with it, including build up JSPs from it. All that's required is an understanding of how the rules are applied.