Java 端点路径中具有最终字段的Spring抽象控制器
假设我想构建一个RESTAPI来存储汽车信息。为了使这篇文章更简单,让我们假设我希望它看起来像这样:Java 端点路径中具有最终字段的Spring抽象控制器,java,spring,rest,inheritance,Java,Spring,Rest,Inheritance,假设我想构建一个RESTAPI来存储汽车信息。为了使这篇文章更简单,让我们假设我希望它看起来像这样: /api/cars/{carmake}/save /api/cars/{carmake}/edit /api/cars/{carmake}/delete @RequestMapping(value="/api/cars/") public abstract class CarController { protected final String CAR_MAKE; publi
/api/cars/{carmake}/save
/api/cars/{carmake}/edit
/api/cars/{carmake}/delete
@RequestMapping(value="/api/cars/")
public abstract class CarController {
protected final String CAR_MAKE;
public CarController(String carMake){
this.CAR_MAKE = carMake;
}
@PostMapping(value = CAR_MAKE + "/save")
public abstract void save(@Valid @RequestBody Serializable car)
@DeleteMapping(value = CAR_MAKE + "/delete")
public abstract void save(@Valid @RequestBody Serializable car);
@PatchMapping(value = CAR_MAKE + "/edit")
public abstract void save(@Valid @RequestBody Serializable car)
}
@RestController
public class AudiController extends CarController {
private AudiService audiService;
@Autowired
public AudiController(AudiService audiService){
super("audi");
this.audiService = audiService;
}
@Override
public void save(@Valid @RequestBody Serializable car) {
audiService.save((Audi) car);
}
.
.
.
}
现在,假设我有多个汽车品牌,每个品牌都需要不同的汽车品牌服务,例如BmwService、Mercedeservice、AudiService
这就是我的想法:一个抽象控制器,看起来像这样:
/api/cars/{carmake}/save
/api/cars/{carmake}/edit
/api/cars/{carmake}/delete
@RequestMapping(value="/api/cars/")
public abstract class CarController {
protected final String CAR_MAKE;
public CarController(String carMake){
this.CAR_MAKE = carMake;
}
@PostMapping(value = CAR_MAKE + "/save")
public abstract void save(@Valid @RequestBody Serializable car)
@DeleteMapping(value = CAR_MAKE + "/delete")
public abstract void save(@Valid @RequestBody Serializable car);
@PatchMapping(value = CAR_MAKE + "/edit")
public abstract void save(@Valid @RequestBody Serializable car)
}
@RestController
public class AudiController extends CarController {
private AudiService audiService;
@Autowired
public AudiController(AudiService audiService){
super("audi");
this.audiService = audiService;
}
@Override
public void save(@Valid @RequestBody Serializable car) {
audiService.save((Audi) car);
}
.
.
.
}
然后一个实际的控制器可能看起来像这样:
/api/cars/{carmake}/save
/api/cars/{carmake}/edit
/api/cars/{carmake}/delete
@RequestMapping(value="/api/cars/")
public abstract class CarController {
protected final String CAR_MAKE;
public CarController(String carMake){
this.CAR_MAKE = carMake;
}
@PostMapping(value = CAR_MAKE + "/save")
public abstract void save(@Valid @RequestBody Serializable car)
@DeleteMapping(value = CAR_MAKE + "/delete")
public abstract void save(@Valid @RequestBody Serializable car);
@PatchMapping(value = CAR_MAKE + "/edit")
public abstract void save(@Valid @RequestBody Serializable car)
}
@RestController
public class AudiController extends CarController {
private AudiService audiService;
@Autowired
public AudiController(AudiService audiService){
super("audi");
this.audiService = audiService;
}
@Override
public void save(@Valid @RequestBody Serializable car) {
audiService.save((Audi) car);
}
.
.
.
}
问题是,如果通过构造函数初始化,spring不允许我将请求映射的值与final变量进行映射(如果CAR\u MAKE在字段声明上正确初始化,例如
protected final String CAR\u MAKE=“s”
有效)。有没有办法解决这个问题,使路径可以来自每个子类?不是在编译器附近,而是类似这样的地方
实现CarService接口:
public interface CarService {
String getBrand();
void save(Car car);
// ...
}
实现实现CarService的AudiCarService、BmwCarService(etc)类型
实现CarService存储库,如:
public class CarServiceRepository {
private Map<String, CarService> carServicesByBrand;
public Optional<CarService> findFor(String brand) {
return Optional.ofNullable(carServicesByBrand.get(brand));
}
@Autowired
public void setCarServicesByBrand(List<CarService> carServices) {
this.carServicesByBrand = carServices.stream().collect(Collectors.toMap(CarService::getBrand, Function.identity()));
}
}
考虑在URL中使用HTTP谓词而不是显式谓词,例如首先,REST实现是不正确的。我们不应该在URI中保存、删除和编辑,而应该使用相同的URI来修改HTTP协议,以便它执行不同的操作。使用PUT进行编辑,POST进行保存,DELETE进行删除。第二,它应该是请求负载,它应该驱动您要调用的服务。