【问题标题】:Spring MVC Matrix Variables retrive only one param valueSpring MVC 矩阵变量只检索一个参数值
【发布时间】:2018-05-31 08:29:16
【问题描述】:

我正在构建一个 spring-mvc REST API 应用程序,我打算为我的一些端点使用矩阵变量。不幸的是,我无法为使用的每个矩阵变量检索多个值。

我的spring-mvc版本是spring-webmvc:4.3.12.RELEASE

我按照此实施示例中显示的步骤操作:http://www.baeldung.com/spring-mvc-matrix-variables

我已启用 Spring MVC 矩阵变量:

package fr.compagny.project.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.util.UrlPathHelper;

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

所以我创建了 2 个测试端点:

package fr.compagny.project.webservice;

import [...]

@Api
@RefreshScope
@RestController
@RequestMapping(value = "/my_awesome_project")
public class ProjectWS {

    //Services
    private ProjectService projectService;

    //Validator
    private ValidatorService validator;

    @ApiOperation(value = "Matrix Variable Test 1.")
    @GetMapping(value = "/matrix_test_one/{vars}", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseStatus(HttpStatus.OK)
    public String getMatrixTestOne (@MatrixVariable(pathVar = "vars", required = true) String v1,
                                    @MatrixVariable(pathVar = "vars", required = true) String v2,
                                    @MatrixVariable(pathVar = "vars", required = true) String v3) {
        return v1 + v2 + v3;
    }

    @ApiOperation(value = "Matrix Variable Test 2.")
    @GetMapping(value = "/matrix_test_two/{vars}", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseStatus(HttpStatus.OK)
    public Map<String, String> getMatrixTestTwo (@MatrixVariable Map<String, String> vars) {
        return vars;
    }

    @Autowired
    public void setProjectService(ProjectService projectService) {
        this.projectService = projectService;
    }

    @Autowired
    public void setValidatorService(ValidatorService validatorService) {
        this.validator = validatorService;
    }
}

当我打电话时

GET http://[...]/my_awesome_project/matrix_test_one/v1=toto;v2=titi;v3=tata
OR
GET http://[...]/my_awesome_project/matrix_test_one/v1=toto

我有同样的错误信息:

出现意外错误(类型=错误请求,状态=400)。失踪 String 类型方法参数的矩阵变量“v2”

但是当我打电话时

GET http://[...]/my_awesome_project/matrix_test_one/v2=titi
OR
GET http://[...]/my_awesome_project/matrix_test_one/[anything except "v1=*"]

我有同样的错误信息:

出现意外错误(类型=错误请求,状态=400)。 字符串类型的方法参数缺少矩阵变量“v1”

所以 Spring 似乎可以获取矩阵变量的第一个元素,但随后停止。

所以我继续尝试第二个测试功能:

GET http://[...]/my_awesome_project/matrix_test_two/v1=toto;v2=titi;v3=tata
OR
GET http://[...]/my_awesome_project/matrix_test_two/v1=toto

返回:

{
    "v1": "toto"
}

-

GET http://[...]/my_awesome_project/matrix_test_two/v2=titi;v1=toto;v3=tata

返回:

{
    "v2": "titi"
}

所以这种行为似乎证实了我的恐惧。

你有没有看到我为了启用矩阵变量支持而遗漏的东西(可能与分号有关)?

【问题讨论】:

    标签: java spring rest spring-mvc spring-web


    【解决方案1】:

    上面提到的例子是使用 Spring Boot。通过 Spring Boot 启动示例按预期工作。如果没有 Spring Boot,它就无法开箱即用,正如Q&A 中所解释的那样。原因是从@Configuration(示例中的第2 点)注入的UrlPathHelper 不用于处理请求。使用UrlPathHelper 的默认实例,因此urlPathHelper.shouldRemoveSemicolonContent() 返回true。这会从请求中删除矩阵变量。

    编辑:

    我调试了一下,发现有两个RequestMappingHandlerMapping类型的bean。

    所以我尝试了这个配置:

    @Configuration
    @ComponentScan(basePackageClasses = { WebMvcConfiguration.class })
    public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    
        @Bean("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping")
        @Qualifier("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping")
        public RequestMappingHandlerMapping fullyQualifiedRequestMappingHandlerMapping() {
            return requestMappingHandlerMapping();
        }
    
        @Bean
        @Override
        public RequestMappingHandlerMapping requestMappingHandlerMapping() {
            RequestMappingHandlerMapping requestMappingHandlerMapping = super.requestMappingHandlerMapping();
            requestMappingHandlerMapping.getUrlPathHelper().setRemoveSemicolonContent(false);
            return requestMappingHandlerMapping;
        }
    
        @Override
        public void configurePathMatch(PathMatchConfigurer configurer) {
            UrlPathHelper urlPathHelper = configurer.getUrlPathHelper();
            if (urlPathHelper == null) {
                urlPathHelper = new UrlPathHelper();
            }
            urlPathHelper.setRemoveSemicolonContent(false);
        }
    
    }
    

    但完全限定的 bean 不是由第一种方法创建的。这个 bean 正在处理请求。所以矩阵变量还是被去掉了。

    由于我无法为 bean 提供工厂方法,我尝试修改 bean 的状态:

    @Component
    public class Initializer {
    
        @Autowired
        private ApplicationContext appContext;
    
        @PostConstruct
        protected void init() {
            initUrlPathHelper("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping");
            initUrlPathHelper("requestMappingHandlerMapping");
        }
    
        protected void initUrlPathHelper(String beanName) {
            AbstractHandlerMapping b = (AbstractHandlerMapping) appContext.getBean(beanName);
            b.setUrlPathHelper(urlPathHelper());
        }
    
        public UrlPathHelper urlPathHelper() {
            UrlPathHelper urlPathHelper = new UrlPathHelper();
            urlPathHelper.setRemoveSemicolonContent(false);
            return urlPathHelper;
        }
    
    }
    

    这是为我做的。矩阵变量已映射。

    【讨论】:

    • 我刚刚修改了我的“matrix_test_one”端点来测试它。我遇到了与我最初的帖子中描述的完全相同的行为。对不起。
    • 我已经设置了你的控制器并复制了这个案例。我找到了一个类似的SO-Q&A。但是您使用的指南设置为urlPathHelper.setRemoveSemicolonContent(false)。所以我还是没有办法。
    • 我回到了baeldung.com的指南。他们正在使用 Spring Boot。所以我将代码更改为通过 Spring Boot 启动并且它工作正常。我更新了我的答案。
    猜你喜欢
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    相关资源
    最近更新 更多