如何用相同的方法和不同的标题简化REST控制器?

问题描述 投票:0回答:3

我有一个Java REST API,供2个不同的使用者使用。默认情况下,REST原则我的API应该定义请求标头的名称。但是现在我没有共同的情况。消费者使用不同的安全层,该安全层提供不同的头,这两种方式都意味着相同的参数。

示例方法: (非真实代码)对于第一个消费者:

@PostMapping("/number")
Integer getNumber(@RequestHeader("no") String number, @RequestBody User user) {
    /*...*/
}

第二消费者:

@PostMapping("/number")
Integer getNumber(@RequestHeader("number") String number, @RequestBody User user) {
    /*...*/
}

我在一个控制器中最多有10个方法,它们应该具有相同的名称和逻辑,但标头不同。请求路径前缀可以不同。


问题:

如何简化REST控制器并且不使用相同的方法和相同的逻辑创建两个不同的控制器?


我尝试过的事情:

我尝试了几个示例,使用相同的方法,但映射不同,创建了一个具有2个不同接口的控制器。

示例:

Controller class

@RestController
@RequestMapping(path ="/application")
@Api(tags = {"application"})
public class ApplicationController implements AppMapping1, AppMapping2 {

    @Override
    public Integer getNumber(String number, User user) {
        /*...*/
    }
}

第一个界面

interface AppMapping1 {

    @PostMapping("/num")
    Integer getNumber(@RequestHeader("num") String number, @RequestBody User user);
}

第二界面

interface AppMapping2 {

    @PostMapping("/number")
    Integer getNumber(@RequestHeader("number") String number, @RequestBody User user);
}

结果:

控制器仅与第一个接口映射。因此,http://.../application/num可以正常工作,但是http://.../application/number-获取404错误代码。这意味着Java Spring-Boot没有这种功能。需要更多的想法。

[Java 8开发的项目; spring-boot:2.1.1.RELEASE; gradle

java spring rest spring-boot gradle
3个回答
0
投票

您可以删除@RequestHeader批注并考虑执行以下操作:

    @PostMapping("/number")
    Integer getNumber(HttpServletRequest request, @RequestBody User user) {
      String number = request.getHeader("num");
      if(number == null){
         number = request.getHeader("number");
      }    
      /*...*/
    }

如果您希望使用更清洁的方法,请考虑创建一个使用HttpServletRequest对象并返回所需标头值的util类。


0
投票

重复两次或多次重复同一代码块只是为了接收具有不同名称(numberno)的相同输入,这对维护不友好。相反,建议阅读所有标头并遍历所有标头以使用不同的名称获取输入。

样本代码

@PostMapping("/number")
public Integer getNumber(@RequestHeader Map<String, String> headers) {
    String number = headers.containsKey("number") ? headers.get("number") : headers.get("no");
    if(Objects.isNull(number)) {
        throw new RuntimeException("Number input not received from header!");
    }

    // relevant processing
}

-1
投票

这是因为您具有相同的签名,并且java将它们标记为相同的方法,所以其中一个在类中使用。您可以简化重命名该方法名称之一的工作。

第一个界面

interface AppMapping1 {

    @PostMapping("/num")
    Integer getNum(@RequestHeader("num") String number, @RequestBody User user);
}

第二界面

interface AppMapping2 {

     @PostMapping("/number")
     Integer getNumber(@RequestHeader("number") String number, @RequestBody User user);
}

绝对需要在控制器类中重写getNum()

© www.soinside.com 2019 - 2024. All rights reserved.