How to use relative paths without including the context root name?
Solution 1
If your actual concern is the dynamicness of the webapp context (the "AppName" part), then just retrieve it dynamically by HttpServletRequest#getContextPath()
.
<head>
<link rel="stylesheet" href="${pageContext.request.contextPath}/templates/style/main.css" />
<script src="${pageContext.request.contextPath}/templates/js/main.js"></script>
<script>var base = "${pageContext.request.contextPath}";</script>
</head>
<body>
<a href="${pageContext.request.contextPath}/pages/foo.jsp">link</a>
</body>
If you want to set a base path for all relative links so that you don't need to repeat ${pageContext.request.contextPath}
in every relative link, use the <base>
tag. Here's an example with help of JSTL functions.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<head>
<c:set var="url">${pageContext.request.requestURL}</c:set>
<base href="${fn:substring(url, 0, fn:length(url) - fn:length(pageContext.request.requestURI))}${pageContext.request.contextPath}/" />
<link rel="stylesheet" href="templates/style/main.css" />
<script src="templates/js/main.js"></script>
<script>var base = document.getElementsByTagName("base")[0].href;</script>
</head>
<body>
<a href="pages/foo.jsp">link</a>
</body>
This way every relative link (i.e. not starting with /
or a scheme) will become relative to the <base>
.
This is by the way not specifically related to Tomcat in any way. It's just related to HTTP/HTML basics. You would have the same problem in every other webserver.
See also:
- Browser can't access/find relative resources like CSS, images and links when calling a Servlet which forwards to a JSP
- Is it recommended to use the <base> html tag?
Solution 2
Just use <c:url>
-tag with an application context relative path.
When the value
parameter starts with an /
, then the tag will treat it as an application relative url, and will add the application-name to the url.
Example:
jsp:
<c:url value="/templates/style/main.css" var="mainCssUrl" />`
<link rel="stylesheet" href="${mainCssUrl}" />
...
<c:url value="/home" var="homeUrl" />`
<a href="${homeUrl}">home link</a>
will become this html, with an domain relative url:
<link rel="stylesheet" href="/AppName/templates/style/main.css" />
...
<a href="/AppName/home">home link</a>
Solution 3
You start tomcat from some directory - which is the $cwd for tomcat. You can specify any path relative to this $cwd.
suppose you have
home
- tomcat
|_bin
- cssStore
|_file.css
And suppose you start tomcat from ~/tomcat, using the command "bin/startup.sh".
~/tomcat becomes the home directory ($cwd) for tomcat
You can access "../cssStore/file.css" from class files in your servlet now
Hope that helps, - M.S.
Solution 4
This could be done simpler:
<base href="${pageContext.request.contextPath}/"/>
All URL will be formed without unnecessary domain:port
but with application context.
Solution 5
Instead using entire link we can make as below (solution concerns jsp files)
With JSTL we can make it like: To link resource like css, js:
<link rel="stylesheet" href="${pageContext.request.contextPath}/style/sample.css" />
<script src="${pageContext.request.contextPath}/js/sample.js"></script>
To simply make a link:
<a id=".." class=".." href="${pageContext.request.contextPath}/jsp/sample.jsp">....</a>
It's worth to get familiar with tags
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
There is also jsp method to do it like below, but better way like above:
<link rel="stylesheet" href="<%=request.getContextPath()%>/style/sample.css" />
<script type="text/javascript" src="<%=request.getContextPath()%>/js/sample.js"></script>
To simply make a link:
<a id=".." class=".." href="<%=request.getContextPath()%>/jsp/sample.jsp">....</a>
Related videos on Youtube
kspacja
Updated on April 06, 2020Comments
-
kspacja about 4 years
To working my static file (CSS, JS) I have to write absolute path like
/AppName/templates/style/main.css
. Is there any solution, that I could write relative path likestyle/main.css
?-
T.J. Crowder over 13 yearsWhy (and where) do you have to write the full path? Nearly anywhere I can think of,
style/main.css
should work. There may well be places where it doesn't, but without your telling people what you're actually trying to do, it's going to be very hit-or-miss whether people can help you. -
kspacja over 13 yearsI just want to link css file to my jsp page. I didn't write explain, becouse it was the simplest and only use I can image, so I think that everybody guess. Even so: I'm sorry. My mistake...
-
-
shareef about 11 yearsi dont use pageContext.request.contextPath and i dont see when i really need it i can change the project properties in netbeans for context can you explain more
-
Matt almost 11 years${pageContext... not working for me. Just generates something like localhost:8080/profile/$%7BpageContext.request.context%7D/css/profile/
-
BalusC almost 11 years@Matt: upgrade to at least JSP 2.0 (released a decade ago). Alternatively, use
<c:out>
. Being a complete ignorant and having very legacy software isn't a fair reason to downvote, btw. -
Matt almost 11 yearsThanks Balus for the kind words. How do I tell what version of JSP I have?
-
Vnge over 10 yearsI know this is kinda old, but how would I be able to use ${pageContext.request.contextPath} in a jquery/js variable and use it like that instead of typing out '${pageContext.request.contextPath}' for every link?
-
BalusC over 10 years@Vnge: just let JSP print it as a JS variable?
-
Vnge over 10 yearsThanks, that makes sense! after a bit of googling i found out i can just print out the variable between ${ } just like the pageContext
-
Natix over 8 yearsBeware that the
<base>
tag approach can break relative urls such as<a href="?var=foo">
(yes, these are valid). If placed in for example/page.html
, they will resolve to/?var=foo
instead of/page.html?var=foo
. -
BalusC over 8 years@Natix: Break? It's intented as base URL of all relative URLs. See also a.o stackoverflow.com/a/1889957 Just don't use it if it doesn't fit your technical implementation.
-
croraf over 7 yearsIt works for me without fn substring part. Is there a need to use fn substring here?
-
Impulse The Fox over 6 years
${pageContext.request.contextPath}
is now just${#request.contextPath}
-
BalusC over 6 years@ImpulseTheFox: Nope. That's only the case when you're using some sort of MVC framework on top of JSP/Servlets.
-
Jonathan Laliberte about 5 yearsThat base tag is brilliant, had no idea it existed. Thanks for the wonderful answer, again.