swagger 抽象类的OpenAPI规范

juzqafwq  于 2023-10-18  发布在  其他
关注(0)|答案(2)|浏览(152)

我使用SpringBoot 3.1.3java17,我有类似的情况如下。
我有一个CommonReadOnlyService这样的:

public class CommonReadOnlyService<T, ID, R extends JpaRepository<T, ID>> {

 @Autowired
 R repository;

 public T findById(ID id) {
    Optional<T> entity = repository.findById(id);
    if (!entity.isPresent()) 
        throw new EntityNotFoundException(String.format("Entity not founr %d", id));
    return entity.get();
 }

 public List<T> findAll() {
    List<T> entity = repository.findAll();
    return entity;
 }

}

每个其他@Service扩展上面的一个如下:

@Service
public class UserService extends CommonRedOnlyService<User, Integer, UserRepository> {

}

我也有一个CommonReadOnlyResource如下:

public abstract class CommonReadOnlyResource<ID, S extends CommonService<?, ID, ?>> {

 @Autowired
 S service;

 @GetMapping("/{id}")
 public D findById(ID id) {
    return service.findById(id);
 }

 @GetMapping
 public List<D> findAll() {
    return service.findAll();
 }

}

而每个其他@RestController扩展了上面的一个。
显然,这样做的原因是为了避免为每个Controller重写findById()findAll()方法。
但是这样我如何指定不同findById()findAll()资源的OpenaAPI Swagger 3 @operation@ApiResponse
有办法吗?
非常感谢您的回复@zufar-sunagatov,但我的想法有点不同。
extendsCommonReadOnlyService的所有服务将不会重新定义findById()findAll()方法。
我需要一些技巧来把一个通用的定义放在这里:

public abstract class CommonReadOnlyResource<ID, S extends CommonService<?, ID, ?>> {

  @Autowired
  S service;
  
  @Override
  @Operation(summary = "Find a {?} by the id", description = "Get a {?} by specifying the id of the {?}.", tags = { "?" })
  @ApiResponses({
    @ApiResponse(responseCode = "200", content = { @Content(schema = @Schema(implementation = {?}.class), mediaType = "application/json") }),
    @ApiResponse(responseCode = "404", description = "The user is not found.")
  })
  @GetMapping("/{id}")
  public D findById(ID id) {
    return service.findById(id);
  }

  @GetMapping
  public List<D> findAll() {
    return service.findAll();
  }

}

例如,关于模式,我在某处读到过类似这样的内容:@Schema(anyOf = User.class, Car.class ecc..),但我不知道我是否可以为所有其他注解做同样的事情。

egdjgwm8

egdjgwm81#

我正在使用SpringBoot 3.1.3 java 17,我遇到了类似于以下的情况。
我有CommonReadOnlyService
我也有一个CommonReadOnlyResource和其他@RestController扩展了上面的一个。
但是这样我如何指定OpenaAPI Swagger3 @操作和不同的findById()和findAll()资源的@ApiResponse?
是的,你可以使用@OperationOverride注解,它允许你覆盖超类中方法的@Operation注解。
例如,你可以用下面的方法覆盖UserService类中的findById()方法:

@Service
public class UserService extends CommonReadOnlyService<User, Integer, UserRepository> {

    @Override
    @Operation(summary = "Find a user by the id", description = "Get a user by specifying the id of the user.", tags = { "users" })
    @ApiResponses({
        @ApiResponse(responseCode = "200", content = { @Content(schema = @Schema(implementation = User.class), mediaType = "application/json") }),
        @ApiResponse(responseCode = "404", description = "The user is not found.")
    })
    public User findById(Integer id) {
        return super.findById(id);
    }

}
pgx2nnw8

pgx2nnw82#

我用这种配置解决了:

@Configuration
public class OpenApiConfig { 

  @Bean 
  public OpenApiCustomizer myOperationIdCustomizer() {
    return new CustomApiPaths();    
  }

  public class CustomApiPaths implements OpenApiCustomizer {
    

    @Override
    public void customise(OpenAPI openApi) {
        Collection<PathItem> paths = openApi.getPaths().values();
        for (PathItem path : paths) {
            for (Operation operation : path.readOperations()) {
                String tag = operation.getTags().stream().findFirst().orElseThrow();
                String method = operation.getOperationId();
                if (method.startsWith("findAll")) {
                    operation.setSummary(String.format("Recupera tutti i/gli %s", tag.toLowerCase()));
                    Tag apiTag = openApi.getTags().stream().filter(t -> t.getName().equals(tag)).findAny().orElseThrow();
                    setResponses(operation, apiTag, tag);

                } else if (method.startsWith("findById")) {
                    operation.setSummary(String.format("Recupera %s in base al loro id", tag.toLowerCase()));
                    Tag apiTag = openApi.getTags().stream().filter(t -> t.getName().equals(tag)).findAny().orElseThrow();
                    setResponses(operation, apiTag, tag);
                }
            }
        }
    }
    
    private void setResponses(Operation operation, Tag tag, String mess) {
        ApiResponses responses = new ApiResponses();
        ApiResponse responseOK = new ApiResponse()
                .description(String.format("%s trovati", mess))
                .content(new Content().addMediaType("application/json", new MediaType().schema(new Schema().$ref(tag.getExtensions().get("x-ref").toString()))));
        ApiResponse responseKO = new ApiResponse()
                .description("Errore Interno del server")
                .content(new Content().addMediaType("application/json", new MediaType()));
        responses.addApiResponse("200", responseOK);
        responses.addApiResponse("500", responseKO);
        operation.setResponses(responses);
    }
    
  }
}

在资源@Tag上添加@Extension

@Tag(name = "Discussion", description = "Operation on discussions", extensions = @Extension(properties = @ExtensionProperty(name = "ref", value = "DiscussionDTO")))
@RestController 
.....

在架构中检索正确的Object。
我不知道这是否是一个最好的做法,任何帮助都是高度赞赏的,但与此同时,希望有所帮助。

相关问题