Spring MVC @PathVariable с точкой (.) усекается

Это продолжение вопроса Spring MVC @PathVariable получает усеченный

Spring forum утверждает, что он исправил (версия 3.2) как часть ContentNegotiationManager. см. ссылку ниже.
https://jira.springsource.org/browse/SPR-6164
https://jira.springsource.org/browse/SPR-7632

В моем приложении requestParameter с .com усечен.

Может ли кто-нибудь объяснить мне, как использовать эту новую функцию? как он настраивается в xml?

Примечание:

http://forum.springsource.org/showthread.php?137000-Spring-MVC-PathVariable-with-dot-(-)-is-getting-truncated&p=444607#post444607

Ответ 1

Насколько я знаю, эта проблема появляется только для pathvariable в конце requestmapping.

Мы смогли решить это, указав addge regex в requestmapping.

 /somepath/{variable:.+}

Ответ 2

Spring считает, что все, что находится за последней точкой, является расширением файла, таким как .json или .xml, и проведите его, чтобы получить свой параметр.

Итак, если у вас есть /somepath/{variable}:

  • /somepath/param, /somepath/param.json, /somepath/param.xml или /somepath/param.anything приведет к параметру со значением param
  • /somepath/param.value.json, /somepath/param.value.xml или /somepath/param.value.anything приведет к параметру со значением param.value

если вы измените свое сопоставление на /somepath/{variable:.+}, как было предложено, любая точка, включая последнюю, будет рассматриваться как часть вашего параметра:

  • /somepath/param приведет к параметру со значением param
  • /somepath/param.json приведет к параметру со значением param.json
  • /somepath/param.xml приведет к параметру со значением param.xml
  • /somepath/param.anything приведет к параметру со значением param.anything
  • /somepath/param.value.json приведет к параметру со значением param.value.json
  • ...

Если вы не любите распознавание расширений, вы можете отключить его, переопределив mvc:annotation-driven automagic:

<bean id="handlerMapping"
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
    <property name="contentNegotiationManager" ref="contentNegotiationManager"/>
    <property name="useSuffixPatternMatch" value="false"/>
</bean>

Итак, если у вас есть /somepath/{variable}:

  • /somepath/param, /somepath/param.json, /somepath/param.xml или /somepath/param.anything приведет к параметру со значением param
  • /somepath/param.value.json, /somepath/param.value.xml или /somepath/param.value.anything приведет к параметру со значением param.value

Примечание: отличие от конфигурации по умолчанию отображается только в том случае, если у вас есть сопоставление, например somepath/something.{variable}. см. Задача проекта Resthub

если вы хотите сохранить управление расширением, так как Spring 3.2 вы также можете установить свойство useRegisteredSuffixPatternMatch для RequestMappingHandlerMapping bean, чтобы поддерживать распознавание suffixPattern, но ограничивается зарегистрированным расширением.

Здесь вы определяете только расширения json и xml:

<bean id="handlerMapping"
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
    <property name="contentNegotiationManager" ref="contentNegotiationManager"/>
    <property name="useRegisteredSuffixPatternMatch" value="true"/>
</bean>

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false"/>
    <property name="favorParameter" value="true"/>
    <property name="mediaTypes">
        <value>
            json=application/json
            xml=application/xml
        </value>
    </property>
</bean>

Обратите внимание, что mvc: annotation-driven теперь принимает параметр contentNegotiation для предоставления пользовательского bean, но свойство RequestMappingHandlerMapping должно быть изменено на true (по умолчанию false) (cf. https://jira.springsource.org/browse/SPR-7632).

По этой причине вам все равно придется переопределить всю конфигурацию mvc: annotation. Я открыл билет на Spring, чтобы запросить пользовательскую RequestMappingHandlerMapping: https://jira.springsource.org/browse/SPR-11253. Пожалуйста, проголосуйте, если вы заняты.

В то время как переопределить, нужно подумать о том, чтобы переопределить обычное управление выполнением. В противном случае все ваши пользовательские сопоставления исключений не удастся. Вам придется повторно использовать messageCoverters со списком bean:

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />

<util:list id="messageConverters">
    <bean class="your.custom.message.converter.IfAny"></bean>
    <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></bean>
    <bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
    <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
    <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
    <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
    <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean>
    <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</util:list>

<bean name="exceptionHandlerExceptionResolver"
      class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
    <property name="order" value="0"/>
    <property name="messageConverters" ref="messageConverters"/>
</bean>

<bean name="handlerAdapter"
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="conversionService" ref="conversionService" />
            <property name="validator" ref="validator" />
        </bean>
    </property>
    <property name="messageConverters" ref="messageConverters"/>
</bean>

<bean id="handlerMapping"
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
</bean>

Я реализовал в проекте с открытым исходным кодом Resthub, что я являюсь частью набора тестов по этим темам: см. https://github.com/resthub/resthub-spring-stack/pull/219/files и https://github.com/resthub/resthub-spring-stack/issues/217

Ответ 3

В дополнение к ответу Мартина Фрея это также можно устранить, добавив конечную косую черту в значение RequestMapping:

/path/{variable}/

Имейте в виду, что это исправление не поддерживает ремонтопригодность. Теперь требуется, чтобы весь URI имел завершающую косую черту - что-то, что может быть неясно для пользователей API/новых разработчиков. Поскольку, вероятно, не все параметры могут иметь . в них, это может также создавать прерывистые ошибки

Ответ 4

Обновление для Spring 4: начиная с 4.0.1 вы можете использовать PathMatchConfigurer (через WebMvcConfigurer), например

@Configuration
protected static class AllResources extends WebMvcConfigurerAdapter {

    @Override
    public void configurePathMatch(PathMatchConfigurer matcher) {
        matcher.setUseRegisteredSuffixPatternMatch(true);
    }

}

В xml это будет (https://jira.spring.io/browse/SPR-10163):

<mvc:annotation-driven>
    [...]
    <mvc:path-matching registered-suffixes-only="true"/>
</mvc:annotation-driven>

Ответ 5

добавление ":. +" работало для меня, но только после того, как я удалил внешние фигурные скобки.

value = { "/имя пользователя /{id:. +}" } не работает

value = "/username/{id:.+}" работает

Надеюсь, я помог кому-то:)

Ответ 6

/somepath/{variable:.+} работает в теге Java requestMapping.

Ответ 7

Здесь подход, основанный исключительно на java-конфигурации:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@Configuration
public class MvcConfig extends WebMvcConfigurationSupport{

    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
        handlerMapping.setUseSuffixPatternMatch(false);
        handlerMapping.setUseTrailingSlashMatch(false);
        return handlerMapping;
    }
}

Ответ 8

Один довольно простой способ обойти эту проблему - добавить конечную косую черту...

например:.

использовать:

/somepath/filename.jpg/

вместо:

/somepath/filename.jpg

Ответ 9

Полное решение, включающее адреса электронной почты в именах путей для spring 4.2,

<bean id="contentNegotiationManager"
    class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
    <property name="favorParameter" value="true" />
    <property name="mediaTypes">
        <value>
            json=application/json
            xml=application/xml
        </value>
    </property>
</bean>
<mvc:annotation-driven
    content-negotiation-manager="contentNegotiationManager">
    <mvc:path-matching suffix-pattern="false" registered-suffixes-only="true" />
</mvc:annotation-driven>

Добавьте это в application-xml

Ответ 10

Если вы используете Spring 3.2.x и <mvc:annotation-driven />, создайте этот маленький BeanPostProcessor:

package spring;

public final class DoNotTruncateMyUrls implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof RequestMappingHandlerMapping) {
            ((RequestMappingHandlerMapping)bean).setUseSuffixPatternMatch(false);
        }
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

Затем поместите это в свой конфигурационный файл MVC xml:

<bean class="spring.DoNotTruncateMyUrls" />

Ответ 11

В Spring Boot, я разрешил их, выполнив следующие шаги: RestController:

@GetMapping("/statusByEmail/{email:.+}") public List<Map<String, Object>> statusByEmail(@PathVariable(value = "email") String email)

И от клиента отдыха:

Get http://webhook.gsikder.com/statusByEmail/[email protected]/

Ответ 12

В Spring Boot, выражение Regular решает проблему, например

@GetMapping("/path/{param1:.+}")