Why does Tomcat resolve context path differently for certain url-mappings?
-
27-10-2019 - |
Question
So, I'm trying to write a servlet which can handle a url mapping like:
domain/context/servlet/resource_id
Before, when I was specifying the url pattern, I was just doing:
/myServlet
But, for what I'm trying to accomplish, I'm doing...
/myServlet/*
THE PROBLEM I'M RUNNING INTO:
I've been using relative path (so, just the file location with respect to my WebContent folder) for my static files (css/js/etc) now that I'm using the /myServlet/*
mapping, the requests for the all static files are now being handled by myServlet. So, basically, the static resources are now resolving to:
domain/context/myServlet/relative_path_I_provide
as opposed to
domain/context/relative_path_I_provide
I'm sure I can fix this myself by just building the absolute path for the resource as opposed to relying on the relative path; but I'm just wondering, why is the resolved path for the static resource changing when I'm using /myServlet/*
url pattern as opposed to /myServlet
?
EDIT:
My folder structure is like
WebContent
|
|
|-- debug
|
|-- css
|
|-- file.css
and I'm adding them in a link tag like:
<link href="debug/css/file.css" rel="stylesheet" type="text/css">
Solution
Ok, that explains it. You're using a relative URL with no path information which means the browser resolves it to same directory as the resource that includes these URLs. When your servlet was mapped to /myServlet
, it didn't appear in the path as a 'directory' i.e. it was the final resource being referred to.
Thus, your URL for the servlet was of the form domain/context/myServlet
and so these relative URLs would also resolve to domain/context/
.
But now, with a mapping of the form /myServlet/*
, the servlet appears as a directory in the URL which means that when you go to domain/context/myServlet/resource_id
, the relative URLs are resolved to the same directory as resource_id
which is domain/context/servlet/
.
See this for more
The fix might be one of the following:
Use relative URLs that are relative to the root of the application i.e. which begin with
/
. However, this would require you to put in the context path for your application in your code which means you can never simply deploy it with a different name without having to change everything. In short, don't do this.Use relative URLs with path information in the form of
../
which will cause the URLs to resolve to a directory one level up. This is also brittle and will break if someone decides to map the resources to URLs of the formdomain/context/myServlet/secondLevel/resource_id
.Create relative URLs that are relative to the context-path of the application. You can do this by setting your
href
values asrequest.getContextPath + "/css/files/file.css"
. This will prepend the context-path to the beginning of each link'shref
thus, for request fordomain/context/myServlet/resource_id
, this will become/context/css/files/file.css
and resolve as you expect.
OTHER TIPS
Has your actual URL changed before and after the url pattern change?
i.e. are you now invoking http://domain/context/myServlet/something
instead of http://domain/context/myServlet
If the answer is yes, then it explains why the static files are now resolving to http://domain/context/myServlet/static_file
(For the same reason why everything was resolving relative to the context in the earlier URL)