JSR 311的許多實現:JAX-RS:RESTful Web服務的Java API提供了開箱即用的運行時WADL生成: Apache CXF , Jersey和Restlet 。 RESTeasy還在等待。 基本上,這些框架檢查帶有JSR-311批注的Java代碼,并在某些URL下生成WADL文檔。 不幸的是,Spring MVC不僅不實現JSR-311標準(請參閱: Spring MVC是否支持JSR 311注釋? ),而且即使它非常適合于我們,也不會為我們生成WADL(請參閱: SPR-8705 )。公開REST服務。
由于種種原因,我開始使用Spring MVC開發服務器端REST服務,過了一會兒(比如說,后來的第三方資源),我開始迷路了。 我確實需要一種對所有可用資源和操作進行分類和記錄的方法。 WADL似乎是一個不錯的選擇。
幸運的是,Spring框架已開放擴展,如果您愿意在一段時間內瀏覽代碼,可以輕松地基于現有基礎結構添加新功能。 為了生成WADL,我需要一個應用程序處理的URI列表,實現的HTTP方法以及(理想情況下)哪種Java方法處理每個方法。 為@Controller,@RequestMapping,@PathVariable等掃描- -顯然Spring啟動捆扎MVC 的DispatcherServlet在做這項工作已經某處這樣看來聰明重用這些信息而不是再次執行任務。
猜猜看,看起來我們需要的所有信息都保存在一個奇怪的RequestMappingHandlerMapping類中。 這是一個調試器屏幕截圖,僅用于概述如何提供豐富的信息:

但是它變得更好:RequestMappingHandlerMapping實際上是一個Spring Bean,您可以輕松地注入和使用它:
@Controller
class WadlController @Autowired()(mapping: RequestMappingHandlerMapping) {@RequestMapping(method = Array(GET))@ResponseBody def generate(request: HttpServletRequest) = new WadlApplication()}
沒錯,我們將使用另一個Spring MVC控制器來生成WADL文檔。 上一次我們設法生成表示WADL文檔的JAXB類(畢竟WADL是一個XML文件),因此通過返回空的WadlApplication實例,我們實際上返回的是空的但有效的WADL:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02"/>
我不會解釋實現的細節(提供完整的源代碼 ,包括示例應用程序)。 基本上,這是將Spring模型重寫為WADL類的問題。 如果您有興趣,請查看WadlGenerator.scala,它是解決方案和測試用例的中心點。 這是其中之一:
test("should add parameter info for template parameter in URL") {given("")val mapping = Map(mappingInfo("/books", GET) -> handlerMethod("listBooks"),mappingInfo("/books/{bookId}", GET) -> handlerMethod("readBook"))when("")val wadl = generate(mapping)then("")assertXMLEqual(wadlHeader + """<resource path="books"><method name="GET"><doc title="com.blogspot.nurkiewicz.springwadl.TestController.listBooks"/></method><resource path="{bookId}"><param name="bookId" required="true" /><method name="GET"><doc title="com.blogspot.nurkiewicz.springwadl.TestController.readBook"/></method></resource></resource>""" + wadlFooter, wadl)
}
不幸的是,我懶得不能正確地給定名稱/何時/然后命名。 但是測試應該可讀性強。
我要提及的唯一技術難題是將Spring基礎結構提供的平面URI模式轉換為分層的WADL對象(基本上是樹)。 這是此問題的簡化版本:具有URI模式的列表,如下所示:
/books
/books/{bookId}
/books/{bookId}/reviews
/books/best-sellers
/readers
/readers/{readerId}
/readers/{readerId}/account/new-password
/readers/active
/readers/passive
生成以下樹數據結構:

當然,數據結構就像持有標簽和Node子列表的Node對象一樣簡單。 并不是那么有挑戰性,但是可能是一個有趣的CodeKata 。
那么,這個WADL有什么意義呢? XML是否真的更具可讀性,并有助于管理大量REST應用程序? 如果沒有對WADL的 soapUI強大的支持,我什至不會打擾它。 為我推送的示例應用程序生成的WADL也可以輕松導入到soapUI:

值得一提的兩個功能。 首先,soapUI顯示一棵 REST資源樹 (與導入WSDL時的平面操作列表相反)。 每個HTTP方法旁邊都有一個相應的Java方法(可以禁用此方法)來處理它,以進行故障排除和調試。 其次,我們可以選擇任何HTTP方法/資源并調用它。 基于WADL的描述,soapUI將創建一個用戶友好的向導,可以在其中輸入參數。 默認值將自動填充。 完成后,應用程序將生成帶有正確URL和內容的HTTP請求,并在到達時顯示響應。 真的很有幫助!
順便說一句,您是否注意到max和page查詢參數? 我們的小型圖書館使用反射來查找@RequestParam批注,例如以下控制器:
@Controller
@RequestMapping(value = Array("/book/{bookId}/review"))
class ReviewController @Autowired()(reviewService: ReviewService) {@RequestMapping(method = Array(GET))@ResponseBody def listReviews(@RequestParam(value = "page", required = false, defaultValue = "1") page: Int,@RequestParam(value = "max", required = false, defaultValue = "20") max: Int) =new ResultPage(reviewService.listReviews(new PageRequest(page - 1, max)))//...}
將被翻譯成與WADL兼容的描述:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02"><doc title="Spring MVC REST appllication"/><resources base="http://localhost:8080/api"><resource path="book"><!-- --><resource path="{bookId}"><param required="true" style="template" name="bookId"/><!-- --><resource path="review"><method name="GET"><doc title="com.blogspot.nurkiewicz.web.ReviewController.listReviews"/><request><param required="false" default="1" style="query" name="page"/><param required="false" default="20" style="query" name="max"/></request></resource></resource></resource></resource
</application>
希望您對我編寫的這個小型圖書館感到開心。 隨時將其包含在您的項目中,不要猶豫,報告錯誤。 GitHub上提供了Apache許可下的完整源代碼: https : //github.com/nurkiewicz/spring-rest-wadl。
參考: JCG合作伙伴 在Spring MVC REST應用程序中自動生成WADL ? Java和社區博客中的Tomasz Nurkiewicz。
翻譯自: https://www.javacodegeeks.com/2012/02/automatically-generating-wadl-in-spring.html