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/

Configure swagger with spring boot的更多相关文章

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

    如果项目上使用了Swagger做RESTful的文档,那么也可以通过Swagger提供的代码生成器生成客户端代码,同时支持Feign客户端. 但是经过测试,生成Feign代码和REST客户端有些臃肿. ...

  2. Swagger Learing - Spring Boot 整合swagger

    学习了一下swagger. 这是编写的Demo 源码 https://github.com/AmberBar/Learning/tree/master/swagger-learning/swagger ...

  3. Spring Boot初识(3)- Spring Boot整合Swagger

    一.本文介绍 如果Web项目是完全前后端分离的话(我认为现在完全前后端分离已经是趋势了)一般前端和后端交互都是通过接口的,对接口入参和出参描述的文档就是Mock文档.随着接口数量的增多和参数的个数增加 ...

  4. Spring Boot 2.x基础教程:Swagger接口分类与各元素排序问题详解

    之前通过Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档一文,我们学习了如何使用Swagger为Spring Boot项目自动生成API文档,有不少用户留言问了关于文档 ...

  5. Spring Boot 集成 Swagger 生成 RESTful API 文档

    原文链接: Spring Boot 集成 Swagger 生成 RESTful API 文档 简介 Swagger 官网是这么描述它的:The Best APIs are Built with Swa ...

  6. Spring Boot实战:集成Swagger2

    一.Swagger简介 上一篇文章中我们介绍了Spring Boot对Restful的支持,这篇文章我们继续讨论这个话题,不过,我们这里不再讨论Restful API如何实现,而是讨论Restful ...

  7. Developing JSF applications with Spring Boot

    Developing JSF applications with Spring Boot Spring Boot can leverage any type of applications, not ...

  8. Spring Boot文档维护:集成Swagger2

    一.Swagger简介 在日常的工作中,我们往往需要给前端(WEB端.IOS.Android)或者第三方提供接口,这个时我们就需要提供一份详细的API说明文档.但维护一份详细的文档可不是一件简单的事情 ...

  9. Spring Boot 入门系列(二十二)使用Swagger2构建 RESTful API文档

    前面介绍了如何Spring Boot 快速打造Restful API 接口,也介绍了如何优雅的实现 Api 版本控制,不清楚的可以看我之前的文章:https://www.cnblogs.com/zha ...

随机推荐

  1. [疑惑与解答] WxPython In Action -1

    在学<活学活用wxPython>第三章的时候,我遇到一点疑惑,那就是下面语句的区别是什么 例 3.1 第4,5行: panel = wx.Panel(self, -1) button = ...

  2. hdu 3642 Get The Treasury(扫描线)

    pid=3642" style="">题目链接:hdu 3642 Get The Treasury 题目大意:三维坐标系,给定若干的长方体,问说有多少位置被覆盖3次 ...

  3. [ES6] Array.findIndex()

    In es5, you can use indexOf to get the index of one item in an array. In es6, you can use findIndex( ...

  4. React Native 从入门到原理

    React Native 是最近非常火的一个话题,介绍如何利用 React Native 进行开发的文章和书籍多如牛毛,但面向入门水平并介绍它工作原理的文章却寥寥无几. 本文分为两个部分:上半部分用通 ...

  5. iOS---多线程实现方案一 (pthread、NSThread)

    在iOS开发中,多线程是我们在开发中经常使用的一门技术.那么本文章将和大家探讨一下针对于多线程的技术实现.本文主要分为如下几个部分: iOS开发中实现多线程的方式 单线程 pthread NSThre ...

  6. Android 系统移植与驱动开发--第二章搭建Android环境核心步骤及心得

    第二章 搭建Android 开发环境 虽然在这一章中讲的是Android底层开发环境,但是相应伴随的还有Android NDK程序来测试Linux驱动,HAL程序库.底层开发不仅需要交叉编译环境,还要 ...

  7. 模板-->Matrix重载运算符:+,-,x

    如果有相应的OJ题目,欢迎同学们提供相应的链接 相关链接 所有模板的快速链接 poj_2118_Firepersons,my_ac_code 简单的测试 INPUT: 1 2 3 1 3 4 3 -1 ...

  8. .net之页面生面周期

    # 事件或方法 功能 描述 1 Init 事件 页面初始化 页面生存周期中的第一个阶段是初始化.当 Init 事件发生时,在.aspx 源文件中静态声明的所有控件都已实例化并取其默认值.应该注意的是, ...

  9. 9.5noip模拟试题

    题目名称 正确答案 序列问题 长途旅行 英文名称 answer sequence travel 输入文件名 answer.in sequence.in travel.in 输出文件名 answer.o ...

  10. codevs 2612 最有分解方案 (贪心)

    /* 数字不重复 将一个正整数分解成若干的整数的和 数字不重复 且数字不相同 保证不重复的话 贪心策略是从2开始分 然后把最后剩下的数均匀分到后面 证明嘛 这里写的可能不是很严谨 对于一个n 如果我们 ...