(这是一篇迟来的文章,从3月份计划到成文花了5个月多……以后需要避免这样的低效率。)
之前写第一篇文章时,只是想试试在Spring中使用Scala。但现在随着工作的需要,已经决定在应用层基于Spring boot进行开发。后面的数据服务和数据整合部分将采用Akka。作者是一个Scala粉,但不脑残。鉴于团队、招人及社区生态多方面考虑,整体使用Scala技术栈还是比较困难的。之前就有考虑过把Spring和Scala结合起来。后来了解到挖财的技术选型,他们就是基于Spring和Scala的,还开源了很多不错的Spring Boot增强插件。这坚定了我之前的想法,也有了我5个月后续写第2篇的能量。
对于Scala还不熟悉的朋友可以先看看《写给Java程序员的Scala入门教程》,好对Scala有个初步映像。
从Maven到Gradle
第一篇文章是基于Maven做项目配置的,现在换成了Gradle。原因?Spring官方默认都是基于Gradle了,而且现在很多大型的Java项目都是基于Gradle进行构建了。如:Android、Kafka(Linkdin整体采用Gradle)。再加上我是一个比较爱折腾的人,既然现在有时间,为什么不试试Gradle呢?
代码在这里:https://github.com/yangbajing/spring-boot-scala,这次不但把构建工具换成了Gradle,还一步到位使用了多项目的构建方式,这样更符合真实开发的场景。
**注意:在build.gradle配置中,需要重新设置Scala和Java源码的搜索路径,把Java源码路径移动Scala的搜索路径来。不然编译时会遇到Java代码找不到Scala代码符号问题
**
1 | sourceSets { |
支持Scala数据类型
Spring Boot默认可以自动转换JSON数据格式到Java类型或反之,但怎样支持Scala数据类型呢?其实很简单,只需要加入jackson-module-scala
依赖:
1 | compile("com.fasterxml.jackson.module:jackson-module-scala_$scalaLibVersion:2.8.0.rc2") |
并添加jacksonModuleScala
Bean 即可:
1 |
|
现在,我们就可以在Spring中自由的使用case class
、Scala Collection
、Option
等类型和数据结构,甚至还可以和Java类型混合使用。比如我们把Java类型嵌入到Scala的case class里。
User.java
1 | public class User { |
Message.scala
1 | case class Message(name: String, |
Scala控制器 (ApiController.scala):
1 | Array("message"), method = Array(RequestMethod.POST)) (path = |
使用Scala编写Spring控制器方法,有些和Java不一样的地方和Scala的惯用法:
- 注解属性为数组时,Scala必需显示使用数组形式传参。如
@RequestMapping
注解的path
发型是一个数组类型,在Scala中需要显示传入一个数组类型的参数:Array("message")
。 - Scala中,方法返回值类型是可以自动推导的。但在写Spring控制器方法时推荐显示注明返回类型。
- Scala的所有表达式都有值,且代码块最后一个表达式的值就是代码块的值。这样,在Scala的函数里不需要使用
return
显示返回数据,也不推荐使用return
。
另外,若在Java代码中使用Scala的数据类型。如:case class。在Java中必需使用new
关键字进行实例化,像Scala那样直接通过类名实例化是不支持的。
Java控制器(WebController.java):
1 |
|
测试效果如下:
1 | $ curl -XPOST -H 'content-type: application/json;utf8' -d '{"user":"杨景","nickname":"羊八井"}' http://localhost:18080/web/message |
Java Function 和 Scala Function[N]
Java 8开始,支持Lambda函数。但是Java的Lambda函数与Scala的函数类型是不兼容的(好消息是,从Scala 2.12开始,将兼容Java Lambda函数)。我们可以使用scala-java8-compat
这个库来还算优雅的解决这个问题。
首先添加scala-java8-comat
依赖:
1 | compile("org.scala-lang.modules:scala-java8-compat_$scalaLibVersion:0.7.0") |
在Scala中访问Java8 Function,可以使用如下方式:
1 | import scala.compat.java8.FunctionConverters._ |
除了显示的使用asJavaSupplier
来转换特定的Java8 Function,还可以使用asJava
隐式转换来自动转换:
1 | name.orElseGet((() => reqMsg.name).asJava) |
总结
也许你并不喜欢Scala,也不需要在Spring中使用Scala,Java 8也足够。但我希望能为你打开了一扇门,在JVM平台上还有如此有意思的语言。
本系列文章