昂首阔步:让开发人员喜欢使用您的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::…

[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…

移动端日期选择插件rolldate

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

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

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

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;如果…

如何使用JSON和Servlet创建JQuery DataTable

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

页面重绘 回流及其优化

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

Servlet异常和错误处理示例教程

有时我写了一篇有关Java异常处理的文章&#xff0c;但是当涉及到Web应用程序时&#xff0c;我们需要的不仅仅是Java中的异常处理。 Servlet异常 如果您注意到&#xff0c;doGet&#xff08;&#xff09;和doPost&#xff08;&#xff09;方法将抛出ServletException和IOExcept…

python数据结构与算法13_python 数据结构与算法 (13)

python 数据结构与算法 (13)选择排序 (Selection sort) 是? 种简单直观的排序算法. 它的? 作原理如 下.? 先在未排序序列中找到最?(?)元素, 存放到排序序列的起始位 置, 然后, 再从剩余未排序元素中继续寻找最?(?)元素, 然后放到已排 序序列的末尾. 以此类推, 直到所有元…

小程序如何发红包

咳咳&#xff0c;直入主题。敲黑板&#xff0c;请看下面一段对话。 产品&#xff1a;我想要小程序发红包这个功能 程序员&#xff1a;目前不支持啊 产品&#xff1a;我不管&#xff01; 程序员&#xff1a;做不到啊&#xff0c;这。。。 产品&#xff1a;我不管&#xff01;我不…

如何实现REST资源的输入验证

如何实现REST资源的输入验证 我正在使用的SaaS平台具有一个RESTful接口&#xff0c;该接口可以接受XML有效负载。 实施REST资源 对于像我们这样的Java商店&#xff0c;使用JAX-B从XML Schema生成JavaBean类是有意义的。 在像Jersey的JAX-RS环境中&#xff0c;使用JAX-B处理X…

Linux系统下,MySQL以及禅道的安装/卸载

1、MySQL卸载&#xff1a; &#xff08;通过yum命令卸载之前安装的mysql&#xff0c; find命令找到mysql文件&#xff0c;再用rm –rf 强制删除/var/lib/mysql&#xff09; 2、MySQL安装&#xff1a; &#xff08;使用yum命令安装mysql&#xff0c;安装完成后启动数据库&#x…

winform 点击全选

代码如下&#xff1a; #region 全选//chkAll_Checked即全选控键的点击事件private void chkAll_CheckedChanged(object sender, EventArgs e){if (chkAll.Checked){chkSun.Checked true;chkMon.Checked true;chkThu.Checked true;chkTue.Checked true;chkWed.Checked true…

今天的考核题目: 你知道React和Vue的区别吗? skr,skr

React 和 Vue 的区别 博主面了几家公司&#xff0c;看简历上写着使用Vue.js框架&#xff0c;就会问&#xff0c;你能说一说 vue 和 react的区别吗 &#xff1f;react 听过&#xff0c;没用过&#xff0c;所以就只能尴尬的说不怎么了解react。这不&#xff0c;最近刚学了react …

Play和Grails Java框架的优缺点

框架通过为程序员提供一些有用的功能来简化应用程序开发过程。 由于开发人员的普遍使用&#xff0c;Java框架经常被开发人员使用。 您可以在市场上找到各种Java开发框架。 新手开发人员经常在论坛上发布一个常见问题&#xff1a;“哪种Java框架是最好的&#xff1f;” 首先&am…