我有一个WidgetDto,我用swagger UI注释进行了注释。最终响应包含一个WidgetDtos列表,其中包含一层元数据(每{21}页的this RESTful最佳实践文档)。例如:
{
"data" : [
{
"id" : 1234,
"prop1" : "val1"
...
},
{
"id" : 5678,
"prop1" : "val2"
...
},
...
]
}
我的java代码如下所示:
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
value = "Get all widgets.",
response = WidgetDto.class
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Returns the list of widgets.")
})
public Response getWidgets() {
List<WidgetDto> widgets;
...
Map<String, Object> responseBody = new HashMap<>();
responseBody.put("data", widgets);
return Response.ok(responseBody).build();
}
我想在多种资源上重复使用此模式,并且我不想为每种响应类型创建列表DTO。是否有一种优雅的方式来使用招摇来记录这些类型的响应主体?
答案 0 :(得分:0)
您的元数据不属于您的资源,但它是您资源代表的一部分。
就我而言,回复类型是&#39; application/hal+json&#39; 和&#39; application / json&#39;,他们每个人都使用不同的metadatas包装器。 为了解决这个问题,我创建了一个extern文档来解释这两个包装器,并为每个包装器解释单个资源和资源列表如何用元数据表示。
我认为我的选择是正确的,因为我将其表示的资源分开(每页7&#39;通过表示来处理资源&#39; this RESTful最佳实践文档)
在您的情况下,您返回WidgetDtos列表,元数据层是资源表示的一部分。
但是,您可以使用spring-hateoas使用的资源和资源等通用类:
public class Resources<T> implements Iterable<T> {
private final Collection<T> content;
Resources(Iterable<T> content) {
this.content = new ArrayList<T>();
for (T element : content) {
this.content.add(element);
}
}
}
并像这样使用它:
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
value = "Get all widgets.",
response = WidgetDto.class
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Returns the list of widgets.")
})
public Response getWidgets() {
List<WidgetDto> widgets;
...
return Response.ok(new Resources<WidgetDto>(widgets)).build();
}
答案 1 :(得分:0)
无论如何这是我的Response类,我曾经回复过所有的回复:
public class Response <AnyData> {
private static final String SUCCESS = "success";
private static final String FAILURE = "failure";
private String status;
private AnyData data;
private String error;
private Response(String status, AnyData data, String error) {
this.status = status;
this.data = data;
this.error = error;;
}
private Response(String status, AnyData data) {
this(status, data,"");
}
private Response(String status, String error) {
this(status, null, error);
}
public static <AnyData> Response<AnyData> success(AnyData data) {
return new Response<AnyData>(SUCCESS, data);
}
public static <AnyData> Response<AnyData> failure(String error) {
return new Response<AnyData>(FAILURE, error);
}
public static <AnyData> Response<AnyData> unimplemented() {
return new Response<AnyData>(FAILURE, "Missing implementation in the backend.");
}
public static <AnyData> Response<AnyData> failureUserNotFound() {
return Response.failure("User not found!");
}
public static <AnyData> Response<AnyData> failureBusinessNotFound() {
return Response.failure("Business not found!");
}
// Removed getters and setters for simplicity.
}
设置完成后,我们将直接从Comtroller创建响应。我改变它以使其与样本一起工作应该足够清晰。请注意,我的响应有静态方法:'success()','error()'...
@RestController
@Api(tags={"Widgets"})
public class WidgetController {
@RequestMapping(value="/api/widgets", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON)
@ApiOperation(value = "Get all widgets.")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Returns the list of widgets.")
})
public Response<List<WidgetDto>> getWidgets() {
List<WidgetDto> widgets = new LinkedList<>();
widgets.add(new WidgetDto(1234, "val1"));
widgets.add(new WidgetDto(5678, "val2"));
return Response.success(widgets);
}
}
希望这有帮助。
答案 2 :(得分:0)
您可以在responseContainer
批注中定义@ApiOperation
属性。
值List
会将WidgetDto
包装在一个容器中。
@ApiOperation(
value = "Get all widgets.",
response = WidgetDto.class,
responseContainer = "List"
)