春のブートHello Worldの例 – 口ひげ
Spring Boot
Webアプリケーションの例、
embedded Tomcat Mustache template engine`を使用し、パッケージを実行可能な
JAR`ファイルとして使用します。
使用される技術:
-
春のブート1.5.2.RELEASE
-
Spring 4.3.7.RELEASE
-
jmustache 1.13
-
タイメレフ2.1.5.リリース
-
Tomcat埋め込み8.5.11
-
Maven 3
-
Java 8
1.プロジェクトディレクトリ
プロジェクトの依存関係
spring-boot-starter-mustache`を宣言すると、
Spring Mustache` Webアプリケーションを開発するために必要なものがすべて得られます。
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>spring-boot-web-mustache</artifactId> <packaging>jar</packaging> <name>Spring Boot Web Mustache Example</name> <description>Spring Boot Web Mustache Example</description> <url>/</url> <version>1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mustache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- hot swapping, live reload --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <!-- Optional, for bootstrap --> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7</version> </dependency> </dependencies> <build> <plugins> <!-- Package as an executable jar/war --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
プロジェクトの依存関係を表示する:
$ mvn dependency:tree [INFO]Scanning for projects...[INFO][INFO]------------------------------------------------------------------------[INFO]Building Spring Boot Web Mustache Example 1.0[INFO]------------------------------------------------------------------------[INFO][INFO]--- maven-dependency-plugin:2.10:tree (default-cli) @ spring-boot-web-mustache --- [INFO]org.springframework.boot:spring-boot-web-mustache:jar:1.0[INFO]+- org.springframework.boot:spring-boot-starter-mustache:jar:1.5.2.RELEASE:compile[INFO]| +- org.springframework.boot:spring-boot-starter:jar:1.5.2.RELEASE:compile[INFO]| | +- org.springframework.boot:spring-boot-starter-logging:jar:1.5.2.RELEASE:compile[INFO]| | | +- ch.qos.logback:logback-classic:jar:1.1.11:compile[INFO]| | | | \- ch.qos.logback:logback-core:jar:1.1.11:compile[INFO]| | | +- org.slf4j:jcl-over-slf4j:jar:1.7.24:compile[INFO]| | | +- org.slf4j:jul-to-slf4j:jar:1.7.24:compile[INFO]| | | \- org.slf4j:log4j-over-slf4j:jar:1.7.24:compile[INFO]| | \- org.yaml:snakeyaml:jar:1.17:runtime[INFO]| +- org.springframework.boot:spring-boot-starter-web:jar:1.5.2.RELEASE:compile[INFO]| | +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.5.2.RELEASE:compile[INFO]| | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.11:compile[INFO]| | | +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.11:compile[INFO]| | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.11:compile[INFO]| | +- org.hibernate:hibernate-validator:jar:5.3.4.Final:compile[INFO]| | | +- javax.validation:validation-api:jar:1.1.0.Final:compile[INFO]| | | +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile[INFO]| | | \- com.fasterxml:classmate:jar:1.3.3:compile[INFO]| | +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.7:compile[INFO]| | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.0:compile[INFO]| | | \- com.fasterxml.jackson.core:jackson-core:jar:2.8.7:compile[INFO]| | +- org.springframework:spring-web:jar:4.3.7.RELEASE:compile[INFO]| | | +- org.springframework:spring-aop:jar:4.3.7.RELEASE:compile[INFO]| | | \- org.springframework:spring-beans:jar:4.3.7.RELEASE:compile[INFO]| | \- org.springframework:spring-webmvc:jar:4.3.7.RELEASE:compile[INFO]| | \- org.springframework:spring-expression:jar:4.3.7.RELEASE:compile[INFO]| \- com.samskivert:jmustache:jar:1.13:compile[INFO]+- org.springframework.boot:spring-boot-starter-test:jar:1.5.2.RELEASE:test[INFO]| +- org.springframework.boot:spring-boot-test:jar:1.5.2.RELEASE:test[INFO]| +- org.springframework.boot:spring-boot-test-autoconfigure:jar:1.5.2.RELEASE:test[INFO]| +- com.jayway.jsonpath:json-path:jar:2.2.0:test[INFO]| | +- net.minidev:json-smart:jar:2.2.1:test[INFO]| | | \- net.minidev:accessors-smart:jar:1.1:test[INFO]| | | \- org.ow2.asm:asm:jar:5.0.3:test[INFO]| | \- org.slf4j:slf4j-api:jar:1.7.24:compile[INFO]| +- junit:junit:jar:4.12:test[INFO]| +- org.assertj:assertj-core:jar:2.6.0:test[INFO]| +- org.mockito:mockito-core:jar:1.10.19:test[INFO]| | \- org.objenesis:objenesis:jar:2.1:test[INFO]| +- org.hamcrest:hamcrest-core:jar:1.3:test[INFO]| +- org.hamcrest:hamcrest-library:jar:1.3:test[INFO]| +- org.skyscreamer:jsonassert:jar:1.4.0:test[INFO]| | \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test[INFO]| +- org.springframework:spring-core:jar:4.3.7.RELEASE:compile[INFO]| \- org.springframework:spring-test:jar:4.3.7.RELEASE:test[INFO]+- org.springframework.boot:spring-boot-devtools:jar:1.5.2.RELEASE:compile[INFO]| +- org.springframework.boot:spring-boot:jar:1.5.2.RELEASE:compile[INFO]| | \- org.springframework:spring-context:jar:4.3.7.RELEASE:compile[INFO]| \- org.springframework.boot:spring-boot-autoconfigure:jar:1.5.2.RELEASE:compile[INFO]\- org.webjars:bootstrap:jar:3.3.7:compile[INFO] \- org.webjars:jquery:jar:1.11.1:compile[INFO]------------------------------------------------------------------------[INFO]BUILD SUCCESS[INFO]------------------------------------------------------------------------[INFO]Total time: 1.796 s[INFO]Finished at: 2017-04-19T11:46:09+08:00[INFO]Final Memory: 22M/437M[INFO]------------------------------------------------------------------------
3.春のブート
3.1 `@ SpringBootApplication`クラスを作成します。 SpringブートWebアプリケーションを起動するには、このクラスを実行します。
SpringBootWebApplication.java
package com.mkyong; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootWebApplication { public static void main(String[]args) throws Exception { SpringApplication.run(SpringBootWebApplication.class, args); } }
3.2単純なコントローラクラス。
WelcomeController.java
package com.mkyong; import java.util.Map; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class WelcomeController { //inject via application.properties @Value("${app.welcome.message}") private String MESSAGE = ""; @Value("${app.welcome.title}") private String TITLE = ""; @RequestMapping("/") public String welcome(Map<String, Object> model) { model.put("title", TITLE); model.put("message", MESSAGE); return "welcome"; } //test 5xx errors @RequestMapping("/5xx") public String ServiceUnavailable() { throw new RuntimeException("ABC"); } }
4. Mustache Resources静的ファイル
4.1 Mustacheテンプレートファイルについては、 `src/main/resources/templates/`に入れます。
src/main/resources/templates/layout/header.html
<!DOCTYPE HTML> <head> <title>{{title}}</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/> <link rel="stylesheet" href="css/main.css"/> </head> <!-- this is header -->
src/main/resources/templates/layout/footer.html
<!-- this is footer --> </html>
src/main/resources/templates/welcome.html
{{>layout/header}} <body> <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">Spring Boot</a> </div> </div> </nav> <div class="container"> <div class="starter-template"> <h1>Spring Boot Web Mustache Example</h1> <h2> {{message}} </h2> </div> </div> <!--/.container --> <script type="text/javascript" src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script> </body> {{>layout/footer}}
4.2 CSSやJavascriptのような静的ファイルの場合、 `/src/main/resources/static/`に入れます。
/src/main/resources/static/css/main.css
h1{ color:#0000FF; } h2{ color:#FF0000; }
4.3エラーテンプレートの場合。
-
注** この記事を読むhttps://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-error-handling[Spring Boot – エラー処理]を使用して、デフォルトのエラーマッピングページの仕組みを理解してください。
src/main/resources/templates/error.html
<!DOCTYPE html> <html lang="en"> <body> Something went wrong: {{status}} {{error}} </body> </html>
src/main/resources/templates/error/5xx.html
<!DOCTYPE html> <html lang="en"> <body> I'm a 5xx </body> </html>
4.4プロパティファイルについては、 `/src/main/resources/`に入れてください。
/src/main/resources/application.properties
app.welcome.message: Hello Mkyong app.welcome.title: Spring Boot Mustache Hello World Example
-
注** リソースを理解するには、http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-static-content[Spring Boot static static content]をお読みくださいマッピング。
5.単体テスト
5.1 SpringブートWebアプリケーションの上でテストするユニットテストの例。
MustacheApplicationTests
package com.mkyong; import static org.assertj.core.api.Assertions.assertThat; import java.util.Arrays; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM__PORT) @DirtiesContext public class MustacheApplicationTests { @Autowired private TestRestTemplate restTemplate; @Test public void testMainPage() throws Exception { ResponseEntity<String> entity = this.restTemplate.getForEntity("/", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("Hello Mkyong"); } @Test public void test404Page() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.TEXT__HTML)); HttpEntity<String> requestEntity = new HttpEntity<String>(headers); ResponseEntity<String> responseEntity = this.restTemplate.exchange("/uri-not-exist", HttpMethod.GET, requestEntity, String.class); assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.NOT__FOUND); assertThat(responseEntity.getBody()).contains("Something went wrong: 404 Not Found"); } @Test public void test5xxPage() throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.TEXT__HTML)); HttpEntity<String> requestEntity = new HttpEntity<String>(headers); ResponseEntity<String> responseEntity = this.restTemplate.exchange("/5xx", HttpMethod.GET, requestEntity, String.class); assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL__SERVER__ERROR); assertThat(responseEntity.getBody()).contains("I'm a 5xx"); } }
6.デモ
メモIDEでは、 `@ SpringBootApplication`アノテーション付きクラスを実行すると、SpringBootアプリケーション全体が開始されます。
6.1 Spring起動Webアプリケーションを起動します。
ターミナル
project$ mvn spring-boot:run //... . ________ __ ____ __ __ /\\/______'__ ____ __ __(__)__ ____ ____ __ \ \ \ \ ( ( )\______ | '__ | '__| | '__ \/__` | \ \ \ \ \\/ ______)| |__)| | | | | || (__| | ) ) ) ) ' |________| .____|__| |__|__| |__\____, |//// =========|__|==============|______/=/__/__/__/ :: Spring Boot :: (v1.5.2.RELEASE) 2017-04-19 12:17:38.014 INFO 6232 ---[ restartedMain]com.mkyong.SpringBootWebApplication : Starting SpringBootWebApplication on MKYONG-WIN10 with PID 6232 (C:\spring-boot\spring-boot-examples\spring-boot-web-mustache\target\classes started by mkyong in C:\spring-boot\spring-boot-examples\spring-boot-web-mustache) 2017-04-19 12:17:38.015 INFO 6232 ---[ restartedMain]com.mkyong.SpringBootWebApplication : No active profile set, falling back to default profiles: default 2017-04-19 12:17:38.074 INFO 6232 ---[ restartedMain]ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@af1619: startup date[Wed Apr 19 12:17:38 SGT 2017]; root of context hierarchy 2017-04-19 12:17:39.352 INFO 6232 ---[ restartedMain]s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2017-04-19 12:17:39.370 INFO 6232 ---[ restartedMain]o.apache.catalina.core.StandardService : Starting service Tomcat 2017-04-19 12:17:39.372 INFO 6232 ---[ restartedMain]org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.11 2017-04-19 12:17:39.481 INFO 6232 ---[ost-startStop-1]o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2017-04-19 12:17:39.481 INFO 6232 ---[ost-startStop-1]o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1410 ms 2017-04-19 12:17:39.649 INFO 6232 ---[ost-startStop-1]o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to[/]2017-04-19 12:17:39.658 INFO 6232 ---[ost-startStop-1]o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to:[/** ]2017-04-19 12:17:39.659 INFO 6232 ---[ost-startStop-1]o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to:[/** ]2017-04-19 12:17:39.659 INFO 6232 ---[ost-startStop-1]o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to:[/** ]2017-04-19 12:17:39.660 INFO 6232 ---[ost-startStop-1]o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to:[/** ]2017-04-19 12:17:39.938 INFO 6232 ---[ restartedMain]s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@af1619: startup date[Wed Apr 19 12:17:38 SGT 2017]; root of context hierarchy 2017-04-19 12:17:39.997 INFO 6232 ---[ restartedMain]s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String com.mkyong.WelcomeController.welcome(java.util.Map<java.lang.String, java.lang.Object>) 2017-04-19 12:17:39.997 INFO 6232 ---[ restartedMain]s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/5xx]}" onto public java.lang.String com.mkyong.WelcomeController.ServiceUnavailable() 2017-04-19 12:17:40.006 INFO 6232 ---[ restartedMain]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) 2017-04-19 12:17:40.006 INFO 6232 ---[ restartedMain]s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2017-04-19 12:17:40.041 INFO 6232 ---[ restartedMain]o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path[/webjars/** ** ]onto handler of type[class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]2017-04-19 12:17:40.041 INFO 6232 ---[ restartedMain]o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path[/** ** ]onto handler of type[class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]2017-04-19 12:17:40.090 INFO 6232 ---[ restartedMain]o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path[/** ** /favicon.ico]onto handler of type[class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]2017-04-19 12:17:40.332 INFO 6232 ---[ restartedMain]o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2017-04-19 12:17:40.373 INFO 6232 ---[ restartedMain]o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2017-04-19 12:17:40.427 INFO 6232 ---[ restartedMain]s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2017-04-19 12:17:40.435 INFO 6232 ---[ restartedMain]com.mkyong.SpringBootWebApplication : Started SpringBootWebApplication in 2.737 seconds (JVM running for 3.124)
6.2アクセス
http://localhost:8080
6.2アクセス
http://localhost:8080/5xx
6.実行可能なJARをビルドする
6.1プロジェクトをパッケージ化して、実行可能な `JAR`ファイルを作成します。
project$ mvn clean package
6.2それを実行し、
http://localhost:8080
に再度アクセスします。
project$ java -jar target/spring-boot-web-mustache-1.0.jar
ソースコードをダウンロードする
ダウンロードする –
spring-boot-web-mustache.zip
(11 KB)
参考文献
-
https://github.com/samskivert/jmustache
[jmustache – Java
Mustacheテンプレート言語の実装]。
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-error-handling
[Spring
ブート – エラー処理]。
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-static-content
[Spring
ブート – 静的コンテンツ]。
https://spring.io/blog/2014/03/07/deploying-spring-boot-applications
[Deploying
春のブートアプリケーション]。リンク://spring-mvc/spring-mvc-how-to-include-js-or-css-files-in-a-jsp-page/[Spring
MVC – Inlucde CSSファイル]。
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-devtools
[Spring
ブート – 開発者ツール]。
https://spring.io/guides/gs/serving-web-content/
[ウェブコンテンツの配信
Spring MVCで]。リンク://spring-boot/spring-boot-hello-world-example-jsp/[Spring Boot
Hello Worldの例 – JSP]