为什么 RequestMapping 注释不适用于 spring boot 应用程序中的 class?

Why RequestMapping annotation does't work with class in springboot application?

我正在尝试通过示例学习 springbott。当我尝试调用在 class 上定义的 restcontroller 时,出现 404 错误。

@RestController
@RequestMapping("/test")
public class ReservationResource {

    public ResponseEntity<ReservationResponse> getAvaliableRooms(
            @RequestParam(value = "checkin") @DateTimeFormat(iso = ISO.DATE) LocalDate checkin,
            @RequestParam(value = "checkout") @DateTimeFormat(iso = ISO.DATE) LocalDate checkout) {

        return new ResponseEntity<>(new ReservationResponse(), HttpStatus.OK);
    }
}

此应用程序没有针对 /error 的显式映射,因此您将其视为后备。 8 月 16 日星期三 16:18:05 2017 年东部夏令时 出现意外错误(类型=未找到,状态=404)。 没有留言

但是当我像下面这样尝试时它成功了!

@RestController
public class ReservationResource {

    @RequestMapping("/test")
    public ResponseEntity<ReservationResponse> getAvaliableRooms(
            @RequestParam(value = "checkin") @DateTimeFormat(iso = ISO.DATE) LocalDate checkin,
            @RequestParam(value = "checkout") @DateTimeFormat(iso = ISO.DATE) LocalDate checkout) {

        return new ResponseEntity<>(new ReservationResponse(), HttpStatus.OK);
    }
}

为什么会出现这种差异?顺便跟个例子,开发者定义的跟第一节一样!

因为如果您在 class 级别使用 @RequestMapping 它将不知道要执行哪个方法,因为您的 class 可以有多个方法

您必须使用 @RequestMapping 注释您的方法。如果没有注释,Controller 无法知道应该执行哪个方法。

@RequestMapping("/test")
Class Level

@RequestMapping
Mehtod Level

Reachable = http://localhost:8080/test

@RequestMapping("/test")
Class Level

@RequestMapping("/abc")
Mehtod Level

Reachable = http://localhost:8080/test/abc

@RequestMapping("/test")
Class Level

@RequestMapping("/abc")
Mehtod Level

@RequestMapping("/def")
Mehtod Level

Reachable = http://localhost:8080/test/abc
Reachable = http://localhost:8080/test/def

当您使用注解@RestController 时,意味着您的class 将作为@Controller 并且在内部定义的所有方法将默认具有@ResponseBody

但是你需要在你的Controller中定义每个方法的具体路径。

例如你可以这样做:

@RestController
@RequestMapping("/test")
public class ReservationResource {

    @RequestMapping("/") 
    public ResponseEntity<ReservationResponse> getAvaliableRooms(
            @RequestParam(value = "checkin") @DateTimeFormat(iso = ISO.DATE) LocalDate checkin,
            @RequestParam(value = "checkout") @DateTimeFormat(iso = ISO.DATE) LocalDate checkout) {

        return new ResponseEntity<>(new ReservationResponse(), HttpStatus.OK);
    }

    @RequestMapping("/second") 
    public ResponseEntity<ReservationResponse> getAvaliableRooms(
                @RequestParam(value = "checkin") @DateTimeFormat(iso = ISO.DATE) LocalDate checkin,
                @RequestParam(value = "checkout") @DateTimeFormat(iso = ISO.DATE) LocalDate checkout) {

            return new ResponseEntity<>(new ReservationResponse(), HttpStatus.OK);
        }
    }

使用此配置,您已使用 GET 方法在 /test/ 中定义了一个路径,其他“/test/second”也为 GET,但默认情况下,您的所有路径都将以“/test”开头

如果您决定在方法级别使用@RequestMapping,您可以在同一 class.

中修改路径

例如:

@RestController
public class ReservationResource {

        @RequestMapping("/test") 
        public ResponseEntity<ReservationResponse> getAvaliableRooms(
                @RequestParam(value = "checkin") @DateTimeFormat(iso = ISO.DATE) LocalDate checkin,
                @RequestParam(value = "checkout") @DateTimeFormat(iso = ISO.DATE) LocalDate checkout) {

            return new ResponseEntity<>(new ReservationResponse(), HttpStatus.OK);
        }

        @RequestMapping("/second") 
        public ResponseEntity<ReservationResponse> getAvaliableRooms(
                    @RequestParam(value = "checkin") @DateTimeFormat(iso = ISO.DATE) LocalDate checkin,
                    @RequestParam(value = "checkout") @DateTimeFormat(iso = ISO.DATE) LocalDate checkout) {

                return new ResponseEntity<>(new ReservationResponse(), HttpStatus.OK);
            }
        }

而且 URL 都可以通过“/test”和“/second”访问

/test 是控制器的 class 级别映射,然后为了使 getAvaliableRooms() public 方法符合请求服务的条件,您需要添加 @RequestMapping("") 到您的 getAvaliableRooms() 方法,如下所示:

@RestController
@RequestMapping("/test")
public class TestController {

    @RequestMapping("")
    public ResponseEntity<ReservationResponse> getAvaliableRooms(
        @RequestParam(value = "checkin") @DateTimeFormat(iso = ISO.DATE) 
                   LocalDate checkin,
        @RequestParam(value = "checkout") @DateTimeFormat(iso = ISO.DATE) 
               LocalDate checkout) {

       return new ResponseEntity<>(new ReservationResponse(), HttpStatus.OK);
    }
}

换句话说,您是在明确地告诉 Spring 容器控制器 class 中的 public 方法中的哪一个实际上是用于服务请求的。