Spring MVC @PathVariable ficando truncado

Eu tenho um controlador que fornece access RESTful às informações:

@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}") public ModelAndView getBlah(@PathVariable String blahName, HttpServletRequest request, HttpServletResponse response) { 

O problema que estou enfrentando é que, se eu acertar o servidor com uma variável de caminho com caracteres especiais, ele será truncado. Por exemplo: http: // localhost: 8080 / blah-server / blah / get / blah2010.08.19-02: 25: 47

O parâmetro blahName será blah2010.08

No entanto, a chamada para request.getRequestURI () contém todas as informações transmitidas.

Alguma idéia de como evitar que o Spring trunque a @PathVariable?

Tente uma expressão regular para o argumento @RequestMapping :

 RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}") 

Isso provavelmente está intimamente relacionado ao SPR-6164 . Resumidamente, o framework tenta aplicar alguns smarts à interpretação da URI, removendo o que ele acha que são extensões de arquivo. Isso teria o efeito de transformar blah2010.08.19-02:25:47 em blah2010.08 , já que acha que o .19-02:25:47 é uma extensão de arquivo.

Conforme descrito no problema vinculado, você pode desabilitar esse comportamento declarando seu próprio bean DefaultAnnotationHandlerMapping no contexto do aplicativo e definindo sua propriedade useDefaultSuffixPattern como false . Isso replaceá o comportamento padrão e impedirá que ele moleste seus dados.

Spring considera que qualquer coisa por trás do último ponto é uma extensão de arquivo como .json ou .xml e truncada para recuperar seu parâmetro.

Então, se você tiver /{blahName} :

  • /param , /param.json , /param.xml ou /param.anything resultará em um param com valor param
  • /param.value.json , /param.value.xml ou /param.value.anything resultará em um parâmetro com valor param.value

Se você alterar seu mapeamento para /{blahName:.+} como sugerido, qualquer ponto, incluindo o último, será considerado como parte de seu parâmetro:

  • /param resultará em um param com valor param
  • /param.json resultará em um param com valor param.json
  • /param.xml resultará em um parâmetro com valor param.xml
  • /param.anything resultará em um param com valor param.anything
  • /param.value.json resultará em um param com valor param.value.json

Se você não se importa com o reconhecimento da extensão, você pode desativá-lo substituindo mvc:annotation-driven automagic do mvc:annotation-driven :

     

Então, novamente, se você tiver /{blahName} :

  • /param , /param.json , /param.xml ou /param.anything resultará em um param com valor param
  • /param.value.json , /param.value.xml ou /param.value.anything resultará em um parâmetro com valor param.value

Nota: a diferença da configuração padrão é visível apenas se você tiver um mapeamento como /something.{blahName} . Veja a questão do projeto Resthub .

Se você quiser manter o gerenciamento de extensão, desde o Spring 3.2, você também pode definir a propriedade useRegisteredSuffixPatternMatch do bean RequestMappingHandlerMapping para manter o reconhecimento suffixPattern ativado, mas limitado à extensão registrada.

Aqui você define apenas as extensões json e xml:

          json=application/json xml=application/xml    

Note que mvc: annotation-driven aceita agora uma opção contentNegotiation para fornecer um bean customizado, mas a propriedade de RequestMappingHandlerMapping deve ser alterada para true (default false) (cf. https://jira.springsource.org/browse/SPR-7632 ).

Por esse motivo, você ainda precisa replace toda a configuração orientada por annotations do mvc:. Eu abri um ticket para Spring para pedir um RequestMappingHandlerMapping customizado: https://jira.springsource.org/browse/SPR-11253 . Por favor vote se você estiver interessado em.

Enquanto sobrescrevendo, tenha cuidado para considerar também a substituição personalizada do gerenciamento de execução. Caso contrário, todos os seus mapeamentos de exceção personalizados falharão. Você terá que reutilizar messageCoverters com um bean de lista:

                            

Implementei, no projeto de código aberto Resthub do qual faço parte, um conjunto de testes sobre esses assuntos: consulte https://github.com/resthub/resthub-spring-stack/pull/219/files e https: // github.com/resthub/resthub-spring-stack/issues/217

Tudo após o último ponto é interpretado como extensão de arquivo e cortado por padrão.
Em seu spring config xml você pode adicionar DefaultAnnotationHandlerMapping e definir useDefaultSuffixPattern como false (o padrão é true ).

Então abra sua fonte xml mvc-config.xml (ou como ela é chamada) e adicione

    

Agora o seu @PathVariable blahName (e todos os outros, também) devem conter o nome completo, incluindo todos os pontos.

EDIT: aqui está um link para a api primavera

Eu também corri para o mesmo problema, e definir a propriedade como false também não me ajudou. No entanto, a API diz :

Observe que os caminhos que incluem um sufixo “.xxx” ou terminam com “/” já não serão transformados usando o padrão de sufixo padrão em qualquer caso.

Eu tentei adicionar “/ end” ao meu URL RESTful e o problema desapareceu. Não estou satisfeito com a solução, mas funcionou.

BTW, eu não sei o que os designers Spring estavam pensando quando eles adicionaram este “recurso” e, em seguida, ativou por padrão. IMHO, deve ser removido.

Usando a class de configuração Java correta:

 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false); } @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(false); } } 

Resolvi por esse hack

1) Adicionado HttpServletRequest em @PathVariable como abaixo

  @PathVariable("requestParam") String requestParam, HttpServletRequest request) throws Exception { 

2) Obtenha o URL diretamente (nesse nível, sem truncamento) na solicitação

 request.getPathInfo() 

Spring MVC @PathVariable com ponto (.) Está ficando truncado

Eu corri para isso e as soluções aqui geralmente não funcionavam como eu esperava.

Sugiro usar uma expressão SpEL e vários mapeamentos, por exemplo

 @RequestMapping(method = RequestMethod.GET, value = {Routes.BLAH_GET + "/{blahName:.+}", Routes.BLAH_GET + "/{blahName}/"}) 

O problema de extensão de arquivo só existe se o parâmetro estiver na última parte do URL. mudança

 @RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}") 

para

 @RequestMapping( method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/safe") 

e tudo ficará bem novamente

Se você puder editar o endereço para o qual as solicitações são enviadas, uma correção simples seria adicionar uma barra final a elas (e também no valor @RequestMapping ):

 /path/{variable}/ 

então o mapeamento ficaria assim:

 RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/") 

Veja também Spring MVC @PathVariable com ponto (.) Está ficando truncado .

 //in your xml dispatcher add this property to your default annotation mapper bean as follow    

adicionando o “:. +” funcionou para mim, mas não até que eu removesse as chaves externas.

value = {"/username/{id:.+}"} não funcionou

value = "/username/{id:.+}" funciona

Espero ter ajudado alguém:]

Solução de configuração baseada em Java para evitar o truncamento (usando uma class não obsoleta):

 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 PolRepWebConfig extends WebMvcConfigurationSupport { @Override @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { final RequestMappingHandlerMapping handlerMapping = super .requestMappingHandlerMapping(); // disable the truncation after . handlerMapping.setUseSuffixPatternMatch(false); // disable the truncation after ; handlerMapping.setRemoveSemicolonContent(false); return handlerMapping; } } 

Fonte: http://www.javacodegeeks.com/2013/01/spring-mvc-customizing-requestmappinghandlermapping.html

ATUALIZAR:

Eu percebi alguns problemas com a configuração automática do Spring Boot quando usei a abordagem acima (algumas configurações automáticas não são efetivas).

Em vez disso, comecei a usar a abordagem BeanPostProcessor . Parecia estar funcionando melhor.

 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor { private static final Logger logger = LoggerFactory .getLogger(MyBeanPostProcessor.class); @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof RequestMappingHandlerMapping) { setRemoveSemicolonContent((RequestMappingHandlerMapping) bean, beanName); setUseSuffixPatternMatch((RequestMappingHandlerMapping) bean, beanName); } return bean; } private void setRemoveSemicolonContent( RequestMappingHandlerMapping requestMappingHandlerMapping, String beanName) { logger.info( "Setting 'RemoveSemicolonContent' on 'RequestMappingHandlerMapping'-bean to false. Bean name: {}", beanName); requestMappingHandlerMapping.setRemoveSemicolonContent(false); } private void setUseSuffixPatternMatch( RequestMappingHandlerMapping requestMappingHandlerMapping, String beanName) { logger.info( "Setting 'UseSuffixPatternMatch' on 'RequestMappingHandlerMapping'-bean to false. Bean name: {}", beanName); requestMappingHandlerMapping.setUseSuffixPatternMatch(false); } } 

Inspirado em: http://ronaldxq.blogspot.com/2014/10/spring-mvc-setting-alwaysusefullpath-on.html

Se tiver certeza de que seu texto não corresponderá a nenhuma das extensões padrão, você poderá usar o código abaixo:

 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseRegisteredSuffixPatternMatch(true); } } 

Minha solução preferível para impedir que o Spring MVC @PathVariable seja truncado é adicionar barra no final da variável path.

Por exemplo:

 @RequestMapping(value ="/email/{email}/") 

Então, a solicitação será semelhante a:

 http://localhost:8080/api/email/test@test.com/