Akka HTTP实战:为Ant Design Pro提供后端接口

jiexray 2018-10-10

本文使用 Ant Design Pro 2.0版本

设置 Ant Design Pro

Ant Design Pro 已经是一个完整的后台前端应用,我们只需要使用 Akka HTTP 为其提供后端API接口服务支持和静态资源文件的HTTP获取功能。

创建API

Akka HTTP 的 Routing DSL 是从上到下一级一级的匹配路由的,当前一个路由不匹配时才判断下一个路由,这样一直到最后一个。利用这个特性,我们可以在整个路由定义的最后来设置返回React SPA需要的静态资源文件。

def route: Route =
 pathPrefix("api") {
 pathGet("currentUser") {
 complete(Mocks.apiCurrentUser)
 } ~
 pathGet("fake_chart_data") {
 complete(Mocks.apiFakeChartData)
 } ~
 pathGet("tags") {
 complete(Mocks.apiTags)
 } ~
 pathGet("activities") {
 complete(Mocks.apiActivities)
 } ~
 pathGet("fake_list") {
 parameter('count.as[Int]) { count =>
 complete(Mocks.apiFakeList(count))
 }
 } ~
 pathPrefix("project") {
 pathGet("notice") {
 complete(Mocks.project.notice)
 }
 }
 } ~
 notPathPrefixTest("api") {
 getFromResourceDirectory("dist") ~
 getFromResource("dist/index.html")
 }

Full source at GitHub

这里的重点在 notPathPrefixTest(api) { .... } 部分,这一块代码是用来返回 Ant Design Pro 静态资源的。首先它将判断请求URI不是以 /api 开头,若请求URI以/api开关则不进入里面的获取静态资源代码逻辑,而是直接返回一个预定义的指令:reject。通常,我们都会将API接口统一到 /api 这样的路径下,这样非 /api 开头的URI请求就可以交到下面的两句代码执行,来实现SPA应用在资源未找到时服务端默认返回 /index.html 的需求。

getFromResourceDirectory("dist") ~

getFromResource("dist/index.html")

  • getFromResourceDirectory:根据URI请求路径从资源目录dist查找文件并返回
  • getFromResource:直接返回 dist/index.html 资源文件

总体上,以上两个指令组合使用就可以实现类似 Nginx 的 try_files $uri /index.html; 效果

Mocks.scala,定义了API接口数据并组装成 HttpEntity 对象。

object project {
 def notice = toJsonEntity(Project.notice)
}
def apiCurrentUser = toJsonEntity(Api.currentUser)
def apiFakeChartData = toJsonEntity(Api.fake_chart_data)
def apiTags = toJsonEntity(Api.tags)
def apiActivities = toJsonEntity(Api.activities)
def toJsonEntity(str: String): HttpEntity.Strict = HttpEntity(ContentTypes.`application/json`, str)

Full source at GitHub

这里为了演示Akka HTTP与Ant Design Pro的集成,我并未直接去实现后端接口数据模型的生成逻辑,比如:model定义、数据存储操作等。而是通过直接返回字符串形式的JSON数据来模拟:

val currentUser =
 """{"name":"羊八井","avatar":"https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png","userid":"00000001","email":"[email protected]","signature":"海纳百川,有容乃大","title":"一个好爸爸","group":"华龙海数-某某某事业群-某某平台部-某某技术部-Developer","tags":[{"key":"0","label":"很有想法的"},{"key":"1","label":"专注后端"},{"key":"2","label":"强~"},{"key":"3","label":"彪悍"},{"key":"4","label":"重庆崽儿"},{"key":"5","label":"海纳百川"}],"notifyCount":12,"country":"China","geographic":{"province":{"label":"重庆市","key":"330000"},"city":{"label":"渝北区","key":"402260"}},"address":"渝北区金开大道西段106号10栋移动新媒体产业大厦11楼","phone":"023-88888888"}"""

Full source at GitHub

通过def toJsonEntity(str: String): HttpEntity.Strict = HttpEntity(ContentTypes.application/json, str)函数,将JSON字符串实例化为一个HttpEntity对象并设置Content-Type为application/json类型。

注意

这里只定义了Ant Design Pro的 dashboard 栏目下3个页面需要的接口,其它接口并未实现,因为对于这个示例它们并不是重点。

添加webpack proxy支持

修改 ant-design-pro/web/config/config.js 文件,在末尾右大括号(})上方添加 proxy 设置API代理访问路径路径。这样所有的前端Ajax请求(请求/api开始的路径)都会被路由到Akka HTTP提供的API服务上。

proxy: {
 '/api': {
 target: 'http://localhost:22222',
 changeOrigin: true,
 },
 },

使用 start:no-mock 启动Ant Design Pro

npm run start:no-mock

打开浏览器,访问 http://localhost:8000 地址:

Akka HTTP实战:为Ant Design Pro提供后端接口

这时还未启动Akka HTTP后端服务,看到在请求后端API /api/currentUser时报504网关超时错误。这代表我们设置的 webpack.proxy 已经生效,接下来让我们启动Akka HTTP后端服务。

启动Akka HTTP Server

Main.scala

object Main extends App with StrictLogging {
 implicit val system = ActorSystem()
 implicit val materializer = ActorMaterializer()
 import system.dispatcher
 val bindingFuture = Http().bindAndHandle(handler = new Routes().route, interface = "0.0.0.0", port = 22222)
 bindingFuture.onComplete {
 case Success(binding) ⇒
 sys.addShutdownHook(system.terminate())
 logger.info(s"启动Akka HTTP Server成功,绑定地址: $binding")
 case Failure(e) ⇒
 logger.error(s"启动Akka HTTP Server失败:${e.getMessage}", e)
 system.terminate()
 }
}

Full source at GitHub

可以看到,编程启动Akka HTTP服务非常简单。我们执行Main.scala即可启动Akka HTTP服务。看到类似输出就代表服务已经启动成功:

10:59:13.659 [default-akka.actor.default-dispatcher-4] INFO scalaweb.ant.design.pro.Main$ - 启动Akka HTTP Server成功,绑定地址: ServerBinding(/0:0:0:0:0:0:0:0:22222)

打包、部署

Ant Design Pro 的 Akka HTTP集成已经完成,我们也在开发模式下分别启动了Webpack Dev Server和Akka HTTP Server来看到我们集成的效果。要把集成的成果部署到服务器上怎么办?非常的简单,执行如下的几行命令就可以生成一个同时提供后端API接口和HTTP静态资源渲染的独立可执行jar包。不需要使用Nginx/Apache的代理静态资源,这样部署更加简洁。当然,你也可以继续使用用Nginx/Apache来代理静态资源,如果需要的话。

pushd ant-design-pro/web

yarn install

yarn run build

popd

rm -rf ant-design-pro/src/main/resources/dist/*

cp ant-design-pro/web/dist/* ant-design-pro/src/main/resources/dist/

sbt "project ant-design-pro" assembly

  1. 首先编译 Ant Design Pro,在 dist 目录生成静态资源。
  2. copy所有静态资源到 resources/dist 目录,这样Akka HTTP可以在生成的jar里通过Java资源文件机制访问到它们。
  3. 使用 sbt assembly 命令打包。
  4. 使用 java -jar 命令执行可执行jar包文件。

运行程序

java -jar ant-design-pro/target/scala-2.12/ant-design-pro-assembly-1.0.0.jar

打开浏览器访问 http://localhost:22222/ 即可看到 Ant Design Pro 的界面。

示例效果

Akka HTTP实战:为Ant Design Pro提供后端接口

总结

我们通过一个简单的实战示例:ant-desigin-pro,将之前几章所讲知识串起来通过Akka HTTP技术实现了一个较为完整的Web应用。

本章源码在:https://github.com/yangbajing/scala-web-development/tree/master/ant-design-pro

相关推荐