8.3 Spring Boot集成Scala混合Java开发
本章我们使用Spring Boot集成Scala混合Java开发一个Web性能测试平台。
使用到的相关技术:
后端:
- phantomjs
- scala
- java
- springboot
- velocity
- jpa
- maven
- mysql
前端:
- jquery
- bootstrap
- adminLTE
- html/css
Scala是一门JVM上的语言。它精心整合了面向对象和函数式编程语言,支持面向对象编程范式,支持函数式编程范式,语法动态简洁表达力丰富,具备静态强类型和丰富的泛型。
新建maven工程,配置pom
添加SpringBoot parent依赖
org.springframework.boot
spring-boot-starter-parent
1.3.5.RELEASE
因为我们要使用scala + java混合开发,添加scala依赖
org.scala-lang
scala-library
${scala.version}
然后,我们使用velocity模板引擎,数据库ORM层使用jpa
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-data-jpa
org.springframework.boot
spring-boot-starter-velocity
构建周期build插件配置:
org.scala-tools
maven-scala-plugin
compile
testCompile
incremental
${scala.version}
app
com.light.sword.ylazy.LightSwordApplication
-deprecation
-Xms256m
-Xmx2048m
org.springframework
springloaded
1.2.6.RELEASE
org.springframework.boot
spring-boot-maven-plugin
org.apache.maven.plugins
maven-dependency-plugin
package
copy-dependencies
system
其中build周期中的maven-scala-plugin是編譯期依賴,scala代碼需要scala的compiler,所以在maven構建過程中,使用一個編譯scala代碼的maven插件.這是typesafe(scala背後的公司)的工程師Josh Suereth開發的,遵循maven插件開發規範.
然後,org.scala-lang:scala-library是Scala應用運行時的依賴.這樣,我們就可以像使用scala來開發SpringBoot应用了。
构建标准maven工程目录
工程目录如下:
配置数据库
我们数据库使用mysql,ORM框架使用spring-jpa,在application.properties配置如下:
#mysql
spring.datasource.url = jdbc:mysql://localhost:3306/ylazy?useUnicode=true&characterEncoding=UTF8
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.max-active=0
spring.datasource.max-idle=0
spring.datasource.min-idle=0
spring.datasource.max-wait=10000
spring.datasource.max-wait-millis=31536000
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# stripped before adding them to the entity manager)
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
写领域实体层代码
package com.light.sword.ylazy.entity
import java.util.Date
import javax.persistence.{Entity, GeneratedValue, GenerationType, Id}
import scala.beans.BeanProperty
import scala.language.implicitConversions
@Entity
class LazyTask {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@BeanProperty
var id: Integer = _
@BeanProperty
var url: String = _
@BeanProperty
var name: String = _
//用例状态: -1未执行 0失败 1成功
@BeanProperty
var state: Integer = _
@BeanProperty
var owner: String = _
@BeanProperty
var resultJson: String = _
@BeanProperty
var executeTimes: Integer = _
@BeanProperty
var executor: Integer = _
@BeanProperty
var gmtCreate: Date = _
@BeanProperty
var gmtModify: Date = _
}
Scala中可以为类、方法、字段、局部变量和参数添加注解,与Java一样。可以同时添加多个注解,先后顺序没有影响。 在Scala中,注解可以影响编译过程,比如@BeanProperty注解。
我们使用@Entity注解标记数据库实体类LazyTask,jpa会自动对应到数据表lazy_task, 同时我们使用@BeanProperty标记实体bean里面的属性字段,jpa会自动映射到表里面的字段,自动映射对应的类型。用scala的@BeanProperty注解,会自动生成JavaBeans的getter,setter方法。
Dao层代码
package com.light.sword.ylazy.dao
import java.util.List
import com.light.sword.ylazy.entity.LazyTask
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.CrudRepository
// JavaConversions
import scala.language.implicitConversions
trait LazyTaskDao extends CrudRepository[LazyTask, Integer] {
def findAll(): List[LazyTask]
def save(t: LazyTask): LazyTask
def findOne(id: Integer): LazyTask
@Query(value = "SELECT * FROM lazy_task where url like '%?1%'", nativeQuery = true)
def listByUrl(url: String): List[LazyTask]
@Query(value = "SELECT * FROM lazy_task where name like '%?1%'", nativeQuery = true)
def listByName(name: String): List[LazyTask]
}
Controller层代码
package com.light.sword.ylazy.controller
import java.util.Date
import com.light.sword.ylazy.config.DomainConfig
import com.light.sword.ylazy.dao.LazyTaskDao
import com.light.sword.ylazy.engine.PhantomjsExecutor
import com.light.sword.ylazy.entity.LazyTask
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.ui.Model
import org.springframework.web.bind.annotation._
import org.springframework.web.servlet.ModelAndView
@RestController
class LazyTaskController @Autowired()(val lazyTaskDao: LazyTaskDao,
val phantomjsExecutor: PhantomjsExecutor,
val domainConfig: DomainConfig) {
@RequestMapping(value = {
Array("/newTask.do")
})
def newTask_do() = {
new ModelAndView("ylazy/newTask")
}
@RequestMapping(value = {
Array("/ylazy/newTask")
}, method = Array(RequestMethod.POST))
@ResponseBody
def newTask(@ModelAttribute lazyTask: LazyTask) = {
lazyTask.gmtCreate = new Date
lazyTask.gmtModify = new Date
lazyTask.executeTimes = 0
lazyTask.state = -1
lazyTaskDao.save(lazyTask)
}
@RequestMapping(value = {
Array("/list.do")
})
def list_do(model: Model) = {
model.addAttribute("lazyTaskList", lazyTaskDao.findAll())
model.addAttribute("domainName", domainConfig.getDomainName)
model.addAttribute("port", domainConfig.getPort)
new ModelAndView("ylazy/list")
}
/**
* 获取一条任务记录
*
* @param id
* @return
*/
@RequestMapping(value = {
Array("/lazytask")
}, method = Array(RequestMethod.GET))
@ResponseBody
def findOne(@RequestParam(value = "id") id: Integer) = lazyTaskDao.findOne(id)
/**
* 获取一条任务记录的返回json
*
* @param id
* @return
*/
@RequestMapping(value = {
Array("/result/{id}")
}, method = Array(RequestMethod.GET))
@ResponseBody
def findResultJson(@PathVariable(value = "id") id: Integer) = lazyTaskDao.findOne(id).resultJson
/**
* 执行任务
* @param id
* @return
*/
@RequestMapping(value = {
Array("/ylazy/runTask")
}, method = Array(RequestMethod.GET))
@ResponseBody
def runTask(@RequestParam(value = "id") id: Integer) = {
phantomjsExecutor.ylazyById(id)
}
@RequestMapping(value = {
Array("/ylazy")
}, method = Array(RequestMethod.GET))
@ResponseBody
def ylazy(@RequestParam(value = "url") url: String) = phantomjsExecutor.ylazy(url)
}
前端代码
对应的前端模板代码我们放在src/main/resources/templates/ylazy/list.html
#parse("/common/header.html")
#parse("/common/aside.html")
YLazy
Web性能测试平台
新增任务
任务列表
Id
名称
URL
运行次数
更新时间
执行结果
操作
运行状态
#foreach ($t in $lazyTaskList)
$!t.id
$!t.name
$!t.url
$!t.executeTimes
#set($testTime=$!DateTool.format('yyyy-MM-dd HH:mm:ss', $t.gmtModify))
$testTime
#end
#parse("/common/footer.html")
完整的工程源代码:
https://github.com/EasySpringBoot/ylazy
运行测试
在pom.xml所在目录,命令行运行:
mvn clean scala:compile scala:run -Dlauncher=app
浏览器访问:http://localhost:9050/list.do
你将看到如下页面:
小结
本章给出了一个使用Scala进行SpringBoot应用的开发实例。
关于SpringBoot集成Scala开发,还可以参考本书中的另外的工程实例源码:
HTTP接口测试平台:
https://github.com/EasySpringBoot/lightsword
Teda自动化用例调度执行平台:
https://github.com/EasySpringBoot/teda
参考资料
http://www.jianshu.com/p/51535e85bae5