原则上,WADL与WSDL类似,但是语言的结构有很大不同。 虽然WSDL定义了使用或产生其中一些消息和操作的平面列表,但WADL强调了RESTful Web服务的分层性质。 在REST中,主要工件是资源。 每个资源(名词)都表示为URI。 每个资源都可以定义CRUD操作(动词,作为HTTP方法实现)和嵌套资源。 嵌套资源与父资源有很强的关系,通常代表所有权。
一个简单的示例是表示书籍列表的http://example.com/api/books资源。 您可以(HTTP)获取此资源,这意味着检索整个列表。 您还可以获取http://example.com/api/books/7资源,以在books资源中获取第7本书的详细信息。 或者,您甚至可以使用相同的URI放置新版本或完全删除资源。 您不仅仅局限于一个嵌套级别:获取http://example.com/api/books/7/reviews?page=2&size=10将会检索第二本书(最多10本书)的第二页(最多10个条目)。 显然,您也可以在书籍旁边放置其他资源,例如http://example.com/api/readers
就像WSDL人员能够做到的那样,要求正式而精确地描述每个可用资源,方法,请求和响应。 WADL是描述“可用URI”的选项之一,尽管有些人认为编写良好的REST服务应该是自描述性的(请参阅HATEOAS )。 但是,这是一个简单的空WADL文档:
<application xmlns="http://wadl.dev.java.net/2009/02"><resources base="http://example.com/api"/>
</application>
这里没什么好看的。 请注意, <resources>标记定义了基本API地址。 我们将要添加的所有命名资源都相对于该地址。 您还可以定义几个<resources>标记来描述多个API。 因此,让我们添加一个简单的资源:
<application xmlns="http://wadl.dev.java.net/2009/02"><resources base="http://example.com/api"><resource path="books"><method name="GET"/><method name="POST"/></resource></resources>
</application>
这使用两种可能的方法在http://example.com/api/books下定义资源:GET用于检索整个列表,而POST用于创建(添加)新项目。 根据您的要求,您可能还希望允许DELETE方法(删除所有项目),并且WADL负责记录允许的内容。
还记得我们开头的示例: / books / 7吗? 显然7只是一个示例,我们不会在WADL中声明所有可能的书ID。 而是有一个方便的占位符语法:
<application xmlns="http://wadl.dev.java.net/2009/02"><resources base="http://example.com/api"><resource path="books"><method name="GET"/><resource path="{bookId}"><param required="true" style="template" name="bookId"/><method name="GET"/></resource></resource></resources>
</application>
您应注意两个重要方面:首先,使用{ bookId }占位符代替嵌套资源。 其次,为了清楚起见,我们正在使用< param />标记记录此占位符。 我们很快将看到如何将其与方法结合使用。 为了确保您仍然与我在一起,上面的文档介绍了GET / books和GET / books / some_id资源。
<application xmlns="http://wadl.dev.java.net/2009/02"><resources base="http://example.com/api"><resource path="books"><method name="GET"/><resource path="{bookId}"><param required="true" style="template" name="bookId"/><method name="GET"/><method name="DELETE"/><resource path="reviews"><method name="GET"><request><param name="page" required="false" default="1" style="query"/><param name="size" required="false" default="20" style="query"/></request></method></resource></resource></resource><resource path="readers"><method name="GET"/></resource></resources>
</application>
Web服务变得越来越复杂,但是它描述了很多操作。 首先, GET / books / 42 / reviews是有效的操作。 但是有趣的部分是嵌套的<request />标记。 如您所见,我们可以独立描述每种方法的参数。 在我们的案例中,定义了可选的查询参数(与之前用于URI占位符的模板参数相反)。 这为客户端提供了有关可接受的页面和大小查询参数的其他知识。 这意味着/ books / 7 / reviews?page = 2&size = 10是有效的资源标识符。 我是否提到过每个资源,方法和参数都可以按照WADL规范附加文档?
我们将在这里停止,仅提及WADL的其余部分。 首先,到目前为止,您可能已经猜到了,每个<method />都有一个<response />子标记。 请求和响应都可以定义请求或响应必须遵循的确切语法(例如,在XML Schema中)。 该响应还可以记录可能的HTTP响应代码。 但是,由于我们将使用到目前为止在代码优先应用程序中获得的知识,因此我特意留下了<grammars />定义。 WADL是敏捷的,它使您可以定义所需的尽可能少的信息。
因此,我们知道了WADL的基础知识,现在我们想使用它,可以作为基于Java的应用程序的使用者或生产者。 幸运的是,该语言本身有一个wadl.xsd XML Schema描述,我们可以使用它来生成可使用JAXB注释的POJO(使用JDK中的xjc工具):
$ wget http://www.w3.org/Submission/wadl/wadl.xsd
$ xjc wadl.xsd
在那里...挂了! 软件开发人员的生活充满挑战和非凡的问题。 有时,这只是一个令人讨厌的网络过滤器,可疑数据包(连同您半个小时的生命)消失了。 一旦您回想起2008年左右写的文章: W3C的DTD流量过大 ,就不难发现问题了:
<xs:import namespace="http://www.w3.org/XML/1998/namespace"schemaLocation="http://www.w3.org/2001/xml.xsd"/>
从浏览器访问xml.xsd会立即返回HTML页面,但是xjc工具将永远等待。 在本地下载此文件并更正wadl.xsd中的schemaLocation属性有助于。 总是小事……
$ xjc wadl.xsd
parsing a schema...
compiling a schema...
net/java/dev/wadl/_2009/_02/Application.java
net/java/dev/wadl/_2009/_02/Doc.java
net/java/dev/wadl/_2009/_02/Grammars.java
net/java/dev/wadl/_2009/_02/HTTPMethods.java
net/java/dev/wadl/_2009/_02/Include.java
net/java/dev/wadl/_2009/_02/Link.java
net/java/dev/wadl/_2009/_02/Method.java
net/java/dev/wadl/_2009/_02/ObjectFactory.java
net/java/dev/wadl/_2009/_02/Option.java
net/java/dev/wadl/_2009/_02/Param.java
net/java/dev/wadl/_2009/_02/ParamStyle.java
net/java/dev/wadl/_2009/_02/Representation.java
net/java/dev/wadl/_2009/_02/Request.java
net/java/dev/wadl/_2009/_02/Resource.java
net/java/dev/wadl/_2009/_02/ResourceType.java
net/java/dev/wadl/_2009/_02/Resources.java
net/java/dev/wadl/_2009/_02/Response.java
net/java/dev/wadl/_2009/_02/package-info.java
由于我们将在基于Maven的项目中使用这些类(并且我讨厌将生成的类提交到源存储库),因此让我们将xjc执行移至maven生命周期:
<plugin><groupId>org.codehaus.mojo</groupId><artifactId>jaxb2-maven-plugin</artifactId><version>1.3</version><dependencies><dependency><groupId>net.java.dev.jaxb2-commons</groupId><artifactId>jaxb-fluent-api</artifactId><version>2.0.1</version><exclusions><exclusion><groupId>com.sun.xml</groupId><artifactId>jaxb-xjc</artifactId></exclusion></exclusions></dependency></dependencies><executions><execution><goals><goal>xjc</goal></goals></execution></executions><configuration><arguments>-Xfluent-api</arguments><bindingFiles>bindings.xjb</bindingFiles><packageName>net.java.dev.wadl</packageName></configuration>
</plugin>
嗯, pom.xml并不是有史以来最简洁的格式……没关系,在每次编译之前,这都会在编译源代码之前生成WADL XML类。 我还喜欢通顺-API插件, 与*()与普通制定者一起的方法增加了 , 这回允许链接。 很方便 最后,我们为生成的工件定义更合适的包名称(如果您发现net.java.dev.wadl._2009._02足够好的包名称,则可以跳过此步骤),并将Wadl前缀添加到所有生成的类bindings.xjb文件中:
<jxb:bindings version="1.0"xmlns:jxb="http://java.sun.com/xml/ns/jaxb"xmlns:xs="http://www.w3.org/2001/XMLSchema"xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"jxb:extensionBindingPrefixes="xjc"><jxb:bindings schemaLocation="../xsd/wadl.xsd" node="/xs:schema"><jxb:schemaBindings><jxb:nameXmlTransform><jxb:typeName prefix="Wadl"/><jxb:anonymousTypeName prefix="Wadl"/><jxb:elementName prefix="Wadl"/></jxb:nameXmlTransform></jxb:schemaBindings></jxb:bindings></jxb:bindings>
现在,我们准备使用JAXB和POJO类以XML格式生成和使用WADL。 有了这些知识和基础,我们就可以开发一些有趣的库了,这将是下一篇文章的主题。
参考: Java和社区博客上我们的JCG合作伙伴 Tomasz Nurkiewicz 对WADL(Java)的简要介绍。
翻译自: https://www.javacodegeeks.com/2012/01/wadl-in-java-gentle-introduction.html