处理不明确的处理程序方法映射约定

Posted

技术标签:

【中文标题】处理不明确的处理程序方法映射约定【英文标题】: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)

【问题讨论】:

【参考方案1】:

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

    /chemical/id 将使用 @GetMapping("/chemicals/id") 按标识符获取您的化学品。 第二个将使用查询参数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

【讨论】:

以上是关于处理不明确的处理程序方法映射约定的主要内容,如果未能解决你的问题,请参考以下文章

流星文件命名约定会阻止它处理?

Flask06 地址约定利用falsk提供的方法渲染模板

API 使用约定

可插拔应用程序的 Django 默认设置约定?

Spring MVC-处理程序映射(Handler Mapping)-控制器类名称处理程序映射(Controller Class Name Handler Mapping)示例(转载实践)

Retrofit响应数据及异常处理策略