LoginSignup
7
8

More than 5 years have passed since last update.

Groovy で Spring Boot アプリを書く

Last updated at Posted at 2015-11-25

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 をよしなに扱ってくれないので dependencies に追加しておいた jackson-datatype-jdk8Jdk8Module を設定しておきます。

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 とか書きたくなるけど、書けないのですよねぇ..

You can think of def as an alias of Object and you will understand it in an instant.
http://www.groovy-lang.org/semantics.html#_variable_definition

次に 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 の設定再読み込みや static なものの細かいケース以外は hot reloading されます。

$ 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 は手軽でよいですね。

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8