SpringFox не находит конечные точки jax-rs

После решения использования Springfox для документирования служб jax-rs в приложении Spring я обнаружил, что ответ SpringFox JSON не показывает никаких API:

{
  "swagger": "2.0",
  "info": {
    "description": "Some description",
    "version": "1.0",
    "title": "My awesome API",
    "contact": {
      "name": "[email protected]"
    },
    "license": {}
  },
  "host": "localhost:9090",
  "basePath": "/myapp"
}

Вот springfox-servlet.xml:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean class="com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON" />
    <bean class="com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider" />
    <bean class="com.wordnik.swagger.jaxrs.listing.ResourceListingProvider" />
</beans>

Это в файле свойств:

swagger.resourcePackage=org.myapp

Swagger настроен на поиск классов реализации с помощью отражающего сканера jax-rs:

@Component
public class SwaggerConfiguration {

    @Value("${swagger.resourcePackage}")
    private String resourcePackage;

    @PostConstruct
    public void init() {
        ReflectiveJaxrsScanner scanner = new ReflectiveJaxrsScanner();
        scanner.setResourcePackage(resourcePackage);
        ScannerFactory.setScanner(scanner);

        ClassReaders.setReader(new DefaultJaxrsApiReader());

        SwaggerConfig config = ConfigFactory.config();
        config.setApiVersion(apiVersion);
        config.setBasePath(basePath);
    }

    public String getResourcePackage() {
        return resourcePackage;
    }

    public void setResourcePackage(String resourcePackage) {
        this.resourcePackage = resourcePackage;
    }
}

Вот конфигурация документации:

@Configuration
@EnableSwagger2
public class ApiDocumentationConfiguration {
    @Bean
    public Docket documentation() {
        System.out.println("=========================================== Initializing Swagger");
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build()
                .pathMapping("/")
                .apiInfo(metadata());
    }

    @Bean
    public UiConfiguration uiConfig() {
        return UiConfiguration.DEFAULT;
    }

    private ApiInfo metadata() {
        return new ApiInfoBuilder()
                .title("My awesome API")
                .description("Some description")
                .version("1.0")
                .contact("[email protected]")
                .build();
    }
}

А вот пример класса с аннотациями API:

@Api(value = "activity")
@Service
@Path("api/activity")
@Produces({ MediaType.APPLICATION_JSON })
public class ActivityService {

    @Autowired
    private CommandExecutor commandExecutor;
    @Autowired
    private FetchActivityCommand fetchActivityCommand;

    @ApiOperation(value = "Fetch logged-in user's activity", httpMethod = "GET", response = Response.class)
    @GET
    @Path("/mine")
    @Consumes(MediaType.TEXT_PLAIN)
    @Produces(MediaType.APPLICATION_JSON)
    @Authorization(rejectionMessage = Properties.Authorization.NOT_LOGGED_IN_MESSAGE_PREFIX + "view your activities.")
    public List<Activity> listMyActivities(@Context HttpServletResponse response, @Context HttpServletRequest request) throws IOException {
        return buildActivityList(response, (UUID) request.getSession().getAttribute(Properties.Session.SESSION_KEY_USER_GUID));
    }
    ...
}

Почему он не раскрывает API? Решит ли это использование библиотеки wordnik swagger или улучшит ли решение?


person Don Branson    schedule 01.10.2015    source источник
comment
К сожалению, Springfox не поддерживает аннотации jax-rs. Я думаю, вам будет лучше использовать библиотеки swagger-core.   -  person Dilip Krishnan    schedule 01.10.2015
comment
@dilip, поддерживает ли swagger напрямую аннотации jax-rs?   -  person Don Branson    schedule 01.10.2015
comment
Да, поддерживает   -  person Dilip Krishnan    schedule 01.10.2015
comment
@DilipKrishnan - Спасибо, это была именно та помощь, которая мне была нужна. Я следил за github. com/swagger-api/swagger-core/wiki/, а затем добавил swagger-ui.   -  person Don Branson    schedule 08.10.2015


Ответы (2)


По умолчанию SpringFox будет документировать ваши службы REST, реализованные с использованием Spring MVC — это так же просто, как добавить аннотацию @EnableSwagger2

@SpringBootApplication
@EnableSwagger2
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

Мне удалось заставить SpringFox работать с JAX-RS. Сначала я добавил некоторые зависимости swagger вместе со SpringFox:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-jersey")
    compile("io.springfox:springfox-swagger-ui:2.4.0")
    compile("io.springfox:springfox-swagger2:2.4.0")
    compile("io.swagger:swagger-jersey2-jaxrs:1.5.8")
    testCompile("junit:junit")
}

Затем я включил JAX-RS (Джерси) с Swagger в своем приложении с весенней загрузкой:

@Component
@ApplicationPath("/api")
public static class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {

        BeanConfig swaggerConfig = new BeanConfig();
        swaggerConfig.setBasePath("/api");
        SwaggerConfigLocator.getInstance().putConfig(SwaggerContextService.CONFIG_ID_DEFAULT, swaggerConfig);

        packages(getClass().getPackage().getName(), ApiListingResource.class.getPackage().getName());
    }

}

Обратите внимание, что все конечные точки JAX-RS будут находиться в контексте /api, иначе это будет конфликтовать с диспетчером Spring-MVC.

Наконец, мы должны добавить swagger json, сгенерированный для конечных точек Джерси, в Springfox:

@Component
@Primary
public static class CombinedSwaggerResourcesProvider implements SwaggerResourcesProvider {

    @Resource
    private InMemorySwaggerResourcesProvider inMemorySwaggerResourcesProvider;

    @Override
    public List<SwaggerResource> get() {

        SwaggerResource jerseySwaggerResource = new SwaggerResource();
        jerseySwaggerResource.setLocation("/api/swagger.json");
        jerseySwaggerResource.setSwaggerVersion("2.0");
        jerseySwaggerResource.setName("Jersey");

        return Stream.concat(Stream.of(jerseySwaggerResource), inMemorySwaggerResourcesProvider.get().stream()).collect(Collectors.toList());
    }

}

Вот и все! Теперь ваши конечные точки JAX-RS будут задокументированы Swagger. Я использовал следующий пример конечной точки:

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Component;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Component
@Path("/hello")
@Api
public class Endpoint {

    @GET
    @ApiOperation("Get message")
    @Produces(MediaType.TEXT_PLAIN)
    public String message() {
        return "Hello";
    }

}

Теперь, когда вы запускаете свой сервер и переходите на http://localhost:8080/swagger-ui.html вы увидите документацию для конечных точек JAX-RS. Используйте поле со списком в верхней части страницы, чтобы переключиться на документацию по конечным точкам Spring MVC.

введите описание изображения здесь

person bedrin    schedule 19.03.2016
comment
Спасибо за Ваш ответ. Я получаю следующую ошибку: **************************** ПРИЛОЖЕНИЕ НЕ ЗАПУЩЕНО ************* ************** Описание: компоненту требовался bean-компонент типа 'springfox.documentation.swagger.web.InMemorySwaggerResourcesProvider', который не удалось найти. Действие: рассмотрите возможность определения bean-компонента типа «springfox.documentation.swagger.web.InMemorySwaggerResourcesProvider» в вашей конфигурации. Где вы определили InMemorySwaggerResourcesProvider? - person yeremy; 21.02.2017
comment
@yeremy убедитесь, что у вас есть аннотация @EnableSwagger2 в классе приложения весенней загрузки - person bedrin; 27.02.2017
comment
@bedrin: я смог перечислить конечные точки майки на springfox swagger 2. Однако кнопка авторизации, которая была видна ранее, исчезла. Помогите, пожалуйста, здесь. Пожалуйста, смотрите: когда я выбираю значение по умолчанию из раскрывающегося списка, появляется кнопка авторизации. - person user966506; 09.10.2019
comment
Я могу просмотреть: localhost:5000/swagger-ui.html#, он загружает Пользовательский интерфейс для меня, но я получаю сообщение об ошибке 500: {метка времени: 2021-05-25T14: 22: 23.485 + 0000, статус: 500, ошибка: Внутренняя ошибка сервера, сообщение: Нет доступных сообщений, путь: / API / swagger .json} localhost:5000/api/swagger.json Более того, пока я пытаюсь просматривать localhost:5000/api/swagger.json , я получаю java.lang.NullPointerException: null на org.glassfish.jersey.server.ResourceConfig.getProperties(ResourceConfig.java:751) - person Forhad; 25.05.2021
comment
Вы случайно не пользуетесь AspectJ? Ваш NPE выглядит примерно так: github.com/spring-projects/spring- загрузка/проблемы/6395 - person bedrin; 26.05.2021

Дополнительная информация об авторизации:

  • Если вы хотите добавить аутентификацию для ресурсов Джерси:
BeanConfig swaggerConfig = new BeanConfig();
Swagger swagger = new Swagger();

swagger.securityDefinition("apiKeyAuth", new ApiKeyAuthDefinition("Authorization", In.HEADER));
  
new SwaggerContextService().updateSwagger(swagger);
swaggerConfig.setBasePath("/api");
SwaggerConfigLocator.getInstance().putConfig(SwaggerContextService.CONFIG_ID_DEFAULT, swaggerConfig);

Конечно, это Auth с токеном JWT. Если вам нужна базовая аутентификация, используйте:

swagger.securityDefinition("basicAuth", new BasicAuthDefinition());
  • Если вам нужно добавить authetnctioan для ресурсов Spring:
@Configuration
public class SwaggerSpringConfig {
    
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.yourPackage"))
                .paths(PathSelectors.any())
                .build()
                .enable(true)
                .securitySchemes(Lists.newArrayList(apiKey()));
    }

    private ApiKey apiKey() {
        return new ApiKey("AUTHORIZATION", "Authorization", "header");
    }

    @Bean
    SecurityConfiguration security() {
        return new SecurityConfiguration(
                null,
                null,
                null,
                null,
                null,
                ApiKeyVehicle.HEADER,
                "Authorization",
                null
        );
    }

}
person steva1988    schedule 08.01.2021