Play WS - это мощная клиентская библиотека HTTP, первоначально разработанная игровой командой для использования с Play Framework. Он использует AsynchttpClient для функциональности клиента HTTP и не имеет игровых зависимостей.
Мы предоставили здесь некоторую документацию о том, как использовать Play WS в вашем приложении (без игры). Для получения дополнительной информации о том, как использовать Play WS в игре, пожалуйста, обратитесь к документации Play.
Чтобы начать, вы можете добавить play-ahc-ws-standalone
в качестве зависимости в SBT:
Библиотека-экипажа += "org.playframework" %% "Play-AHC-WS-Standalone" % "Последняя_версия" // До версии 3.0.0: LibraryDependences += "com.typesafe.play" %% "Play-AHC-WS- автономный " %" Последняя_версия "
Где вы заменяете LATEST_VERSION
на версию, показанную на этом изображении :.
Это добавляет автономную версию Play WS, подкрепленную AsynchttpClient. Эта библиотека содержит как Scala, так и Java API, в play.api.libs.ws
и play.libs.ws
Чтобы добавить поддержку XML и JSON с помощью Play-JSON или Scala XML, добавьте следующее:
BibraryDependences += "org.playframework" %% "Play-ws-Standalone-xml" % playwsstandaloneversion LibraryDependences += "org.playframework" %% "Play-ws-standalone-json" % playwsstandaloneversion // до версии 3.0.0: LibraryDependences += "com.typesafe.play" %% "Play-ws-standalone-xml" % playwsstandaloneversion BibraryDependences += "com.typesafe.play" %% "Play-ws-standalone-json" % playwsstandaloneversion
Play WS использует затененные версии Asynchttpclient и Oauth Signpost, переупакованные под play.shaded.ahc
и play.shaded.oauth
Package names соответственно. Затенение AsynchttpClient означает, что версия Netty, используемой за AsynchttpClient, полностью не зависит от приложения и воспроизводить в целом.
В частности, затенение Asynchttpclient означает, что между Netty 4.0 и Netty 4.1 не введено конфликты версий.
ПРИМЕЧАНИЕ . Если вы разрабатываете Play-WS и публикуете
shaded-asynchttpclient
иshaded-oauth
, используяsbt publishLocal
, вы должны знать, что обновление~/.ivy2/local
~/.ivy2/cache
Ваш обновленный затененный код, пока вы не удалите его из кеша. См. Http://eed3si9n.com/field-test для получения более подробной информации. Эта ошибка была подана как SBT/SBT#2687.
Поскольку воспроизводитесь ws shades asynchttpclient, настройки по умолчанию также затенены и поэтому не придерживаются документации AHC. Это означает, что настройки в ahc-default.properties
и свойства Asynchttpclient System приготовлены с помощью play.shaded.ahc
, например, настройка usePooledMemory
в заштрихованной версии Asynchttpclient определяется так: так:
play.shaded.ahc.org.asynchttpclient.usepooledmemory = true
Система типов в Play-WS изменилась, так что тело запроса и корпус ответа могли использовать более богатые типы.
Вы можете определить свой собственный кузовный или читаемый на корпусе, но если вы хотите использовать по умолчанию из настройки поле, вы можете импортировать сопоставления типов с помощью по умолчанию CompoblyReadables / по умолчанию.
Import play.api.libs.ws.defaultbodyreadables._import play.api.libs.ws.defaultbodywritables._
Скорее всего, вы захотите поддержку XML и JSON:
Импорт play.api.libs.ws.xmlbodyreadables._import play.api.libs.ws.xmlbodywritables._
или
Импорт play.api.libs.ws.jsonbodyreadables._import play.api.libs.ws.jsonbodywritables._
Чтобы использовать обработанное тело в ответе, вы должны явно ввести ответ:
Импорт scala.concurrent. {execution context, future} import play.api.libs.ws.standalonewsclientimport play.api.libs.ws.xmlbodyredables._ // обязательный Def Haperlexml (ws: standalonewsclient) (неятный ec: ecuritioncontext): future [scala: scala .xml.elem] = ws.url ("..."). get (). map {response => response.body [scala.xml.elem] }
или с использованием Play-json:
Импорт scala.concurrent. {execution context, future} import play.api.libs.json.jsvalueimport play.api.libs.ws.standalonewsclientimport play.api.libs.ws.jsonbodyReadables._/ обязательный handsonresp (WS: standalonewsclient) ( неявный EC: executionContext): будущее [JSValue] = ws.url ("..."). get (). map {response => response.body [jsvalue] }
Обратите внимание, что есть особый случай: когда вы транслируете ответ, вы должны получить тело в качестве источника:
Import Scala.concurrent.executionContextImport org.apache.pekko.util.bytestringimport org.apache.pekko.stream.scaladsl.sourceimport play.api.libs.ws.standalonewsclientdef usewsstream (ws: standalonewsclient) (Excution ec: ectureckeclectectecter) = eCectionContectectectempem ws.url ("..."). Stream (). Map {response => val source: source [bytestring, _] = response.bodyassource val _ = source // Сделайте что -нибудь с источником }
Чтобы опубликовать, вы должны пройти в тип, который имеет неявное сопоставление классов Bodywarte:
Import Scala.concurrent.executionContextImport play.api.libs.ws.defaultybodywritables._ // обязанный Def Postexamplestring (ws: play.api.libs.ws.standalonewsclient) (INMELICE EC: ExecutionContext) = {val StringData = "Hello World" ws.url ("..."). post (stringdata) .map {response => / * сделать что -нибудь * /} }
Вы также можете определить свой собственный корпус.
Import play.api.libs.ws.bodyReadableImport play.api.libs.ws.ahc.standaloneahcwsresponsecase class foo (body: string) неявное val foobobodyreadable = bodyReadable [foo] {response => Импорт play.shaded.ahc.org.asynchttpclient. {response => ahcresponse} val ahcresponse = response.asinstanceof [stancaloneahcwsresponse]. Неоплачиваемое [ahcresponse] foo (ahcresponse.getresponse) }
или пользовательский корпус:
Импорт org.apache.pekko.util.bytestringimport play.api.libs.ws. -3,2 BodyWable (foo => inmemorybody (bytestring.fromString (foo.toString)), "Application/vnd.company.category+foo") }
Чтобы использовать сопоставления типа по умолчанию в Java, вы должны использовать следующее:
Import play.libs.ws.defaultybodeReadables; import play.libs.ws.defaultbodywartables;
с последующим:
Общедоступный класс MyClient реализует по умолчанию bodyTobyBritables, по умолчанию {public opplionStage <String> doStuff () {return Client.url ("http://example.com") .post (body ("hello world")). thenapply (response -> response .body (string ()) ); } }
Обратите внимание, что есть особый случай: когда вы используете поток, вы должны получить тело в качестве источника:
Класс MyClass {public opplionStage <source <Bytestring, за исключением >> readresponseAsstream () {return ws.url (url) .stream (). thenapply (response -> response.bodyassource () ); } }
Вы также можете опубликовать источник:
Класс myclass {public opplionStage <string> dostuff () {source <bytestring, nated> source = fromSource (); return ws.url (url) .post (body (source)). thenapply (response -> response.body () ); } }
Вы можете определить настраиваемое BodyReadable
:
Import play.libs.ws.ahc.*; импорт play.shaded.ahc.org.asynchtpclient.response; класс Foroereadable реализует BodyReadable <SondaloneWSresponse, foo> {Public Foo Apply (STANDALONEWSResponse ответ) {ответ AHCRESPONSE = (ответ) ответ. getunderlying (); return foo.serialize (ahcresponse.getResponsebody (standardcharsets.utf_8)); } }
Вы также можете определить свой собственный BodyWritable
:
открытый класс myClient {private BodyWrable <string> someTherMethod (String String) {org.apache.pekko.util.bytestring bytestring = org.apache.pekko.util.bytestring.fromString (String); вернуть новые defaultbodywritables.inmemorybodywritable (bytestring, "text/plain"); } }
Автономный клиент нуждается в PEKKO для обработки потоковых данных внутри:
В Scala способ вызовать веб -сервис и закрыть клиента:
Пакет PlaywsclientImport org.apache.pekko.actor.actorsystemport org.apache.pekko.stream._import play.api.libs.ws._import play.api.libs.ws.ahc._import scala.concurrent.futureobject scalaclient {импорт. _ Импорт Scala.concurrent.executionContext.Implicits._ def Main (args: array [string]): unit = {// Создать систему Pekko для потока и потокового управления val System = actorsystem () System.RegisterRemporment {System.Exit (0) } неявный Val Materializer = SystemMaterializer (System) .materializer // Создание автономного клиента WS // нет аргументов по умолчанию для AHCWSClientConfig, созданного из // "ahcwsclientConfigfactory.forConfig (configfactory.load, this.getClassloader)" val wsclient = strantaloneAhclasclasclasclasclas () позвонить (wsclient) .andThen {case _ => wsclient.close ()} . и {case _ => System.Terminate ()} } def Call (wsclient: sonfortonewsclient): будущее [Unit] = { wsclient.url ("http://www.google.com") .get (). Map {response => val statustext: string = response.statustext val body = response.body [строка] println (s "получил ответ $ statustext: $ body") } } }
Вы также можете создать автономный клиент непосредственно из экземпляра AsynchttpClient:
Object scalaclient {def main (args: array [string]): unit = {// Использовать импорт play.shaded.ahc.org.asynchttpclient._val asynchttpclientconfig = new defaultasynchttpclientconfig.builder () .setmaxRequestretry (0) .SetShutDownquietPeriod (0) .SetShutDownTimeout (0) .BuildVal asynchttpClient = new DefaultAsynchtpClient (asynchttpclientConfig) val wsclient = new stantaloneahcwsclient (asynchttpclient) //////////////////////////////////////////////////////////////////// } }
Это полезно, когда есть параметр конфигурации AsynchttpClient, которая недоступна в слое конфигурации WS.
На Java API почти такой же:
Package playwsclient; import org.apache.pekko.actor.actorsystem; import org.apache.pekko.stream.*; import com.typesafe.config.configfactory; import play.libs.ws.*; import play.libs.ws. ahc.*; открытый класс Javaclient реализует DefaultBodyReadables {Private Final StandaloneahCwsClient Client; частная конечная система ActorSystem; Public Static void main (String [] args) {// Настройка Pekko Materviteiz Actorsystem.create (name); System.RegisterOntermination (() -> System.exit (0)); Materializer Materializer = SystemMaterializer.get (System) .materializer (); // Создать клиент WS из `application.conf` Файл, текущий класс загрузчика и Materializer.standaloneahcwsclient ws = standaloneahcwsclient.create (ahcwsclientconfigactory.forconfig (configficecory.load (), System.getClass (). GetClassLoader (), Materializer); Javaclient Javaclient = javaclient (System); javaclient javaclient = javaclient (system); javaclient.run (); } Javaclient (система Actorsystem, Constantaloneahcwsclient Client) {this.system = system; this.client = client; } public void run () {client.url ("http://www.google.com") .get () .whencoMplete ((response, throwable) -> {string statustext = response.getStatustext (); string body = response.getbody (string ()); System.out.println ("Получил ответ" + statustext); }) .ThenRun (() -> {try {client.Close (); } catch (Exception e) {e.printstackTrace (); } }) .ThenRun (System :: прекратите); } }
Аналогичным образом, вы можете явно предоставить клиенту AsynchttpClient от конфигурации:
Общедоступный класс Javaclient реализует по умолчанию BodyBodeReadables {public static void main (string [] args) {// ... // Настройка asynchttpclient непосредственно из configAsynchtpclientConfig asynchttpclientConfig = new DefaultAsynchttpClientConfig.Builder () .setmaxRequestretry (0) .SetShutDownquietPeriod (0) .SetShutDownTimeout (0) .build ();; asynchttpclient asynchttpclient = new DefaultAsynchtpClient (asynchttpclientConfig); // Настройка экземпляра wsclient непосредственно от asynchttpclient.wsclient client = new ahcwsclient (asynchttpclient, materializer); // ...} }
Воспроизвести ws реализует кэширование HTTP через CachingAsynchttpclient, Ahchttpcache и Cachecontrol, минимальную библиотеку управления кэшами HTTP в Scala.
Чтобы создать автономный клиент AHC, который использует кэширование, передайте экземпляр Ahchttpcache с адаптером кеша к базовой реализации. Например, чтобы использовать кофеин в качестве базового кеша, вы можете использовать следующее:
Import Scala.concurrent.futureImport java.util.concurrent.timeunitimport com.github.benmanes.caffeine.cache. {Caffeine, Ticker} Импорт Play.api.libs.ws.ahc.standaloneahcwsclientimport play.api.libs.ws.ahc. Кэш. {ahchttpcache, Cache, EffectiveUrikey, responseNtry} класс CaffeineHttpCache Extends Cache {val maphying = caffeine.newbuilder () .ticker (ticker.systemticker ()) .expireafterWrite (365, TimeUnit.days) .build [EffectiRikey, ReplowEntry] () def Remove (Key: EffectiveRikey) = future.successful (option (boonwying.invalidate (key))) def (Key: effectyUrikey, intry: responseNtry) = future.successful (offly.put.put. (Key, Entry)) def get (key: effecativeUrikey) = future.successful (option (базовый ключ Getifresent)) def close (): unit = boonly.cleanup () } def withCache (Imptiant m: org.apache.pekko.stream.materializer): standaloneahcwsclient = {неявный def ec = m.executycontext Val cache = new Caffeinehttpcache () standaloneahcwsclient (httpcache = некоторые (new Ahchtpcache (cacache))))) }
Есть ряд гидов, которые помогают в составлении заголовков контроля кэша:
Руководство Mozilla по кэшированию HTTP
Гид Марка Ноттингема по кэшированию
Http кэширование
REST легко: http cache
См. Https://github.com/playframework/.github/blob/main/releasing.md
Play WS лицензируется по лицензии Apache, версия 2. См. Файл лицензии для получения дополнительной информации.