如今,公开的API终于获得了应有的关注,公司也开始意识到其战略价值。 但是,使用第三方API确实是一项繁琐的工作,尤其是当这些API维护不当,设计不当或缺少任何文档时。 这就是为什么我决定四处寻找可以为集成编程人员和其他团队成员提供适当文档的方法的原因。 一种方式是使用WADL,WADL是专门设计用于描述基于HTTP的Web应用程序(如REST Web服务)的标准。 但是,使用WADL时几乎没有什么缺点,这使我无法在其他地方寻找如何正确记录和公开API文档的解决方案。
昂首阔步
另一种方法可能是与Swagger一起使用。 Swagger是规范和框架实现,均支持RESTful Web服务开发的整个生命周期。 规范本身是与语言无关的,在异构环境中可能会派上用场。 Swagger还带有Swagger UI模块,该模块允许程序员和其他团队成员与API进行有意义的交互,并为他们提供了一种使用它的方式,同时提供了对文档的访问权限。
Spring with Jersey示例
不久前,我遇到了一篇描述Swagger规范的文章,我很感兴趣尝试一下。 那时,我正在开发一种不错的微服务,因此我有一个理想的测试场来进行尝试。 基于此,我准备了一个简短的示例,说明了在使用Spring框架和Jersey时如何在应用程序中使用Swagger。 示例代码模型简化了商店应用程序场景中可能的API子集的REST API。
注意:所有Java代码示例均省略了导入声明。
泽西小服务程序
在开始将Swagger引入我们的代码之前,让我们花点时间来探讨一下我们的示例。 首先,让我们看一下web.xml
。 下面的代码示例中有简单的旧web.xml
,几乎没有简单的声明和映射。 这里没什么特别的,只是一堆配置。
<web-app id="SpringWithSwagger" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Jersey Swagger Example</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.jakubstas.swagger.SpringWithSwagger</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
终点
我们需要的第二件事是定义我们的REST服务的端点-例如用于列出当前雇员的雇员端点。 再一次,没有什么特别的,只有少数提供核心API功能的公开方法。
package com.jakubstas.swagger.rest;
@Path("/employees")
public class EmployeeEndpoint {
private List<Employee> employees = new ArrayList<Employee>();
{
final Employee employee = new Employee();
employee.setEmployeeNumber(1);
employee.setFirstName("Jakub");
employee.setSurname("Stas");
employees.add(employee);
}
@OPTIONS
public Response getProductsOptions() {
final String header = HttpHeaders.ALLOW;
final String value = Joiner.on(", ").join(RequestMethod.GET, RequestMethod.OPTIONS).toString();
return Response.noContent().header(header, value).build();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getEmployees() {
return Response.ok(employees).build();
}
}
昂首阔步的依赖
我们要做的第一件事是在pom.xml
包含所有必需的Swagger依赖项,如下所示(幸运的是,这只是一个依赖项)。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
...
<properties>
...
<swagger-version>1.3.8</swagger-version>
...
</properties>
...
<dependencies>
...
<!-- Swagger -->
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey2-jaxrs_2.10</artifactId>
<version>${swagger-version}</version>
</dependency>
...
</dependencies>
</project>
昂首阔步的配置
现在,让我们看一下Swagger如何集成到我们的示例中。 与在项目中引入任何新依赖项一样,您应该关注此过程的侵入性和成本。 受影响的唯一地方将是您的REST端点,Spring配置和一些传输对象(假设您选择包括它们),如以下代码示例中所示。 这意味着Swagger不需要在web.xml
进行配置即可与您的Spring应用程序一起使用,这意味着它以这种方式是非侵入性的,并且仍受API领域的限制。
您需要Swagger才能使用三个基本属性:
- API版本
- 提供应用程序API的版本
- 基本路径
- 提供API的根URL
- 资源包
- 定义在哪里寻找Swagger注释的包
由于API维护主要由分析人员和程序员负责,因此我希望将此配置保存在名为swagger.properties
的单独属性文件中。 这样,它就不会与应用程序配置混合在一起,并且不太可能被意外修改。 以下片段描述了这样的配置文件。
swagger.apiVersion=1.0
swagger.basePath=http://[hostname/ip address]:[port]/SpringWithSwagger/rest
swagger.resourcePackage=com.jakubstas.swagger.rest
对于配置的第二部分,我利用前面提到的属性创建了一个配置bean。 使用Spring的@PostConstruct
批注提供bean生命周期挂钩,我们可以实例化和设置Swagger所需的某些属性,但不能获取(至少在当前版本中)。
package com.jakubstas.swagger.rest.config;
/**
* Configuration bean to set up Swagger.
*/
@Component
public class SwaggerConfiguration {
@Value("${swagger.resourcePackage}")
private String resourcePackage;
@Value("${swagger.basePath}")
private String basePath;
@Value("${swagger.apiVersion}")
private String apiVersion;
@PostConstruct
public void init() {
final ReflectiveJaxrsScanner scanner = new ReflectiveJaxrsScanner();
scanner.setResourcePackage(resourcePackage);
ScannerFactory.setScanner(scanner);
ClassReaders.setReader(new DefaultJaxrsApiReader());
final SwaggerConfig config = ConfigFactory.config();
config.setApiVersion(apiVersion);
config.setBasePath(basePath);
}
public String getResourcePackage() {
return resourcePackage;
}
public void setResourcePackage(String resourcePackage) {
this.resourcePackage = resourcePackage;
}
public String getBasePath() {
return basePath;
}
public void setBasePath(String basePath) {
this.basePath = basePath;
}
public String getApiVersion() {
return apiVersion;
}
public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}
}
最后一步是声明以下三个Swagger bean: ApiListingResourceJSON
, ApiDeclarationProvider
和ResourceListingProvider
。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.jakubstas.swagger" />
<context:property-placeholder location="classpath:swagger.properties" />
<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,您可以检查设置是否正常运行。 只需从basePath
变量中输入URL,然后在浏览器中输入/api-docs
并检查结果即可。 在我的示例中,您应该看到类似于访问http://[hostname]:[port]/SpringWithSwagger/rest/api-docs/
后收到的以下代码片段的输出。
{"apiVersion":"1.0","swaggerVersion":"1.2"}
下一步是什么?
如果执行了所有步骤,则现在应该可以使用API文档开始进行设置。 在我的下一篇名为Swagger的Spring Rest API –创建文档中,我将展示如何使用Swagger注释描述API。 该微型系列中使用的代码在GitHub上发布,并提供了所有讨论的功能和工具的示例。 请享受!