使用 Maven 时如何在 Play 框架项目中注入 WSClient?

How to inject WSClient in a Play framework project when using Maven?

在创建Play框架项目并使用WSClient进行REST调用时,官方Play框架文档建议将ws添加到build.sbt以管理依赖项。如果使用 Maven,ws 依赖项包含在:

<dependency>
  <groupId>com.typesafe.play</groupId>
  <artifactId>play-ws_2.12</artifactId>
  <version>${play2.version}</version>
</dependency>

然而,当尝试使用这样的片段调用 Web 服务时:

@Singleton
class Controller @Inject()(
  ws: WSClient,
  controllerComponents: ControllerComponents
)(implicit ec: ExecutionContext)
  extends AbstractController(controllerComponents) {
  def callApi(): Action[AnyContent] = Action.async { _ =>
    ws
      .url("https://mywebservice.com/api/bla")
      .get()
      .map(response => Ok(response.body.toString))
  }
}

然后出现如下错误:

CreationException: Unable to create injector, see the following errors:

1) No implementation for play.api.libs.ws.WSClient was bound.
  while locating play.api.libs.ws.WSClient
    for the 1st parameter of controllers.MyController.<init>(MyController.scala:13)
  while locating controllers.MyController
    for the 3rd parameter of router.Routes.<init>(Routes.scala:33)
  at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:123):
Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon)

如文档所述:

Note: In Play 2.6, Play WS has been split into two, with an underlying standalone client that does not depend on Play, and a wrapper on top that uses Play specific classes. In addition, shaded versions of AsyncHttpClient and Netty are now used in Play WS to minimize library conflicts, primarily so that Play’s HTTP engine can use a different version of Netty. Please see the 2.6 migration guide for more information.

查看 2.6 迁移指南,我们可以阅读:

If you have a Play SBT project, you can still add WS by adding the following line to your build.sbt:

libraryDependencies += ws

This includes the play-ahc-ws module [...]

所以要解决这个问题,我们必须将 play-ahc-ws 模块添加到 Maven 的 pom.xml:

<dependency>
  <groupId>com.typesafe.play</groupId>
  <artifactId>play-ahc-ws_2.12</artifactId>
  <version>${play2.version}</version>
</dependency>

如果像代码示例中那样使用 Guice,依赖注入将由 Guice 处理。