如果还不清楚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的完整日志路径
至此整个工程部署完成就可以进行测试了。