Spring BootでRESTfulなサービスを作ってみる
丹内です。 spring bootのドキュメントBuilding a RESTful Web Serviceを参考にして、簡単なアプリケーションを作ってみます。
環境
- Mac OSX 10.10.5
- InteliJ IDEA 14.1.5
- java version "1.7.0_79"
- Gradle 2.7
サンプルプロジェクトのセットアップ
最初に、サンプルコードをダウンロードします。
$ cd devel $ git clone https://github.com/spring-guides/gs-rest-service.git Cloning into 'gs-rest-service'... remote: Counting objects: 1312, done. remote: Total 1312 (delta 0), reused 0 (delta 0), pack-reused 1312 Receiving objects: 100% (1312/1312), 673.48 KiB | 322.00 KiB/s, done. Resolving deltas: 100% (673/673), done. Checking connectivity... done.
とりあえずドキュメントにそって、gs-rest-service/initial
の中身を見てみましょう。
$ cd gs-rest-service/initial $ ls build.gradle gradle gradlew gradlew.bat pom.xml src
次に、InteliJにこのプロジェクトをインポートします。
以後、InteliJの画面でファイルを作っていきます。
ファイルの作成
まずはsrc/main/java/hello/Greeting.java
です。
package hello; public class Greeting { private final long id; private final String content; public Greeting(long id, String content) { this.id = id; this.content = content; } public long getId() { return id; } public String getContent() { return content; } }
このクラスは、今回返したい以下のレスポンスに対応しています。
{ "id": 1, "content": "Hello, World!" }
Jackson JSONというライブラリを使っているので、その命名規則に従うようです。
次にsrc/main/java/hello/GreetingController.java
です。
package hello; import java.util.concurrent.atomic.AtomicLong; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class GreetingController { private static final String template = "Hello, %s!"; private final AtomicLong counter = new AtomicLong(); @RequestMapping("/greeting") public Greeting greeting(@RequestParam(value="name", defaultValue = "World") String name) { return new Greeting(counter.incrementAndGet(), String.format(template, name)); } }
@RequestMapping
でパスとメソッドを結びつけます。
なお、これだとどのHTTPメソッドでも対応します。これをGETだけに限定したい場合は、@RequestMapping(method=GET)
とするようです。
最後にsrc/main/java/hello/Application.java
です。
package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
@SpringBootApplication
アノテーションが、いわゆる「魔法のアノテーション」のようです。
これでOKです。
動かしてみる
今回は、サンプルコードに同梱されているgradlew
というスクリプトでビルドします。
$ ./gradlew build Downloading https://services.gradle.org/distributions/gradle-2.3-bin.zip ........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... Unzipping /Users/tannaiyuki/.gradle/wrapper/dists/gradle-2.3-bin/5asu2gih68751vffoiv0n84555/gradle-2.3-bin.zip to /Users/tannaiyuki/.gradle/wrapper/dists/gradle-2.3-bin/5asu2gih68751vffoiv0n84555 Set executable permissions for: /Users/tannaiyuki/.gradle/wrapper/dists/gradle-2.3-bin/5asu2gih68751vffoiv0n84555/gradle-2.3/bin/gradle :compileJava FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':compileJava'. > 1.8は無効なソース・リリースです * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. BUILD FAILED Total time: 6 mins 23.322 secs
エラーになってしまいました。どうやらjavaのバージョンが設定と合っていないということのようです。
今回は、build.gradle
の設定値を変えることで対応します。
これを
sourceCompatibility = 1.8 targetCompatibility = 1.8
こうします。
sourceCompatibility = 1.7 targetCompatibility = 1.7
これでまたビルドしてみます。
$ ./gradlew build :compileJava :processResources UP-TO-DATE :classes :jar :findMainClass :startScripts :distTar :distZip :bootRepackage :assemble :compileTestJava UP-TO-DATE :processTestResources UP-TO-DATE :testClasses UP-TO-DATE :test UP-TO-DATE :check UP-TO-DATE :build BUILD SUCCESSFUL Total time: 11.28 secs
できたようです。実行してみます。
java -jar build/libs/gs-rest-service-0.1.0.jar . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.2.6.RELEASE) 2015-10-14 09:45:39.241 INFO 23040 --- [ main] hello.Application : Starting Application on HL00096.local with PID 23040 (/Users/tannaiyuki/devel/gs-rest-service/initial/build/libs/gs-rest-service-0.1.0.jar started by tannaiyuki in /Users/tannaiyuki/devel/gs-rest-service/initial) 2015-10-14 09:45:39.319 INFO 23040 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@4aec078b: startup date [Wed Oct 14 09:45:39 JST 2015]; root of context hierarchy 2015-10-14 09:45:40.150 INFO 23040 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]] 2015-10-14 09:45:41.157 INFO 23040 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2015-10-14 09:45:41.558 INFO 23040 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat 2015-10-14 09:45:41.560 INFO 23040 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.0.26 2015-10-14 09:45:41.721 INFO 23040 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2015-10-14 09:45:41.722 INFO 23040 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2405 ms 2015-10-14 09:45:42.768 INFO 23040 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] 2015-10-14 09:45:42.774 INFO 23040 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] 2015-10-14 09:45:42.774 INFO 23040 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] 2015-10-14 09:45:43.042 INFO 23040 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@4aec078b: startup date [Wed Oct 14 09:45:39 JST 2015]; root of context hierarchy 2015-10-14 09:45:43.129 INFO 23040 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/greeting]}" onto public hello.Greeting hello.GreetingController.greeting(java.lang.String) 2015-10-14 09:45:43.133 INFO 23040 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2015-10-14 09:45:43.134 INFO 23040 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest) 2015-10-14 09:45:43.171 INFO 23040 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2015-10-14 09:45:43.171 INFO 23040 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2015-10-14 09:45:43.227 INFO 23040 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2015-10-14 09:45:43.336 INFO 23040 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2015-10-14 09:45:43.451 INFO 23040 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2015-10-14 09:45:43.453 INFO 23040 --- [ main] hello.Application : Started Application in 4.956 seconds (JVM running for 5.682) 2015-10-14 09:45:51.412 INFO 23040 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet' 2015-10-14 09:45:51.412 INFO 23040 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started 2015-10-14 09:45:51.431 INFO 23040 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 19 ms
では、ブラウザからアクセスしてみましょう。
うまく行ったようです。
まとめ
Spring Bootを使って、簡単にアプリケーションを作成することができました。
今回雑に解決したバージョンの部分は、今後適切に対処していきたいです。