読者です 読者をやめる 読者になる 読者になる

プログラマーの調べ物

プログラマーが調べ物をするときに役に立つサイトを作ります。

Spring Bootを起動させてもすぐにShutdownしてしまう場合にやること

http://stackoverflow.com/questions/39363570/spring-boot-application-shutdown-immediate-after-starting

こちらの回答の通りにやったらうまくいった。

The only possible explanation i can think of is that tomcat embedded jar is not included in the dependencies/jar. Since you have already defined "spring-boot-starter-web" dependency, it should have transitively pulled the embedded tomcat dependencies as well. But somehow it is excluded.

Things to try out.

Execute "mvn dependency:tree" and check whether the tomcat dependencies exist and in "compile" scope
Change the spring boot starter version to 1.4.0.RELEASE.
 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
    </parent>

最初、1.5.0.RELEASEなんてしてたのを、1.4.0に変更。 Run as…のRun configurationでMaven Build で、Goalsのところに「dependency:tree」を書いてRun

GradleでTomcatプロジェクトを実行する

gradle init --type java-library

で雛形を作ります。

次に、build.gradleを以下のように書きます。

/*
 * This build file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java project to get you started.
 * For more details take a look at the Java Quickstart chapter in the Gradle
 * user guide available at https://docs.gradle.org/3.3/userguide/tutorial_java_projects.html
 */

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.bmuschko:gradle-tomcat-plugin:2.0'
  }
}


apply plugin: 'war'
apply plugin: 'com.bmuschko.tomcat'

repositories {
  mavenCentral()
}

dependencies {
  providedCompile 'javax:javaee-web-api:6.0'
  compile 'org.slf4j:slf4j-api:1.7.5'
  testCompile 'junit:junit:4.11'

  def tomcatVersion = '7.0.52'
  tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
         "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
  tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
        exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
  }
}

src/main/java/exampleというディレクトリを作り、サーブレットを作成します。

HelloServet.javaです。

package exapmle;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

@WebServlet(name="HelloServlet", urlPatterns={"/hello"})
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException {
            res.getWriter().print("Hello!");
    }
}

src/main/webapp/というディレクトリを作成し、webapp以下にindex.htmlを作成します。

index.htmlです。

<h1>Hello, tomcat plugin.</h1>

ここまでやったら、

gradle tomcatRunWar

を実行します。 省略形はgradle tRWでOKです。

ビルドを実行すると、

  • Tomcatのライブラリなど依存ライブラリのダウンロード
  • Webアプリケーションのビルドとパッケージング(WARファイルの作成)
  • 組み込みTomcatの起動
  • Webアプリケーション(WARファイル)を組み込みTomcatへデプロイ

という一連の手順がGradleによって自動的に行われます。

GradleをインストールしてEclipseに取り込む

Gradleのインストール

brew install gradle

を実行。

コマンド

build.gradleに以下を記述。

task hello << {
    println 'Hello Gradle World!'
}

で、

gradle hello

を実行すると、task helloが実行される。

taskの一覧表示は

gradle tasks

ビルドスクリプトに定義されているプロパティの一覧を表示するタスクは以下。

gradle properties

GradleでJavaのプロジェクトを作成

以下のコマンドでJavaプロジェクトを作成できる。

gradle init --type java-library

Gradleで作成したプロジェクトをEclipseに追加する手順。

build.gradleに

apply plugin: 'eclipse'

を追記する。

次に、

gradle eclipse

を実行する。 すると、.classpathや.projectが作成される。

Eclipseで、"import" -> "Existing Projects into Workspace"をクリック。

gradle eclipseを実行したディレクトリを選択してインポートする。

gradle build

でGradleプロジェクトをビルドすることができる。

ThymeleafでListを繰り返して表示してみる。

Thymeleafのth:eachを使って、繰り返し表示してみます。

package com.example;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.form.EchoForm;

@Controller
@RequestMapping("echo")
public class EchoController {

    @RequestMapping(method = RequestMethod.GET)
    public String viewInput(Model model) {
        
        List<String> nameList = new ArrayList<String>();
        nameList.add("藤本祥");
        nameList.add("中川淳一");
        nameList.add("安倍隆弘");
        
        model.addAttribute("nameList",nameList);
        
        return "echo/input";
    }

HTMLはこんな感じ。

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<link href="/css/style.css" th:href="@{/css/style.css}" rel="stylesheet"/>
</head>
<body>
<h2>Name List</h2>

<table class="tbtest">
<tr>
  <th>Name</th>
</tr>

<tr th:each="name : ${nameList}">
  <td th:text="${name}" class="tdtest"></td>
</tr>
</table>

</body>
</html>

Spring BootでThymeleafを使ってViewを実装してみる。

ThymeleafはWebアプリケーションと親和性の高いテンプレートエンジンです。 テンプレートエンジンとは、雛形となるドキュメントに対し、可変データを埋め込むことで動的にドキュメントを生成する仕組みのことです。

Themeleafを使ってViewを作ってみます。

pom.xmlは以下のように書きます。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

コントローラーは以下のように書きます。

src/main/java/com/example/EchoController.java

package com.example;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.form.EchoForm;

@Controller
@RequestMapping("echo")
public class EchoController {

    @RequestMapping(method = RequestMethod.GET)
    public String viewInput(Model model) {
        EchoForm form = new EchoForm();
        model.addAttribute(form);
        return "echo/input";
    }
    
    @RequestMapping(method = RequestMethod.POST)
    public String echo(EchoForm form) {
        return "echo/output";
    }
}

フォームクラスを作成します。

src/main/java/com/example/form/EchoForm.java

package com.example.form;

import java.io.Serializable;

public class EchoForm implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
    
}

次にViewの部分です。

src/main/resources/templates/echo/input.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<h2>Echo Application</h2>
<form action="./output.html" th:action="@{/echo}"
  th:object="${echoForm}" method="POST">
  <div>Input Text</div>
  <div>
    <input type="text" name="text" th:field="*{text}"/><br/>
    <span th:if="${#fields.hasErrors('text')}"
        th:errors="*{text}">error message</span>
  </div>  
  <div>
    <button type="submit">Submit</button>
  </div>
</form>
</body>
</html>

src/main/resources/templates/echo/output.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
      
<body>
    <h2>出力画面</h2>
    <div>入力したテキストは...</div>
    <div><span th:text="*{echoForm.text}">ここに入力した値が表示される</span></div>
    <br/>
    <div>です</div>
    <div>
        <a href="../index.html" th:href="@{/}">トップ画面に戻る</a>
    </div>
</body>
      
</html>

テキストの出力

式の構文

名称 意味
変数式 ${echoForm.text} Thymeleafが管理する変数へアクセスしたり、メソッドを実行できる。プロパティ名を指定することで、フォームオブジェクトなどのModelに格納された情報にアクセスできる。
選択変数式 *{echoForm.text} 特定のオブジェクトに対するプロパティに連続してアクセスしたい時、th:object="${echoForm}"などと組み合わせて使う。
メッセージ式 #{status.reserved.message} メッセージをkey-valueで管理するための仕組み
リンクURL式 @{/echo} 指定したURLへのリンクを貼ることができる

Spring Bootでフォームアプリケーションを作成する

Spring Bootでフォームアプリケーションを作ります。

テキストボックスに値を入力

それをコントローラーで受け取って、モデルオブジェクトに突っ込む

モデルオブジェクトの内容を別のHTMLに表示する

というありがちな流れを作ってみます。

まずは、フォームの情報を格納するbeanを作成します。

こいつにフォームで入力した情報をぶち込みます。 src/main/java/com/example/form/Search.java

package com.example.form;

public class Search {
    private String userName;
    private String tagName;
    private String location;
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getTagName() {
        return tagName;
    }
    public void setTagName(String tagName) {
        this.tagName = tagName;
    }
    public String getLocation() {
        return location;
    }
    public void setLocation(String location) {
        this.location = location;
    }
    
    
}

次に、フォームを作りましょう。

src/main/resource/templates/search.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Search Form</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1>Form</h1>
    <form action="#" th:action="@{/search}" th:object="${search}" method="post">
        <p>User Name: <input type="text" th:field="*{userName}" /></p>
        <p>Tag Name: <input type="text" th:field="*{tagName}" /></p>
        <p>Location: <input type="text" th:field="*{location}" /></p>
        <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
    </form>
</body>
</html>

これが送信フォームです。 Submitボタン(送信ボタン)を押すと、リクエストが投げられます。

では、そのリクエストを処理するコントローラーを作りましょう。

src/main/java/com/example/SearchController.java

package com.example;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.example.form.Search;

@Controller
public class SearchController {

    @GetMapping("/search")
    public String searchForm(Model model) {
        model.addAttribute("search", new Search());
        return "search";
    }
    
    @PostMapping("/search")
    public String searchSubmit(@ModelAttribute Search search) {
        return "result";
    }
}

これで飛ばされたリクエストを処理することができます。 最後に、結果を表示するHTMLです。

src/main/resource/templates/result.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<title>Result</title>
</head>
<body>
<h1>Result</h1>
    <p th:text="'user name: ' + ${search.userName}" />
    <p th:text="'tag name: ' + ${search.tagName}" />
    <p th:text="'location: ' + ${search.location}" />
    <a href="/search">another search</a>
</body>
</html>

これで、送信した内容を表示することができます。

https://spring.io/guides/gs/handling-form-submission/

Spring Bootでフォームを送って結果を返す

とりあえずって感じですが、formタグで囲まれた情報をJava側に送りつけて、その結果をHTMLで返すサンプルです。

まずは、HTTP GETで情報を送信するHTMLです。

account.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<title>SAMPLE</title>
</head>
<body>
<form action="/result">
  <fieldset>
    <input type="text" name="name" />
    <input type="submit" value="Subscribe me!" />
  </fieldset>
</form>
</body>
</html>

これを受け取るJavaを書きます。

package com.example;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class RestaurantController {
    
    @RequestMapping("/account")
    public String account(Model model) {
        return "account";
    }
    
    @RequestMapping(value = "/result", method = RequestMethod.GET)
    public String form(Model model,@RequestParam String name) {
        model.addAttribute("name", name);
        return "result";
    }
    
}

結果を表示するHTMLです。

result.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<title>結果</title>
</head>
<body>
結果:
<span th:text="${name}"></span>
</body>
</html>

「結果: test」とブラウザに表示されます。