I\'ve mapped the Spring MVC dispatcher as a global front controller servlet on /*
.
Map the controller servlet on a more specific url-pattern
like /pages/*
, put the static content in a specific folder like /static
and create a Filter
listening on /*
which transparently continues the chain for any static content and dispatches requests to the controller servlet for other content.
In a nutshell:
<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>/pages/*</url-pattern>
</servlet-mapping>
with the following in filter's doFilter()
:
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
if (path.startsWith("/static")) {
chain.doFilter(request, response); // Goes to default servlet.
} else {
request.getRequestDispatcher("/pages" + path).forward(request, response);
}
No, this does not end up with /pages
in browser address bar. It's fully transparent. You can if necessary make "/static"
and/or "/pages"
an init-param
of the filter.
Add the folders which you don't want to trigger servlet processing to the <static-files>
section of your appengine-web.xml file.
I just did this and looks like things are starting to work ok. Here's my structure:
/
/pages/<.jsp files>
/css
I added "/pages/**" and "/css/**" to the <static-files>
section and I can now forward to a .jsp file from inside a servlet doGet without causing an infinite loop.
Serving static content with appropriate suffix in multiple servlet-mapping definitions solved the security issue which is mentioned in one of the comments in one of the answers posted. Quoted below:
This was a security hole in Tomcat (WEB-INF and META-INF contents are accessible this way) and it has been fixed in 7.0.4 (and will be ported to 5.x and 6.x as well). – BalusC Nov 2 '10 at 22:44
which helped me a lot. And here is how I solved it:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
What you do is add a welcome file in your web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
And then add this to your servlet mappings so that when someone goes to the root of your application, they get sent to index.html internally and then the mapping will internally send them to the servlet you map it to
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>
End result: You visit /Application, but you are presented with /Application/MainActions servlet without disrupting any other root requests.
Get it? So your app still sits at a sub url, but automatically gets presented when the user goes to the root of your site. This allows you to have the /images/bob.img still go to the regular place, but '/' is your app.
With regard to Tomcat, a lot depends on the particular version. There was a bug fix https://bz.apache.org/bugzilla/show_bug.cgi?id=50026 which means the servlet-mapping (other than for '/') for the default servlet behaves differently in Tomcat 6.0.29 (and earlier) compared with later versions.
With Spring 3.0.4.RELEASE and higher you can use
<mvc:resources mapping="/resources/**" location="/public-resources/"/>
As seen in Spring Reference.