Ceci est la suite de la question Spring MVC @PathVariable est tronqué
Le forum Spring indique qu'il a été corrigé (version 3.2) dans le cadre de ContentNegotiationManager. voir le lien ci-dessous.
https://jira.springsource.org/browse/SPR-6164
https://jira.springsource.org/browse/SPR-7632
Dans mon application, requestParameter avec .com est tronqué.
Quelqu'un pourrait-il m'expliquer comment utiliser cette nouvelle fonctionnalité? comment est-il configurable au format xml?
Remarque: spring forum- # 1 Spring MVC @PathVariable avec le point (.) Est tronqué
Autant que je sache, ce problème n'apparaît que pour la variable de chemin à la fin du requestmapping.
Nous avons pu résoudre ce problème en définissant l'addon regex dans le requestmapping.
/somepath/{variable:.+}
Spring considère que tout ce qui se cache derrière le dernier point est une extension de fichier telle que .json
ou .xml
et l'exerce pour récupérer votre paramètre.
Donc si vous avez /somepath/{variable}
:
/somepath/param
, /somepath/param.json
, /somepath/param.xml
ou /somepath/param.anything
donnera un paramètre avec la valeur param
/somepath/param.value.json
, /somepath/param.value.xml
ou /somepath/param.value.anything
donnera un paramètre avec la valeur param.value
si vous modifiez votre correspondance en /somepath/{variable:.+}
comme suggéré, tout point, y compris le dernier, sera considéré comme faisant partie de votre paramètre:
/somepath/param
donnera un paramètre avec la valeur param
/somepath/param.json
donnera un paramètre avec la valeur param.json
/somepath/param.xml
donnera un paramètre avec la valeur param.xml
/somepath/param.anything
donnera un paramètre avec la valeur param.anything
/somepath/param.value.json
donnera un paramètre avec la valeur param.value.json
Si vous ne vous souciez pas de la reconnaissance d’extension, vous pouvez la désactiver en remplaçant 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>
Donc, encore une fois, si vous avez /somepath/{variable}
:
/somepath/param
, /somepath/param.json
, /somepath/param.xml
ou /somepath/param.anything
donnera un paramètre avec la valeur param
/somepath/param.value.json
, /somepath/param.value.xml
ou /somepath/param.value.anything
donnera un paramètre avec la valeur param.value
remarque: la différence par rapport à la configuration par défaut n'est visible que si vous avez un mappage comme somepath/something.{variable}
. voir Numéro du projet Resthub
si vous souhaitez conserver la gestion des extensions, vous pouvez également, depuis Spring 3.2, définir la propriété useRegisteredSuffixPatternMatch du bean RequestMappingHandlerMapping afin de laisser la reconnaissance suffixPattern activée, mais limitée à l'extension enregistrée.
Ici, vous définissez uniquement 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 que la propriété de RequestMappingHandlerMapping doit être remplacée par true (valeur par défaut) (cf. https://jira.springsource.org/browse/SPR -7632 ).
Pour cette raison, vous devez toujours remplacer la configuration all mvc: annotation. J'ai ouvert un ticket à Spring pour demander un RequestMappingHandlerMapping personnalisé: https://jira.springsource.org/browse/SPR-11253 . S'il vous plaît voter si vous êtes intéressé.
Bien que prioritaire, prenez soin de considérer également le dépassement personnalisé de la gestion d'exécution. 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 mis en œuvre, dans le projet open source Resthub dont je fais partie, une série de tests sur ces sujets: voir https://github.com/resthub/resthub-spring-stack/pull/219/ fichiers & https://github.com/resthub/resthub-spring-stack/issues/217
Mise à jour du printemps 4: depuis la version 4.0.1, vous pouvez utiliser PathMatchConfigurer
(via votre WebMvcConfigurer
), par exemple.
@Configuration
protected static class AllResources extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseRegisteredSuffixPatternMatch(true);
}
}
En XML, ce serait ( https://jira.spring.io/browse/SPR-10163 ):
<mvc:annotation-driven>
[...]
<mvc:path-matching registered-suffixes-only="true"/>
</mvc:annotation-driven>
En plus de la réponse de Martin Frey, ceci peut également être corrigé en ajoutant une barre oblique finale dans la valeur RequestMapping:
/path/{variable}/
Gardez à l'esprit que ce correctif ne prend pas en charge la maintenabilité. À présent, tous les URI doivent être précédés d'une barre oblique, ce qui peut ne pas être évident pour les utilisateurs d'API/les nouveaux développeurs. Parce que ce ne sont probablement pas tous les paramètres qui peuvent avoir un .
, cela peut aussi créer des bugs intermittents
l'ajout du ":. +" a fonctionné pour moi, mais pas avant d'avoir supprimé les accolades extérieures.
valeur = {"/ nom d'utilisateur/{id:. +}"} n'a pas fonctionné
value = "/username/{id:.+}" fonctionne
J'espère que j'ai aidé quelqu'un :)
Dans Spring Boot Rest Controller, j'ai résolu ces problèmes en procédant comme suit:
@GetMapping("/statusByEmail/{email:.+}/")
public String statusByEmail(@PathVariable(value = "email") String email){
//code
}
Get http://mywebhook.com/statusByEmail/[email protected]/
/somepath/{variable:.+}
fonctionne dans la balise Java requestMapping
.
Voici une approche qui repose uniquement sur la configuration 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;
}
}
Un moyen assez facile de contourner ce problème consiste à ajouter une barre oblique de fin ...
par exemple.:
utilisation :
/somepath/filename.jpg/
au lieu de:
/somepath/filename.jpg
Dans Spring Boot, l’expression rationnelle résout le problème tel que
@GetMapping("/path/{param1:.+}")
La solution complète, y compris les adresses électroniques dans les noms de chemins pour Spring 4.2, est
<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>
Ajoutez ceci à l'application-xml
Si vous utilisez Spring 3.2.x et <mvc:annotation-driven />
, créez cette petite 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;
}
}
Ensuite, mettez ceci dans votre XML MVC config:
<bean class="spring.DoNotTruncateMyUrls" />
Enfin, j'ai trouvé une solution dans Spring Docs :
Pour désactiver complètement l'utilisation des extensions de fichier, vous devez définir les deux éléments suivants:
useSuffixPatternMatching(false), see PathMatchConfigurer favorPathExtension(false), see ContentNegotiationConfigurer
Ajouter ceci à mon implémentation WebMvcConfigurerAdapter
a résolu le problème:
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
@Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseSuffixPatternMatch(false);
}
Pour moi le
@GetMapping(path = "/a/{variableName:.+}")
fonctionne, mais seulement si vous codez également le "point" dans votre URL de requête en tant que "% 2E", cela fonctionne. Mais il faut que l'URL soit ce que ... qui n'est pas un codage "standard", bien que valide. On se sent comme un bug: |
L’autre solution, similaire à la méthode "barre de fin", consiste à déplacer la variable qui aura le point "en ligne", par exemple:
@GetMapping (path = "/ {NomVol}}/a")
maintenant tous les points seront préservés, aucune modification ni regex n'est nécessaire.