scala akka http基本使用

来源:互联网 发布:广西广电网络收费标准 编辑:程序博客网 时间:2024/06/05 20:49

scala的akka框架有一个极简的http service组件,是把原来spray框架集成到akka里面修改而成,本文简单介绍了akka http 的使用,在一些简单web service项目或者将web作为一个简单模块的后台项目中非常适合。

sbt配置

name := "MockServer"version := "0.1"scalaVersion := "2.12.3"libraryDependencies ++= Seq(    "com.typesafe.akka" %% "akka-http" % "10.0.10",    "com.typesafe.akka" %% "akka-stream" % "2.5.4",    "com.typesafe.akka" %% "akka-actor"  % "2.5.4",    "com.typesafe.akka" %% "akka-http-spray-json" % "10.0.10",    "ch.megard" %% "akka-http-cors" % "0.2.2")

code

httpserver

import akka.actor.ActorSystemimport akka.http.scaladsl.Httpimport akka.stream.ActorMaterializerimport akka.Doneimport akka.http.scaladsl.server.Routeimport akka.http.scaladsl.server.Directives._import akka.http.scaladsl.model.StatusCodesimport akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._import akka.http.scaladsl.model.headers.HttpOriginRangeimport ch.megard.akka.http.cors.scaladsl.CorsDirectives.corsimport ch.megard.akka.http.cors.scaladsl.settings.CorsSettingsimport spray.json.DefaultJsonProtocol._import scala.io.StdInimport scala.collection.mutableobject MockServer{    // cors setting for other origin access    val settings = CorsSettings.defaultSettings.copy(        allowedOrigins = HttpOriginRange.* // * refers to all    )    // model    final case class User(name: String, age: Int, addr: String)    implicit val itemFormat = jsonFormat3(User) // jsonFormatX refers to X number arguments    final case class UserGroup(items: List[User])    implicit val orderFormat = jsonFormat1(UserGroup)    // object variable    private val userGroup = mutable.ListBuffer[User]()    def main(args: Array[String]): Unit =    {        implicit val system = ActorSystem("mock_system")        implicit val materializer = ActorMaterializer()        // needed for the future flatMap/onComplete in the end        implicit val executionContext = system.dispatcher        // define routes, notice there are many ways        val route: Route =            (path("hello") & get & cors(settings))            {                complete("hello akka")            } ~            (path("list_all") & cors(settings))            {                // simple get                get                {                    // add elem to userGroup, can use this.userGroup += User("jack", 18, "NewYork")                    userGroup.clear()                    userGroup += User("jack", 18, "NewYork")                    userGroup += User("mike", 21, "paris")                    val user_group = UserGroup(this.userGroup.toList)                    complete(user_group)                }            } ~            get            {                // get by params using akka http path matcher                (pathPrefix("user" / IntNumber ) & cors(settings))                {                    age =>                    {                        val user = User("lucy", age.toInt, "tokyo")                        complete(user)                    }                }            } ~            post {                (path("create_user") & cors(settings))                {                    entity(as[User])                    {                        user =>                        {                            println(user)                            // do sth to process                            userGroup += user                            println(userGroup)                            complete("done")                        }                    }                }            }        // bind to ip and port and start server        val bindingFuture = Http().bindAndHandle(route, "localhost", 7070)        println(s"Server online at http://localhost:7070/\nPress RETURN to stop...")        StdIn.readLine() // let it run until user presses return//        while (1) // or use a dead loop        // stop server        bindingFuture            .flatMap(_.unbind()) // trigger unbinding from the port            .onComplete(_ => system.terminate()) // and shutdown when done    }}

其中,

  • get和post的内容需要写在route里面
  • 如果想要传入传出自定义的数据结构,需要用json序列化和反序列化
  • 为了支持跨域访问,加入了cors的setting
  • 如果要支持https,请参考官网文档

httpclient

import akka.actor.ActorSystemimport akka.http.scaladsl.Httpimport akka.http.scaladsl.model._import akka.http.scaladsl.unmarshalling.Unmarshalimport akka.stream.ActorMaterializerimport scala.concurrent.Futureimport scala.util.{Failure, Success}object WebClient extends App{    implicit val system = ActorSystem()    implicit val materializer = ActorMaterializer()    // needed for the future flatMap/onComplete in the end    implicit val executionContext = system.dispatcher    val host_url = "http://www.easy-mock.com/mock/59ed7cef591f361bb0d95ad8" // this is a mock service    val get_api = "user"    val post_api = "login"    val post_username_param = "mike"    val post_password_param = "ethhvhe35"    // url can be rest or non-rest    def getReq(url: String): Unit =    {        val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = url, method = HttpMethods.GET))        responseFuture.onComplete {                case Success(res) => {                    println(res)                    Unmarshal(res.entity).to[String].map { json_str =>                        Right {                            // here we can deserialize json string to object or list of object                            // sth like val res_obj = Json.deserialize([Model])(json_str)                            // or val res_obj = Json.deserialize(Seq[Model])(json_str)                            println("get result: ", json_str)                        }                    }                }                case Failure(error) => println(error.getMessage)            }    }    def postReq(url: String): Unit =    {        val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = url, method = HttpMethods.POST))        responseFuture.onComplete {            case Success(res) => {                println(res)                Unmarshal(res.entity).to[String].map { json_str =>                    Right {                        // here we can deserialize json string to object or list of object                        // sth like val res_obj = Json.deserialize([Model])(json_str)                        // or val res_obj = Json.deserialize(Seq[Model])(json_str)                        println("post result: ", json_str)                    }                }            }            case Failure(error) => println(error.getMessage)        }    }    // test get    getReq(host_url + "/" + get_api)    // test post    postReq(s"$host_url/$post_api?username=$post_username_param&password=$post_password_param")}

其中,

  • 可以将entity解析成json字符串,然后将json字符串绑定到自定义的class获得数据
  • Future传出到外面就失效了,必须带context
  • 也可以写成actor的形式,请参考官网文档

download

github: akka_http_demo

原创粉丝点击