How to build robust relative links in Servlet and JSP applications.
The various types of paths that can be found in a Java
web application are explains in: TypesOfPaths
; please read that FAQ first. This entry goes into further details regarding server-relative paths: the type we should be using for any resource referenced from a page in our web applications.
Let's say the we have an image in your images folder that we want to display in your page, the absolute link to that image could look like this
This is absolute because it contains all the information that a browser would need to find it anywhere on the web; including scheme, domain and path on the server.
This is the approach you should
use when the resource (in this case an image) is located in another web application. It should not
be used when the resource is in the same web application.
So why not always just use absolute links?
The code within your web app should never be hard-coded to a specific domain, or even to a specific context path. All resource references to resources within the web app should be relative to itself. That makes it easy to deploy anywhere; and easy to run locally for development and testing
Introducing Relative Links
Since the browser already knows what the domain and path are for the currently loaded resource, you might think that it makes sense to be able to use a path in your tag that is relative to the location of that resource as follows:
But do not do this
In this case the browser will look for an image under an images directory under the same path as the currently loaded resource. This has a number of problems:
Firstly. this creates a strong binding between the URL of the page and the resource paths. That's a fragile way to do things and considered a poor practice.Secondly, the path is likely to be a servlet mapping and not a path to real file in some real folder. Relative paths between some virtual folder, and real folders, are a problem just waiting to happen. If you change your mapping, you need to hunt down all the references and change them accordingly, if you can get it to work at all (there's often no physical folder that matches the servlet path).
So what's the correct way to create paths?
References relative to the server
For paths that are requested from the browser, the correct approach is to use a path that is relative to the server. You do this by prefixing the path to the resource with the context path of the application. For example:
This tells the browser to look for this image under the given path relative to the server hosting the application. This works all the time and forms no strong binding with any other path.
You can now change servlet paths with impunity, and move the entire site anywhere you like. The only time you need to change this path is if you move the folder hierarchy where the images are stored.
What's a context path?
If you are new to servlets, you might not be aware of the context path
Servlet/JSP containers can house multiple webapps under one domain. This is a great feature in JEE
and it lets us deploy more than one application on the same server or domain.
In order to differentiate between the different webapps running under the same domain, the container looks at the first part of the path after the domain name. This is called the context path
How you configure this context path depends upon the servlet container. For Tomcat
, the easiest way is to place the web app in a folder named for the context path in its webapps folder.
If your app is in webapps/my-app, the path to a servlet mapped to /my-servlet would look like this:
All of what we've talked about so far still applies except the location of the site's root directory (from the browser's standpoint).
But earler we said that you should never hard-code the context path in a web app. So how do we handle that?
The getContextPath Method
In servlet code, using the getContextPath() method in servletRequest, we can determine the context path for our application at run time.
In a modern JSP using the EL
What about in legacy JSPs? (Those written prior to 2001)
In a JSP 1.2 app with JSP Scriptlet Expressions
Note that modern JSP pages should never
use scriptlets or Java code inside of them.
You can now move your entire application from domain to domain without having to alter any references. You can also use any context path and run multiple copies under one container and still not have to alter the path for your resources.
See also: TypesOfPaths