現在的Web,孤立的應用已經再也不吃香,隨之而來的是與其餘應用(如Twitter)或服務(如S3)交互的意願愈來愈強烈。對於Groovy而言,HTTPBuilder絕對是應對這一需求的不二之選。html
若是熟悉HttpClient,那麼你對HTTPBuilder就不會感到陌生,它是對前者的封裝,使之更符合Groovy的使用慣例。下面的例子摘自HTTPBuilder的文檔,它充分展現了本身的特色:java
import groovyx.net.http.HTTPBuilder import static groovyx.net.http.Method.GET import static groovyx.net.http.ContentType.TEXT def http = new HTTPBuilder( 'http://www.google.com/search' ) http.request(GET,TEXT) { req -> uri.path = '/mail/help/tasks/' headers.'User-Agent' = 'Mozilla/5.0' //請求成功 response.success = { resp, reader -> assert resp.statusLine.statusCode == 200 println "My response handler got response: ${resp.statusLine}" println "Response length: ${resp.headers.'Content-Length'}" System.out << reader // print response stream } //404 response.'404' = { resp -> println 'Not found' } // 401 http.handler.'401' = { resp -> println "Access denied" } //其餘錯誤,不實現則採用缺省的:拋出異常。 http.handler.failure = { resp -> println "Unexpected failure: ${resp.statusLine}" } }
無需過多的講解,上述的例子已經很是明白地說明了HTTPBuilder的基本使用。儘管如此,對於上例中的內容類型(即request括號中的TEXT),仍是有必要囉嗦幾句。HTTPBuilder支持對響應內容的自動解析,解析的方式可在請求中指定,缺省除了TEXT以外,還支持XML、HTML和JSON。若是在請求中不指定解析方式,那麼它會根據響應的內容類型選擇最合適的方式進行解析。對於每一種內容類型:apache
要想按照本身的意願解析內容,你能夠建立本身的內容解析器:json
import au.com.bytecode.opencsv.CSVReader import groovyx.net.http.ParserRegistry //註冊本身的內容類型和解析器 http.parser.'text/csv' = { resp -> return new CSVReader( new InputStreamReader( resp.entity.content , ParserRegistry.getCharset( resp ) ) ) } //驗證使用 http.get( uri : 'http://somehost.com/contacts.csv' , contentType : 'text/csv' ) { resp, csv -> assert csv instanceof CSVReader // parse the csv stream here. }
除了展現如何支持新的內容類型,上例還展現另外一種GET請求方法:直接使用HTTPBuilder的get方法。該方法簡化了GET請求的操做,很是適合簡單的場景。提到了GET,就不能不提POST,使用HTTPBuilder完成POST請求的方法以下:安全
import groovyx.net.http.HTTPBuilder def http = new HTTPBuilder('http://twitter.com/statuses/') http.request( POST ) { uri.path = 'update.xml' body = [ status : 'update!' , source : 'httpbuilder' ] requestContentType = ContentType.URLENC response.success = { resp -> println "Tweet response status: ${resp.statusLine}" assert resp.statusLine.statusCode == 200 } }
一樣很是簡單,不一樣則在於POST中須要指定body和requestContentType,使用它徹底能夠模擬窗體的提交。在GET請求中咱們談到了對於響應內容的解析,與之對應的則是如何在POST中提交不一樣的內容類型:異步
http.request( POST, XML ) { body = { auth { user 'Bob' password 'pass' } } }
http.request( POST, JSON ) { req -> body = [ first : 'Bob', last : 'Builder', address : [ street : '123 Some St', town : 'Boston', state : 'MA', zip : 12345 ] ] response.success = { resp, json ->...} }
一樣,HTTPBuilder對於POST也提供了便利的post方法,關於它的使用也請參見文檔。工具
REST是現在Web的寵兒,許多Web 2.0 API都宣稱本身是RESTful的。且不論其中的真僞,做爲給HTTP操做提供DSL的工具,HTTPBuilder天然沒有錯過這個潮流。RESTClient即是它對於這種趨勢的迴應,其自己是HTTPBuilder的子類,雖然損失了部分靈活性,但簡化了爲GET、PUT、POST、DELETE和HEAD操做:post
twitter = new RESTClient( 'https://twitter.com/statuses/' ) //HEAD twitter.head( path : 'public_timeline.json' ).status == 200 //GET def resp = twitter.get( path : 'friends_timeline.json' ) //POST def msg = "I'm using HTTPBuilder's RESTClient on ${new Date()}" resp = twitter.post( path : 'update.xml', body : [ status:msg, source:'httpbuilder' ] , requestContentType : URLENC ) //DELETE resp = twitter.delete( path : "destroy/${postID}.json" )
AsyncHTTPBuilder是該工具的另外一個類,看名字就知道,它主要用於異步請求。它的使用方式相似HTTPBuilder,只是返回結果是一個java.util.concurrent.Future類型,關於它的使用詳情,可參見文檔。ui
想找臺免費的機器嗎?如今已徹底不是天方夜譚,Google GAE就是你要找的目標。雖說它是免費的並不徹底對,它在必定配額內免費,但這個配額對於我的實驗或小規模的應用,應該夠用了。開發GAE應用對於Grails來說並不是難事,但若是你想在應用裏使用HTTPBuilder去發起請求,那麼就不會那麼順利。因爲GAE的安全限制,你不能直接去打開Socket,這正是HTTPBuilder底層(HttpClient)的機制。這時,就須要使用HTTPURLConnection完成這一任務。以它爲基礎,HTTPBuilder工具包內提供了另外一個兼容GAE的「HTTPBuilder」:HttpURLClient。使用其餘並不複雜:google
import groovyx.net.http.* def http = new HttpURLClient( url: 'http://twitter.com/statuses/' ) def resp = http.request( path: 'user_timeline.json' , query: [id:'httpbuilder', count:5] ) println "JSON response: ${resp.status}" resp.data.each { println it.created_at println ' ' + it.text }
本文最後要介紹的一個組件是URIBuilder,它並不直接面對HTTP請求,而是輔助HTTPBuilder構造複雜的URL,在其內部使用。它的基本使用以下:
import groovyx.net.http.URIBuilder def uri = new URIBuilder( 'http://www.google.com/one/two?a=1#frag' ) uri.scheme = 'https' assert uri.toString() == 'https://www.google.com:80/one/two?a=1#frag' uri.host = 'localhost' assert uri.toString() == 'https://localhost:80/one/two?a=1#frag' uri.port = 8080 assert uri.toString() == 'https://localhost:8080/one/two?a=1#frag' uri.fragment = 'asdf2' assert uri.toString() == 'https://localhost:8080/one/two?a=1#asdf2' // relative paths: uri.path = 'three/four.html' assert uri.toString() == 'https://localhost:8080/one/three/four.html?a=1#asdf2' uri.path = '../four/five' assert uri.toString() == 'https://localhost:8080/one/four/five?a=1#asdf2' // control the entire path with leading '/' : uri.path = '/six' assert uri.toString() == 'https://localhost:8080/six?a=1#asdf2'
同時也提供了對查詢字符串的處理:
def uri = new groovyx.net.http.URIBuilder( 'http://localhost?a=1&b=2' ) assert uri.query instanceof Map assert uri.query.a == '1' assert uri.query.b == '2' uri.addQueryParam 'd', '4' uri.removeQueryParam 'b' assert uri.toString() == 'http://localhost?d=4&a=1' uri.query = [z:0,y:9,x:8] assert uri.toString() == 'http://localhost?z=0&y=9&x=8' uri.query = null assert uri.toString() == 'http://localhost' // parameters are also properly escaped as well: uri.query = [q:'a:b',z:'war & peace'] assert uri.toString() == 'http://localhost?q=a%3Ab&z=war+%26+peace'
但願經過本文的浮光掠影式的介紹,能讓你們對於HTTPBuilder有個簡單的瞭解;)