【问题标题】:Handle Ambiguous handler methods mapped convention处理不明确的处理程序方法映射约定
【发布时间】:2022-01-05 03:09:08
【问题描述】:

我有 Chemical 资源的 2 个 GET 端点: 在第一个端点中,我想要化学对象的 id,这在每种化学物质中都是唯一的。

@GetMapping("/chemical/{id}")

在第二个 GET 端点中,我想要与特定实验室相对应的所有化学品(实验室是强制性的)。

@GetMapping("/chemical/{labKey}")

Spring无法区分/chemical/myLab/chemical/12,这个我可以理解。我知道我应该更改端点映射,但是如何更改?有人可以为这种特定情况提出一个好的约定吗?例如。 @GetMapping("/chemical/{labKey}/{id}" 对我来说似乎是多余的,因为我不使用 labKey pathVariable,我只需要 id,我会这样称呼:chemicalService.findById(id)

【问题讨论】:

    标签: spring-boot rest http get


    【解决方案1】:

    我认为最好的方法是使用两个端点:

    1. /chemical/{id} 将使用 @GetMapping("/chemicals/{id}") 按标识符获取您的化学品。
    2. 第二个将使用查询参数labKey 根据实验室密钥进行过滤。这将有一个通用的@GetMapping("/chemicals")chemicals?labKey=lab1 将是 URI。

    以下是我的实现。 控制器类

    import org.springframework.stereotype.Service;
    
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Optional;
    import java.util.stream.Collectors;
    
    @Service
    public class ChemicalService {
    
        private List<ChemicalDTO> chemicals = Arrays.asList(
            new ChemicalDTO(1L, "chem1", "lab1"),
                new ChemicalDTO(2L, "chem2", "lab2"),
                new ChemicalDTO(3L, "chem3", "lab1"),
                new ChemicalDTO(4L, "chem4", "lab3")
        );
    
        public Optional<ChemicalDTO> getChemicalById(Long id) {
            return chemicals.stream().filter(e -> e.getId().equals(id)).findAny();
        }
    
        public List<ChemicalDTO> getChemicalByLabKey(String labKey) {
            if( labKey.isBlank() || labKey.isEmpty() ) return new ArrayList<>();
            return chemicals
                    .stream()
                    .filter(e -> e.getLabKey().equals(labKey))
                    .collect(Collectors.toList());
        }
    
    }
    

    服务类

    import org.springframework.stereotype.Service;
    
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Optional;
    import java.util.stream.Collectors;
    
    @Service
    public class ChemicalService {
    
        private List<ChemicalDTO> chemicals = Arrays.asList(
            new ChemicalDTO(1L, "chem1", "lab1"),
                new ChemicalDTO(2L, "chem2", "lab2"),
                new ChemicalDTO(3L, "chem3", "lab1"),
                new ChemicalDTO(4L, "chem4", "lab3")
        );
    
        public Optional<ChemicalDTO> getChemicalById(Long id) {
            return chemicals.stream().filter(e -> e.getId().equals(id)).findAny();
        }
    
        public List<ChemicalDTO> getChemicalByLabKey(String labKey) {
            if( labKey.isBlank() || labKey.isEmpty() ) return new ArrayList<>();
            return chemicals
                    .stream()
                    .filter(e -> e.getLabKey().equals(labKey))
                    .collect(Collectors.toList());
        }
    
    }
    

    DTO 类

    import lombok.AllArgsConstructor;
    import lombok.Data;
    
    @Data
    @AllArgsConstructor
    public class ChemicalDTO {
    
        private Long id;
        private String name;
        private String labKey;
    
    }
    

    您可以在REST resource naming conventions 和示例here 中找到更多信息

    【讨论】:

      【解决方案2】:

      如果路径相同且路径变量的数量也相同,则以下是处理这种情况的干净方法。

      你可以考虑下面的代码sn-p

      @GetMapping(value = "/chemical", params = "id")
      public String getChemicalById(@RequestParam(value = "id") String id) {
          return "ID method: "+id;
      }
      
      @GetMapping(value = "/chemical", params = "label")
      public String getChemicalByLabel(@RequestParam(value = "label") String label) {
          return "Label method: "+label;
      }
      

      网址如下:

      • /chemical?id=ID
      • /chemical?label=LABEL

      【讨论】:

        猜你喜欢
        • 2021-01-22
        • 1970-01-01
        • 2014-07-30
        • 2017-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-05
        • 2014-10-23
        相关资源
        最近更新 更多