昂首阔步:让开发人员喜欢使用您的REST API
隨著JAX-RS API的發展,以及今年早些時候在JSR-339下發布的2.0版本,使用出色的Java平臺創建REST服務變得更加容易。
但是,極大的簡化帶來了巨大的責任:記錄所有這些API,以便其他開發人員可以快速了解如何使用它們。 不幸的是,在這方面開發人員只能靠自己: JSR-339并沒有太大幫助。 可以肯定的是,從源代碼生成冗長且易于遵循的文檔,而不是要求某人在開發過程中編寫它,真是太棒了。 聽起來不真實,對吧? 在某種程度上確實如此,但是幫助以Swagger的形式出現。
本質上, Swagger做的是一件簡單但非常強大的事情:通過添加一些附加注釋,它會生成REST API描述( HTTP方法,路徑/查詢/表單參數,響應, HTTP錯誤代碼等),甚至提供了一個簡單的Web UI來玩對您的API的REST調用(更不用說所有這些元數據也可以通過REST獲得)。
在深入研究實現細節之前,讓我們快速看一下Swagger來自API消費者預期的含義。 假設您已經開發了一種出色的REST服務來管理人員。 作為良好的公民,此REST服務具有完整的功能,并提供以下功能:
- 列出所有人( GET )
- 通過電子郵件查找人( GET )
- 添加新人( POST )
- 更新現有人員( PUT )
- 最后刪除人( DELETE )
從Swagger的角度來看,這是相同的API:
看起來很漂亮。 讓我們做更多的事情,并從Swagger UI調用我們的REST服務,這真棒。 最復雜的用例是添加新人( POST ),因此將仔細研究這一情況。
如您在上面的快照中所見,每一個REST服務調用都存在:
- 服務說明
- 相對語境路徑
- 參數(形式/路徑/查詢),必需或可選
- HTTP狀態碼: 201 CREATED和409 CONFLICT
- 準備出發嘗試一下! 立即調用REST服務(具有開箱即用的參數驗證功能)
為了完成演示部分,讓我展示另一個示例,其中涉及REST資源(在我們的例子中,這是一個簡單的Person類)。 Swagger能夠提供其屬性和有意義的描述以及預期的響應內容類型。
看起來不錯! 轉到下一部分,所有內容都與實現細節有關。 Swagger支持與JAX-RS服務的無縫集成,在現有注釋的頂部僅需幾個附加注釋。 首先,在我們的示例中,應該記錄的每個單個JAX-RS服務都應使用@Api注釋進行注釋:
@Path( "/people" ) @Api( value = "/people", description = "Manage people" ) public class PeopleRestService {// ... }接下來,相同的方法適用于REST服務操作:應該記錄的每個方法都應使用@ApiOperation批注(可選)并使用@ ApiResponses / @ ApiResponse進行批注 。 如果它接受參數,則應使用@ApiParam批注進行批注。 這里有幾個例子:
@Produces( { MediaType.APPLICATION_JSON } ) @GET @ApiOperation( value = "List all people", notes = "List all people using paging", response = Person.class, responseContainer = "List" ) public Collection< Person > getPeople( @ApiParam( value = "Page to fetch", required = true ) @QueryParam( "page") @DefaultValue( "1" ) final int page ) {// ... }還有一個:
@Produces( { MediaType.APPLICATION_JSON } ) @Path( "/{email}" ) @GET @ApiOperation( value = "Find person by e-mail", notes = "Find person by e-mail", response = Person.class ) @ApiResponses( {@ApiResponse( code = 404, message = "Person with such e-mail doesn't exists" ) } ) public Person getPeople( @ApiParam( value = "E-Mail address to lookup for", required = true ) @PathParam( "email" ) final String email ) {// ... }REST資源類(或模型類)需要特殊的注釋: @ApiModel和@ApiModelProperty 。 這是我們的Person類的樣子:
@ApiModel( value = "Person", description = "Person resource representation" ) public class Person {@ApiModelProperty( value = "Person's first name", required = true ) private String email;@ApiModelProperty( value = "Person's e-mail address", required = true ) private String firstName;@ApiModelProperty( value = "Person's last name", required = true ) private String lastName;// ... }最后一步是將Swagger插入JAX-RS應用程序。 我開發的示例使用Spring Framework , Apache CXF , Swagger UI和嵌入式Jetty (完整項目可在Github上找到 )。 集成Swagger只需添加配置bean( swaggerConfig ),一個附加的JAX-RS服務( apiListingResourceJson )和兩個JAX-RS提供程序( resourceListingProvider和apiDeclarationProvider )即可。
package com.example.config;import java.util.Arrays;import javax.ws.rs.ext.RuntimeDelegate;import org.apache.cxf.bus.spring.SpringBus; import org.apache.cxf.endpoint.Server; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.core.env.Environment;import com.example.resource.Person; import com.example.rs.JaxRsApiApplication; import com.example.rs.PeopleRestService; import com.example.services.PeopleService; import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import com.wordnik.swagger.jaxrs.config.BeanConfig; import com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider; import com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON; import com.wordnik.swagger.jaxrs.listing.ResourceListingProvider;@Configuration public class AppConfig {public static final String SERVER_PORT = "server.port";public static final String SERVER_HOST = "server.host";public static final String CONTEXT_PATH = "context.path"; @Bean( destroyMethod = "shutdown" )public SpringBus cxf() {return new SpringBus();}@Bean @DependsOn( "cxf" )public Server jaxRsServer() {JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint( jaxRsApiApplication(), JAXRSServerFactoryBean.class );factory.setServiceBeans( Arrays.< Object >asList( peopleRestService(), apiListingResourceJson() ) );factory.setAddress( factory.getAddress() );factory.setProviders( Arrays.< Object >asList( jsonProvider(), resourceListingProvider(), apiDeclarationProvider() ) );return factory.create();}@Bean @Autowiredpublic BeanConfig swaggerConfig( Environment environment ) {final BeanConfig config = new BeanConfig();config.setVersion( "1.0.0" );config.setScan( true );config.setResourcePackage( Person.class.getPackage().getName() );config.setBasePath( String.format( "http://%s:%s/%s%s",environment.getProperty( SERVER_HOST ),environment.getProperty( SERVER_PORT ),environment.getProperty( CONTEXT_PATH ),jaxRsServer().getEndpoint().getEndpointInfo().getAddress() ) );return config;}@Beanpublic ApiDeclarationProvider apiDeclarationProvider() {return new ApiDeclarationProvider();}@Beanpublic ApiListingResourceJSON apiListingResourceJson() {return new ApiListingResourceJSON();}@Beanpublic ResourceListingProvider resourceListingProvider() {return new ResourceListingProvider();}@Bean public JaxRsApiApplication jaxRsApiApplication() {return new JaxRsApiApplication();}@Bean public PeopleRestService peopleRestService() {return new PeopleRestService();}// ... }為了擺脫任何可能的硬編碼配置,所有參數都通過命名屬性( SERVER_PORT , SERVER_HOST和CONTEXT_PATH )傳遞。 Swagger公開了其他REST端點來提供API文檔,在我們的示例中,可以通過以下網址訪問它: http:// localhost:8080 / rest / api / api-docs 。 Swagger UI使用它,它本身已嵌入最終的JAR存檔中,并由Jetty用作靜態Web資源。
最后一個難題是啟動嵌入式Jetty容器,該容器將所有這些部件粘合在一起并封裝到Starter類中:
package com.example;import org.apache.cxf.transport.servlet.CXFServlet; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.resource.Resource; import org.springframework.core.io.ClassPathResource; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;import com.example.config.AppConfig;public class Starter {private static final int SERVER_PORT = 8080;private static final String CONTEXT_PATH = "rest";public static void main( final String[] args ) throws Exception {Resource.setDefaultUseCaches( false );final Server server = new Server( SERVER_PORT ); System.setProperty( AppConfig.SERVER_PORT, Integer.toString( SERVER_PORT ) );System.setProperty( AppConfig.SERVER_HOST, "localhost" );System.setProperty( AppConfig.CONTEXT_PATH, CONTEXT_PATH ); // Configuring Apache CXF servlet and Spring listener final ServletHolder servletHolder = new ServletHolder( new CXFServlet() ); final ServletContextHandler context = new ServletContextHandler(); context.setContextPath( "/" );context.addServlet( servletHolder, "/" + CONTEXT_PATH + "/*" ); context.addEventListener( new ContextLoaderListener() ); context.setInitParameter( "contextClass", AnnotationConfigWebApplicationContext.class.getName() );context.setInitParameter( "contextConfigLocation", AppConfig.class.getName() );// Configuring Swagger as static web resourcefinal ServletHolder swaggerHolder = new ServletHolder( new DefaultServlet() );final ServletContextHandler swagger = new ServletContextHandler();swagger.setContextPath( "/swagger" );swagger.addServlet( swaggerHolder, "/*" );swagger.setResourceBase( new ClassPathResource( "/webapp" ).getURI().toString() );final HandlerList handlers = new HandlerList();handlers.addHandler( context );handlers.addHandler( swagger );server.setHandler( handlers );server.start();server.join(); } }幾點評論使事情變得更加清晰:我們的JAX-RS服務將在/ rest / *上下文路徑下可用,而Swagger UI在/ swagger上下文路徑下可用。 關于Resource.setDefaultUseCaches(false)的一個重要說明:因為我們正在從JAR文件提供靜態Web內容,所以必須將此屬性設置為false作為此bug的解決方法。
現在,讓我們通過輸入以下內容來構建并運行我們的JAX-RS應用程序:
mvn clean package java -jar target/jax-rs-2.0-swagger-0.0.1-SNAPSHOT.jar稍后,您的瀏覽器中將提供Swagger UI , 網址為: http:// localhost:8080 / swagger /
最后一點,關于Swagger還有很多話要說,但是我希望這個簡單的示例能夠顯示出使我們的REST服務具有自文檔化的功能,并且只需很少的工作即可輕松使用。 非常感謝Wordnik團隊。
- 源代碼可在Github上獲得 。
翻譯自: https://www.javacodegeeks.com/2013/10/swagger-make-developers-love-working-with-your-rest-api.html
總結
以上是生活随笔為你收集整理的昂首阔步:让开发人员喜欢使用您的REST API的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 内部最低 1 折清库存,古尔曼称苹果 A
- 下一篇: 手机发热是怎么回事
