Swagger-UI дублирование конечных точек с интерфейсом и реализацией контроллера - PullRequest
0 голосов
/ 09 мая 2018

У меня есть приложение весенней загрузки. Я решил реализовать свои контроллеры как интерфейс, определяющий конечную точку и ее соответствующую реализацию (т.е. EndpointX, EndpointXController с EndpointXController, являющимся реализацией). У меня есть все мои аннотации для swagger в интерфейсных файлах, чтобы предотвратить загромождение класса реализации; Тем не менее, я вижу дубликаты конечных точек на пользовательском интерфейсе Swagger, как показано ниже:

enter image description here

Это мои настройки:

    @Bean
    public Docket customImplementation() {
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.withMethodAnnotation(RequestMapping.class))
            .paths(PathSelectors.ant("/consent/*"))
            .build()
            .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class)
            .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class)
            .apiInfo(apiInfo());
}

Как я могу сказать swagger / swagger-ui, чтобы он показывал только одну конечную точку для остальной службы? I.e-api-controller согласия не будет показан или подобран чванством.

Редактировать: Опубликован контроллер и код интерфейса

@Controller
public class ConsentApiController implements ConsentApi {

@Autowired
private IConsentApiService consentApiService;

private final ObjectMapper objectMapper;

private final HttpServletRequest request;

@Autowired
public ConsentApiController(ObjectMapper objectMapper, HttpServletRequest request) {
    this.objectMapper = objectMapper;
    this.request = request;
}

@Override
public Optional<ObjectMapper> getObjectMapper() {
    return Optional.ofNullable(objectMapper);
}

@Override
public Optional<HttpServletRequest> getRequest() {
    return Optional.ofNullable(request);
}

public ResponseEntity getConsent(@ApiParam(value = "Identifier for the consent object to be retrieved", required = true) @Valid @RequestBody ConsentReadRequestParent consentReadRequestParent) {
    return consentApiService.getConsent(consentReadRequestParent);
}

public ResponseEntity postConsent(@ApiParam(value = "Populated consent object") @Valid @RequestBody ConsentParentRequest consentObj) {
    // Pass request to service where it will be split into DTOs and passed to DAOs and get response
    return consentApiService.postConsent(consentObj);
}

public ResponseEntity searchConsent(@Valid @RequestBody SearchParentRequest spr){
    return consentApiService.searchConsent(spr);
}



}


@Api(value = "consent")
public interface ConsentApi {

default Optional<ObjectMapper> getObjectMapper() {
    return Optional.empty();
}

default Optional<HttpServletRequest> getRequest() {
    return Optional.empty();
}

default Optional<String> getAcceptHeader() {
    return getRequest().map(r -> r.getHeader("Accept"));
}

@ApiOperation(value = "The Read Consent API is a resource that conforms to a RESTful syntax to retrieve the details of a single consent record.", nickname = "getConsent", notes = "Cannot read without parameters. Minimum of 2 characters in each field. Maximum of 50 characters in each field. Should be able to handle special characters.", response = Consent.class, tags = {"consent",})
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "OK", response = Consent.class),
        @ApiResponse(code = 400, message = "Bad Request"),
        @ApiResponse(code = 405, message = "Method Not Allowed"),
        @ApiResponse(code = 500, message = "Internal Server Error"),
        @ApiResponse(code = 604, message = "Could Not Retrieve Data for Consent"),
        @ApiResponse(code = 714, message = "Consent Not Found Matching Input Values")})
@RequestMapping(value = "/consent/read",
        method = RequestMethod.POST,
        consumes = {MediaType.APPLICATION_JSON_VALUE},
        produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> getConsent(@ApiParam(value = "Identifier for the consent object to be retrieved.", required = true) @Valid @RequestBody ConsentReadRequestParent consentReadRequestParent);

@ApiOperation(value = "The Create Consent API is a resource that conforms to a RESTful syntax to persist a single consent record.", nickname = "postConsent", notes = "<business and backend logic/requirements>", response = ConsentResponseParent.class, tags = {"consent",})
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "OK", response = ConsentResponseParent.class),
        @ApiResponse(code = 400, message = "Bad Request"),
        @ApiResponse(code = 405, message = "Method Not Allowed"),
        @ApiResponse(code = 500, message = "Internal Server Error")})
@RequestMapping(value = "/consent/create",
    method = RequestMethod.POST,
    consumes = {MediaType.APPLICATION_JSON_VALUE},
    produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> postConsent(@ApiParam(value = "filled-out consent object")  @Valid @RequestBody ConsentParentRequest consentObj);

@ApiOperation(value = "The Search Consent API is a resource that conforms to a RESTful syntax to query consent records.", response = SearchParentResponse.class, tags = {"consent",})
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "OK", response = SearchParentResponse.class),
        @ApiResponse(code = 400, message = "Bad Request"),
        @ApiResponse(code = 405, message = "Method Not Allowed"),
        @ApiResponse(code = 500, message = "Internal Server Error")})
@RequestMapping(value = "/consent/search",
        method = RequestMethod.POST,
        consumes = {MediaType.APPLICATION_JSON_VALUE},
        produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<?> searchConsent(@Valid @RequestBody SearchParentRequest spr);

}

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

Удалить атрибут "tags" из @ApiOperation аннотации. Добавление тегов приведет к тому, что API появится в контекстном меню, а также в отдельном меню.

0 голосов
/ 09 мая 2018

Вы можете явно исключить контроллеры, которые не должны отображаться, переместив интерфейсы в другой пакет и используя

.apis(RequestHandlerSelectors.basePackage("my.impl.package"))

или написав собственный настраиваемый набор предикатов и передав их в .apis ().

Однако это было бы мне больше похоже на обходной путь. Вы уверены, что в реализующих классах нет аннотаций @RequestMapping? Я не мог повторить это поведение локально.

...