弹簧靴子控制器

时间:2019-02-16 14:30:07

标签: java spring rest spring-boot architecture

让我们想象一下一个场景,其中我有一个Spring Boot应用程序(采用控制器/服务/存储库模式),其中包含用于汽车的控制器。现在,我想创建看起来像这样的路径:

"/api/cars/bmw"
"/api/cars/mercedes"
"/api/cars/audi"

以此类推。对于每个汽车制造商,我都希望有多个端点,其中一些端点对于所有汽车制造商都是通用的(不确定是否真的很重要,但是仅出于此目的,我们可以说“ / order”和“ / cancelOrder” ),但其中一些有所不同。

现在实现该方案的正确方法是什么?有没有一种方法可以为/car/{producer}路径创建CarController,该路径将成为AudiController处理/car/audi请求的其他控制器的代理?在一个控制器中有3个汽车生产商,并为每个汽车生产商提供服务是可以的,但是如果我只有一个CarController,那么拥有30个汽车生产商将产生很多注入的依赖项(将30个服务注入到控制器中)。

我相信node.js Express框架将允许我们在汽车的“控制器”脚本中执行此操作(不确定它们是否在express中称为控制器或什么):

var app = express();
app.use('/audi', '{path to audi controller script}');

春季有类似的可能性吗?还是这可能是个坏主意,反模式?

另一个很简单但似乎不太优雅的想法是跳过CarController并实现一个:

  • 带有@RequestMapping("/api/cars/audi")

  • 的AudiController
  • 带有@RequestMapping("/api/cars/bmw")

  • 的BmwController
  • 带有@RequestMapping("/api/cars/mercedes")

  • 的MercedesController

那么,什么是最好的主意?

1 个答案:

答案 0 :(得分:1)

Spring为此提供了@PathVariable,可通过以下方式使用:

@RestController
@RequestMapping("/api/cars/")
public class MyController {

    @GetMapping
    @RequestMapping("{producer}/cancelOrder")
    public String cancelOrder(@PathVariable String producer) {
        return "Cancel order for " + producer;
    }
}

我们可以这样称呼此端点:http://localhost:8080/api/cars/Mercedes/cancelOrder

Spring中没有子控制器之类的东西。如果要为每个具有某些常用功能的生产者创建一个单独的控制器,则可以使用继承:

父控制器类(请注意,它没有任何Controller注释):

@RequestMapping("/api/cars/")
public class BaseCarController {
    @GetMapping("/common")
    public String common() {
        return "Common stuff";
    }
}

子控制器类:

@RestController
public class MercedesController extends BaseCarController{

    private MercedesService mercedesService;

    // Spring will autowire this by default, no need to add @Autowired
    public MercedesController(MercedesService mercedesService) {
        this.mercedesService = mercedesService;
    }

    @GetMapping
    @RequestMapping("Mercedes/cancelOrder")
    public String cancelOrder() {
        return "Cancel order for Mercedes.";
    }
}

@RestController
public class AudiController extends BaseCarController{
    private AudiService audiService;

    // Spring will autowire this by default, no need to add @Autowired
    public AudiController(AudiService audiService) {
        this.audiService = audiService;
    }

    @GetMapping
    @RequestMapping("Audi/cancelOrder")
    public String cancelOrder() {
        return "Cancel order for Audi.";
    }
}

我们可以这样称呼产生特定端点: http://localhost:8080/api/cars/Mercedes/cancelOrderhttp://localhost:8080/api/cars/Audi/cancelOrder。此外,我们可以通过以下方式调用公共端点:http://localhost:8080/api/cars/common