Невозможно связать Swagger-UI с моим проектом Swagger Spring MVC
В настоящее время я создаю API Rest с использованием Eclipse, Spring Framework MVC, и я только что добавил в свой проект Swagger. Я могу получить доступ к json результат swagger, но мне нужно добавить swagger ui.
Вот все мои файлы, созданные для swagger-springmvc:
WebAppInitializer.java
public class WebAppInitializer implements WebApplicationInitializer {
private AnnotationConfigWebApplicationContext ctx = null;
@Override
public void onStartup(final ServletContext sc) throws ServletException {
System.setProperty("spring.profiles.active", "web");
// Create the 'root' Spring application context
ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringBaseWebConfiguration.class,
SpringSwaggerConfiguration.class);
// Manages the lifecycle
sc.addListener(new ContextLoaderListener(ctx));
sc.addListener(new ContextCleanupListener());
// Spring WebMVC
ServletRegistration.Dynamic springWebMvc = sc.addServlet("ws",
new DispatcherServlet(ctx));
springWebMvc.setLoadOnStartup(1);
springWebMvc.addMapping("/ws/*");
springWebMvc.setAsyncSupported(true);
}
@PreDestroy
protected final void cleanup() {
if (ctx != null) {
ctx.close();
}
}
}
SpringSwaggerConfiguration.java
public class SpringSwaggerConfiguration {
public static final List<String> DEFAULT_INCLUDE_PATTERNS = Arrays
.asList(new String[]{"/com/sa/rnd/dark/resources/.*"});
public static final String SWAGGER_GROUP = "ApiDark";
public static final String RELATIVE_GROUP = "ApiDark";
@Autowired
private SpringSwaggerConfig springSwaggerConfig;
/**
* Adds the jackson scala module to the MappingJackson2HttpMessageConverter
* registered with spring Swagger core models are scala so we need to be
* able to convert to JSON Also registers some custom serializers needed to
* transform swagger models to swagger-ui required json format
*/
@Bean
public JacksonScalaSupport jacksonScalaSupport() {
final JacksonScalaSupport jacksonScalaSupport = new JacksonScalaSupport();
// Set to false to disable
jacksonScalaSupport.setRegisterScalaModule(true);
return jacksonScalaSupport;
}
/**
* Global swagger settings
*/
@Bean
public SwaggerGlobalSettings swaggerGlobalSettings() {
final SwaggerGlobalSettings swaggerGlobalSettings = new SwaggerGlobalSettings();
swaggerGlobalSettings.setGlobalResponseMessages(springSwaggerConfig
.defaultResponseMessages());
swaggerGlobalSettings.setIgnorableParameterTypes(springSwaggerConfig
.defaultIgnorableParameterTypes());
return swaggerGlobalSettings;
}
/**
* API Info as it appears on the swagger-ui page
*/
private ApiInfo apiInfo() {
return new ApiInfo(
"Swagger Spring MVC for Dark Api",
"Sample application demonstrating how to use swagger-springmvc in a no-XML environment.",
"http://en.wikipedia.org/wiki/Terms_of_service",
"michael@laccetti.com", "Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0.html");
}
/**
* Configure a SwaggerApiResourceListing for each swagger instance within
* your app. e.g. 1. private 2. external apis Required to be a spring bean
* as spring will call the postConstruct method to bootstrap swagger
* scanning.
*
* @return
*/
@Bean
public SwaggerApiResourceListing swaggerApiResourceListing() {
// The group name is important and should match the group set on
// ApiListingReferenceScanner
// Note that swaggerCache() is by DefaultSwaggerController to serve the
// swagger json
final SwaggerApiResourceListing swaggerApiResourceListing = new SwaggerApiResourceListing(
springSwaggerConfig.swaggerCache(), SWAGGER_GROUP);
// Set the required swagger settings
swaggerApiResourceListing
.setSwaggerGlobalSettings(swaggerGlobalSettings());
// Supply the API Info as it should appear on swagger-ui web page
swaggerApiResourceListing.setApiInfo(apiInfo());
// Use the default path provider
swaggerApiResourceListing.setSwaggerPathProvider(springSwaggerConfig
.defaultSwaggerPathProvider());
// Global authorization - see the swagger documentation
swaggerApiResourceListing.setAuthorizationTypes(authorizationTypes());
// Sets up an auth context - i.e. which controller request paths to
// apply global auth to
swaggerApiResourceListing
.setAuthorizationContext(authorizationContext());
// Every SwaggerApiResourceListing needs an ApiListingReferenceScanner
// to scan the spring request mappings
swaggerApiResourceListing
.setApiListingReferenceScanner(apiListingReferenceScanner());
return swaggerApiResourceListing;
}
@Bean
/**
* The ApiListingReferenceScanner does most of the work.
* Scans the appropriate spring RequestMappingHandlerMappings
* Applies the correct absolute paths to the generated swagger resources
*/
public ApiListingReferenceScanner apiListingReferenceScanner() {
ApiListingReferenceScanner apiListingReferenceScanner = new ApiListingReferenceScanner();
// Picks up all of the registered spring RequestMappingHandlerMappings
// for
// scanning
apiListingReferenceScanner
.setRequestMappingHandlerMapping(springSwaggerConfig
.swaggerRequestMappingHandlerMappings());
// Excludes any controllers with the supplied annotations
apiListingReferenceScanner.setExcludeAnnotations(springSwaggerConfig
.defaultExcludeAnnotations());
//
apiListingReferenceScanner
.setResourceGroupingStrategy(springSwaggerConfig
.defaultResourceGroupingStrategy());
// Path provider used to generate the appropriate uri's
apiListingReferenceScanner
.setSwaggerPathProvider(relativeSwaggerPathProvider());
// Must match the swagger group set on the SwaggerApiResourceListing
apiListingReferenceScanner.setSwaggerGroup(SWAGGER_GROUP);
// Only include paths that match the supplied regular expressions
apiListingReferenceScanner.setIncludePatterns(DEFAULT_INCLUDE_PATTERNS);
return apiListingReferenceScanner;
}
private List<AuthorizationType> authorizationTypes() {
final List<AuthorizationType> authorizationTypes = new ArrayList<>();
authorizationTypes.add(new BasicAuth());
return authorizationTypes;
}
@Bean
public AuthorizationContext authorizationContext() {
final List<Authorization> authorizations = newArrayList();
AuthorizationScope authorizationScope = new AuthorizationScope(
"global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[]{authorizationScope};
authorizations.add(new Authorization("basic", authorizationScopes));
AuthorizationContext authorizationContext = new AuthorizationContext.AuthorizationContextBuilder(
authorizations).withIncludePatterns(DEFAULT_INCLUDE_PATTERNS)
.build();
return authorizationContext;
}
// Relative path example
@Bean
public SwaggerApiResourceListing relativeSwaggerApiResourceListing() {
SwaggerApiResourceListing swaggerApiResourceListing = new SwaggerApiResourceListing(
springSwaggerConfig.swaggerCache(), RELATIVE_GROUP);
swaggerApiResourceListing
.setSwaggerGlobalSettings(swaggerGlobalSettings());
swaggerApiResourceListing
.setSwaggerPathProvider(relativeSwaggerPathProvider());
swaggerApiResourceListing
.setApiListingReferenceScanner(relativeApiListingReferenceScanner());
return swaggerApiResourceListing;
}
@Bean
public ApiListingReferenceScanner relativeApiListingReferenceScanner() {
ApiListingReferenceScanner apiListingReferenceScanner =
new ApiListingReferenceScanner();
apiListingReferenceScanner
.setRequestMappingHandlerMapping(springSwaggerConfig
.swaggerRequestMappingHandlerMappings());
apiListingReferenceScanner.setExcludeAnnotations(springSwaggerConfig
.defaultExcludeAnnotations());
apiListingReferenceScanner
.setResourceGroupingStrategy(springSwaggerConfig
.defaultResourceGroupingStrategy());
apiListingReferenceScanner
.setSwaggerPathProvider(relativeSwaggerPathProvider());
apiListingReferenceScanner.setSwaggerGroup(RELATIVE_GROUP);
apiListingReferenceScanner.setIncludePatterns(DEFAULT_INCLUDE_PATTERNS);
return apiListingReferenceScanner;
}
@Bean
public SwaggerPathProvider relativeSwaggerPathProvider() {
return new ApiRelativeSwaggerPathProvider();
}
private class ApiRelativeSwaggerPathProvider extends
DefaultSwaggerPathProvider {
@Override
public String getAppBasePath() {
return "/ApiDark/ws";
}
}
}
SpringBaseWebConfiguration.java:
@Configuration
@ComponentScan(basePackages = {"com.sa.rnd.dark.resources",
"com.mangofactory.swagger.configuration",
"com.mangofactory.swagger.controllers"})
@EnableWebMvc
public class SpringBaseWebConfiguration extends WebMvcConfigurerAdapter {
private List<HttpMessageConverter<?>> messageConverters;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/api-docs").setViewName("redirect:index.html");
}
/**
* The message converters for the content types we support.
*
* @return the message converters; returns the same list on subsequent calls
*/
private List<HttpMessageConverter<?>> getMessageConverters() {
if (messageConverters == null) {
messageConverters = new ArrayList<>();
final MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJackson2HttpMessageConverter();
final ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
mappingJacksonHttpMessageConverter.setObjectMapper(mapper);
messageConverters.add(mappingJacksonHttpMessageConverter);
}
return messageConverters;
}
@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
converters.addAll(getMessageConverters());
}
@Bean
public static PropertyPlaceholderConfigurer swaggerProperties() {
final PropertyPlaceholderConfigurer swaggerProperties = new PropertyPlaceholderConfigurer();
swaggerProperties.setLocation(new ClassPathResource(
"swagger.properties"));
return swaggerProperties;
}
}
Вот мои 3 файла для добавления сваггера в мой проект, я просто решил проверить только 1 метод:
@Api(description = "CRUD services for containers working with WebDark",
value = "CRUD Services Containers")
@RestController
@RequestMapping(value = "/container", produces = MediaType.APPLICATION_JSON_VALUE)
public class ContainersResources {
/**
* Find all children of a container.
*
* @param containerId
* ID of the parent container
* @return ApiResponse
*/
@ApiOperation(response = ApiResponse.class,
value = "Find all children containers of one container",
notes = "Find all children containers of one container")
@RequestMapping(method = RequestMethod.GET, value = "/{containerId}")
@ResponseStatus(HttpStatus.OK)
public @ResponseBody ApiResponse<List<ContainerModel>> getContainerChildren(
@ApiParam(required = true, value = "The id of the container parent",
name = "containerId")@PathVariable("containerId") final String containerId) {
ApiResponse<List<ContainerModel>> result = new ApiResponse<>();
result.setMessage("getContainerChildren method of new Api Dark");
result.setSuccess(true);
result.setTotal(9000);
return result;
}
}
Мои результаты: я могу получить доступ к следующему URL http://localhost:8080/ApiDark/ws/api-docs
но я получаю значение JSON, как:
{"apiVersion": "1", "swaggerVersion": "1.2", "authorizations": {"basicAuth": {"type": "basicAuth"}}, "info": {"title": "Swagger Spring MVC для Dark Api","description":" Пример приложения, демонстрирующего использование swagger-springmvc в среде без XML. "," rulesOfServiceUrl ":" http://en.wikipedia.org/wiki/Terms_of_service"," contact ":" michael@laccetti.com "," license ":" Apache 2.0 "," licenseUrl ":" http://www.apache.org/licenses/LICENSE-2.0.html"}}
Вот почему я решил добавить Swagger-UI. Я добавляю содержимое папки dist (взятой из swagger-ui) в папку src/main/webapp. И измените содержимое index.html так, чтобы он указывал на мой URL:
<script type="text/javascript">
$(function () {
window.swaggerUi = new SwaggerUi({
url: "http://localhost:8080/ApiDark/ws/api-docs.json",
dom_id: "swagger-ui-container",
Но я не могу получить доступ к интерфейсу swagger-ui, у меня просто результат json... Нужна помощь, чтобы он заработал, пожалуйста!
2 ответа
Эта проблема кажется старой, но стоит поделиться ей с недавними версиями swagger-springmvc и springmvc-ui, что стало очень легко и менее сложно интегрировать swagger & swagger-ui с вашим веб-сервисом, чтобы увидеть их в рабочей документации REST API.
Добавлена аннотация @EnableSwagger, которая позволяет использовать swagger-springmvc из коробки. Сгенерированный swagger json Resource Listing доступен в /api-docs.
Вы можете обратиться к следующей ссылке, чтобы узнать, как интегрировать swagger-springmvc и swagger-ui в ваш проект spring mvc. https://github.com/martypitt/swagger-springmvc
Что вы подразумеваете под "я не могу получить доступ к интерфейсу Swagger-UI"?
В моем случае мой браузер не загружал index.html (я думаю, что он выбрасывает 404), который у меня был в подпапке вместе со всеми файлами dist: webapp/doc/index.html. Мне пришлось исключить подпапку из отображения сервлета в web.xml, как я кратко описал здесь: Java swagger с ошибками выбрасывания JaxRS
Мой фрагмент web.xml выглядит следующим образом:
<servlet-mapping>
<servlet-name>My application servlet-name</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/doc/*</url-pattern>
</servlet-mapping>
(почему это работает, смотрите здесь: http://blog.ericdaugherty.com/2010/02/excluding-content-from-url-pattern-in.html)
Надеюсь, это поможет!