Case 1
<servlet-mapping>
<servlet-name>myapp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Case 2
<servlet-mapping>
<servlet-name>myapp</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
If I use case 1 then I dont get any of my pages styled with <link rel="stylesheet" type="text/css" href="${contextPath}/assets/styles.css" />
, but if I use case 2 everything gets styled.
Could someone help me understand why?
Also, could someone tell me which pattern should be used so that I don't have to worry about extensions开发者_开发百科? Like should I be using /*
? The thing is that if I use /*
now when I've been using *.do
while developing my application, everything seems to be breaking, not only the styles but I don't get any pictures rendered, no JCaptcha and all that has to do with links.
And If I try to send a GET request from a REST Client like http://localhost:8080/myapp/user/1
it doesn't work and I need to add .do
at the end and send the same request like http://localhost:8080/myapp/user/1.do
.
Thanks.
Browsers sends separate HTTP requests on linked resources such as CSS files, JS files and images. The URLs of those requests also match the URL pattern of /
. So your myapp
servlet is also called on those requests. However, your myapp
servlet doesn't seem to process them properly, so those requests returns something entirely different. Try requesting those resources yourself separately to learn what your servlet is actually returning to the webbrowser:
http://localhost:8080/myapp/assets/styles.css
In your case, you want to let your myapp
servlet ignore requests on those resources. The best way is to create a filter which does that. Assuming that all of those resources are in a folder called /assets
, then you can achieve this by mapping your servlet on a more specific URL pattern, such as for example /myapp/*
and creating a Filter
listening on /*
which transparently continues the request/response chain for any requests on /assets
and dispatches all other requests to /myapp
.
So, this configuration
<filter>
<filter-name>filter</filter-name>
<filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/myapp/*</url-pattern>
</servlet-mapping>
in combination with the following in filter's doFilter()
:
String uri = ((HttpServletRequest) request).getRequestURI();
if (uri.startsWith("/assets")) {
chain.doFilter(request, response); // Goes to container's default servlet.
} else {
request.getRequestDispatcher("/myapp" + uri).forward(request, response);
}
should work for you.
Here is the relevant page from the Oracle J2EE Tutorial: http://download.oracle.com/docs/cd/E13222_01/wls/docs81/webapp/components.html#148787
This page gives some examples, and refers the reader to the Servlet specs:
For more information on servlet mappings, such as general servlet mapping rules and conventions, refer to Section 11 of the Servlet 2.3 specification at: http://www.jcp.org/aboutJava/communityprocess/final/jsr053/
The spec is worth a read, but you need to click an "I agree" to download the PDF, so I can't link to it directly.
A summary of what the spec says is that the following rules are used (in order):
- An attempt is made to perform an exact match.
- An attempt is made to do a prefix match, with priority given to the match with the longest prefix.
- An attempt is made to do a suffix match.
- "[T]he the container will attempt to serve content appropriate for the resource requested. If a "default" servlet is defined for the application, it will be used."
精彩评论