【问题标题】:Spring does not ignore file extensionSpring 不会忽略文件扩展名
【发布时间】:2014-05-10 08:17:36
【问题描述】:

在我的 Spring XML 中,我有以下 sn-p:

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="useDefaultSuffixPattern" value="false"/>
</bean>

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="objectMapper" ref="objectMapper" />
        </bean>        
    </mvc:message-converters>
</mvc:annotation-driven>

据我了解,这意味着当我有“abc”的映射时,Spring 应该注册“abc.*”和“abc/”。

在我的一个控制器中,我有一个将图像写入响应的方法:

@RequestMapping(value="{path}", method=RequestMethod.GET, produces=MediaType.IMAGE_PNG_VALUE)
@ResponseBody
public void getPath(
        @PathVariable String path,
        HttpServletResponse res) {

    ...
}

当我请求“abc”之类的内容时,这很有效,但是当我请求“abc.com”时,它会在文本中引发 406 错误:

The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers."

当我请求“abc.img”时,“path”参数只接收文本“abc”; Spring 省略了扩展。

似乎 Spring 没有正确地忽略后缀模式。这是为什么呢?

编辑我从 Dirk 的评论中翻译了 java 配置,下面的 XML 似乎解决了这个问题:

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
</bean>

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="objectMapper" ref="objectMapper" />
        </bean>        
    </mvc:message-converters>
</mvc:annotation-driven>

我仍然不确定为什么我原来的代码不起作用,但这已经解决了我的问题

【问题讨论】:

  • 作为记录,我也尝试过使用@RequestMapping(value="{path:.+}"),但没有运气
  • 也许你遇到过和我一样的问题。看看这个问题:stackoverflow.com/q/22329393/1686330
  • 是的,这似乎是同一个问题!我使用了该问题中的等效 XML,并且能够解决我的问题。如果您想将其发布为答案,我很乐意接受!

标签: java spring spring-mvc uri http-status-code-406


【解决方案1】:

当请求进入 spring 调度程序时,控制器映射/匹配的一部分是将客户端上接受的媒体类型与控制器端的可生产媒体类型匹配(因此您可以拥有只能通过其生产来区分的控制器媒体类型)。

坏消息是 springmvc 在其默认配置中支持请求 url 的 extension 而不是请求中的任何接受标头。

在您的示例中,当您请求 abc 时,扩展名上没有匹配项,因此其他内容协商策略开始最终解析为正确的类型(通过 accept 标头)。但是,如果您请求 abc.com,spring 将派生一个与控制器的 produces 不匹配的 application/octet-stream 的 mime 类型并生成 406(因为没有匹配的控制器)。

您可以在 org/springframework/mail/javamail/mime.types 的 spring-context-support.jar 中找到路径扩展的默认 mime 匹配(参见 https://github.com/spring-projects/spring-framework/blob/master/spring-context-support/src/main/resources/org/springframework/mail/javamail/mime.types#L278)。

您可以在调度程序配置中禁用此“功能”,以便 spring 不会使用路径扩展来解析 mime 类型:

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
</bean>

如果您使用的是 java 配置,请查看我的 related question/answer

【讨论】:

  • 完美答案。但是不要忘记在注解驱动中指定自定义的Content Negotiation Manager -> ''''
  • 另见:devpolito.wordpress.com/2016/09/19/… 用于 Java 配置
  • @ImpulseTheFox 或者你使用link in my answer
  • 从 5.3 版开始,favorPathExtension 默认为 false,因此不再需要此解决方法。见docs
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-29
  • 2014-02-14
  • 1970-01-01
  • 2013-05-07
  • 2018-09-20
相关资源
最近更新 更多