昂首阔步:让开发人员喜欢使用您的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 CREATED409 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提供程序( resourceListingProviderapiDeclarationProvider )即可。

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_PORTSERVER_HOSTCONTEXT_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上获得 。

参考: Swagger:让开发人员喜欢在我们的JCG合作伙伴 Andrey Redko {devmind}博客上使用您的REST API 。

翻译自: https://www.javacodegeeks.com/2013/10/swagger-make-developers-love-working-with-your-rest-api.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

thinkphp mysql 更新_THINKPHP5修改数据库数据出现“缺少更新条件”的错误

查询数据库的数据分配显示在页面山修改后的数据准备传递到第三章图里接收数据&#xff0c;然后修改到数据问题出现的环境背景及自己尝试过哪些方法相关代码// 请把代码文本粘贴到下方(请勿用图片代替代码)第一张图代码public function edit(){$db_01new DB();$id_editRequest::…

angular ajax get post 参数,Angular的Post 传递参数问题及解决方法

一、传递参数过程中POST会出问题&#xff0c;问题来源&#xff1a;我们都知道向后台传参可以使用get、post&#xff0c;其形式类似于nameiyy&id001 。但是在angular中却发现使用$http post 进行异步传输的过程中后台是接收不到数据的&#xff0c;其实这个问题就是因为请求头…

[No0000187]可能是把Java内存区域讲的最清楚的一篇文章

写在前面&#xff08;常见面试题&#xff09; 基本问题&#xff1a; 介绍下 Java 内存区域&#xff08;运行时数据区&#xff09;Java 对象的创建过程&#xff08;五步&#xff0c;建议能默写出来并且要知道每一步虚拟机做了什么&#xff09;对象的访问定位的两种方式&#xff…

Java语言基础及java核心

一、Java语言特点 1、 简单 2、 面向对象 3、 分布式 4、 健壮 5、 安全 6、 中性架构跨平台 7、 超强的可移植性 8、 高性能 9、 多线程 二、java的环境变量 JAVA_HOMEC:\Program Files\Java\jdk1.8.0_101 &#xff08;到你的安装目录下&#xff09; CLASSPASH./ &#xff0…

如何使用Quartz Scheduler和日志记录创建Web应用程序

我有时会在Quartz Scheduler论坛中为用户提供帮助。 有时&#xff0c;有人会问他/她如何在Web应用程序中设置Quartz。 实际上&#xff0c;这是一件相当简单的事情。 该库已经带有一个ServletContextListener &#xff0c;您可以使用它启动调度程序。 我将在这里向您展示一个简单…

移动端日期选择插件rolldate

rolldate为上一版jquery移动端时间插件的全新版本&#xff0c;目前保留了上一版的大部分功能&#xff0c;并且增加了回调函数&#xff0c;以及主题风格选取&#xff0c;最重要的是解决了上一版本的遗留问题&#xff0c;依赖jquery、滑动不够流畅、参数设计不够合理等等。开发日…

ik分词器 mysql php_php环境下使用elasticSearch+ik分词器进行全文搜索

首先需要说明的一点是&#xff0c;如果需要启用ik分词器&#xff0c;那么分词器的版本必须与es版本一致&#xff0c;即6.3.0的分词器需要同样6.3.0版本的es支持。安装javawin-64bit的安装包需要去java英文官网查找安装ES6.3.0版本es下载地址&#xff1a;https://www.elastic.co…

服务器如何查看gpu型号,linux 查看服务器gpu

linux 查看服务器gpu 内容精选换一换本节操作介绍通过华为云APP连接Linux实例的操作步骤。云服务器状态为“运行中”。已获取Linux云服务器用户名和密码&#xff0c;忘记密码请参考在控制台重置云耀云服务器密码重置密码。云耀云服务器已经绑定弹性公网IP。所在安全组入方向已开…

Antd-Select组件的深入用法

一、Antd-Select提供几种类型 最基础版只提供下拉功能的选择器带搜索功能的下拉选择器可多选的下拉选择器可搜索、可多选、可随意输入内容的tag下拉选择器(支持自动分词)多级联动下拉选择器搜索远程数据下拉框二、一些潜在用法 如果Select.Option选项的数量特别大:2k、3k... 假…

WS-Security:使用BinarySecurityToken进行身份验证

众所周知&#xff0c;WS-Security设定的目标之一是对SOAP消息强制执行完整性和/或保密。 在完整性的情况下&#xff0c;添加到SOAP消息的签名是数学过程的结果&#xff0c;该过程涉及发送者的私钥&#xff0c;从而导致加密的消息摘要。 默认情况下&#xff0c;大多数框架&…

Vue(ES6)中的data属性为什么不能是一个对象?

以下引官网原文&#xff1a;当一个组件被定义&#xff0c;data 必须声明为返回一个初始数据对象的函数&#xff0c;因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象&#xff0c;则所有的实例将共享引用同一个数据对象&#xff01;通过提供 data 函数&#xff…

echarts vue 柱状图实例_VUE中使用Echarts绘制柱状图

在main.js中引入echartsimport echarts from ‘echarts‘Vue.prototype.$echarts echarts在相应的vue中导入echartsimport echarts from ‘echarts‘;实现柱状图显示mounted: function () {// 基于准备好的dom&#xff0c;初始化echarts实例let myChart echarts.init(documen…

从计算机体系结构方面思考深度学习

今年 1 月&#xff0c;谷歌人工智能负责人 Jeff Dean&#xff08;当时还是谷歌大脑负责人&#xff09;与 2017 年图灵奖得主、体系结构巨擘 David Patterson&#xff08;当时获奖结果尚未公布&#xff09;联合发表了题为《计算机体系结构黄金时代&#xff1a;赋能机器学习革命》…

使用Apollo通过WebSocket通过STOMP轻松进行消息传递

在我以前的文章中&#xff0c;我介绍了几个有趣的用例&#xff0c;这些用例使用著名的消息代理HornetQ和ActiveMQ通过Websockects实现STOMP消息传递。 但是我没有介绍的是Apollo&#xff0c;因为我个人认为它的API是冗长的&#xff0c;并且不像Java开发人员那样表现力强。 尽管…

h5渲染性能一瞥

内容来源&#xff1a;2018 年 6 月 30 日&#xff0c;饿了么前端主管向勇在“饿了么技术沙龙・第27弹 【前端专场】”进行《h5渲染性能一瞥》演讲分享。IT 大咖说&#xff08;微信id&#xff1a;itdakashuo&#xff09;作为独家视频合作方&#xff0c;经主办方和讲者审阅授权发…

爬虫系列之requests

爬取百度内容&#xff1a; 1 import requests2 url "https://www.baidu.com"3 4 if __name__ __main__:5 try:6 kv {user-agent: Mozilla/5.0}7 r requests.get(url, headerskv)8 r.raise_for_status() #返回状态值&#xff0c;如果…

高并发常见面试题

1、线程与进程 进程是一个实体。每一个进程都有它自己的地址空间&#xff0c;一般情况下&#xff0c;包括文本区域&#xff08;text region&#xff09;、数据区域&#xff08;data region&#xff09;和堆栈&#xff08;stack region&#xff09;。文本区域存储处理器执行的代…

如何使用JSON和Servlet创建JQuery DataTable

在本文中&#xff0c;我将介绍使用简单servlet传递的JSON创建JQuery DataTable所需的基本编码。 DataTable是基于JQuery的非常强大的网格&#xff0c;具有高级功能&#xff0c;可以使用自定义功能在短时间内构建。 安装 下载最新的JQuery DataTable下载 上面的下载将提供两个…

python将json转换为excel_使用python将Excel转换为JSON_python_酷徒编程知识库

我有一个excel文件&#xff0c;我想转换为JSON文件&#xff0c;excel类似于&#xff1a;Col A Col C Col F1 A EE2 B FF4 C FF5 D HH6 D HH7 A EE8 E EE希望JSON遵循以下格式&#xff1a;{"EE": {"A": {"Col A key":"1","Col A k…

页面重绘 回流及其优化

在讨论页面重绘、回流之前。需要对页面的呈现流程有些了解&#xff0c;页面是怎么把html结合css等显示到浏览器上的&#xff0c; 下面的流程图显示了浏览器对页面的呈现的处理流程。可能不同的浏览器略微会有些不同。但基本上都是类似的。 1. 浏览器把获取到的HTML代码解析成1…