假设我要构建一个用于存储汽车信息的REST API。为了使这篇文章更简单,假设我希望它看起来像这样:
/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是通过构造函数初始化的,则spring不允许我使用带有最终变量的请求映射的值(如果CAR_MAKE是在字段声明(例如protected final String CAR_MAKE = "s"
上初始化的),则可以正常工作)。那么有什么办法可以解决这个问题,以便路径可以来自每个子类?
答案 0 :(得分:0)
不是靠近编译器,而是类似的东西。
实现CarService接口:
public interface CarService {
String getBrand();
void save(Car car);
// ...
}
实现实现CarService的AudiCarService,BmwCarService(等)类型。
实现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()));
}
}
实现单个控制器“ CarController”:
@RequestMapping(value="/api/cars")
@Component
public class CarController {
@Autowired
private CarServiceRepository carServiceRepository;
@PostMapping(value = "/{brand}/save")
public void save(@Valid @RequestBody Serializable car, @PathParam String brand) {
carServiceRepository.findFor(brand).ifPresent(carService -> carService.save(car));
}
// ...
}
与URL中的显式动词相比,还建议使用HTTP动词,例如Why does including an action verb in the URI in a REST implementation violate the protocol?