文档章节

Scala开发者的Spring-Boot快速上手指南 02:Scala惯用法

羊八井
 羊八井
发布于 2016/10/12 17:15
字数 1331
阅读 207
收藏 2

(这是一篇迟来的文章,从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代码符号问题 **

    sourceSets {
        main {
            scala {
                srcDirs = ['src/main/scala', 'src/main/java']
            }
            java {
                srcDirs = []
            }
        }
        test {
            scala {
                srcDirs = ['src/test/scala', 'src/test/java']
            }
            java {
                srcDirs = []
            }
        }
    }

支持Scala数据类型

Spring Boot默认可以自动转换JSON数据格式到Java类型或反之,但怎样支持Scala数据类型呢?其实很简单,只需要加入jackson-module-scala依赖:

compile("com.fasterxml.jackson.module:jackson-module-scala_$scalaLibVersion:2.8.0.rc2")

并添加jacksonModuleScala Bean 即可:

    @Bean
    public Module jacksonModuleScala() {
        return new DefaultScalaModule();
    }

现在,我们就可以在Spring中自由的使用case classScala CollectionOption等类型和数据结构,甚至还可以和Java类型混合使用。比如我们把Java类型嵌入到Scala的case class里。

User.java

public class User {
    private String name;
    private String nickname;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getNickname() {
        return nickname;
    }
    public void setNickname(String nickname) {
        this.nickname = nickname;
    }
}

Message.scala

case class Message(name: String,
                   age: Int,
                   user: User,
                   status: Option[Boolean]) {
  @BeanProperty val createdAt: LocalDateTime = LocalDateTime.now()
}

Scala控制器 (ApiController.scala):

  @RequestMapping(path = Array("message"), method = Array(RequestMethod.POST))
  def message(@RequestBody reqMsg: Message): Seq[Message] = {
    List(
      reqMsg,
      reqMsg.copy(age = reqMsg.age + 1, status = Some(true))
    )
  }

使用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):

    @RequestMapping(path = "message", method = RequestMethod.POST)
    public Message message(@RequestBody User user) {
        return new Message("Yang Jing", 30, user, new Some(false));
    }

测试效果如下:

$ curl -XPOST -H 'content-type: application/json;utf8' -d '{"user":"杨景","nickname":"羊八井"}' http://localhost:18080/web/message

{"name":"Yang Jing","age":30,"user":{"name":null,"nickname":"羊八井"},"status":false,"createdAt":"2016-08-25T17:22:50.841"}

$ curl -XPOST -H 'content-type: application/json;utf8' -d '{"name":"yangbajing","age":30,"user":{"name":"杨景","nickname":"羊八井"}}' http://localhost:18080/api/message

[{"name":"yangbajing","age":30,"user":{"name":"杨景","nickname":"羊八井"},"status":null,"createdAt":"2016-08-25T17:26:03.352"},{"name":"yangbajing","age":31,"user":{"name":"杨景","nickname":"羊八井"},"status":true,"createdAt":"2016-08-25T17:26:03.352"}]

Java Function 和 Scala Function[N]

Java 8开始,支持Lambda函数。但是Java的Lambda函数与Scala的函数类型是不兼容的(好消息是,从Scala 2.12开始,将兼容Java Lambda函数)。我们可以使用scala-java8-compat这个库来还算优雅的解决这个问题。

首先添加scala-java8-comat依赖:

    compile("org.scala-lang.modules:scala-java8-compat_$scalaLibVersion:0.7.0")

在Scala中访问Java8 Function,可以使用如下方式:

import scala.compat.java8.FunctionConverters._

def(@RequestParam name: Optional[String], ...

  name.orElseGet(asJavaSupplier(() => reqMsg.name))

除了显示的使用asJavaSupplier来转换特定的Java8 Function,还可以使用asJava隐式转换来自动转换:

 name.orElseGet((() => reqMsg.name).asJava)

总结

也许你并不喜欢Scala,也不需要在Spring中使用Scala,Java 8也足够。但我希望能为你打开了一扇门,在JVM平台上还有如此有意思的语言。

© 著作权归作者所有

羊八井

羊八井

粉丝 93
博文 41
码字总数 51095
作品 0
朝阳
技术主管
私信 提问
Scala开发者的Spring-Boot快速上手指南 01

做为一个Scala爱好者,是很想基于 Lightbend 的一套架构进行软件开发的。Play,Akka,Scala,Spark……。不过理想很丰满,现实却很骨感。鉴于那批原教旨主义者,他们对 Spring 已经疯狂迷恋,...

羊八井
2016/03/04
1K
2
Java/Scala互操作实践 1:基础操作

本文将以Spring Boot为例,介绍下实际工作中的Java/Scala互操作。在提高个人效率、满足自我追求的情况下更多的照顾到团队不同人的实际。同时也是想说明,在同一个工程里混用Java和Scala语言是...

羊八井
2016/10/10
2.3K
10
第9章 Spring Boot开发者工具

第9章 Spring Boot开发者工具 Spring Boot为Maven和Gradle提供构建工具插件。 9.1 Spring Boot maven plugin Spring Boot Maven Plugin,提供了使用Maven构建Spring Boot 工程的支持。我们可...

程序员诗人
2017/04/25
0
0
8.4 Spring Boot集成Kotlin混合Java开发

8.4 Spring Boot集成Kotlin混合Java开发 本章介绍Spring Boot集成Kotlin混合Java开发一个完整的spring boot应用:Restfeel,一个企业级的Rest API接口测试平台(在开源工程restfiddle[1]基础...

程序员诗人
2017/04/25
0
0
SpringBoot整合Scala构建Web服务

今天我们尝试Spring Boot整合Scala,并决定建立一个非常简单的Spring Boot微服务,使用Scala作为编程语言进行编码构建。 创建项目 初始化项目 修改pom.xml增加java和scala的支持 一个简单的应...

qianmoQ
03/01
49
0

没有更多内容

加载失败,请刷新页面

加载更多

Redis集群搭建

服务器资源 ip 账号 配置 操作系统 xxx.70 root/xxx 磁盘50G(/)+150G(/home)、内存16G、CPU 16core CentOS Linux release 7.2.1511 (Core) xxx.74 root/xxx 磁盘50G(/)+150G(/home)、......

jxlgzwh
16分钟前
2
0
avro

一、 ```我们已经接触过很多序列化框架(或者集成系统),比如protobuf、hessian、thrift等,它们各有优缺点以及各自的实用场景,Avro也是一个序列化框架,它的设计思想、编程模式都和thi...

hexiaoming123
17分钟前
3
0
QML TextInput的字体超出控件范围

本文链接:https://blog.csdn.net/chyuanrufeng/article/details/54691998 问题描述 :QML TextInput输入内容超过TextInput的大小 当输入过多的字符串时,会出现内容超过TextInput的大小,字...

shzwork
19分钟前
2
0
《Java 8 in Action》Chapter 10:用Optional取代null

1965年,英国一位名为Tony Hoare的计算机科学家在设计ALGOL W语言时提出了null引用的想法。ALGOL W是第一批在堆上分配记录的类型语言之一。Hoare选择null引用这种方式,“只是因为这种方法实...

HelloDeveloper
20分钟前
1
0
进击的 Java ,云原生时代的蜕变

作者| 易立 阿里云资深技术专家<br /> <br />导读:云原生时代的来临,与Java 开发者到底有什么联系?有人说,云原生压根不是为了 Java 存在的。然而,本文的作者却认为云原生时代,Java 依然...

阿里巴巴云原生
22分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部