Warm tip: This article is reproduced from stackoverflow.com, please click
gradle java rest spring spring-boot

How to simplify REST controllers with same methods and different headers?

发布于 2020-03-27 15:42:32

I have one Java REST API which is used by 2 different consumers. By default REST principles my API should define the names of request headers. But now I have not common situation. Consumers use different security layer which provides different headers which means same parameter in both ways.

Example method: (not real code)
For 1st consumer:

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

For 2nd consumer:

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

I have up to 10 methods in one controller and they should be with same name and logic, but different header. The request path prefix could be different.


Question:

How to simplify REST controller and don't create 2 different controllers with same methods and same logic?


What I tried:

I tried several examples to create one controller with 2 different interfaces with same methods, but different mapping.

Example:

Controller class

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

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

First interface

interface AppMapping1 {

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

Second interface

interface AppMapping2 {

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

Result:

Controller maps only with the first interface. So http://.../application/num works fine, but http://.../application/number - gets 404 error code. That means Java Spring-Boot doesn't have such functionality. Need some more ideas.

Project developed with Java 8; spring-boot:2.1.1.RELEASE; gradle

Questioner
Dumbo
Viewed
105
Mehrdad HosseinNejad 2020-01-31 17:48

According to this , If we're not sure which headers will be present, or we need more of them than we want in our method's signature, we can use the @RequestHeader annotation without a specific name.

You have a few choices for variable type: a Map, a MultiValueMap or an HttpHeaders object.

Sample

@PostMapping("/number")
public Integer getNumber(@RequestHeader Map<String, String> headers) {

    if (Optional.ofNullable(headers.get("no")).isPresent()){
        //...
    }
    else if (Optional.ofNullable(headers.get("number")).isPresent())
    {
        //...
    }

}