Scala 封装API接口并实现客户端查询(干货)

@羲凡——只为了更好的活着

Scala 封装Api接口并实现客户端查询(干货)

像把大象装冰箱一样,一共有三步:写好查询语句;写好server并启动;写好client查询结果

1.推荐官网(内容非常值得详看)——https://doc.akka.io/docs/akka-http/current/
2.注意server端中文乱码,URLDecoder.decode(name, “UTF-8”)
3.注意client端中文乱码,URLEncoder.encode(“司马懿”,“UTF8”)

0.添加maven依赖

<!-- Spark Core -->
<dependency>
	<groupId>org.apache.spark</groupId>
	<artifactId>spark-core_2.11</artifactId>
	<version>${spark.version}</version>
</dependency>
<!-- Spark SQL -->
<dependency>
	<groupId>org.apache.spark</groupId>
	<artifactId>spark-sql_2.11</artifactId>
	<version>${spark.version}</version>
</dependency>
<!-- Mysql connector -->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.38</version>
</dependency>
<!-- Restful Api -->
<dependency>
	<groupId>com.typesafe.akka</groupId>
	<artifactId>akka-http_2.11</artifactId>
	<version>10.1.9</version>
</dependency>
<dependency>
	<groupId>com.typesafe.akka</groupId>
	<artifactId>akka-stream_2.11</artifactId>
	<version>2.5.23</version>
</dependency>
<dependency>
	<groupId>ch.megard</groupId>
	<artifactId>akka-http-cors_2.11</artifactId>
	<version>0.2.2</version>
</dependency>
<dependency>
	<groupId>com.typesafe.akka</groupId>
	<artifactId>akka-http-spray-json_2.11</artifactId>
	<version>10.1.9</version>
</dependency>
<dependency>
	<groupId>org.scalaj</groupId>
	<artifactId>scalaj-http_2.11</artifactId>
	<version>2.4.1</version>
</dependency>

1.Mysql的增改查代码

import java.sql.{Connection, DriverManager, ResultSet}
import java.util.Properties
import scala.collection.mutable

object MysqlUtil {
  val url = "jdbc:mysql://deptest23:3306/test_data"
  val user = "root"
  val password = "1q2w3e4r"
  val props = new Properties()
  props.put("user", user)
  props.put("password", password)
  props.setProperty("useSSL", "false")
  props.setProperty("useUnicode", "true")
  props.setProperty("characterEncoding", "utf8")
  var connection: Connection = null

  def queryMysql1(name : String, age:Int) ={
    var resMap = mutable.Map[String,String]()
    try {
      classOf[com.mysql.jdbc.Driver]
      connection = DriverManager.getConnection(url, props)
      val sql =
        s"""
           |select * from test_data.mysql_stu_info
           |where name = "$name" and age=$age
         """.stripMargin
      val resSet: ResultSet = connection.createStatement().executeQuery(sql)
      while(resSet.next()){
        val str1: String = resSet.getString("name")
        val str2: String = resSet.getString("age")
        resMap += str1 -> str2
      }
    } catch {
      case e: Exception => println(e.printStackTrace())
    } finally {
      connection.close()
    }
    resMap
  }

  def queryMysql2(name : String) ={
    var resMap = mutable.Map[String,String]()
    try {
      classOf[com.mysql.jdbc.Driver]
      connection = DriverManager.getConnection(url, props)
      val sql =
        s"""
           |select * from test_data.mysql_stu_info
           |where name = "$name"
         """.stripMargin
      val resSet: ResultSet = connection.createStatement().executeQuery(sql)
      while(resSet.next()){
        val str1: String = resSet.getString("name")
        val str2: String = resSet.getString("age")
        resMap += str1 -> str2
      }
    } catch {
      case e: Exception => println(e.printStackTrace())
    } finally {
      connection.close()
    }
    resMap
  }

  def insertMysql(name : String, age : Int) ={
    try {
      classOf[com.mysql.jdbc.Driver]
      connection = DriverManager.getConnection(url, props)
      val sql = s"insert into test_data.mysql_stu_info(name,age) values('$name',$age)"
      val resSet: Int = connection.createStatement().executeUpdate(sql)
      println(resSet)
    } catch {
      case e: Exception => println(e.printStackTrace())
    } finally {
      connection.close()
    }
  }

  def updateMysql(name : String, age : Int) ={
    try {
      classOf[com.mysql.jdbc.Driver]
      connection = DriverManager.getConnection(url, props)
      val sql = s"update test_data.mysql_stu_info set age = $age where name='$name'"
      val resSet: Int = connection.createStatement().executeUpdate(sql)
      println(resSet)
    } catch {
      case e: Exception => println(e.printStackTrace())
    } finally {
      connection.close()
    }
  }
}

2.封装API接口(server端)

import java.net.URLDecoder
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.model.headers.HttpOriginRange
import ch.megard.akka.http.cors.scaladsl.CorsDirectives.cors
import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings
import org.json4s.DefaultFormats
import org.json4s.jackson.Json
import spray.json.DefaultJsonProtocol._
import scala.io.StdIn
import scala.collection.mutable

object WebServer {
  val settings = CorsSettings.defaultSettings.copy(
    allowedOrigins = HttpOriginRange.*
  )

  final case class User(name: String, age: Int, addr: String)
  implicit val itemFormat = jsonFormat3(User)
  final case class Info(name: String, age: Int)
  implicit val itemFormat2 = jsonFormat2(Info)
  final case class UserGroup(items: List[User])
  implicit val orderFormat = jsonFormat1(UserGroup)
  private val userGroup = mutable.ListBuffer[User]()

  def main(args: Array[String]): Unit = {
    implicit val system = ActorSystem("mock_system")
    implicit val materializer = ActorMaterializer()
    implicit val executionContext = system.dispatcher

    val route: Route =
      (path("hello") & get & cors(settings)) {
        // 基本测试
        complete("hello akka")
      } ~
        (path("list_all") & cors(settings)) {
          get {
            // 添加两个元素到UserGroup组中,列出所有的内容
            userGroup.clear()
            userGroup += User("jack", 18, "NewYork")
            userGroup += User("mike", 21, "paris")
            val user_group = UserGroup(this.userGroup.toList)
            complete(user_group)
          }
        } ~
        (path("query1") & cors(settings)) {
          get {
            parameters('name.as[String], 'age.as[Int]) {
              (name, age) => {
                val res = Json(DefaultFormats).write(MysqlUtil.queryMysql1(name, age))
                complete(res)
              }
            }
          }
        } ~
        get {
          // 传参用pathPrefix,数字用IntNumber、LongNumber,字符串用Remaining
          (pathPrefix("query2" / Remaining) & cors(settings)) {
            name => {
              val nameStr = URLDecoder.decode(name, "UTF-8")
              val res = Json(DefaultFormats).write(MysqlUtil.queryMysql2(nameStr))
              complete(res)
            }
          }
        } ~
        post {
          (path("insert") & cors(settings)) {
            entity(as[Info]) {
              info => {
                val res = MysqlUtil.insertMysql(info.name, info.age)
                complete("done")
              }
            }
          }
        } ~
        post {
          (path("update") & cors(settings)) {
            entity(as[Info]) {
              info => {
                val res = MysqlUtil.updateMysql(info.name, info.age)
                complete("done")
              }
            }
          }
        }
    // 绑定ip和端口
    val bindingFuture = Http().bindAndHandle(route, "localhost", 8227)
    println(s"Server online at http://localhost:8227/\nPress RETURN to stop...")
    StdIn.readLine()
    bindingFuture.flatMap(_.unbind()).onComplete(_ => system.terminate())
  }
}

3.查询API接口(client端)

import java.net.URLEncoder
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.ActorMaterializer
import scalaj.http.HttpOptions
import scala.util.{Failure, Success}

object WebClient extends App  {
  implicit val system = ActorSystem()
  implicit val materializer = ActorMaterializer()
  implicit val executionContext = system.dispatcher

  val host_url = "http://localhost:8227"

  def getReq(url: String): Unit = {
    val responseFuture = Http().singleRequest(HttpRequest(uri = url, method = HttpMethods.GET))
    responseFuture.onComplete {
      case Success(res) => {
        println(res)
        Unmarshal(res.entity).to[String].map { json_str =>
          Right {
            println("get result: ", json_str)
          }
        }
      }
      case Failure(error) => println(error.getMessage)
    }
  }

  def postReq(url: String,map:Map[String, Any]): Unit = {
    val name = map("name")
    val age = map("age")
    val body = scalaj.http.Http(url)
      .postData(
        s"""{
          |"name":"$name",
          |"age":$age
          |}""".stripMargin)
      .header("Content-Type", "application/json")
      .header("Charset", "UTF-8")
      .options(HttpOptions.readTimeout(10000)).asString.body
    println(body)
  }

  val nameUtf8: String = URLEncoder.encode("司马懿","UTF8")

  getReq(s"$host_url/query1?name=$nameUtf8&age=27")
  Thread.sleep(2000)
  getReq(s"$host_url/query2/$nameUtf8")
  Thread.sleep(2000)
  postReq(host_url+"/insert",Map("name" -> "夏侯惇","age" -> 10))
  Thread.sleep(2000)
  postReq(host_url+"/update",Map("name" -> "夏侯惇","age" -> 72))
}

参考资料
1.官网——https://doc.akka.io/docs/akka-http/current/
2.这位仁兄的github项目——https://github.com/tashaxing/MockServer

====================================================================

@羲凡——只为了更好的活着

若对博客中有任何问题,欢迎留言交流

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值