Spring не игнорирует расширение файла

В моем Spring XML у меня есть следующий фрагмент:

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

Насколько я понимаю, это означает, что Spring НЕ должен регистрировать «abc.*» и «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 неправильно игнорирует шаблон суффикса. Почему это?

Изменить: я перевел конфигурацию 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>

Я до сих пор не понимаю, почему исходный код не работал, но это решило мою проблему


person user2221343    schedule 10.05.2014    source источник
comment
Для справки, я также пытался использовать @RequestMapping(value={path:.+}), но безуспешно   -  person user2221343    schedule 10.05.2014
comment
Возможно, вы столкнулись с той же проблемой, что и я. Взгляните на этот вопрос: stackoverflow.com/q/22329393/1686330   -  person Dirk Lachowski    schedule 10.05.2014
comment
Да, похоже, это та же проблема! Я использовал эквивалентный XML из этого вопроса и смог решить свою проблему. Если вы хотите опубликовать это как ответ, я с радостью приму это!   -  person user2221343    schedule 10.05.2014


Ответы (1)


Когда запрос поступает в диспетчер Spring, часть сопоставления/сопоставления контроллера сопоставляет принятые типы носителей на стороне клиента с типами производимых носителей на стороне контроллера (поэтому вы можете иметь контроллеры, которые можно отличить только по их производимым типам носителей) .

Плохая новость заключается в том, что springmvc в своей конфигурации по умолчанию предпочитает расширение запрошенного URL-адреса любому заголовку accept в запросе.

В вашем примере, когда вы запрашиваете abc, в расширении нет соответствия, поэтому другие стратегии согласования содержимого в конечном итоге разрешаются до правильного типа (через заголовок accept). Но если вы запросите abc.com, Spring получит тип mime application/octet-stream, который не соответствует produces вашего контроллера, и сгенерирует 406 (поскольку нет соответствующего контроллера).

Вы можете найти сопоставление mime по умолчанию для расширений пути в файле spring-context-support.jar в org/springframework/mail/javamail/mime.types (см. 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, посмотрите мой связанный вопрос/ответ.

person Dirk Lachowski    schedule 11.05.2014
comment
Идеальный ответ. Но не забудьте указать пользовательский Content Negotiation Manager в управляемом аннотациями -› ''‹mvc:annotation-driven content-negotiation-manager=contentNegotiationManager /›'' - person Dani; 07.05.2016
comment
См. также: devpolito.wordpress.com/ 2016/09/19/ для конфигурации Java - person Impulse The Fox; 10.10.2018
comment
@ImpulseTheFox Или используйте ссылку в моем ответе. - person Dirk Lachowski; 11.10.2018
comment
Начиная с версии 5.3, favorPathExtension по умолчанию имеет значение false, поэтому этот обходной путь больше не требуется. См. документы. - person Alex Lipov; 16.12.2020