这是问题的延续 Spring MVC @PathVariable被截断

Spring论坛声明它已经固定(3.2版本)作为ContentNegotiationManager的一部分。请看下面的链接。 https://jira.springsource.org/browse/SPR-6164 https://jira.springsource.org/browse/SPR-7632

在我的应用程序中,带有。com的requestParameter被截断了。

谁能告诉我如何使用这个新功能?如何在xml中配置它?

注:春季论坛- #1 Spring MVC @PathVariable带点(.)会被截断


当前回答

最后,我在Spring Docs中找到了解决方案:

要完全禁用文件扩展名,您必须同时设置以下两项: useSuffixPatternMatching(false),参见PathMatchConfigurer favorpatheextension (false),参见ContentNegotiationConfigurer

将此添加到我的WebMvcConfigurerAdapter实现解决了这个问题:

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(false);
}

@Override
public void configurePathMatch(PathMatchConfigurer matcher) {
    matcher.setUseSuffixPatternMatch(false);
}

其他回答

下面是一种完全依赖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;
    }
}

对我来说

@GetMapping(path = "/a/{variableName:.+}")

确实工作,但只有当你也编码的“点”在你的请求url为“%2E”,然后它工作。但要求URL都是…虽然有效,但这不是“标准”编码。感觉像是一个bug:|

另一种类似于“后斜杠”的方法是移动带有点“inline”ex的变量:

@GetMapping(path = "/{variableName}/a")

现在所有的点都将被保留,不需要修改。

在spring 4.2的路径名中包含电子邮件地址的完整解决方案是

<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>

将其添加到应用程序xml中

Spring 5.2.4 (Spring Boot v2.2.6.RELEASE) PathMatchConfigurer。setUseSuffixPatternMatch和ContentNegotiationConfigurer。favorPathExtension已弃用(https://spring.io/blog/2020/03/24/spring-framework-5-2-5-available-now和https://github.com/spring-projects/spring-framework/issues/24179)。

真正的问题是客户端请求特定的媒体类型(比如。com),而Spring默认添加了所有这些媒体类型。在大多数情况下,您的REST控制器只会生成JSON,因此它不支持所请求的输出格式(.com)。 为了克服这个问题,你应该通过更新你的rest控制器(或特定的方法)来支持“输出”格式(@RequestMapping(produces = mediattype . all_value)),当然也允许像点({username:.+})这样的字符。

例子:

@RequestMapping(value = USERNAME, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public class UsernameAPI {

    private final UsernameService service;

    @GetMapping(value = "/{username:.+}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.ALL_VALUE)
    public ResponseEntity isUsernameAlreadyInUse(@PathVariable(value = "username") @Valid @Size(max = 255) String username) {
        log.debug("Check if username already exists");
        if (service.doesUsernameExist(username)) {
            return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        }
        return ResponseEntity.notFound().build();
    }
}

Spring 5.3及以上版本将只匹配已注册的后缀(媒体类型)。

简单的解决方案:添加一个正则表达式{q:。+}在@RequestMapping

@RequestMapping("medici/james/Site")
public class WebSiteController {

    @RequestMapping(value = "/{site:.+}", method = RequestMethod.GET)
    public ModelAndView display(@PathVariable("site") String site) {
        return getModelAndView(site, "web site");

    }
}

现在,对于input /site/jamesmedice.com,“site”将显示正确的james's site