【问题标题】:@RequestParam with Optional Spring REST带有可选 Spring REST 的 @RequestParam
【发布时间】:2020-07-27 22:59:03
【问题描述】:

我有一个带有可选请求参数的 Spring REST 端点,如下所示:

public ResponseEntity<Product> globalProduct(@RequestParam Optional<Integer> id, @RequestParam Optional<String> name){

return ResponseEntity.ok(tm));
}

当我尝试测试这个使用 Mockito 框架的端点时

@Test                                                                               
public void testGlobalProduct() throws Exception {                        
    URI uri = UriComponentsBuilder.fromPath("/api/products")                  
            .queryParam("id", Optional.of(1)                                               
            .queryParam("name", Optional.empty())                                 
            .build().toUri();                                                       
    mockMvc.perform( MockMvcRequestBuilders.get(uri)                                
            .accept(MediaType.APPLICATION_JSON))                                    
            .andExpect(status().isOk())                                             
            .andExpect(content().contentType(MediaType.APPLICATION_JSON))           
            .andDo(MockMvcResultHandlers.print())                                   
            .andReturn();                                                           
} 

所以 queryParams id 和 name 应该是 Optional.of(1) 和 Optional.empty() ,但是当我在 rest api implementationaion 中调试时,我看到 idname 已经用值 Optional[Optional[1]] 包装了和Optiona[Optional.empty]]

我知道我可以使用 @RequestParams(required=false) 但我不想在这种情况下使用这种方式。

我们如何解开 Optional[Optional[1]] Optiona[Optional.empty]] 这是正确的吗?请问有什么建议吗?

提前致谢!

【问题讨论】:

    标签: java spring-boot rest


    【解决方案1】:

    这是因为您在查询参数中传递了一个 Optional,该参数再次包装在控制器层的一个可选参数中。尝试关注并检查。

    @Test                                                                               
    public void testGlobalProduct() throws Exception {                        
        URI uri = UriComponentsBuilder.fromPath("/api/products")                  
                .queryParam("id", 1)                                                                               
                .build().toUri();                                                       
        mockMvc.perform( MockMvcRequestBuilders.get(uri)                                
                .accept(MediaType.APPLICATION_JSON))                                    
                .andExpect(status().isOk())                                             
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))           
                .andDo(MockMvcResultHandlers.print())                                   
                .andReturn();                                                           
    } 
    

    【讨论】:

    • 感谢您的回复是的,我已经尝试传递 .queryParam("id", 1) 它可以工作,但是当我尝试为 queryParam "name" 传递 Optional.empty() 时,该值api 端点接收是可选的[Optional.empty[]]。当我检查name.orElse("no value") 之类的东西时,当我调试“名称”时,总是显示 Optional[Optional.empty[] 并且它应该给出“无价值”。但它从不考虑 orElse 值,即“没有价值”。即使我使用 .queryParam("name", "") 它也永远不会通过 orElse("no value")。只是想知道我将如何传递空值。
    • 如果您希望它为空,请不要传递参数。空意味着它不在请求中。
    【解决方案2】:

    它正在工作。我为参数'name'设置了默认值

    public ResponseEntity<Product> globalProduct(@RequestParam Optional<Integer> id,  @RequestParam(value = "") Optional<String> name){
    
            return ResponseEntity.ok(tm));
       }
    

    而且我没有通过测试中的任何 requestParam,所以它默认为空。它有效。

    @Test                                                                               
    public void testGlobalProduct() throws Exception {                        
        URI uri = UriComponentsBuilder.fromPath("/api/products")                  
                .queryParam("id", Optional.of(1)                                               
                .build().toUri();                                                       
        mockMvc.perform( MockMvcRequestBuilders.get(uri)                                
                .accept(MediaType.APPLICATION_JSON))                                    
                .andExpect(status().isOk())                                             
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))           
                .andDo(MockMvcResultHandlers.print())                                   
                .andReturn();                                                           
    } 
    

    感谢大家的建议。

    【讨论】:

      猜你喜欢
      • 2018-08-13
      • 1970-01-01
      • 2015-08-28
      • 2016-12-01
      • 2014-04-17
      • 1970-01-01
      • 2016-03-21
      • 2016-01-14
      • 1970-01-01
      相关资源
      最近更新 更多