我有一个控制器,提供对信息的RESTful访问:
@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
public ModelAndView getBlah(@PathVariable String blahName, HttpServletRequest request,
HttpServletResponse response) {
我遇到的问题是,如果我使用带有特殊字符的路径变量命中服务器,它会被截断。例如: http://localhost:8080/blah-server/blah/get/blah2010.08.19-02:25:47
参数blahName将为blah2010.08
但是,对request.getRequestURI()的调用包含传入的所有信息。
知道如何阻止Spring截断@PathVariable?
答案 0 :(得分:144)
尝试@RequestMapping
参数的正则表达式:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}")
答案 1 :(得分:55)
这可能与SPR-6164密切相关。简而言之,该框架尝试将一些智能应用于URI解释,删除它认为的文件扩展名。这会将blah2010.08.19-02:25:47
转换为blah2010.08
,因为它认为.19-02:25:47
是文件扩展名。
如链接问题中所述,您可以通过在应用程序上下文中声明自己的DefaultAnnotationHandlerMapping
bean并将其useDefaultSuffixPattern
属性设置为false
来禁用此行为。这将覆盖默认行为,并停止骚扰您的数据。
答案 2 :(得分:29)
Spring认为最后一个点后面的任何内容都是文件扩展名,例如.json
或.xml
,并截断它以检索您的参数。
所以如果你有/{blahName}
:
/param
,/param.json
,/param.xml
或/param.anything
会产生价值为param
/param.value.json
,/param.value.xml
或/param.value.anything
将生成一个值为param.value
如果您按照建议将映射更改为/{blahName:.+}
,则任何点(包括最后一个点)都将被视为参数的一部分:
/param
会生成一个值为param
/param.json
会生成一个值为param.json
/param.xml
会生成一个值为param.xml
/param.anything
会生成一个值为param.anything
/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>
所以,再次,如果你有/{blahName}
:
/param
,/param.json
,/param.xml
或/param.anything
会产生价值为param
/param.value.json
,/param.value.xml
或/param.value.anything
将生成一个值为param.value
注意:仅当您具有/something.{blahName}
之类的映射时,才能看到与默认配置的差异。请参阅Resthub project issue。
如果你想保持扩展管理,从Spring 3.2开始,你也可以设置RequestMappingHandlerMapping bean的useRegisteredSuffixPatternMatch属性,以保持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)(参见https://jira.springsource.org/browse/SPR-7632)。
因此,您仍然必须覆盖所有mvc:annotation驱动的配置。我打开了一张Spring的票,要求自定义RequestMappingHandlerMapping:https://jira.springsource.org/browse/SPR-11253。如果您有兴趣,请投票。
在覆盖时,请注意自定义执行管理覆盖。否则,所有自定义异常映射都将失败。您必须将messageCoverters与list 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 :(得分:15)
最后一个点后的所有内容都被解释为文件扩展名并默认为中断
在您的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
(以及其他所有其他内容)应包含全名,包括所有点。
答案 4 :(得分:7)
我也遇到了同样的问题,将属性设置为false对我也没有帮助。但是,the API says:
请注意包含“.xxx”后缀或以“/”结尾的路径 在任何情况下都不会使用默认后缀模式进行转换。
我尝试在我的RESTful URL中添加“/ end”,问题就消失了。我不满意解决方案,但确实有效。
顺便说一下,我不知道Spring设计师在添加这个“功能”时会想到什么,然后默认打开它。恕我直言,它应该被删除。答案 5 :(得分:7)
使用正确的Java配置类:
@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);
}
}
答案 6 :(得分:4)
我通过这个黑客解决了
1)在@PathVariable中添加了HttpServletRequest,如下所示
@PathVariable("requestParam") String requestParam, HttpServletRequest request) throws Exception {
2)在请求中直接获取URL(在此级别没有截断)
request.getPathInfo()
答案 7 :(得分:3)
我刚刚碰到了这个,这里的解决方案通常不像我预期的那样工作。
我建议使用SpEL表达式和多个映射,例如
@RequestMapping(method = RequestMethod.GET,
value = {Routes.BLAH_GET + "/{blahName:.+}",
Routes.BLAH_GET + "/{blahName}/"})
答案 8 :(得分:3)
仅当参数位于URL的最后部分时,才存在文件扩展名问题。改变
@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
到
@RequestMapping(
method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/safe")
一切都会好起来的 -
答案 9 :(得分:3)
如果您可以编辑发送请求的地址,那么简单的修复就是向它们添加一个尾部斜杠(以及@RequestMapping
值):
/path/{variable}/
所以映射看起来像:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/")
另见Spring MVC @PathVariable with dot (.) is getting truncated。
答案 10 :(得分:3)
//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>
答案 11 :(得分:3)
添加“:。+”为我工作,但直到我删除外部花括号。
value = {"/username/{id:.+}"}
无效
value = "/username/{id:.+}"
有效
希望我能帮助某人:]
答案 12 :(得分:2)
基于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 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;
}
}
<强>更新强>
当我使用上述方法时,我意识到Spring Boot自动配置存在一些问题(某些自动配置无法生效)。
相反,我开始使用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);
}
}
Inspired from: http://ronaldxq.blogspot.com/2014/10/spring-mvc-setting-alwaysusefullpath-on.html
答案 13 :(得分:2)
如果您确定自己的文字与以下代码中的任何默认扩展名都不匹配,则可以使用
Started by user anonymous
Building in workspace C:\Users\Uday\.jenkins\workspace\MavenProj
FSSCM.checkout D:\FrameworkDemos\MavenHAF to C:\Users\Uday\.jenkins\workspace\MavenProj
FSSCM.check completed in 62 milliseconds
Parsing POMs
Discovered a new module MavenWebHAF:MavenWebHAF MavenWebHAF
Modules changed, recalculating dependency graph
[MavenProj] $ "C:\Program Files\Java\jdk1.8.0_60/bin/java" -cp C:\Users\Uday\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven31-agent-1.5.jar;E:\Softwares\apache-maven-3.3.3\boot\plexus-classworlds-2.5.2.jar;E:\Softwares\apache-maven-3.3.3/conf/logging jenkins.maven3.agent.Maven31Main E:\Softwares\apache-maven-3.3.3 C:\Users\Uday\.jenkins\war\WEB-INF\lib\remoting-2.52.jar C:\Users\Uday\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven31-interceptor-1.5.jar C:\Users\Uday\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven3-interceptor-commons-1.5.jar 52877
<===[JENKINS REMOTING CAPACITY]===>channel started
Executing Maven: -B -f C:\Users\Uday\.jenkins\workspace\MavenProj\pom.xml test -Dtest=TestSuite.TestAutomationDriver
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for MavenWebHAF:MavenWebHAF:jar:0.0.1-SNAPSHOT
[WARNING] 'dependencies.dependency.systemPath' for com.relevantcodes:extentreports:jar should use a variable instead of a hard-coded path E:\Programming Samples\Selenium Jars\extentreports_Updated.jar @ line 33, column 21
[WARNING] 'dependencies.dependency.systemPath' for org.monte:media:jar should use a variable instead of a hard-coded path E:\Programming Samples\Selenium Jars\MonteScreenRecorder.jar @ line 40, column 21
[WARNING] 'dependencies.dependency.systemPath' for com.sun:tools:jar should use a variable instead of a hard-coded path C:\Program Files\Java\jdk1.8.0_60\lib\tools.jar @ line 52, column 29
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MavenWebHAF 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ MavenWebHAF ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\Users\Uday\.jenkins\workspace\MavenProj\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ MavenWebHAF ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ MavenWebHAF ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\Users\Uday\.jenkins\workspace\MavenProj\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ MavenWebHAF ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
[INFO] Compiling 7 source files to C:\Users\Uday\.jenkins\workspace\MavenProj\target\test-classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /C:/Users/Uday/.jenkins/workspace/MavenProj/src/test/java/FrameworkLibraries/FunctionLibraries/CommonFunctionLibrary.java:[244,39] strings in switch are not supported in -source 1.5
(use -source 7 or higher to enable strings in switch)
[ERROR] /C:/Users/Uday/.jenkins/workspace/MavenProj/src/test/java/FrameworkLibraries/FunctionLibraries/CommonFunctionLibrary.java:[287,39] strings in switch are not supported in -source 1.5
(use -source 7 or higher to enable strings in switch)
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17.643 s
[INFO] Finished at: 2015-09-29T23:47:29+05:30
[INFO] Final Memory: 24M/273M
[INFO] ------------------------------------------------------------------------
Waiting for Jenkins to finish collecting data
[JENKINS] Archiving C:\Users\Uday\.jenkins\workspace\MavenProj\pom.xml to MavenWebHAF/MavenWebHAF/0.0.1-SNAPSHOT/MavenWebHAF-0.0.1-SNAPSHOT.pom
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile (default-testCompile) on project MavenWebHAF: Compilation failure: Compilation failure:
[ERROR] /C:/Users/Uday/.jenkins/workspace/MavenProj/src/test/java/FrameworkLibraries/FunctionLibraries/CommonFunctionLibrary.java:[244,39] strings in switch are not supported in -source 1.5
[ERROR] (use -source 7 or higher to enable strings in switch)
[ERROR] /C:/Users/Uday/.jenkins/workspace/MavenProj/src/test/java/FrameworkLibraries/FunctionLibraries/CommonFunctionLibrary.java:[287,39] strings in switch are not supported in -source 1.5
[ERROR] (use -source 7 or higher to enable strings in switch)
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
channel stopped
Finished: FAILURE
答案 14 :(得分:1)
阻止Spring MVC @PathVariable被截断的优选解决方案是在路径变量的末尾添加尾部斜杠。
例如:
@RequestMapping(value ="/email/{email}/")
因此,请求将如下所示:
http://localhost:8080/api/email/test@test.com/
答案 15 :(得分:0)
您面临的问题是由于 spring 解释了点(。)之后的uri的 last 部分。 作为 文件扩展名 ,例如.json或.xml。因此,当spring尝试解析path变量时,它会在uri末尾遇到点(。)之后,将截断其余数据。 注意:只有当您将路径变量保留在uri的末尾时,这种情况也会发生。
例如,考虑uri:https://localhost/example/gallery.df/link.ar
@RestController
public class CustomController {
@GetMapping("/example/{firstValue}/{secondValue}")
public void example(@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
// ...
}
}
在上面的网址firstValue =“ gallery.df”和secondValue =“ link”中,。之后的最后一位。在解释路径变量时被截断。
因此,为防止这种情况的发生,有两种可能的方法:
1。)使用正则表达式映射
在映射的末尾使用正则表达式
@GetMapping("/example/{firstValue}/{secondValue:.+}")
public void example(
@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
//...
}
通过使用+,我们指示点后的任何值也将成为路径变量的一部分。
2。)在我们的@PathVariable末尾添加斜杠
@GetMapping("/example/{firstValue}/{secondValue}/")
public void example(
@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
//...
}
这将包含我们的第二个变量,以保护它不受Spring的默认行为影响。
3)通过覆盖Spring的默认webmvc配置
Spring提供了一些方法来覆盖通过使用注释 @EnableWebMvc 导入的默认配置。我们可以通过声明我们自己的 DefaultAnnotationHandlerMapping 来定制Spring MVC配置。 Bean,然后将其 useDefaultSuffixPattern 属性设置为false。 示例:
@Configuration
public class CustomWebConfiguration extends WebMvcConfigurationSupport {
@Bean
public RequestMappingHandlerMapping
requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping
= super.requestMappingHandlerMapping();
handlerMapping.setUseSuffixPatternMatch(false);
return handlerMapping;
}
}
请记住,覆盖此默认配置会影响所有网址。
注意::在这里,我们扩展了WebMvcConfigurationSupport类以覆盖默认方法。通过实现WebMvcConfigurer接口,还有另一种方法来覆盖默认配置。 有关更多信息,请阅读:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html