如何在不修改整个响应的情况下 return 基于 HATEOAS 的 URL?
How to return URLs based on HATEOAS without modifying the whole response?
我使用 Spring Boot 开发了一项服务。这是代码(简化):
@RestController
@RequestMapping("/cars")
public class CarController {
@Autowired
private CarService carService;
@Autowired
private CarMapper carMapper;
@GetMapping("/{id}")
public CarDto findById(@PathVariable Long id) {
Car car = carService.findById(id);
return carMapper.mapToCarDto(car);
}
}
CarMapper
是使用 mapstruct 定义的。这是代码(也经过简化):
@Mapper(componentModel="spring",
uses={ MakeModelMapper.class })
public interface CarMapper {
@Mappings({
//fields omitted
@Mapping(source="listaImagenCarro", target="rutasImagenes")
})
CarDto mapToCarDto(Car car);
String CAR_IMAGE_URL_FORMAT = "/cars/%d/images/%d"
/*
MapStruct will invoke this method to map my car image domain object into a String. Here's my issue.
*/
default String mapToUrl(CarImage carImage) {
if (carImage == null) return null;
return String.format(
CAR_IMAGE_URL_FORMAT,
carImage.getCar().getId(),
carImage.getId()
);
}
}
调用服务时得到的JSON响应:
{
"id": 9,
"make": { ... },
"model": { ... },
//more fields...
//the urls for the car images
"images": [
"/cars/9/images/1"
]
}
我需要 images
字段 returns 关于我的应用部署的服务器和路径的有效 URL。例如,如果我通过端口 8080 使用 localhost 部署应用程序,我想得到这个:
{
"id": 9,
"make": { ... },
"model": { ... },
//more fields...
"imagenes": [
"http://localhost:8080/cars/9/images/1"
]
}
我已经查看了 Building a Hypermedia-Driven RESTful Web Service,这似乎是我想要的。除了我只需要这些 url,我不想改变我的整个响应对象。
还有其他方法可以实现吗?
Spring HATEOAS 专门为此提供了 LinkBuilder 服务。
尝试以下操作:
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
//...//
linkTo(methodOn(CarController.class).findById(9)).withRel("AddYourRelHere");
这应该输出一个指向您的资源的绝对 URL。您没有遵守 HAL 约定,因此您应该更改或删除 "withRel("")"
部分
您可以将此添加到要更改的特定 DTO:
CarDto dto = carMapper.mapToCarDto(car);
if(dto.matches(criteria)){
dto.setUrl(linkTo...);
}
return dto;
顺便说一下,所有这些都显示在您提到的教程的 "Create a RestController" 部分。
我使用 Spring Boot 开发了一项服务。这是代码(简化):
@RestController
@RequestMapping("/cars")
public class CarController {
@Autowired
private CarService carService;
@Autowired
private CarMapper carMapper;
@GetMapping("/{id}")
public CarDto findById(@PathVariable Long id) {
Car car = carService.findById(id);
return carMapper.mapToCarDto(car);
}
}
CarMapper
是使用 mapstruct 定义的。这是代码(也经过简化):
@Mapper(componentModel="spring",
uses={ MakeModelMapper.class })
public interface CarMapper {
@Mappings({
//fields omitted
@Mapping(source="listaImagenCarro", target="rutasImagenes")
})
CarDto mapToCarDto(Car car);
String CAR_IMAGE_URL_FORMAT = "/cars/%d/images/%d"
/*
MapStruct will invoke this method to map my car image domain object into a String. Here's my issue.
*/
default String mapToUrl(CarImage carImage) {
if (carImage == null) return null;
return String.format(
CAR_IMAGE_URL_FORMAT,
carImage.getCar().getId(),
carImage.getId()
);
}
}
调用服务时得到的JSON响应:
{
"id": 9,
"make": { ... },
"model": { ... },
//more fields...
//the urls for the car images
"images": [
"/cars/9/images/1"
]
}
我需要 images
字段 returns 关于我的应用部署的服务器和路径的有效 URL。例如,如果我通过端口 8080 使用 localhost 部署应用程序,我想得到这个:
{
"id": 9,
"make": { ... },
"model": { ... },
//more fields...
"imagenes": [
"http://localhost:8080/cars/9/images/1"
]
}
我已经查看了 Building a Hypermedia-Driven RESTful Web Service,这似乎是我想要的。除了我只需要这些 url,我不想改变我的整个响应对象。
还有其他方法可以实现吗?
Spring HATEOAS 专门为此提供了 LinkBuilder 服务。
尝试以下操作:
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
//...//
linkTo(methodOn(CarController.class).findById(9)).withRel("AddYourRelHere");
这应该输出一个指向您的资源的绝对 URL。您没有遵守 HAL 约定,因此您应该更改或删除 "withRel("")"
部分您可以将此添加到要更改的特定 DTO:
CarDto dto = carMapper.mapToCarDto(car);
if(dto.matches(criteria)){
dto.setUrl(linkTo...);
}
return dto;
顺便说一下,所有这些都显示在您提到的教程的 "Create a RestController" 部分。