Configure swagger with spring boot

If you haven’t starting working with spring boot yet, you will quickly find that it pulls out all the common configuration from across your applications. Recently I helped in an effort to modularize configuration and worked on creating a spring-boot-swagger starter project. This project, like other boot modules, would be included in the pom and you would enjoy the fruits of auto configuration.

If you aren‘t familiar with swagger, swagger is a "specification and complete framework implementation for describing, producing, consuming, and visualizing RESTful web services". It has various integration points with java back end technologies (JAX-RS, scala, php, nodejs, etc) but even better it has separated the front end into a project called swagger-ui. So as long as your service complies to the spec you can have a pretty UI on top of your rest services. It does lack official support spring MVC though there are various projects on github that attempt to integrate the two, even I started a project. Also there has been talk in spring’s JIRA about swagger support.

We went with swagger-springmc simply due to the number of watchers/stars and it fit in pretty good with little effort. It can be integrated with traditional spring XML or through java config both ways requiring two properties to be set to specify the API version and the base path. With the direction of spring-boot, we wanted to abstract the dependency and defaults so consuming apps would just have to plug it in to the pom.xml. It lead us down a few options which we described below and in the end landed on #3 of Injecting ConfigurableApplicationContext in one of our auto configuration classes.

Option 1 - PropertyPlaceholderConfigurer

As martypitt / swagger-springmvc states in the documentation you can configure the properties programmatically with the PropertyPlaceholderConfigurer. We need the properties in spring‘s Environment class, a class that manages profiles and properties, but PropertyPlaceholderConfigurer is not able to add properties to environment. PropertySourcesPlaceholderConfigurer uses Environment and not vice versa. Also, we wanted this in the spring boot module, not all consuming rest applications. In case this works for you, this is what the configuration would look like:

 @Bean
public static PropertyPlaceholderConfigurer swaggerProperties() throws UnknownHostException {

    // Swagger expects these to property values to be replaced. We don‘t want to propagate these to consumers of
    // this configuration, so we derive reasonable defaults here and configure the properties programmatically.
    Properties properties = new Properties();
    properties.setProperty("documentation.services.basePath", servletContext.getContextPath());
    // this property will be overridden at runtime, so the value here doesn‘t matter
    properties.setProperty("documentation.services.version", "REPLACE-ME");

    PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
    configurer.setProperties(properties);
    configurer.setIgnoreUnresolvablePlaceholders(true);
    return configurer;
}

Option 2 - Implementing ApplicationContextInitializer

ApplicationContextInitializer is a call back interface for initializing ConfigurableApplicationContext prior to being refreshed typically used within web applications that require some programmatic initialization of the application context. So this would work great, on start up we can set the two properties but what it doesn‘t give us is the ability to get hold of a ServletContext through ServletContextAware because it fires to early on in the spring lifecycle.

So if your application will deploy to a single environment or if you want to require each of your applications to specify the properties required in the application.properties file, this solution might work for you. It would look something like this:

In your spring.factories within your boot starter project you would need to add:

org.springframework.context.ApplicationContextInitializer=com.levelup.SomeInitializer

Then add the following class

public class SwaggerApplicationContextInitializer implements
        ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {

        MutablePropertySources propertySources = applicationContext
                .getEnvironment().getPropertySources();

        Map<String, Object> propertyMap = new HashMap<String, Object>();
        propertyMap.put("documentation.services.basePath",
                "http://localhost:8080/participant");
        propertyMap.put("documentation.services.version", "REPLACE-ME");

        propertySources.addFirst(new MapPropertySource(
                "documentation.services", propertyMap));

    }
}

Option 3 - Injecting ConfigurableApplicationContext

At the end of the day this solution may not be spring certified and there probably another way to do it but worked. ConfigurableApplicationContext classprovides facilities to configure an application context in addition to the application context client methods. So we created a class that implements InitializingBean that allows us to react once all their properties have been set. It allows us to configure the properties need and then add them to the environment so when the DocumentationConfig looks for them, they are available.

@Configuration
@AutoConfigureBefore(SwaggerAutoConfiguration.class)
@EnableConfigurationProperties({ SwaggerBeanProperties.class })
public class SwaggerPropertiesAutoConfiguration implements InitializingBean,
        ServletContextAware {

    private ServletContext servletContext;

    @Autowired
    ConfigurableApplicationContext applicationContext;

    @Autowired
    SwaggerBeanProperties swaggerBeanProperties;

    @Override
    public void afterPropertiesSet() throws Exception {

        MutablePropertySources propertySources = applicationContext
                .getEnvironment().getPropertySources();

        Map<String, Object> propertyMap = new HashMap<String, Object>();
        propertyMap.put("documentation.services.basePath",
                getDocumentBasePath());

        propertyMap.put("documentation.services.version", getDocumentVersion());

        propertySources.addFirst(new MapPropertySource(
                "documentation.services", propertyMap));

    }

    private String getDocumentBasePath() {

        if (swaggerBeanProperties.getBasePath() != null) {
            return swaggerBeanProperties.getBasePath();
        } else {
            return servletContext.getContextPath();
        }
    }

    private String getDocumentVersion() {

        if (swaggerBeanProperties.getVersion() != null) {
            return swaggerBeanProperties.getVersion();
        } else {
            return "1.0";
        }
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }
}

We all have heard it before, "we don‘t want the base configuration" so we created a @ConfigurationProperties class that will look for the properties and will be injected into SwaggerPropertiesAutoConfiguration above. If properties are set in the application we will apply them, otherwise we will look for the defaults in hopes to create consistency across all apps.

@AutoConfigureBefore(SwaggerPropertiesAutoConfiguration.class)
@ConfigurationProperties(name = "documentation.services", ignoreUnknownFields = true)
public class SwaggerBeanProperties  {

    private String basePath;
    private String version;

    public String getBasePath() {
        return basePath;
    }
    public void setBasePath(String basePath) {
        this.basePath = basePath;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
}

The last class was simply to import the DocumentationConfig.class

@Configuration
@Import(DocumentationConfig.class)
public class SwaggerAutoConfiguration  {
}

Finally, the spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=boot.web.swagger.autoconfigure.SwaggerAutoConfiguration,boot.web.swagger.autoconfigure.SwaggerPropertiesAutoConfiguration

org.springframework.context.ApplicationContextInitializer=

Spring-boot was made to solve the "we have ever which way to configure an application" syndrome but occasionally you still might have get dirty. It might not be perfect but it works for now. If you have suggestions or other ways this could be handled, let me know.

Configure swagger with spring boot posted by Justin Musgrove on 16 April 2014

http://www.leveluplunch.com/blog/2014/04/16/spring-boot-swagger-springmvc-configuration/

时间: 2024-12-18 22:26:51

Configure swagger with spring boot的相关文章

使用Swagger生成Spring Boot REST客户端(支持Feign)(待实践)

如果项目上使用了Swagger做RESTful的文档,那么也可以通过Swagger提供的代码生成器生成客户端代码,同时支持Feign客户端. 但是经过测试,生成Feign代码和REST客户端有些臃肿. 官方网站:https://github.com/swagger-api/swagger-codegen 参考: https://stackoverflow.com/questions/46019180/how-to-generate-spring-cloud-feign-client-using-

Swagger Learing - Spring Boot 整合swagger

学习了一下swagger. 这是编写的Demo 源码 https://github.com/AmberBar/Learning/tree/master/swagger-learning/swagger 需要的小伙伴可以clone直接运行 访问地址 http://localhost:9999/swagger-ui.html#/ 原文地址:https://www.cnblogs.com/amberbar/p/10308256.html

Spring boot中使用springfox来生成Swagger Specification小结

Rest接口对应Swagger Specification路径获取办法: 根据location的值获取api   json描述文件 也许有同学会问,为什么搞的这么麻烦,api json描述文件不就是http://domain:port/v2/api-docs获取的么. 因为如果使用group,api json描述文件就不是上面的情况哦 https://github.com/springfox/springfox-demos/tree/master/boot-swagger 再小结一下swagge

How to configure spring boot through annotations in order to have something similar to &lt;jsp-config&gt; in web.xml?

JSP file not rendering in Spring Boot web application You will need not one but two dependencies (jasper and jstl) in your pom.xml for this to work. <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifa

spring boot + swagger + mysql + maven

1.首先编写 yaml 文件,创建项目所需的接口,在swagger.io官网上生成 spring boot项目: 2.由于生成的spring boot项目是公共类的所以还需要修改成所需的项目名称,主要修改四个地方,分别是: 1) 包名: 2)Application  : 3)把 configuration/SwaggerDocumentationConfig.java中的包名修改为现在的包名 4) 修改pom.xml文件 其中Artifact和Project两项 spring boot + my

spring boot项目添加swagger 2.7.0(只需两步操作)

1.pom.xml引入swagger 2.7的jar包 <!-- swagger2 rest api start--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <dependenc

Spring boot整合Swagger

本文github位置:https://github.com/WillVi/springboot-swagger2-demo 环境准备 JDK版本:1.8 Spring boot版本:1.5.16 Swagger及其Swagger-ui版本:2.6.1(关于swagger-ui版本 每个版本的汉化方式可能有不同) 默认url:http://localhost:8080/swagger-ui.html Maven依赖 <!-- swagge2 --> <dependency> <

星舟平台的使用(GIT、spring Boot 的使用以及swagger组件的使用)

一.介绍星舟平台 ????1.星舟简介 ????2.网关kong的介绍 ????3.客户端 ????????1).服务注册:Eureka ????????2).客户端负载均衡:Ribbon ????4.服务器端 ????????1).服务注册:Marathon+Marathon-LB.HAProxy+Confd+Etcd ????????2).服务端负载均衡:HAProxy ????5.pinpoint调用链技术 ????????traceid 透明数据传输 ????6.服务调用可以使用ELK采

Spring Boot:整合Swagger在线文档

综合概述 spring-boot作为当前最为流行的Java web开发脚手架,越来越多的开发者选择用其来构建企业级的RESTFul API接口.这些接口不但会服务于传统的web端(b/s),也会服务于移动端.在实际开发过程中,这些接口还要提供给开发测试进行相关的白盒测试,那么势必存在如何在多人协作中共享和及时更新API开发接口文档的问题. 假如你已经对传统的wiki文档共享方式所带来的弊端深恶痛绝,那么尝试一下Swagger2 方式,一定会让你有不一样的开发体验. 使用 Swagger 集成文档