Spring MVC @PathVariable被截断
我有一个提供REST式访问信息的控制器:
@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}") public ModelAndView getBlah(@PathVariable String blahName, HttpServletRequest request, HttpServletResponse response) {
我遇到的问题是,如果我用具有特殊字符的pathvariables打到服务器,它将被截断。 例如: http:// localhost:8080 / blah-server / blah / get / blah2010.08.19-02:25:47
参数blahName将是blah2010.08
但是,调用request.getRequestURI()包含传入的所有信息。
任何想法如何防止截断@PathVariable的Spring?
尝试使用@RequestMapping
参数的正则expression式:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}")
这可能与SPR-6164密切相关。 简而言之,该框架试图将一些智能应用到URI解释,删除它认为是文件扩展名。 这将会使blah2010.08.19-02:25:47
变成blah2010.08
,因为它认为.19-02:25:47
是一个文件扩展名。
如链接问题中所述,可以通过在应用程序上下文中声明您自己的DefaultAnnotationHandlerMapping
bean并将其useDefaultSuffixPattern
属性设置为false
来禁用此行为。 这将覆盖默认行为,并停止骚扰您的数据。
Spring认为最后一个点后面的任何内容都是文件扩展名,例如.json
或.xml
并截断它以检索您的参数。
所以如果你有/{blahName}
:
-
/param
,/param
/param.json
,/param
/param.xml
或/param.anything
将会产生一个参数值param
-
/param.value.json
或/param.value.anything
将会产生一个参数param.value
如果您按照build议将映射更改为/{blahName:.+}
,则包括最后一个点在内的任何点都将被视为参数的一部分:
-
/param
将导致一个参数值param
-
/param.json
将产生一个param值为param.json
的参数 -
/param.xml
将生成一个param值为param.xml
的参数 -
/param.anything
将导致一个参数的值param.anything
-
/param.value.json
将会产生一个param值为param.value.json
的参数 - …
如果您不关心扩展识别,可以通过覆盖mvc:annotation-driven
来禁用它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>
所以,再一次,如果你有/{blahName}
:
-
/param
,/param
/param.json
,/param
/param.xml
或/param.anything
将会产生一个参数值param
-
/param.value.json
或/param.value.anything
将会产生一个参数param.value
注意:仅当您有像/something.{blahName}
这样的映射时,才能看到与默认configuration的区别。 请参阅Resthub项目问题 。
如果你想保持扩展pipe理,从Spring 3.2开始,你还可以设置RequestMappingHandlerMapping bean的useRegisteredSuffixPatternMatch属性,以保持后缀模式识别的激活,但限于注册扩展。
这里只定义了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)(参见https://jira.springsource.org/browse/SPR-7632 )。
因此,您仍然必须覆盖所有mvc:注释驱动的configuration。 我打开了Spring的一张票,要求一个自定义的RequestMappingHandlerMapping: https : //jira.springsource.org/browse/SPR-11253 。 请投票,如果你有兴趣。
在压倒一切的时候,要小心的考虑自定义的执行pipe理覆盖。 否则,所有的自定义exception映射都将失败。 您将不得不重复使用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的开源项目中实现了一个关于这些主题的testing: https: //github.com/resthub/resthub-spring-stack/pull/219/files和https:// github.com/resthub/resthub-spring-stack/issues/217
最后一个点之后的所有内容都被解释为文件扩展名,并且默认为closures
在你的spring config xml中,你可以添加DefaultAnnotationHandlerMapping
并且设置useDefaultSuffixPattern
为false
(默认值为true
)。
所以打开你的spring xml mvc-config.xml
(或者叫它)然后添加
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="useDefaultSuffixPattern" value="false" /> </bean>
现在,您的@PathVariable
blahName
(以及其他全部)应该包含全名,包括所有的点。
编辑:这是一个链接到spring的api
我也遇到了同样的问题,并将该属性设置为false也没有帮助我。 但是, API说 :
请注意,包含“.xxx”后缀或以“/”结尾的path在任何情况下都不会使用默认的后缀模式进行转换。
我尝试添加“/结束”到我的RESTfulurl,问题就消失了。 我不喜欢解决scheme,但它确实有效。
顺便说一下,我不知道Springdevise者在添加这个“function”时是怎么想的,然后默认打开它。 恕我直言,它应该被删除。
使用正确的Javaconfiguration类:
@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); } }
我通过这个黑客解决了
1)像下面那样在@PathVariable中添加了HttpServletRequest
@PathVariable("requestParam") String requestParam, HttpServletRequest request) throws Exception {
2)请求中直接获取URL(在这个级别上不截断)
request.getPathInfo()
带点(。)的Spring MVC @PathVariable正在被截断
我刚刚遇到了这个问题,这里的解决scheme通常没有像我预期的那样工作。
我build议使用SpELexpression式和多个映射,例如
@RequestMapping(method = RequestMethod.GET, value = {Routes.BLAH_GET + "/{blahName:.+}", Routes.BLAH_GET + "/{blahName}/"})
只有当参数位于URL的最后部分时,文件扩展名问题才存在。 更改
@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
至
@RequestMapping( method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/safe")
一切都会好起来的 –
如果你可以编辑发送请求的地址,简单的修正就是给它们添加一个斜线(还有在@RequestMapping
值中):
/path/{variable}/
所以映射将如下所示:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/")
使用点(。)的Spring MVC @PathVariable也被截断 。
//in your xml dispatcher add this property to your default annotation mapper bean as follow <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> <property name="alwaysUseFullPath" value="true"></property> </bean>
添加“:。+”为我工作,但直到我删除外大括号。
value = {"/username/{id:.+}"}
不起作用
value = "/username/{id:.+}"
作品
希望我帮助过某人:]
基于Java的configuration解决scheme,以防止截断(使用一个不被弃用的类):
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; } }
资料来源:http://www.javacodegeeks.com/2013/01/spring-mvc-customizing-requestmappinghandlermapping.html
更新:
当我使用上面的方法时,我意识到Spring Boot自动configuration有一些问题(一些自动configuration不起作用)。
相反,我开始使用BeanPostProcessor
方法。 它似乎工作得更好。
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); } }
受启发:http://ronaldxq.blogspot.com/2014/10/spring-mvc-setting-alwaysusefullpath-on.html
如果你确定你的文本不符合任何默认的扩展名,你可以使用下面的代码:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseRegisteredSuffixPatternMatch(true); } }
防止Spring MVC @PathVariable被截断的最佳解决scheme是在pathvariables的末尾添加尾部斜线。
例如:
@RequestMapping(value ="/email/{email}/")
所以,请求将如下所示:
http://localhost:8080/api/email/test@test.com/