使用 Swagger UI 和带有 Java Spring 端点的 ApiResponses 注释时如何干燥?

2022-01-22 00:00:00 swagger swagger-ui spring java swagger-2.0

I like Swagger because it makes your apis very user friendly. I use Swagger annotations like

  • @ApiParam
  • @ApiResponse | @ApiResponses
  • @ApiOperation
  • Others

On endpoints, query params, request params, request body and so on.

I like to keep my POJO classes clean and in general I try my best to follow DRY rule however, when it comes to swagger I noticed that I keep repeating myself over and over as shown below

@ApiOperation(value = "Retrieve object by id")
@ApiResponses(value = {
    @ApiResponse(code = 200, message = "OK"),
    @ApiResponse(code = 404, message = "Not Found"),
    @ApiResponse(code = 400, message = "Bad Request"),
    @ApiResponse(code = 500, message = "ISE")
})
public Response retrieveById(@ApiParam(value = "Some id") @PathParam("sid") int id) {       
}

@ApiOperation(value = "Create object")
@ApiResponses(value = {
    @ApiResponse(code = 201, message = "Created"),
    @ApiResponse(code = 404, message = "Not Found"),
    @ApiResponse(code = 400, message = "Bad Request"),
    @ApiResponse(code = 500, message = "ISE")
})
public Response create(@ApiParam(value = "Request body") RequestBody body) {
}

How to avoid repeating yourself with Swagger annotations?

解决方案

I did some Googling around and came across this github issue and some other SO questions that are not directly related to ApiResponses annotations and none of them seem to present a working solution.

Using Swagger UI 2.0 I thought let's give it a try, so I did the following

  1. I created a custom annotations GroupedApiResponses..
  2. I annotated GroupedApiResponses.. with a group of Swagger annotations
  3. I used the GroupedApiResponses.. annotations on top of endpoints
  4. Works just like before

See below

package com.raf.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "Ok"),
        @ApiResponse(code = 404, message = "Not Found"),
        @ApiResponse(code = 400, message = "Bad Request"),
        @ApiResponse(code = 500, message = "ISE") 
})
public @interface GroupedApiResponsesAvecOk {
}

Similarly (you can group annotations as you want in one or more than one custom annotation depending on structure of your endpoints and the response messages it return)

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ApiResponses(value = {
        @ApiResponse(code = 201, message = "Created"),
        @ApiResponse(code = 404, message = "Not Found"),
        @ApiResponse(code = 400, message = "Bad Request"),
        @ApiResponse(code = 500, message = "ISE") 
})
public @interface GroupedApiResponsesAvecCreated {
}

And then I used the above @GroupedApiResponsesAvecOk on retrieveById and @GroupedApiResponsesAvecCreated on create endpoint in place of @ApiResponses and worked it just like before.

As shown above, the ApiResponse annotations relating to 400, 404, 500 can now be reused across other endpoints.

相关文章