使用Groovy编写Spring Boot应用

考虑到我正在使用Gradle,我本打算尝试用Groovy来写应用程序的,但昨天被 IDEA 15 的建议打败了,我写成了Kotlin,但今天决定还是试试用Groovy来写。

这个 build.gradle 是不是看起来很简单呢?

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.RELEASE")
        classpath("org.springframework:springloaded:1.2.4.RELEASE")
    }
}

apply plugin: 'groovy'
apply plugin: 'spring-boot'
apply plugin: 'idea'

idea {
    module {
        inheritOutputDirs = false
        outputDir = file("$buildDir/classes/main/")
    }
}

sourceSets {
    main.groovy.srcDirs += 'src/main/groovy'
}
repositories {
    mavenCentral()
}
dependencies {
    compile("org.codehaus.groovy:groovy-all")
    compile("com.fasterxml.jackson.datatype:jackson-datatype-jdk8")
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("org.springframework.boot:spring-boot-starter-test")
}

在使用./gradlew idea进行设置之后,我们将使用Groovy来编写代码。

Groovy与Kotlin一样,没有类型,因此我们使用java.util.Optional。由于Spring Boot的JSON渲染使用的Jackson默认不会很好地处理Optional,所以我们需要将jackson-datatype-jdk8的Jdk8Module添加到dependencies并进行配置。

package friendlist

import com.fasterxml.jackson.datatype.jdk8.Jdk8Module
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration

@Configuration
@EnableAutoConfiguration
@ComponentScan
class Application {
    @Configuration
    static class JacksonModuleConfiguration {
        @Bean
        Jdk8Module javaOptionalModule() {
            new Jdk8Module()
        }
    }

    static void main(String[] args) {
        SpringApplication.run(Application.class, args)
    }
}

Groovy真是个方便易用的语言,可以直接在Java代码中进行修改。不过,有时候我会想写上”static def main”之类的代码,可惜它是不能写的呢。

你可以将def视为Object的别名,一瞬间就会理解。

下面我们将写下与Kotlin示例中的model和Controller相似的代码。

package friendlist.model

class Friend {
    Integer id
    Optional<String> name

    private static ALL_FRIENDS = Arrays.asList(
            new Friend(id: 1, name: Optional.of("Alice")),
            new Friend(id: 2, name: Optional.of("Bob")),
            new Friend(id: 3, name: Optional.of("Chris")),
            new Friend(id: 4, name: Optional.of("Denny")),
    )

    static List<Friend> findAll() {
        ALL_FRIENDS
    }

    static Optional<Friend> findById(Integer id) {
        Optional.ofNullable(ALL_FRIENDS.find { f -> f.id == id })
    }
}

class FriendResponse {
    Optional<Friend> friend
}
class FriendsResponse {
    List<Friend> friends
}

Groovy这种无需写return就可以的特点真是太棒了。


package friendlist.web

import friendlist.model.Friend
import friendlist.model.FriendResponse
import friendlist.model.FriendsResponse
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class HomeController {

    @RequestMapping("/")
    // def でも動く
    def home() {
        showAll()
    }

    @RequestMapping("/friends")
    FriendsResponse showAll() {
        new FriendsResponse(friends: Friend.findAll())
    }

    @RequestMapping("/friends/{id}")
    FriendResponse show(@PathVariable Integer id) {
        new FriendResponse(friend: Friend.findById(id))
    }
}

使用./gradlew bootRun命令启动它。Spring Loaded已启用,如果更改了Groovy代码,则除了重新加载Spring配置和静态内容的细微情况外,将进行热重载。

$ curl -v localhost:8080/
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 25 Nov 2015 12:43:38 GMT
<
* Connection #0 to host localhost left intact
{"friends":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"},{"id":3,"name":"Chris"},{"id":4,"name":"Denny"}]}

$ curl -v localhost:8080/friends/1
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /friends/1 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 25 Nov 2015 12:43:44 GMT
<
* Connection #0 to host localhost left intact
{"friend":{"id":1,"name":"Alice"}}

$ curl -v localhost:8080/friends/10
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /friends/10 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 25 Nov 2015 12:43:46 GMT
<
* Connection #0 to host localhost left intact
{"friend":null}

这也很顺利。Gradle + Spring Boot 真是方便又好用啊。

bannerAds