如果還不清楚akka http的使用,可參看 使用scala基于AKKA HTTP開發REST接口的簡單執行個體,工程目錄結構如下:

整個處理過程:用戶端發送get或者post請求->服務端處理->結果傳回用戶端(以json字元串方式傳回),這裡的用戶端測試工具采用的是IDEA自帶的rest測試工具,可通過Tools->Test RESTful Web Service調出。
看服務端的一個get請求處理代碼:
val route = get {
path("row") {
parameter("rowkey") { rowkey =>
val result: Future[Option[String]] = selectByRowkey(rowkey)
onSuccess(result) {
case Some(item) if (!"".equals(item)) => complete(item)
case Some(item) if ("".equals(item)) => complete("nothing was found with the rowkey:" + rowkey)
case None => complete(StatusCodes.NotFound)
}
}
}
}
代碼的邏輯是根據rowkey查hbase對應的記錄,比較簡單。查詢的時候使用Future異步處理查詢請求,查詢完成時将結果傳回用戶端,啟動服務,在rest用戶端測試:
配置好後,點選左上角的綠色三角箭頭進行測試,如果是POST請求(服務端接受post參數可參看官網文檔),測試配置如下:
還可以通過浏覽器測試get請求,如在浏覽器輸入:http://localhost:8080/row?rowkey=1001進行測試。
業務邏輯編寫測試完成後緊接着就是将程式部署到伺服器上去,在前一篇介紹akka http的執行個體時,将依賴的jar包整個打進項目jar包中 ,配置檔案也沒有分離,本次對這兩項做了優化,先看項目在伺服器端的部署結構:
其中:bin-存放程式啟停shell腳本(java -jar方式運作程式)
conf-存放的配置檔案
lib-第三方依賴包
logs-程式日志目錄
一.項目打包不包含依賴包
這個給出完整的pom檔案,供參考
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.vip.bigdata</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
<inceptionYear>2008</inceptionYear>
<properties>
<scala.version>2.12.6</scala.version>
</properties>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-http_2.12</artifactId>
<version>10.1.3</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-stream_2.12</artifactId>
<version>2.5.12</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-http-spray-json_2.12</artifactId>
<version>10.1.3</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-it</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-common</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.aliyun.phoenix</groupId>
<artifactId>ali-phoenix-core</artifactId>
<version>4.11.0-AliHBase-1.1-0.3</version>
</dependency>
<!--<dependency>-->
<!--<groupId>jdk.tools</groupId>-->
<!--<artifactId>jdk.tools</artifactId>-->
<!--<version>1.8</version>-->
<!--<scope>system</scope>-->
<!--<systemPath>C:/Program Files/Java/jdk1.8.0_171/lib/tools.jar</systemPath>-->
<!--</dependency>-->
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>conf/*</exclude>
</excludes>
</resource>
</resources>
<sourceDirectory>src/main/scala</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.vip.bigdata.server.HbaseServer</mainClass>
</manifest>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<scalaVersion>${scala.version}</scalaVersion>
<args>
<arg>-target:jvm-1.8</arg>
</args>
</configuration>
</plugin>
</plugins>
</build>
</project>
最主要是配置這兩塊的内容:
maven-jar-plugin插件裡的:
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.vip.bigdata.server.HbaseServer</mainClass>
</manifest>
maven-dependency-plugin插件裡的:
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
上面的配置是把依賴的jar包拷貝打包後的lib檔案夾下,如下所示:
把lib檔案夾的包傳到伺服器上的lib檔案夾下。
二.打包不包含配置檔案
在有一篇博文中有提到:maven打包不包含配置檔案
在上面給出的配置中:
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>conf/*</exclude>
</excludes>
</resource>
這個地方就是配置打包時不包含conf下所有的配置檔案,将conf裡的配置檔案上傳到伺服器中的conf目錄下,需要注意的是讀取配置檔案的類也要響應的調整路徑,下面給出完成的代碼:
package com.vip.bigdata.util
import java.io.{BufferedInputStream, File, FileInputStream}
import java.util.Properties
import scala.util.Try
object PropertyConfig extends Logging {
val directory = new File("..")
val filePath = directory.getAbsolutePath
val appConfName = "application.properties"
val appConfPath = filePath + "/conf/"+appConfName
val prop = new Properties() {
new Properties() {
if (sys.env.get("os").mkString.toLowerCase.contains("windows")) {
logInfo("load resource from peoperties file inside on windows")
if (Try(new BufferedInputStream(new FileInputStream(appConfPath))).isFailure)
logWarn("Cannot load resource from properties file inside on windows, maybe properties file doesn't exists")
} else {
if (new File(appConfPath).exists()) {
logInfo("Load resource from properties file outside")
load(new FileInputStream(appConfPath))
} else {
logInfo("Load resource from properties file inside")
if (Try(load(this.getClass.getClassLoader.getResourceAsStream(appConfPath))).isFailure)
logWarn("Cannot load resource from properties file inside, maybe properties file doesn't exists")
}
}
}.getProperty(appConfName, appConfName)
.split(",")
.foreach(line => {
val f = filePath+"/conf/"+line
if (sys.env.get("os").mkString.toLowerCase.contains("windows")) {
logInfo("load resource from peoperties file inside on windows")
if (Try(load(new BufferedInputStream(new FileInputStream(f)))).isFailure)
logWarn("Cannot load resource from properties file inside on windows, maybe properties file doesn't exists")
} else {
if (new File(f).exists()) {
logInfo(s"Load resource $f from properties file outside")
load(new FileInputStream(f))
} else {
logInfo(s"Load resource $f from properties file inside")
if (Try(new BufferedInputStream(new FileInputStream(f))).isFailure)
logWarn(s"Cannot load resource $f from properties file inside, maybe properties file $f doesn't exists")
}
}
})
}
def getProperty(key: String): String = {
logInfo(s"the $key of property value is:"+this.prop.getProperty(key))
return this.prop.getProperty(key);
}
}
上面的代碼是先加載application.properties配置檔案,這個配置檔案裡放的是要加載的所有的配置檔案,格式如下:
配置檔案間以逗号隔開,這樣所有的配置檔案都會一次性加載進去,上面的類繼承了自定義的Logging日志類,可以忽略。
還需要注意一點,因為把log4j的配置檔案放到了conf目錄下,代碼要稍作改動,不然無法讀到log4j的配置檔案,日志功能也就不起作用了,具體如下,因為我有一個Logging日志接口,是以在裡面添加下面的代碼即可,
PropertyConfigurator.configure(filePath+"/conf/log4j.properties")//log4j的完整日志路徑
至此整個工程部署完成就可以進行測試了。