2

I have a Spring MVC app with various methods annotated by for example

@RequestMapping(value="/SomeUrl/{filename:.+}", method=RequestMethod.GET)

In the majority of cases this works perfectly fine; the ".+" regex means filenames containing a dot character with an extension also work fine (as described here Spring MVC @PathVariable getting truncated )

However if the request is "/SomeUrl/Something.jsp", then the request never even hits my method, presumably because Spring MVC has built in processing that notices that the extension is .jsp and then searches for an actual file called Something.jsp.

My app does have JSPs, but they are all accessed via @RequestMapping methods or servlets, the JSPs are never accessed directly. So how can I disable Spring MVC from performing any special processing with the .jsp extension?

FYI in my web.xml I pipe everything into the MVC dispatcher like so:

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

dispatcher-servlet.xml contains the following:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <!-- Turn off working out content type based on URL file extension, should fall back to looking at the Accept headers -->
    <property name="favorPathExtension" value="false" />
</bean>

<!-- This allows the static content (the CSS file) to be accessed still via the dispatcher -->
<mvc:resources mapping="/resources/**" location="/resources/" />

<context:component-scan base-package="com.myservicepackage" />

Many thanks for any suggestions on this!

Community
  • 1
  • 1
nigelg
  • 151
  • 3
  • 12
  • Is your intention to allow access to jsp or prevent access? ` So how can I disable Spring MVC from performing any special processing with the .jsp extension`. This is confusing me as you seem to be interested in getting the request to your methods.. – minion May 11 '15 at 14:00
  • My intention is that /SomeUrl/Something.jsp is no different than /SomeUrl/Something.txt and is handled by my @RequestMapping annotated method – nigelg May 11 '15 at 14:07

4 Answers4

4

Mapping dispatcher servlet to / is not exactly the same as mapping it to /*. With /*, you effectively ask the servlet container to give all requests to Spring MVC dispatcher servlet. With /, you set the dispatcher servlet as the default servlet for the servlet container, that is a low priority catch all.

From Servlet specification 3.0, chapter 12 Mapping Requests to Servlets :

The first successful match is used with no further matches attempted:

  1. The container will try to find an exact match of the path of the request to the path of the servlet. A successful match selects the servlet.
  2. The container will recursively try to match the longest path-prefix. This is done by stepping down the path tree a directory at a time, using the ’/’ character as a path separator. The longest match determines the servlet selected.
  3. If the last segment in the URL path contains an extension (e.g. .jsp), the servlet container will try to match a servlet that handles requests for the extension. An extension is defined as the part of the last segment after the last ’.’ character.
  4. If neither of the previous three rules result in a servlet match, 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. Many containers provide an implicit default servlet for serving content.

The order of descending priority for servlet mapping will be /* *.jsp, /. And servlet container usually have an implicit mapping for *.jsp (from same reference) :

If the container has an internal JSP container, the *.jsp extension is mapped to it, allowing JSP pages to be executed on demand. This mapping is termed an implicit mapping. If a *.jsp mapping is defined by the Web application, its mapping takes precedence over the implicit mapping.

So an URL ending in *.jsp will not be mapped to Spring by the servlet container. It is no use to try to modify spring mvc configuration.

IMHO, you have two ways to solve it :

  • map dispatcher servlet to /* - but depending on remaining parts of your configuration it may have side effects : thoroughly test everything (it is mainly if the servlet container directly serve some files not declared in <mvc:resources ...>)
  • add an explicit mapping for *.jsp to the dispatcher servlet - but be sure to document it to easily fix the problem if it occurs later with another
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0

If defined request for static resources are not handled by dispatcher servelet, you have configured it as

<mvc:resources mapping="/resources/**" location="/resources/" />

So any URL in the form /resources/ wont be handled by dispatcher servlet.

Ajinkya
  • 22,324
  • 33
  • 110
  • 161
  • Sure but how to do I get it so requests in the form "/xxxx/xxx.jsp" DO come into my method? They aren't static resources, the /resources/ mapping to access static resources is working just fine. – nigelg May 11 '15 at 13:29
  • @nigelg All requests except which are in the form `/resources/**` will be handled by dispatcher servlet. Can you add some example of URL which are not working? – Ajinkya May 11 '15 at 13:31
  • Not exactly. Request in the form `/resources/**` **are** handled by `DispatcherServlet` per mapping `/`. But URLs mapped by `` are forwarded to default servlet of servlet container, that knows how to send static files. But this is unrelated to current question. – Serge Ballesta May 11 '15 at 14:18
  • @SergeBallesta OP have defined resources as ``, that's why I said URL with form `/resources/**` wont be handled by dispatcher servlet. – Ajinkya May 11 '15 at 14:30
  • @Karna What I understand is that OP wants a request `/SomeUrl/*` to be processed by its controller even if the path parameter ends in `.jsp`. It is not a question to serve anything as a static file ... But my answer also missed the point :-( – Serge Ballesta May 11 '15 at 14:45
0

It is not just related about spring. In JAVA Web if you do not want people to reach your files directly typing the the address in browser put them inside WEB-INF folder. You can create subfolders there as your wish.

Cheers !!!

Igor
  • 91
  • 1
  • 12
  • Even though file is accessible or hidden, all requests will be handled by dispatcher servlet. `/` specifies that all requests should be sent to dispatcher servlet, using `` you can define exclusions. – Ajinkya May 11 '15 at 13:55
0

I started putting breakpoints in the MVC DispatcherServlet, trying to see at what point it examines the extension and processes .jsp extensions differently, and this made it clear that the "/SomeUrl/something.jsp" requests weren't coming into the DispatcherServlet at all. So the problem must be in web.xml and not in the configuration of the DispatcherServlet.

After experimenting I found the solution. I had:

<url-pattern>/</url-pattern>

Replacing this by:

<url-pattern>/*</url-pattern>

has now solved the problem, though I'm rather surprised by this, that there's a difference between / and /*

Thanks all very much for trying to help with this question.

nigelg
  • 151
  • 3
  • 12
  • 1
    I've just written the reason in my answer, but the time I write it, you had already found the solution :-) – Serge Ballesta May 11 '15 at 15:24
  • Your answer is much more thorough though, I stumbled across this solution but didn't really understand how the precedence worked. Also you pointed out using /* may break other URLs, which I hadn't thought to verify, but it has, so now fixing those up :) – nigelg May 11 '15 at 17:36