【问题标题】:How to disable processing of JSP URLs in Spring MVC?如何在 Spring MVC 中禁用对 JSP URL 的处理?
【发布时间】:2015-07-22 00:41:26
【问题描述】:

我有一个 Spring MVC 应用程序,其中包含例如注释的各种方法

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

在大多数情况下,这完全可以正常工作; ".+" 正则表达式意味着包含点字符的文件名也可以正常工作(如此处所述 Spring MVC @PathVariable getting truncated

但是,如果请求是“/SomeUrl/Something.jsp”,那么该请求甚至不会命中我的方法,大概是因为 Spring MVC 已经内置处理,注意到扩展名是 .jsp,然后搜索名为的实际文件东西.jsp。

我的应用确实有 JSP,但它们都是通过 @RequestMapping 方法或 servlet 访问的,JSP 永远不会被直接访问。那么如何禁止 Spring MVC 使用 .jsp 扩展名执行任何特殊处理呢?

在我的 web.xml 中仅供参考,我将所有内容通过管道传输到 MVC 调度程序中,如下所示:

<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 包含以下内容:

<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" />

非常感谢您对此提出任何建议!

【问题讨论】:

  • 您打算允许访问jsp还是阻止访问? ` 那么我怎样才能禁止 Spring MVC 使用 .jsp 扩展名执行任何特殊处理`。这让我很困惑,因为您似乎有兴趣将请求发送给您的方法..
  • 我的意图是 /SomeUrl/Something.jsp 与 /SomeUrl/Something.txt 没有什么不同,由我的 @RequestMapping 注释方法处理

标签: java spring jsp spring-mvc


【解决方案1】:

将调度程序 servlet 映射到 / 与将其映射到 /* 并不完全相同。使用/*,您可以有效地要求 servlet 容器将所有请求提供给 Spring MVC 调度程序 servlet。使用/,您可以将调度程序 servlet 设置为 servlet 容器的默认 servlet,这是一个低优先级的包罗万象。

来自 Servlet 规范 3.0,第 12 章将请求映射到 Servlet:

使用第一个成功的匹配,不再匹配 尝试:

  1. 容器将尝试查找请求路径与 servlet 路径的完全匹配。成功匹配选择 servlet。
  2. 容器将递归地尝试匹配最长的路径前缀。这是通过使用“/”字符作为路径分隔符一次将路径树下移一个目录来完成的。最长的匹配决定了选择的 servlet。
  3. 如果 URL 路径中的最后一段包含扩展名(例如 .jsp),则 servlet 容器将尝试匹配处理扩展请求的 servlet。扩展定义为最后一个“.”字符之后的最后一段。
  4. 如果前三个规则都没有导致 servlet 匹配,则容器将尝试提供适合所请求资源的内容。如果为应用程序定义了一个“默认”servlet,它将被使用。许多容器为服务内容提供了一个隐式的默认 servlet。

servlet 映射的优先级降序为/**.jsp/。 servlet 容器通常对*.jsp 有一个隐式映射(来自同一参考):

如果容器有一个内部 JSP 容器,则 *.jsp 扩展名映射到它, 允许按需执行 JSP 页面。这种映射称为隐式 映射。如果 Web 应用程序定义了 *.jsp 映射,则它的映射采用 优先于隐式映射。

所以以*.jsp 结尾的URL 将不会被servlet 容器 映射到Spring。尝试修改spring mvc配置是没有用的。

恕我直言,您有两种解决方法:

  • 将调度程序 servlet 映射到 /* - 但根据配置的其余部分,它可能会产生副作用:彻底测试所有内容(主要是如果 servlet 容器直接提供一些未在 &lt;mvc:resources ...&gt; 中声明的文件)
  • *.jsp 的显式映射添加到调度程序 servlet - 但请务必将其记录下来,以便在稍后与另一个问题发生时轻松解决问题

【讨论】:

    【解决方案2】:

    如果已定义的静态资源请求未由调度程序 serverlet 处理,则您已将其配置为

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

    因此,/resources/ 形式的任何 URL 都不会由调度程序 servlet 处理。

    【讨论】:

    • 当然可以,但是我该怎么做才能让“/xxxx/xxx.jsp”形式的请求进入我的方法?它们不是静态资源,访问静态资源的 /resources/ 映射工作正常。
    • @nigelg 除了/resources/** 形式的请求之外的所有请求都将由调度程序servlet 处理。您能否添加一些无效的 URL 示例?
    • 不完全是。 /resources/** 格式的请求DispatcherServlet 处理,每个映射&lt;url-pattern&gt;/&lt;/url-pattern&gt;。但是 &lt;mvc:resources ...&gt; 映射的 URL 被转发到 servlet 容器的默认 servlet,它知道如何发送静态文件。但这与当前问题无关。
    • @SergeBallesta OP 已将资源定义为 &lt;mvc:resources mapping="/resources/**" location="/resources/" /&gt;,这就是为什么我说带有 /resources/** 形式的 URL 不会由调度程序 servlet 处理。
    • @Karna 我的理解是,即使路径参数以.jsp 结尾,OP 也希望其控制器处理请求/SomeUrl/*。将任何东西用作静态文件不是问题......但我的回答也没有抓住重点:-(
    【解决方案3】:

    这不仅仅与春天有关。在 JAVA Web 中,如果您不希望人们直接访问您的文件,请在浏览器中输入地址,将它们放在 WEB-INF 文件夹中。您可以根据需要在其中创建子文件夹。

    干杯!!!

    【讨论】:

    • 即使文件可访问或隐藏,所有请求都将由调度程序 servlet 处理。 &lt;url-pattern&gt;/&lt;/url-pattern&gt; 指定应将所有请求发送到调度程序 servlet,使用 &lt;mvc:resources&gt; 您可以定义排除项。
    【解决方案4】:

    我开始在 MVC DispatcherServlet 中设置断点,试图查看它在什么时候检查扩展并以不同方式处理 .jsp 扩展,这清楚地表明“/SomeUrl/something.jsp”请求没有进入DispatcherServlet。所以问题肯定出在 web.xml 中,而不是 DispatcherServlet 的配置中。

    经过实验,我找到了解决方案。我有:

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

    替换为:

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

    现在已经解决了这个问题,虽然我对此感到相当惊讶,但 / 和 /* 之间存在差异

    非常感谢大家帮忙解答这个问题。

    【讨论】:

    • 我刚刚在我的答案中写了原因,但是当我写它的时候,你已经找到了解决方案:-)
    • 不过,您的回答要彻底得多,我偶然发现了这个解决方案,但并不真正了解优先级是如何工作的。您还指出使用 /* 可能会破坏其他 URL,我没想过要验证,但它已经验证了,所以现在修复它们:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    • 2018-09-26
    • 1970-01-01
    相关资源
    最近更新 更多