i want to tell my java servlet to ignore calls for static files, for example, if the file exists - just return the actual file without actually loading the servlet.
in my example i have a MyServlet in netbeans, and under the "web pages" directory i placed image.jpg.
next, i generated a .war file and placed it under tomcat/webapps
when i try to make a request to localhost:8080/MyServlet/image.jpg - the file is not loaded, the servlet is executed instead.
what i want is that if the file exists - it will return it, otherwise will run the servlet.
is there a quick way to implement it?
Mapping your servlet to / or /* is not the standard way for implementing servlets. In general you map global (controller) servlets to a path like /myServlet/*. Tomcat's default servlet is already available to serve your static content. It's configured in <tomcat>/conf/web.xml. Extract from inline documentation:
<!-- The default servlet for all web applications, that serves static -->
<!-- resources. It processes all requests that are not mapped to other -->
<!-- servlets with servlet mappings (defined either here or in your own -->
If you follow the above mentioned approach URLs in your application may look like this:
Static resource: http://myserver/myWAR/images/image.gif
Your servlet's URLs: http://myserver/myWAR/myServlet/* (* := wildcard)
Of course, more complex options like offloading static content to an external web server are available. You can override the standard configuration as well, but in most situations this is not necessary (at least in my experience).
Normally you'd handle this via your servlet mapping or by putting your static resources away from your servlet mapping.
Otherwise, if the request is mapping to your servlet, you either need to (a) check for the file in the servlet, and redirect to the real filename or stream back the image yourself, or (b) write a filter that knows enough about your webapp's structure to see if the request should be handled by your servlet, or the container.
If you described your usecase it'd be easier to be more helpful.
For static files you most likely need just to use http://localhost:8080/image.jpg (i.e. without the MyServlet part in the URL)
Related
I'd like to know if anyone has a solution to access resources of a website through a servlet only.
I have all my resources under WEB-INF. In other words, I don't want users to have direct access to any of my resources.
You can use ServletContext#getResource() for that.
URL resource = getServletContext().getResource("/WEB-INF/file.ext");
File file = new File(resource.getPath());
// ...
You can even use ServletContext#getResourceAsStream() to get an InputStream directly:
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/file.ext");
// ...
As you can see in the examples, the ServletContext is available in servlets by the inherited GenericServlet#getServletContext() method.
That said, the phrase I don't want users to have direct access to any of my resources. is a bit contradicting. You're serving those resources by a servlet anyway? A servlet is directly accessible by URL. How is that different from "direct access"? Or do you just want to control the access based on some conditions? I'd say, a Filter is more suitable for this task.
Usually one would only fully hide the JSP files from direct access. In a Servlet which acts as front controller (according the MVC pattern) you could then forward requests to JSP files using RequestDispatcher#forward() which you in turn can obtain by ServletRequest#getRequestDispatcher().
request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
You can hide jsp from the end user. In fact, you don't even have to deploy original jsp files with your web application, you can precompile them:
http://tomcat.apache.org/tomcat-5.5-doc/jasper-howto.html#Web%20Application%20Compilation
And the only way to hide html/js/css files is not to use them. Anything that's sent to the browser can be viewed there.
I have a simple web app that allows the user to upload and access files. When the user accesses an uploaded file, the server needs to support all of the header types such as Accept-Ranges so that partial-content responses can be made on large media files. The DefaultServlet (in Tomcat) handles everything well in its serveResource() method called by doGet(), so I would like to use the DefaultServlet for the uploaded files. This is easy enough in normal circumstances since it is the DEFAULT servlet, but unfortunately for my case, I am unable to find a way to use the default servlet.
In order to prevent the uploaded files from being deleted when the webapp is redeployed, I need to store them outside of the webapp directory.
These files should only be accessible to the user that uploaded them, so I created a javax.servlet.Filter to handle resource access authorization. I know that if I add a new context in server.xml for the external resource directory, they will be accessible, and the DefaultServlet will be used.
<Context docBase="/path/to/resources" path="/resource" />
But I do not want to do that because then I am required to invasively modify server.xml which is not recommended (for reasons), and when a context exists for the /resource path, my filter for that url-mapping will not be invoked. So I do not think creating a new context is a good solution.
The only other solution I can think of would be to create a servlet for all requests at '/resource/*' which extends DefaultServlet, and somehow override functionality that would instead get the requested file at its actual external location rather than returning 404 on the non-existent resource in the webapp.
However, I have not been able to find an easy way to convert the DefaultServlet into one that can fetch files external to the webapp directory. Maybe there is a way?
How would I go about handling this?
Not an answer
In order to prevent the uploaded files from being deleted when the
webapp is redeployed
It means you are re-deploying your stuffs wrong(in a very bad manner), probably using war files, or worse(worst) tomcat manager.
I know that if I add a new context in server.xml for the external
resource directory, they will be accessible, and the DefaultServlet
will be used.
You are right, but you are wrong about having another context, it's not necessary.
Solutions:
Dear Michael-O specified the easiest and probably best answer.
You may also implement something like DefaultServlet too, sometimes(not for your case) it's better to implement things from zer0 rather than configuring and maintaining many too much complex stuffs.
I have a group of static files (mainly the static files, including css and images, that make up the ExtJS JavaScript framework). This group of static files rarely changes and therefore I decided NOT to include them within the items in the web application's war file. (I.e. I didn't follow the approach recommended by this answer.)
Right now I serve all these static files under /extjs by having the following Context container defined in server.xml:
<Context docBase="/path/to/extjs-4.1.1" path="/extjs" />
That "works" so far; still if anyone is able to suggest a better approach please do.
However I can't find a way to add expires HTTP headers to files served by this context.
Any idea how to configure Tomcat7 in this respect?
It doesn't appear that Tomcat's default servlet (org.apache.catalina.servlets.DefaultServlet) has a way to do this.
The easiest thing to do would be to create a servlet filter that simply adds the HTTP headers you need to every request. Since the <context> defines a webapp, you can add a WEB-INF/web.xml file to /extjs and load your filter there. Since /extjs is a separate context, your 'real' application won't be affected.
i'm trying to find a way remap a path to an absolute one in order to retrieve images stored in the server filesystem, i'm also using spring mvc but the <mvc:resource> can't map absolute paths, and i can't find a nice way to do this with spring controllers
i.e. I need to map all the image requests from /images/** to /root/var/img/**, in this way when a client browser try to load an image of the page, every images stays in the path above mentioned
You can create a new context with docBase referencing to your folder (/root/var/img) It should look like this:
<Context path=”/images” docBase=”/root/var/img/” ... >
</Context>
Refer to Tomcat context configuration documentation for more details (e.g., for Tomcat 6: Apache Tomcat Configuration Reference: The Context Container).
Introduction to this document lists possible places where context elements can be defined.
EDIT
As I mentioned in comments, Spring-specific way to do this without creating any new context seems to be using RedirectView (link to Spring v2.5 JavaDoc). According to JavaDoc:
"View that redirects to an absolute, context relative, or current
request relative URL, by default exposing all model attributes as HTTP
query parameters."
EDIT2
It seems I've misunderstood RedirectView purpose, which is a good old URL redirection. Thus, answer by #Jens should be more appropriate (+1). I still wonder if there's an existing standard solution in Spring (what I originally thought RedirectView would do..) It's not like there's much code to write, but still :)
EDIT3
After reading more on this topic, I found out that <mvc:resources> is able to do this (i.e., mapping resource using not only relative path, or classpath), you just need to correctly configure location using file: prefix . In fact, there's already answer on SO that explains exactly what you need to do: Spring : serving static resources outside context root
not sure if I am getting that right but I think the common way to do that is to set up a controller which is mapped on the requests to /images/:
#RequestMapping(value ="/images/")
public void fetchImage(#RequestParam String id, HttpServletResponse response)
Then the controller can load the requested image from a configured directory like "/root/var/img" and write it the the OutputStream of the response. E.g:
org.apache.commons.io.IOUtils.copy(fileInputStram, response.getOutputStream())
In addition you have to set the correct mime type etc. in the response.
Jens
We want to share user validation configuration between a Java validation class (for sanity checking) and a Javascript-enabled form web interface (for usability). What's the best way to deploy this static file in our web application so that it is both available to the server-side code, and available via a URL accessed by the client?
So far I've thought of putting the file in the application root and pointing the validation class at it when it is used, and putting the file in the WEB-INF/classes directory and somehow configuring the container to serve it.
Has anyone else configured a web application like this? What did you end up doing?
Yeah. Put it in the WEB-INF/classes and have a servlet serve out the relevant portion of the validation configurations based on something like a form-id. Better yet, have the servlet transform the configuration into a JSON object and then you can simply include a script tag and start using it :)