Spring considère que tout ce qui se trouve derrière le dernier point est une extension de fichier telle que .json
ou .xml
et la tronque pour récupérer votre paramètre.
Donc si vous avez /{blahName}
:
/param
, /param.json
, /param.xml
Ou /param.anything
se traduira par une valeur avec paramparam
/param.value.json
, /param.value.xml
ou /param.value.anything
aboutira à un paramètre avec une valeurparam.value
Si vous modifiez votre mappage /{blahName:.+}
comme suggéré, tout point, y compris le dernier, sera considéré comme faisant partie de votre paramètre:
/param
se traduira par un paramètre avec une valeur param
/param.json
se traduira par un paramètre avec une valeur param.json
/param.xml
se traduira par un paramètre avec une valeur param.xml
/param.anything
se traduira par un paramètre avec une valeur param.anything
/param.value.json
se traduira par un paramètre avec une valeur param.value.json
- ...
Si vous ne vous souciez pas de la reconnaissance des extensions, vous pouvez la désactiver en mvc:annotation-driven
remplaçant automagic:
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<property name="useSuffixPatternMatch" value="false"/>
</bean>
Donc, encore une fois, si vous avez /{blahName}
:
/param
, /param.json
, /param.xml
Ou /param.anything
se traduira par une valeur avec paramparam
/param.value.json
, /param.value.xml
ou /param.value.anything
aboutira à un paramètre avec une valeurparam.value
Remarque: la différence par rapport à la configuration par défaut n'est visible que si vous avez un mappage comme /something.{blahName}
. Voir le problème du projet Resthub .
Si vous souhaitez conserver la gestion des extensions, depuis Spring 3.2, vous pouvez également définir la propriété useRegisteredSuffixPatternMatch du bean RequestMappingHandlerMapping afin de garder la reconnaissance suffixPattern activée mais limitée à l'extension enregistrée.
Ici, vous ne définissez que les extensions json et 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>
Notez que mvc: annotation-driven accepte désormais une option contentNegotiation pour fournir un bean personnalisé mais la propriété de RequestMappingHandlerMapping doit être changée en true (par défaut false) (cf. https://jira.springsource.org/browse/SPR-7632 ).
Pour cette raison, vous devez toujours remplacer toute la configuration mvc: basée sur les annotations. J'ai ouvert un ticket pour Spring pour demander un RequestMappingHandlerMapping personnalisé: https://jira.springsource.org/browse/SPR-11253 . Veuillez voter si cela vous intéresse.
Lors du remplacement, veillez à prendre en compte également le remplacement de la gestion de l'exécution personnalisée. Sinon, tous vos mappages d'exceptions personnalisés échoueront. Vous devrez réutiliser messageCoverters avec un bean list:
<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>
J'ai implémenté, dans le projet open source Resthub dont je fais partie, un ensemble de tests sur ces sujets: voir https://github.com/resthub/resthub-spring-stack/pull/219/files et https: // github.com/resthub/resthub-spring-stack/issues/217