代码之家  ›  专栏  ›  技术社区  ›  Udders

scala从REST服务获取响应

  •  0
  • Udders  · 技术社区  · 6 年前

    如果200,则将响应数据推到视图中并显示它。

    我写了一个这样的连接器,

    package connectors
    
    import com.google.inject.Inject
    import config.AppConfig
    import play.api.libs.json.Json
    import play.api.libs.ws.{WSClient, WSResponse}
    import play.mvc.Http.Status
    import scala.concurrent.ExecutionContext.Implicits.global
    import scala.concurrent.Future
    import play.api.libs.json._
    class RegisterConnector @Inject() (appConfig: AppConfig, ws: WSClient) {
    
      val customerBaseUrl: String = appConfig.customerBaseUrl
    
      def verifyCustomer(code: String): Future[Boolean] = {
        ws.url(s"$customerBaseUrl/customer/$code").post(code).map(processResponseStatus)
      }
    
      private def processResponseStatus(resp: WSResponse): Boolean = resp.status match {
        case code if (Status.OK until Status.MULTIPLE_CHOICES).contains(code) => true
        case _ => throw new RegisterException(s"Server error: ${resp.status} . ${resp.body}");
      }
    
    }
    
    class RegisterException(message: String) extends RuntimeException(message: String)
    

        package controllers
    
    import com.google.inject.{Inject, Singleton}
    import config.AppConfig
    import play.api.i18n.{I18nSupport, MessagesApi}
    import play.api.mvc._
    import scala.concurrent._
    import ExecutionContext.Implicits.global
    import connectors.RegisterConnector
    import play.api.Logger
    import views.html.register.verified
    
    @Singleton
    class VerifiedController @Inject()(registerConnector: RegisterConnector,
                                        val messagesApi: MessagesApi)
                                       (implicit appConfig: AppConfig) extends Controller with I18nSupport {
    
      def verify(code: String): Action[AnyContent] = Action.async { implicit request: Request[AnyContent] =>
    
        registerConnector.verifyCustomer(code).map {
          case true =>
    
          case _ =>
    
        }.recover {
          case ex =>
    
        }
    
      }
    
      def show(): Action[AnyContent] = Action { implicit request: Request[AnyContent] =>
        Ok(verified())
      }
    
      def error(): Action[AnyContent] = Action { implicit request: Request[AnyContent] =>
        Ok(verified())
      }
    
    }
    

    一些帮助和指导将是非常棒的!

    1 回复  |  直到 6 年前
        1
  •  1
  •   Bruno Paulino    6 年前

    假设JSON是响应格式,我通常开始在case类中包装响应结构。 假设以下JSON响应:

    {
      "city": "Vienna",
      "forecast": 10
    }
    

    现在这个案子看起来是这样的:

    case class WeatherUpdate(city: String, forecast: Int)
    

    使用singleton进行API调用的策略非常好。我们给他打电话 WeatherService Future[Boolean] 您可以使用Scala标准库 Try .

    class WeatherService @Inject() (ws: WSClient) {
    
      private val logger = Logger(getClass)
    
      def getWeather(): Future[Try[WeatherUpdate]] = {
        ws.get("https://myweather.com/api/update") // this is all fake
          .map {
            case response if response.status == 200 =>
              val city = (response.json \ "city").as[String]
              val forecast = (response.json \ "forecast").as[Int]
              Success(WeatherUpdate(city, forecast))
            case response =>
              Failure(new WeatherException("Could not get weather response"))
          }.recover { // always recover from a future. It could throw an exception and you would never know
            case ex: Exception =>
              logger.error("could not get weather info", ex)
              Failure(ex)
          }
      }
    
    }
    
    class WeatherException(message: String) extends RuntimeException(message: String)
    

    在控制器上,现在可以使用天气更新渲染模板:

    def verify(code: String): Action[AnyContent] = Action.async { 
      implicit request =>
        weatherService.getWeather().map {
          case Success(weatherUpdate) => Ok(weather_template(weatherUpdate))
          case Failure(ex) => BadRequest(weather_error())
        }
    }