我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

Play Framework 2.6 WS 迁移指南:从 play-ws 独立化到 WSClient 与 BodyWritable 全面升级

Play Framework 2.6 WS 迁移指南:从 play-ws 独立化到 WSClient 与 BodyWritable 全面升级 后端Web框架【免费下载链接】playframeworkThe Community Maintained High Velocity Web Framework For Java and Scala.项目地址https://gitcode.com/gh_mirrors/pl/playframework点击查看免费下载Play 2.6 对 WS 客户端做了一次里程碑式的重构WS 被拆分为一个可脱离 Play 独立使用的play-ws库并借助包重命名shading规避依赖冲突同时 Scala/Java 两套 API 统一收敛到单一play-ahc-ws模块以注入式WSClient取代旧式单例入口。本指南完整梳理 2.6 迁移涉及的依赖声明、包结构变化、Scala/Java API 改动与测试工具用法并结合当前仓库源码说明底层实现帮助你一次性完成升级。一、为什么迁移Play WS 的独立化与依赖收敛Play 2.6 之前WS 的历史实现由两个库构成wsScala API与playWsJava API两者各自在后台创建独立的 AsyncHTTPClient 实例造成资源重复与行为不一致。2.6 开始单一play-ahc-ws库同时包含 Scala 与 Java 的WSClient实例二者都指向单例的AsyncHttpClientProviderWS 被重写为「Play 专用包装层 独立 WS 核心库」的两层结构独立库不依赖任何 Play 类独立库内部使用重命名shaded版本的 AsyncHttpClient、Signpost 与 Netty 4.0从而大幅降低与其他库、其他项目的类冲突概率让 WS 更灵活、更易于被非 Play 项目复用。从当前仓库的目录结构可以印证这一分层transport/client/play-ws/存放与 Play 无关的 Standalone API 与WSClient接口transport/client/play-ahc-ws/则存放 Play 特有的 AHC 实现、依赖注入绑定与组件见 transport/client。其中 AhcWSModule.scala 通过SimpleModule依次绑定了AsyncHttpClient、StandaloneWSClient与WSClient三个 Provider正是文档所述「单例 AsyncHttpClient Provider」的实现位置。二、依赖声明Play 项目与非 Play 项目分别如何引入2.1 在 Play sbt 项目中Play WS 虽有独立版本但 Play sbt 项目依然可以像以前一样在build.sbt中通过关键字引入libraryDependencies ws该依赖会引入play-ahc-ws模块。它把独立版 WS 包装起来补齐了Play 依赖注入绑定DI bindings、组件components、配置解析以及一切与 Play 深度集成所需的逻辑。2.2 需要缓存支持时如果要用 WS 的 HTTP 缓存除了ws之外还需要ehcache并参考 WsCache 配置指南 完成缓存的启用与配置libraryDependencies ws libraryDependencies ehcache从源码看缓存是 WS 客户端的可选增强AhcWSModule中的AsyncHttpClientProvider会先通过OptionalAhcHttpCacheProvider判断缓存配置若启用则用CachingAsyncHttpClient包装底层客户端见 AhcWSModule.scala。缓存相关配置项如play.ws.cache.enabled、play.ws.cache.name、play.ws.cache.heuristics.enabled、play.ws.cache.cacheManagerResource等在 AhcWSModule.scala 中解析。2.3 在非 Play 的 sbt 项目中使用独立版独立版不依赖 Play可以直接以坐标形式加入任意 sbt 项目libraryDependencies com.typesafe.play %% play-ahc-ws-standalone % 1.0.1 libraryDependencies com.typesafe.play %% play-ws-standalone-json % 1.0.1 libraryDependencies com.typesafe.play %% play-ws-standalone-xml % 1.0.1play-ahc-ws-standalone提供基于 AHC 的 HTTP 能力play-ws-standalone-json与play-ws-standalone-xml分别提供 JSON / XML 的读写支持可按需取舍。三、项目结构变化shaded 依赖与 Play 特有扩展3.1 为什么用 shaded 依赖独立 WS 库将 AsyncHttpClient、Signpost、Netty 4.0 进行包名重命名后内嵌发布。这样即使应用里同时存在其他版本的 Netty / AHC也不会与 WS 内部实现发生类加载冲突这是「更少冲突」承诺的具体实现手段也使得 WS 可以被安全地嵌入到各种运行环境。3.2 Play 特有的 Multipart 扩展Play WS API 在 Standalone WS 的post基础上扩展了 Play 特有的Http.Multipart与Multipart类型。例如在 WSRequest.scala 中可以看到def post(body: Source[MultipartFormData.Part[Source[ByteString, ?]], ?]): Future[Response]这意味着可以基于 Pekko Stream 的Source流式上传 multipart 表单无需把整个请求体载入内存。3.3 Signpost OAuth 实现替换Signpost OAuth 的实现从基于 Commons HTTPClient 的OAuthProvider改为DefaultOAuthProvider后者底层使用HTTPURLConnection。这一改动减少了 WS 对 Commons HTTPClient 的依赖行为上对调用方透明。四、Scala API 迁移清单4.1 入口删除WSAPI以WSClient为唯一入口WSAPI类已被移除。WSClient接口是 WS API 的唯一入口。仓库中 WSClient.scala 定义的trait WSClient extends Closeable只暴露三个能力url(url: String): WSRequest生成请求、underlying[T]: T访问底层实现、close()释放资源。同时被弃用的 Scala 单例对象play.api.libs.ws.WS已删除必须改用WSClient实例。4.2 请求体withBody改用BodyWritable类型类旧版WSRequest.withBodyT(implicit writable: play.api.http.Writable[T])难以追踪Writable的行为已被替换为自定义的BodyWritable[T]类型类其实例定义在 Standalone WS 中override def withBodyT: BodyWritable在 WSRequest.scala 中可以确认withBody、post、patch、put等接口全部改为[T: BodyWritable]约束。升级时若你曾自定义过play.api.http.Writable实例需要改写成BodyWritable实例内置类型String、JSON、XML、文件等由 Standalone WS 预置实例覆盖。4.3 依赖注入方式Guice 注入与编译期组件Guice运行时 DI系统默认提供一个可注入的WSClientclass MyService Inject()(ws: WSClient) { def call(): Unit { ws.url(http://localhost:9000/foo).get() } }编译期 DI如果使用编译期依赖注入应将AhcWSComponentstrait 混入组件中。仓库中的 AhcWSComponents.scala 展示了完整的组件链wsClient→standaloneWSClient基于StandaloneAhcWSClient→asyncHttpClient由AsyncHttpClientProvider提供且三者均为lazy val并按需依赖Environment、Configuration、ApplicationLifecycle、Materializer与ExecutionContext。手动创建如果无法使用注入的WSClient也可以自行创建自己的 WSClient 实例但此时必须自行管理客户端生命周期调用close()释放连接与线程资源否则会造成资源泄漏。4.4 测试play.api.test.WsTestClient函数式测试中可以用play.api.test.WsTestClient.withClient快速获取一个独立 WSClient测试结束自动关闭play.api.test.WsTestClient.withClient { ws ws.url(http://localhost:9000/foo).get() }4.5 包与类重命名ning→ahcning包已替换为ahc包Ning*类全部替换为AHC*。例如旧的NingWSClient对应新的AhcWSClient仓库中的实现类位于 play-ahc-ws 的 ahc 包AhcWSClient、AhcWSRequest、AhcWSResponse、AhcWSModule、AhcWSComponents。如果你在代码里直接引用了play.api.libs.ws.ning.*迁移时需同步修改 import。4.6 流式响应stream()现在返回WSResponsestream()不再返回StreamedResponse而是返回普通的WSResponse实例。流式结果的获取方式变为调用response.bodyAsSource。这一点在 WSResponse.scala 中有对应定义override def bodyAsSource: Source[ByteString, ?]4.7 请求头与查询串的方法重命名带弃用过渡play.api.libs.ws.WSRequest上有一批方法重命名语义更加显式迁移时需格外小心区分「追加」与「覆盖」两种行为旧方法已弃用新方法追加语义新方法覆盖语义withHeaders(headers: (String, String)*)addHttpHeaders(hdrs: (String, String)*)在已有请求头上追加withHttpHeaders(headers: (String, String)*)丢弃已有请求头withQueryString(parameters: (String, String)*)addQueryStringParameters(parameters: (String, String)*)在已有查询串上追加withQueryStringParameters(parameters: (String, String)*)丢弃已有查询串在 WSRequest.scala 中可以看到旧方法带有deprecated(Use withHttpHeaders or addHttpHeaders, 2.6.0)与deprecated(Use addQueryStringParameters or withQueryStringParameters, 2.6.0)注解这印证了 2.6 正是弃用点。迁移时如果旧代码依赖「追加」行为请改用add*系列避免误用覆盖语义丢数据。五、Java API 迁移清单5.1 弃用play.libs.ws.WS改用注入的WSClientJava 侧play.libs.ws.WS类已弃用应注入WSClient实例public class MyService { private final WSClient ws; Inject public MyService(WSClient ws) { this.ws ws; } public void call() { ws.url(http://localhost:9000/foo).get(); } }仓库中 WSClient.java 定义的接口除url()与close()外还提供getUnderlying()访问底层实现以及asScala()获取对应的 ScalaWSClient视图。5.2 手动创建与生命周期如果无法注入也可自行创建 WSClient 实例但要负责其生命周期。例如 AhcWSClient.java 提供了静态工厂AhcWSClient.create(config, cache, materializer)其 Javadoc 明确提示该客户端不受 Play 生命周期管理必须调用ws.close()否则会出现内存泄漏。5.3 测试play.test.WsTestClient函数式测试可用play.test.WsTestClient.newClient(port)启动一个独立 WSClient测试结束后手动关闭WSClient ws play.test.WsTestClient.newClient(19001); ... ws.close();从 WSTestClient.java 的实现看该测试客户端有两个值得注意的行为它基于独立的ActorSystem与DefaultAsyncHttpClient构建close()时会同时关闭客户端并Await.result等待 ActorSystem 终止当传入的 URL 以/开头相对路径时会自动拼接为http://localhost:port/...非常适合测试 Play 应用自身暴露的路由端点。5.4 流式响应getBodyAsSource()与 Scala 侧对应Java 的stream()同样返回普通WSResponse而非StreamedResponse流式结果通过response.getBodyAsSource()获取见 WSResponse.javaSourceByteString, ? getBodyAsSource();六、迁移自查清单完成 2.6 升级后建议按以下顺序核对依赖Play 项目确认libraryDependencies ws需要缓存时追加ehcache并参考 WsCache 配置非 Play 项目使用play-ahc-ws-standalone/play-ws-standalone-json/play-ws-standalone-xml。入口删除对play.api.libs.ws.WS单例Scala与play.libs.ws.WSJava的静态调用改为注入或创建WSClientScala 编译期 DI 混入AhcWSComponents。类型类自定义Writable请求体改写为BodyWritable实例。包与类名ning→ahc、Ning*→AHC*。流式响应stream()返回WSResponse改用bodyAsSource/getBodyAsSource()。方法重命名withHeaders→addHttpHeaders/withHttpHeaderswithQueryString→addQueryStringParameters/withQueryStringParameters注意追加与覆盖的语义差异。生命周期凡手动创建的客户端含测试场景务必close()。对照本清单逐项检查即可平滑完成 Play 2.6 WS 的迁移并充分利用独立化、shaded 依赖与统一WSClient带来的简洁性与稳定性。赞分享后端Web框架【免费下载链接】playframeworkThe Community Maintained High Velocity Web Framework For Java and Scala.项目地址https://gitcode.com/gh_mirrors/pl/playframework点击查看免费下载相关推荐Play Framework 2.6 Cache API 迁移指南从 CacheApi 到 Sync/Async CacheApiPlay Framework 2.6 Cache API 迁移指南从 CacheApi 到 Sync/Async CacheApi 本文是 Play Fram后端Web框架Play Framework Scala 中使用 Play WS 调用 REST API 完整指南Play Framework Scala 中使用 Play WS 调用 REST API 完整指南 Play Framework 自带 WSWebServic后端Web框架Play Framework 2.4 迁移指南Anorm 独立化与新版本特性全解析Play Framework 2.4 迁移指南Anorm 独立化与新版本特性全解析 本指南基于 Play Framework 2.4 迁移文档中关于 Anor后端Web框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表