Как стать автором
Обновить

Комментарии 6

При использовании этого решения натыкался на проблему: при наличии в контроллере более одного маппинга на один и тот же адрес, но с разными параметрами, в Сваггере в итоге все эти маппинги превращались в один эндпоинт, описание, схема и прочее которого случайно бралось от одного из маппингов, а в параметрах были абсолютно все параметры из всех маппингов по этому адресу, и с пометкой required (даже если в самих маппингах явно стоит required = false)

Судя по всему, он просто мержит все эндпоинты на основании их адреса, а не методов с маппингами. В итоге вместо нескольких нормальных маппингов получается один, в который навалено все подряд в случайном порядке, да еще и вводящие в заблуждение параметры указаны

Есть ли какой-то способ это починить?

Есть ссылка на гит* ? Без примеров кода сложно представить конструкцию.
Не обещаю что починю, но посмотрю обязательно :)

Я чуть ниже запостил код, если что-то еще понадобится - обращайтесь)

То есть, код следующего вида:

@ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "Successful operation",
                    content = @Content(mediaType = "application/json",
                            array = @ArraySchema(schema = @Schema(implementation = RegionDTO.class)))),
            @ApiResponse(responseCode = "400", description = "Invalid name of region supplied", content = @Content),
            @ApiResponse(responseCode = "404", description = "No regions found", content = @Content)
    })
    @GetMapping(params = { "name" })
    public ResponseEntity<Object> getByName(
            @Parameter(description = "Name of required region")
            @NotBlank(message = "Region name can't be blank")
            @Size(max = 255, message = "Region name can't be longer than 255 characters")
            @Pattern(regexp = "[а-яА-Я() -]+",
                    message = "Region name must contain only Cyrillic, spaces, dashes and brackets")
            @RequestParam String name) throws RecordNotFoundException {
        List<RegionDTO> regionDTOs = regionDirectoryService.getByName(name);
        
        return ResponseEntity.ok(regionDTOs);
    }

@ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "Successful operation",
                    content = @Content(mediaType = "application/json",
                            array = @ArraySchema(schema = @Schema(implementation = RegionDTO.class)))),
            @ApiResponse(responseCode = "400", description = "Invalid beginning of region name supplied",
                    content = @Content),
            @ApiResponse(responseCode = "404", description = "No regions found", content = @Content)
    })
    @GetMapping(params = { "name-beginning" })
    public ResponseEntity<Object> getByNameBeginning(
            @Parameter(description = "Beginning of name of required region")
            @Size(max = 255, message = "Beginning of region name can't be longer than 255 characters")
            @Pattern(regexp = "[А-Я][а-я]*",
                    message = "Beginning of region name can't be blank, must contain only Cyrillic letters and " +
                            "begins with Capital one")
            @RequestParam("name-beginning") String nameBeginning) throws RecordNotFoundException {
        List<RegionDTO> regionDTOs = regionDirectoryService.getByNameBeginning(nameBeginning);
        
        return ResponseEntity.ok(regionDTOs);
    }

@ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "Successful operation",
                    content = @Content(mediaType = "application/json",
                            array = @ArraySchema(schema = @Schema(implementation = RegionDTO.class)))),
            @ApiResponse(responseCode = "400", description = "Invalid short name of region supplied", content =
            @Content),
            @ApiResponse(responseCode = "404", description = "No regions found", content = @Content)
    })
    @GetMapping(params = { "short-name" })
    public ResponseEntity<Object> getByShortName(
            @Parameter(description = "Short name of required region")
            @Pattern(regexp = "[А-Я]{3}",
                    message = "Region short name can't be blank and must be 3 Capital Cyrillic letters")
            @RequestParam("short-name") String shortName) throws RecordNotFoundException {
        List<RegionDTO> regionDTOs = regionDirectoryService.getByShortName(shortName);
        
        return ResponseEntity.ok(regionDTOs);
    }

Превращается в такой вот эндпоинт:

Все верно. С точки зрения REST и OpenApi - это и есть один эндпоинт, так как имеет общий uri.

Посмотрите спецификацию. Все начинается с path. Попробуйте сформулировать свое желание сначала в виде спецификации https://editor.swagger.io/ а потом сгенерировать код.

Я вижу интересный вариант по разнесению одного эндпоинта за счет применения params, но тогда для того чтобы это работало нужно:
1. Указать параметры для спецификации как 'required = false'
2. Предусмотреть вариант когда пользователь не ввел никаких параметров "поиска". Наверняка в вашем контроллере есть что-то типа getAll() без параметров и он тоже попал в этот эндпоинт.

Я бы предложил пересмотреть подход и вместо вызова отдельных методов репозитория использовать спецификации и один энпоинт `/search`

@semo, у меня к вам есть вопрос такого характера: не сталкивались ли вы с возможной проблемой springdoc, что он не понимает контекст урла?

Например, если сервис крутится на адресе dev.host.ru/api/service/swagger-ui.html, то при открытии он редиректит в dev.host.ru/swagger-ui.html , документация по springdoc ничего не дала, или я не туда глядел.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории