■目次
Spring Framework と Spring Boot開発環境インストールプロジェクトの作成プログラムの作成プログラムのパッケージ化についてJARファイルの作成IntelliJ IDEA + Spring Boot での開発IntelliJ IDEA + Spring Boot での開発 引き続きVagrantでアプリケーション(JAR)を起動EC2でアプリケーション(JAR)を起動Elastic Beanstalk でアプリケーション(JAR)を起動その他参考になりそうなページ
■Spring Framework と Spring Boot
Spring Frameworkは、Javaのアプリケーションフレームワーク 任意のJavaアプリケーション作成に使うことができ、Webアプリケーションを構築するための機能も豊富に用意されている ただし多機能な分、機能の使い分けが困難となっている そのため、「Spring Boot」としてWebアプリケーション開発を手軽に扱えるようにして提供されている (PHPでの「重厚なSymfonyと手軽なLaravel」のような関係なのかもしれない) Spring Framework - Wikipedia https://ja.wikipedia.org/wiki/Spring_Framework 多様化するJavaのフレームワーク問題を解決する、「Spring Boot」とは? (1/3):CodeZine(コードジン) https://codezine.jp/article/detail/11310
■開発環境インストール
※後からIntelliJ IDEAでの開発について検証した 詳細は後述の「IntelliJ IDEA + Spring Boot での開発」を参照 Spring Tools 4 http://spring.io/tools SpringBootに入門する為の助走本(随時更新) - Qiita https://qiita.com/sugaryo/items/5695bfcc21365f429767 ■JDKインストール Java環境構築(Windows版) JDKインストール | ITエンジニア"が作るメディア Tech Fun Magazine https://techfun.cc/java/windows-jdk-install.html Java環境構築(Windows版) パスの設定 | ITエンジニア"が作るメディア Tech Fun Magazine https://techfun.cc/java/windows-jdk-pathset.html コマンドプロンプトで以下のように表示できれば成功 >java -version java version "14.0.1" 2020-04-14 Java(TM) SE Runtime Environment (build 14.0.1+7) Java HotSpot(TM) 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing) ■Mavenインストール WindowsにSpring Tool Suiteを導入する - Qiita https://qiita.com/segur/items/4cd283d9763a1953f336 C:\apache-maven-3.6.3 に配置 ■Spring Toolsインストール 【第一回】Spring Frameworkを使ってみる 〜Spring Framework概要と準備〜 | TECH Projin https://tech.pjin.jp/blog/2016/04/28/springframework1/ 上記ページの解説で触れられている Spring Tools 4 for Eclipse を試してみる Download STS4 (for Windows 64-bit) をダウンロード ※2020年5月16日現在、多くの解説にあるようにzipファイルはダウンロードできない 代わりにjarファイルをダウンロードできるようになっている JDKをインストール済みなら、ファイルを実行すれば解答できる C:\sts4 に配置 C:\sts4\SpringToolSuite4.exe を実行して起動 Select a directory as workspace C:\Users\refirio\sts4 に設定して「Launch」 日本語化のため、いったん終了させる ■日本語化 WindowsにSpring Tool Suiteを導入する - Qiita https://qiita.com/segur/items/4cd283d9763a1953f336 setup.exe を実行 C:\sts4\SpringToolSuite4.exe を選択して「日本語化する」ボタンを押す SpringToolSuite4.exe を実行して起動。日本語化されていることを確認する
■プロジェクトの作成
【第二回】Spring Frameworkを使ってみる 〜プロジェクト作成からビルドまで〜 | TECH Projin https://tech.pjin.jp/blog/2016/04/28/springframework2/ 「Spring Legacy Project」が見当たらない 色々変更されているようなので以下を参考に進める SpringBootに入門する為の助走本(随時更新) - Qiita https://qiita.com/sugaryo/items/5695bfcc21365f429767 ファイル → 新規 → Spring スターター・プロジェクト を実行 「新規 Spring スターター・プロジェクト」ダイアログが開くので、そのまま「次へ」をクリック 「新規 Spring スターター・プロジェクト依存関係」が表示されるので、「テンプレートエンジン → Thymeleaf」と「Web → Spring Web」にチェックを入れて「次へ」をクリック 「新規 Spring スターター・プロジェクト」ダイアログが開くので、そのまま「完了」をクリック で設定完了
■プログラムの作成
[Java] Spring BootでHello World!(入門編) | マリンロード https://www.marineroad.com/staff-blog/16785.html ファイル → 新規 → クラス ソース・フォルダー: demo/src/main/java パッケージ: com.example.demo 名前: HelloController
package com.example.demo; public class HelloController { }
が作成されるので、以下のように変更する
package com.example.demo; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; @RestController public class HelloController { @RequestMapping("/hello") public String hello() { return "Hello World !!"; } }
プロジェクトを右クリックし、 実行 → Spring Boot アプリケーション を選択。コンソールに色々表示され、8080番ポートでTomcatが起動し、アプリケーションが開始したと表示される 以下にアクセスすると「Hello World !!」と表示される http://localhost:8080/hello プログラムを編集し、ツールバーの赤い四角で停止し、緑の再生ボタンで実行すると、編集内容が反映された ■リクエストマッピングの追加 以下のようにすると / と /hello と /goodbye でそれぞれテキストが表示されるようになる
package com.example.demo; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; @RestController public class HelloController { @RequestMapping("/") public String index() { return "Demo"; } @RequestMapping("/hello") public String hello() { return "Hello World."; } @RequestMapping("/goodbye") public String bye() { return "Good Bye World !!"; } }
■リクエストパラメータの受け取り
import org.springframework.web.bind.annotation.RequestParam; @RequestMapping("/request") private String testRequestParam(@RequestParam("name") String param) { return "受け取ったリクエストパラメータ:" + param; }
http://localhost:8080/request/?name=test ■パスパラメータの受け取り
import org.springframework.web.bind.annotation.PathVariable; @RequestMapping("/path/{param}") private String testPathVariable(@PathVariable String param) { return "受け取ったパスパラメータ:" + param; }
http://localhost:8080/path/abc
■プログラムのパッケージ化について
JAR,WAR,EARそれぞれの違いについて - Java習得を目指すブログ https://java-wizard.hatenadiary.org/entry/20140311/1394538929 SpringBootで実行可能Jarを作る - 【Spring Hack】 https://springhack.com/springboot%E3%81%A7%E5%AE%9F%E8%A1%8C%E5%8F%AF%E8%83%BDjar%E3%82%92%E4%BD%9C%... SpringBootアプリケーション(Jar)をCentOS7にデプロイ - Qiita https://qiita.com/Masahiro_Uemura1234/items/2c60ad1e0365e3b7bdc9 JAR ... Java ARchive Javaプログラムの実行に必要なクラスファイルや設定ファイルがまとめられているアーカイブ WAR ... Web ARchive Java製のWebアプリで利用されるクラスファイル、設定ファイル、JSPやHTMLファイル、JAR形式のライブラリなどがまとめられているアーカイブ ただしSpringBootで書き出せるJarにはTomcatが含まれていて、単体で実行可能となっている 特に理由がなければJARでパッケージ化するといい(この後のメモもJARを書き出す内容となっている)
■JARファイルの作成
※Spring Boot のJARファイルはTomcatも含まれているので、WARよりもJARを書き出す方が環境構築が容易になる Spring Boot をはじめてみるよ - Multi Vitamin & Mineral http://hiranoon.hatenablog.com/entry/2015/12/30/111829#jar-%E3%81%AE%E4%BD%9C%E6%88%90%E3%81%A8%E5%A... プロジェクト直下の pom.xml を開き、以下のように編集する groupIdは作成しているプログラムのパッケージ名に合わせる…と思ったが、この編集は行わなくても大丈夫だった
<groupId>com.example</groupId> ↓ <groupId>com.example.demo</groupId>
プロジェクトを右クリックし、 実行 → 5 Maven Install を選択。しばらく待つと、以下にファイルが作成された C:\Users\refirio\sts4\demo\target\demo-0.0.1-SNAPSHOT.jar
■IntelliJ IDEA + Spring Boot での開発
■プロジェクトの作成 Spring Initializr https://start.spring.io/ 今回は以下のように設定する Spring WebにはTomcatが付属しているため、Webアプリケーションサーバを用意しなくてもプログラムを動作させることができる Project: Maven Language: Java Spring Boot: 3.0.1(デフォルト、または「SNAPSHOT」や「M1」などが付いていない最新バージョンを選択するといい) Group: com.example Artifact: demo Name: demo Description: Demo project for Spring Boot Package name: com.example.demo Packaging: Jar Java: 17 Dependencies: Spring Web(「ADD DEPENDENCIES」ボタンから追加する) 設定したら「GENERATE」ボタンをクリックするとZIPファイルがダウンロードできる これはプロジェクトの雛形なので、展開して適当なフォルダに配置する 今回は「C:\Users\refirio\IdeaProjects\demo」に配置した IntelliJ IDEA の初期画面で「開く」から上記プロジェクトを開く 「プロジェクトを信頼して開きますか?」のダイアログが表示されたら、「プロジェクトを信頼」をクリックする (Mavenにより必要なものがダウンロードされるので、初回の起動は時間がかかる) 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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
main メソッドは src/main/java/com/example/demo/DemoApplication.java にあり、以下が記述されている
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
■コードスタイルの設定 ファイル → 設定 → エディター → コードスタイル → HTML HTMLのインデントがスペース2つで入力されるため、スペース4に変更した 上記設定上はデフォルトでスペース4となっていたが、そのままOKとすると、次回からスペース4で入力されるようになった …と思ったが、HTMLファイルの新規作成直後はスペース2つになってしまっている? ファイルを閉じて再度開くと、設定どおりスペース4つと認識されるみたい? IDEの不具合かも? ■プロジェクトの設定 JDKの設定を行う メニューバーの「ファイル → プロジェクト構造 → プロジェクト」で、JDKを「17」にする (デフォルトでそのように設定されていた) 実行構成の設定を行う メニューバーの「実行 → 実行構成の編集」で、左上の「+」アイコンをクリックし、「アプリケーション」を選択する 名前: Tomcat SDK: java 17 メインクラス: com.example.demo.DemoApplication 「OK」ボタンを押すと、ツールバーで「現在のファイル」と表示されていたセレクトボックスが「Tomcat」に変わることを確認できる ■プロジェクトの実行 プロジェクトの実行ボタンを押す 実行されると、実行結果として「Spring」のアスキーアートと実行ログが表示される ログの中に「Tomcat started on port(s): 8080 (http) with context path ''」というメッセージがある ブラウザで http://localhost:8080/ にアクセスすると、画面に以下が表示される
Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Tue Jan 03 17:10:56 JST 2023 There was an unexpected error (type=Not Found, status=404).
プロジェクトを再実行する場合、実行ボタンがあった場所に再実行ボタンが表示されているので押す 「プロセス'Tomcat'は実行中です」と表示されたら、「停止して再実行」でいい プロジェクトを停止する場合、実行ボタンの右側にある停止ボタンを押す ■プロジェクトの実行エラーと対策 もし以下のメッセージが表示されたら、ポート8080はすでに使用されているために起動できていない
Description: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
この場合、src/main/resources/application.properties を開いて以下の内容を記述することで、8888ポートで起動することができる (他のポート番号を指定することもできる)
server.port = 8888
■エンドポイントの作成と再実行 com.example.demo 内に HomeRestController を作る HomeRestController.java が作成されるので、以下の内容を記述する
package com.example.demo; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.time.LocalDateTime; @RestController public class HomeRestController { @RequestMapping(value="/") String index() { return "Spring Boot"; } @RequestMapping(value="/now") String now() { return "現在時刻は%sです。".formatted(LocalDateTime.now()); } }
プロジェクトを再実行し、ブラウザで http://localhost:8080/ にアクセスすると、画面に以下が表示される
Spring Boot
またブラウザで http://localhost:8080/hello にアクセスすると、画面に以下が表示される
現在時刻は2023-01-03T17:22:32.596689400です。
■実行可能なJARファイルを作成 IntelliJ IDEA の画面右端に「Maven」というタブが折りたたまれているので、クリックして表示させある 画面内で「demo → ライフサイクル」内にある「package」を右クリックし、「Mavenビルドの実行」を選択する 実行ウインドウに「BUILD SUCCESS」と表示されれば成功 C:\Users\refirio\IdeaProjects\demo\target 内に「demo-0.0.1-SNAPSHOT.jar」が作成されていることを確認できる コマンドプロンプトで以下を実行すると、先ほどと同じ画面を表示させることができる (実行前に、IntelliJ IDEA で実行したものは停止させておく)
java -jar C:\Users\refirio\IdeaProjects\demo\target\demo-0.0.1-SNAPSHOT.jar
プログラムは「Ctrl+C」で終了させることができる ■プロパティの上書き(引数) 以下のように起動して、ポート番号を上書き変更できる src/main/resources/application.properties で指定した値も上書き指定できる 開発環境などで、簡易的に値を変更する場合などに使えそう
java -jar demo-0.0.1-SNAPSHOT.jar --server.port=8888
この場合、以下のようにしてアクセスできる http://localhost:8888/ http://localhost:8888/task http://localhost:8888/task_add Spring-Bootの設定プロパティと環境変数 - Qiita https://qiita.com/NewGyu/items/d51f527c7199b746c6b6 ■プロパティの上書き(src/main/resources/application-xxx.properties) src/main/resources/application.properties で設定を指定できるが、 src/main/resources/application-production.properties src/main/resources/application-staging.properties のようにファイルを作ることで、環境ごとの設定を指定できる 通常の手順でjarファイルを作成すれば、それを実行する際に以下のようにファイルを指定できる
# java -jar demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=production
本番環境のデータベース接続情報などがリポジトリに含むことになるなら微妙かもしれないが、 「本番環境のファイルのみ .gitignore の対象とする」「本番環境はElasticBeanstalkの仕組みに従って別途指定する」 など色々とやりようはありそう ■プロパティの上書き(config/application.properties) ※プログラムをサービスとして稼働させたときは反映されなかった 引き続き要確認 jarファイルと同じ場所に config/application.properties を作成して以下のように書いておくと、起動時に値が上書きされる 本番環境や検収環境で、接続設定などを変更する場合に使えそう
server.port = 8765 spring.datasource.url=jdbc:mysql://localhost:3306/spring-test spring.datasource.username=test spring.datasource.password=test1234
起動の際は、以下のとおりファイルのパスなどを指定する必要は無い
java -jar demo-0.0.1-SNAPSHOT.jar
■プロパティの上書き(環境変数) ※プログラムをサービスとして稼働させたときは反映されなかった 引き続き要確認 ~/.bash_profile に環境変数として定義(ファイルの最後に追記)しておくと、起動時に値が上書きされる(恒久的な設定になる) 本番環境や検収環境で、接続設定などを変更する場合に使えそう $ vi ~/.bash_profile
export SERVER_PORT=8888 export SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/spring-test export SPRING_DATASOURCE_USERNAME=test export SPRING_DATASOURCE_PASSWORD=test1234
設定後、以下で値を反映する $ source ~/.bash_profile 以下のようにして反映を確認できる echo $SERVER_PORT echo $SPRING_DATASOURCE_URL echo $SPRING_DATASOURCE_USERNAME echo $SPRING_DATASOURCE_PASSWORD いまさらですがLinuxで環境変数を設定したい - Qiita https://qiita.com/chihiro/items/bb687903ee284766e879 ■Webアプリケーションの作成 com.example.demo 内に新規Javaクラス HomeController を作る HomeController.java が作成されるので、以下の内容を記述する @RestController はレスポンスとして文字列を返すような場合に使用する @Controller はレスポンスとしてHTMLを返すような場合に使用する
package com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.time.LocalDateTime; @Controller public class HomeController { @RequestMapping("/") @ResponseBody String index() { return """ <html> <head> <title>Spring Boot</title> </head> <body> <h1>Spring Boot</h1> <p>It works!</p> </body> </html> """; } @RequestMapping("/now") @ResponseBody String now() { return """ <html> <head> <title>Spring Boot</title> </head> <body> <h1>Spring Boot</h1> <p>現在時刻は%sです。</p> </body> </html> """.formatted(LocalDateTime.now()); } }
■HTMLテンプレートを利用する テンプレートエンジンのThymeleafを利用するため、pom.xml に以下を追加する 追加したら、Mavenの変更を読み込む
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
src/main/resources/templates/index.html を作成し、以下の内容を記述する
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Spring Boot</title> </head> <body> <h1>Spring Boot</h1> <p>It works!</p> </body> </html>
src/main/resources/templates/now.html を作成し、以下の内容を記述する
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Spring Boot</title> </head> <body> <h1>Spring Boot</h1> <p>現在時刻は<span th:text="${time}"></span>です。</p> </body> </html>
HomeController.java の内容を以下に変更する
package com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.time.LocalDateTime; @Controller public class HomeController { @RequestMapping("/") String index() { return "index"; } @RequestMapping("/now") String now(Model model) { model.addAttribute("time", LocalDateTime.now()); return "now"; } }
■MySQLを利用する(JDBCの場合) ここでは、MySQLはXAMPPに付属しているものを使用することにする XAMPPのApacheとMySQLを起動する phpMyAdminで今回は「spring」というデータベースを作成しておく データベースの文字コードは「utf8mb4_general_ci」としておく 以下のテーブルを作成する
CREATE TABLE tasks ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, title VARCHAR(80) NOT NULL, text TEXT, PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
MySQLを利用するため、pom.xml に以下を追加する 追加したら、Mavenの変更を読み込む
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
src/main/resources/application.properties にデータベースへの接続設定を記述する (昔はドライバに「com.mysql.jdbc.Driver」が指定されたようだが、今は非推奨らしい)
spring.jpa.hibernate.ddl-auto=none spring.datasource.url=jdbc:mysql://localhost:3306/spring spring.datasource.username=root spring.datasource.password=1234 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
Spring BootでMySQLに接続する | 株式会社CONFRAGE ITソリューション事業部 https://confrage.jp/spring-boot%E3%81%A7mysql%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B/ You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support. | 株式会社CONFRAGE ITソリューション事業部 https://confrage.jp/you-must-configure-either-the-server-or-jdbc-driver-via-the-servertimezone-confi... src/main/java/com/example/demo/Task.java としてデータクラスを作成する
package com.example.demo; public class Task { private String id; private String title; private String text; public Task(String id, String title, String text) { this.id = id; this.title = title; this.text = text; } public String id() { return id; } public String title() { return title; } public String text() { return text; } }
src/main/java/com/example/demo/TaskDao.java としてデータベースアクセスクラスを作成する
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class TaskDao { private final JdbcTemplate jdbcTemplate; @Autowired TaskDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void add(Task task) { SqlParameterSource param = new BeanPropertySqlParameterSource(task); SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate).withTableName("tasks"); insert.execute(param); } public List<Task> findAll() { String query = "SELECT * FROM tasks"; List<Map<String, Object>> result = jdbcTemplate.queryForList(query); List<Task> tasks = result.stream() .map((Map<String, Object> row) -> new Task( row.get("id").toString(), row.get("title").toString(), row.get("text").toString() )).toList(); return tasks; } }
src/main/resources/templates/task.html としてデータ一覧のテンプレートを作成する
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Spring Boot</title> </head> <body> <h1>Spring Boot</h1> <p>タスクは以下のとおりです。</p> <table> <tr> <th>ID</th> <th>タイトル</th> <th>テキスト</th> </tr> <tr th:each="task : ${tasks}"> <td th:text="${task.id}"></td> <td th:text="${task.title}"></td> <td th:text="${task.text}"></td> </tr> </table> </body> </html>
src/main/resources/templates/task_add.html としてデータ登録完了のテンプレートを作成する
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Spring Boot</title> </head> <body> <h1>Spring Boot</h1> <p>タスクを登録しました。</p> </body> </html>
src/main/java/com/example/demo/HomeController.java
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.time.LocalDateTime; import java.util.List; @Controller public class HomeController { private final TaskDao taskDao; @Autowired HomeController(TaskDao taskDao) { this.taskDao = taskDao; } @RequestMapping("/") String index() { return "index"; } @RequestMapping("/now") String now(Model model) { model.addAttribute("time", LocalDateTime.now()); return "now"; } @RequestMapping("/task") String task(Model model) { List<Task> tasks = taskDao.findAll(); model.addAttribute("tasks", tasks); return "task"; } @RequestMapping("/task_add") String addTask() { Task task = new Task(null, "テスト", "テスト。\nこれはテストです。"); taskDao.add(task); return "task_add"; } }
http://localhost:8080/task_add にアクセスするとタスクが登録される http://localhost:8080/task にアクセスするとタスクが一覧表示される データベースの接続情報を環境ごとに用意する方法は、このファイル内の「プロパティの上書き」を参照 ■MySQLを利用する(Spring Data JPAの場合) SpringBoot JPAを使う方法(Spring Data JPA の使用方法) - Web系開発メモ https://web-dev.hatenablog.com/entry/spring-boot/intro/jpa Spring Boot入門:MySQLにSpring Boot アプリケーションからアクセスする - あるSEのつぶやき・改 https://www.aruse.net/entry/2019/08/04/003838 Spring Boot+JPAでデータベースに接続する方法 - ITを分かりやすく解説 https://medium-company.com/spring-boot%EF%BC%8Bjpa%E3%81%A7%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%8... ここでは、MySQLはXAMPPに付属しているものを使用することにする XAMPPのApacheとMySQLを起動する phpMyAdminで今回は「spring」というデータベースを作成しておく データベースの文字コードは「utf8mb4_general_ci」としておく 以下のテーブルを作成する
CREATE TABLE tasks ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, title VARCHAR(80) NOT NULL, text TEXT, PRIMARY KEY(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
MySQLを利用するため、pom.xml に以下を追加する 追加したら、Mavenの変更を読み込む
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
src/main/resources/application.properties にデータベースへの接続設定を記述する
spring.jpa.hibernate.ddl-auto=none spring.datasource.url=jdbc:mysql://localhost:3306/spring spring.datasource.username=root spring.datasource.password=1234
src/main/java/com/example/demo/Task.java としてエンティティクラスを作成する
package com.example.demo; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Table; import jakarta.persistence.Id; @Entity @Table(name="tasks") public class Task { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String title; private String text; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getText() { return text; } public void setText(String text) { this.text = text; } }
src/main/java/com/example/demo/TaskRepository.java としてリポジトリクラスを作成する
package com.example.demo; import org.springframework.data.jpa.repository.JpaRepository; public interface TaskRepository extends JpaRepository<Task, Integer> { }
src/main/resources/templates/task.html としてデータ一覧のテンプレートを作成する
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Spring Boot</title> </head> <body> <h1>Spring Boot</h1> <p>タスクは以下のとおりです。</p> <table> <tr> <th>ID</th> <th>タイトル</th> <th>テキスト</th> </tr> <tr th:each="task : ${tasks}"> <td th:text="${task.id}"></td> <td th:text="${task.title}"></td> <td th:text="${task.text}"></td> </tr> </table> </body> </html>
src/main/resources/templates/task_add.html としてデータ登録完了のテンプレートを作成する
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Spring Boot</title> </head> <body> <h1>Spring Boot</h1> <p>タスクを登録しました。</p> </body> </html>
src/main/java/com/example/demo/HomeController.java
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.time.LocalDateTime; import java.util.List; @Controller public class HomeController { @Autowired private TaskRepository taskRepository; @RequestMapping("/") String index() { return "index"; } @RequestMapping("/now") String now(Model model) { model.addAttribute("time", LocalDateTime.now()); return "now"; } @RequestMapping("/task") String task(Model model) { List<Task> tasks = taskRepository.findAll(); model.addAttribute("tasks", tasks); return "task"; } @RequestMapping("/task_add") String addTask() { Task task = new Task(); task.setId(null); task.setTitle("テスト"); task.setText("テスト。\nこれはリポジトリのテストです。"); taskRepository.save(task); return "task_add"; } }
http://localhost:8080/task_add にアクセスするとタスクが登録される http://localhost:8080/task にアクセスするとタスクが一覧表示される データベースの接続情報を環境ごとに用意する方法は、このファイル内の「プロパティの上書き」を参照
■IntelliJ IDEA + Spring Boot での開発 引き続き
■レイヤー 以下を参考に、ひととおりの流れを作ってみると良さそう フォーム投稿&バリデーションについても触れられている Spring Boot + Thymeleafで新規登録画面を作成する - ITを分かりやすく解説 https://medium-company.com/spring-boot-thymeleaf%E3%81%A7%E6%96%B0%E8%A6%8F%E7%99%BB%E9%8C%B2%E7%94%... SpringBoot/各レイヤの責務 - KobeSpiral2021 https://cs27.org/wiki/kobespiral2021/?SpringBoot/%E5%90%84%E3%83%AC%E3%82%A4%E3%83%A4%E3%81%AE%E8%B2... Spring Bootで実装するときに気をつけて欲しいポイントベスト3〜構成編〜 - 自主的20%るぅる https://www.agent-grow.com/self20percent/2020/04/13/spring-boot-check-point-structure/ Spring Bootアプリケーションのコードレビューポイント - Qiita https://qiita.com/cross-xross/items/144f8bde2ef6fa4b379f @Component、@Service、@Repository、@Controllerの違いについて - Qiita https://qiita.com/KevinFQ/items/abc7369cb07eb4b9ae29 Spring Boot Thymeleaf でリンク(a href)を記載する方法 | ITエンジニアの定時退社Tips https://www.early2home.com/blog/programming/html/post-1564.html ■Spring Data JPA Spring Data JPA は引き続き確認しておきたい 【Spring Data JPA】基本操作とクエリ実装 https://b1san-blog.com/post/spring/spring-jpa/ [Spring Boot] JPAでデータベースに接続 | DevelopersIO https://dev.classmethod.jp/articles/use_spring-boot-jpa-jpql/ Spring Data JPAを使用したDBアクセス - アルファテックブログ https://www.alpha.co.jp/blog/202209_01 Spring Boot入門:MySQLにSpring Boot アプリケーションからアクセスする - あるSEのつぶやき・改 https://www.aruse.net/entry/2019/08/04/003838 ■マイグレーション Flywayを導入するのが定番の方法みたい SpringBoot FlywayでDBのマイグレーションをする方法 - Web系開発メモ https://web-dev.hatenablog.com/entry/spring-boot/intro/flyway FlywayでSpringBootプロジェクトのDBマイグレーション - 【Spring Hack】 https://springhack.com/flyway%E3%81%A7springboot%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%... Spring BootにDBマイグレーションツール「flyway」を導入する - ブログ - 株式会社Smallit(スモーリット) https://smallit.co.jp/blog/687/ ■テンプレート Thymeleafについても確認しておきたい divやspanなどタグに対して値や分岐を設定したくない場合、「<th:block></th:block>」や「<th th:text="${test}"></th>」とできるか(要検証) Thymeleafとは?基本構文・Spring Bootでの使い方を解説 | プログラミングを学ぶならトレノキャンプ(TRAINOCAMP) https://camp.trainocate.co.jp/magazine/about-thymeleaf/ Thymeleaf if文 条件分岐を行うサンプル | ITSakura https://itsakura.com/thymeleaf-if-loop Spring Boot + Thymeleafで詳細画面を作成する - ITを分かりやすく解説 https://medium-company.com/spring-boot-thymeleaf%E3%81%A7%E8%A9%B3%E7%B4%B0%E7%94%BB%E9%9D%A2%E3%82%... replaceを使うことで、ヘッダやフッタを共通パーツとして分離させることができる Thymeleafを使ってheaderとheadとfooterの共通化 - エキサイト TechBlog. https://tech.excite.co.jp/entry/2022/08/08/162241 layoutを使うことで、基本のレイアウトを作ることができる Spring BootとThymeleafでLayoutを共通化する方法 | ホームページ制作のサカエン Developer's Blog https://www.saka-en.com/java/spring-boot-thymeleaf-layout/ src/main/resources 内に static か public ディレクトリを作成て、静的コンテンツを配置できる Thymeleafで外部のCSSファイルを読み込む方法 - ミルラク https://miruraku.com/java/thymeleaf/css/ SpringBoot 静的コンテンツを返す方法(html, js, css など) - Web系開発メモ https://web-dev.hatenablog.com/entry/spring-boot/intro/response-static-content ■認証 Spring Boot ログイン画面 - 公式サンプルコード https://spring.pleiades.io/guides/gs/securing-web/ 【SpringBoot入門】Spring Securityで認証機能 - Qiita https://qiita.com/morioheisei/items/ecfeee4860944d0b4a3b Spring Boot入門:Spring Securityで認証と認可 | ツチヤの備忘録 https://www.tsuchiya.blog/spring-boot-step7/ ■その他 以下のページはサンプルが多くて有用そう Spring Framework | ITSakura https://itsakura.com/spring-framework SpringBoot フォームの値を別画面に渡す | ITSakura https://itsakura.com/java-springboot-submit SpringBoot メール送信のサンプル | ITSakura https://itsakura.com/sb-mailsend
■Vagrantでアプリケーション(JAR)を起動
■プログラムの準備 「プロパティの上書き(src/main/resources/application-xxx.properties)」を参考に、環境ごとの設定ファイルを用意しておく ここでは、Vagrant用に application-test.properties を作成したものとする ■基本設定 # localectl set-locale LANG=ja_JP.UTF-8 # timedatectl set-timezone Asia/Tokyo # yum install -y https://cdn.azul.com/zulu/bin/zulu-repo-1.0.0-1.noarch.rpm # yum install -y zulu17-jdk # java -version openjdk version "17.0.5" 2022-10-18 LTS OpenJDK Runtime Environment Zulu17.38+21-CA (build 17.0.5+8-LTS) OpenJDK 64-Bit Server VM Zulu17.38+21-CA (build 17.0.5+8-LTS, mixed mode, sharing) CentOS 7にOpenJDK 17をインストール(Azul Zulu Builds of OpenJDK) - Qiita https://qiita.com/witchcraze/items/014da8ee2c638737e9bc Javaのサポートについてのまとめ2018 - Qiita https://qiita.com/nowokay/items/edb5c5df4dbfc4a99ffb ■プログラムの実行(MySQLなし) 同期フォルダである /var/www に demo-0.0.1-SNAPSHOT.jar を配置 $ nohup java -jar /var/www/demo-0.0.1-SNAPSHOT.jar & 以下でアクセスできることを確認(確認できたら終了しておく) $ curl http://localhost:8080/ $ curl http://localhost:8080/now ■プログラムの実行(MySQLあり) # curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash # yum -y install MariaDB-server MariaDB-client # systemctl start mariadb # systemctl enable mariadb # mariadb-secure-installation $ mysql -u root -p mysql> CREATE DATABASE spring DEFAULT CHARACTER SET utf8; mysql> CREATE USER webmaster@localhost IDENTIFIED BY 'abcd1234'; mysql> GRANT ALL PRIVILEGES ON spring.* TO webmaster@localhost; mysql> QUIT $ mysql -u webmaster -p mysql> USE spring mysql> CREATE TABLE ... (必要なテーブルを作成する) mysql> QUIT ■サービスの設定 # vi /etc/systemd/system/spring.service
[Unit] Description = Spring Boot Application [Service] ExecStart = /usr/bin/java -jar /var/www/demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=test … 実行したいjarファイルの場所とその環境を指定(jarファイルとjavaは絶対パスで指定) Restart = always Type = simple User = vagrant … 環境に合わせてユーザ名を指定する Group = vagrant … 環境に合わせてユーザ名を指定する SuccessExitStatus = 143 [Install] WantedBy = multi-user.target
UserとGroupに専用のユーザを指定する場合、「useradd xxxxx」のようにしてユーザを作成しておく また、このファイルがjarファイルを読み取りできるようにしておく # systemctl list-unit-files -t service | grep spring … サービスの状態を確認(Unitがサービスとして認識されたか確認) spring.service disabled # systemctl enable spring … サービスの自動起動を有効化 Created symlink from /etc/systemd/system/multi-user.target.wants/spring.service to /etc/systemd/system/spring.service. # systemctl list-unit-files -t service | grep spring … サービスの自動起動を確認 spring.service enabled # systemctl start spring … サービスを起動 # systemctl status spring … サービスの起動を確認 ● spring.service - Spring Boot Application Loaded: loaded (/etc/systemd/system/spring.service; enabled; vendor preset: disabled) Active: failed (Result: start-limit) since 金 2023-01-06 14:47:44 JST; 1s ago Process: 3212 ExecStart=/var/www/demo-0.0.1-SNAPSHOT.jar (code=exited, status=203/EXEC) Main PID: 3212 (code=exited, status=203/EXEC) 1月 06 14:47:43 localhost.localdomain systemd[1]: spring.service: main process exited, code=exited, status=203/EXEC 1月 06 14:47:43 localhost.localdomain systemd[1]: Unit spring.service entered failed state. 1月 06 14:47:43 localhost.localdomain systemd[1]: spring.service failed. 1月 06 14:47:44 localhost.localdomain systemd[1]: spring.service holdoff time over, scheduling restart. 1月 06 14:47:44 localhost.localdomain systemd[1]: Stopped Spring Boot Application. 1月 06 14:47:44 localhost.localdomain systemd[1]: start request repeated too quickly for spring.service 1月 06 14:47:44 localhost.localdomain systemd[1]: Failed to start Spring Boot Application. 1月 06 14:47:44 localhost.localdomain systemd[1]: Unit spring.service entered failed state. 1月 06 14:47:44 localhost.localdomain systemd[1]: spring.service failed. # systemctl stop spring … サービスを停止させる場合 サービスとしての稼働については、 Dropbox\サーバ\Etcetera.txt 内にある「バックグラウンドで処理を実行する(サービス)」も参照 ■Nginxの導入 ※あらかじめ、SELinuxを無効化しておく # yum -y install epel-release # yum -y install nginx # vi /etc/nginx/nginx.conf
server { listen 80 default_server; listen [::]:80 default_server; server_name _; #root /usr/share/nginx/html; … 公開ディレクトリをコメントアウト # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass http://localhost:8080; … ブロックに内容を追加 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }
# systemctl start nginx # systemctl enable nginx http://192.168.33.10/ http://192.168.33.10/now ■トラブルシューティング 起動時のログやエラー時のログは /var/log/message に出力される 例えば「--spring.profiles.active=test」による環境の指定を行った場合、以下が出力されていた
2023-01-19T12:18:53.234+09:00 INFO 3207 --- [ main] com.example.demo.DemoApplication : The following 1 profile is active: "test"
データベースに接続できないとき、以下が出力されていた
Jan 19 11:45:41 localhost mariadbd: 2023-01-19 11:45:41 3 [Warning] Access denied for user 'root'@'localhost' Jan 19 11:45:42 localhost java: 2023-01-19T11:45:42.454+09:00 ERROR 3011 --- [nio-8888-exec-3] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization. Jan 19 11:45:42 localhost java: java.sql.SQLException: Access denied for user 'root'@'localhost'
データベースにテーブルが作成されていないとき、以下が出力されていた Windows環境ではテーブルの大文字と小文字は区別されないようだが、Linux(Vagrant)環境では区別されるので注意
2023-01-18T17:51:21.182+09:00 ERROR 3560 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [SELECT * FROM tasks]] with root cause java.sql.SQLSyntaxErrorException: Table 'spring.tasks' doesn't exist
■EC2でアプリケーション(JAR)を起動
■プログラムの準備 前述の「Vagrantでアプリケーション(JAR)を起動」の同項目を参照 ■EC2の起動 通常の手順でEC2を作成 Amazon Linux 2 の t2.micro を選択。EIPは無し セキュリティグループで8080番ポートを空けておく SSHで接続して以下を行なう ・言語を設定 ・タイムゾーンを設定 ・パッケージ管理システムを設定 ・各種ツールをインストール ここまでは通常の立ち上げと同じ ■Javaのインストール Amazon Linux には始めからJavaがインストールされていたようだが、 Amazon Linux 2 にはインストールされていない $ java -version … Amazon Linux 2 にはJavaはインストールされていない -bash: java: command not found エクストラリポジトリには存在するが、Java11と少し古い(今回はJava17をインストールしたい) # amazon-linux-extras list | grep java 33 java-openjdk11 available [ =11 =stable ] 以下の記事を参考にインストールする CorrettoはAWSが用意しているJDKで、JavaSE標準との互換性があるとされている 【EC2】minecraft1.18のサーバーをEC2で立ち上げてみた - Qiita https://qiita.com/nahiro_tus/items/021d095f49cb65404a2c Amazon Corretto(本番環境に対応したOpenJDKディストリビューション)| AWS https://aws.amazon.com/jp/corretto/ # yum install -y https://corretto.aws/downloads/latest/amazon-corretto-17-x64-al2-jre.rpm # java -version openjdk version "17.0.5" 2022-10-18 LTS OpenJDK Runtime Environment Corretto-17.0.5.8.1 (build 17.0.5+8-LTS) OpenJDK 64-Bit Server VM Corretto-17.0.5.8.1 (build 17.0.5+8-LTS, mixed mode, sharing) ■プログラムの実行 AWS EC2上で Spring Bootアプリ起動 - 闘うITエンジニアの覚え書き https://www.magata.net/memo/index.php?AWS%20EC2%BE%E5%A4%C7%20Spring%20Boot%A5%A2%A5%D7%A5%EA%B5%AF%... AWSクラウド環境の構築からSpring Bootアプリのデプロイまで(初心者向け) - Qiita https://qiita.com/KevinFQ/items/119521ebd12bb7890761 SFTPなどで /home/ec2-user/demo-0.0.1-SNAPSHOT.jar に配置する $ java -jar /home/ec2-user/demo-0.0.1-SNAPSHOT.jar EC2のIPアドレスが 54.178.199.100 の場合、以下にアクセスすると Spring Boot で作成したアプリケーションの画面が表示される アクセスできない場合、8080番ポートを空けているか確認する(確認できたら終了しておく) http://54.178.199.100:8080/ ■サービスの設定 前述の「Vagrantでアプリケーション(JAR)を起動」の同項目を参照 ■Nginxの導入 インストール自体は以下で行える # amazon-linux-extras install -y nginx1 以降の設定については、前述の「Vagrantでアプリケーション(JAR)を起動」の同項目を参照 ■その他参考になりそうなページ EC2+RDS+Spring bootで簡単なAPIを作ってみる? - Qiita https://qiita.com/yseki_/items/81c84d78895b009c2aa6 【AWS】入門その? EC2とRDSを利用して簡易Webアプリを構築してみる - SEワンタンの独学備忘録 https://www.wantanblog.com/entry/2019/09/21/190819 ■トラブルシューティング 前述の「Vagrantでアプリケーション(JAR)を起動」の同項目を参照
■Elastic Beanstalk でアプリケーション(JAR)を起動
サーバメモの AWS.txt の「Elastic Beanstalk」を参照
■その他参考になりそうなページ
Spring Tool Suite インストールと日本語化 for Windows - Qiita https://qiita.com/andna0410/items/e9cc07c9e2e34a542245 Spring Tool Suite (STS)と Spring Boot で始める Web アプリケーション開発(1) TECHSCORE BLOG http://www.techscore.com/blog/2016/11/22/start-with-sts-and-spring-boot-1/ AWSクラウド環境の構築からSpring Bootアプリのデプロイまで(初心者向け) - Qiita https://qiita.com/KevinFQ/items/119521ebd12bb7890761 Spring Bootで作ったJarをAWSのElastic BeanstalkですぐにWebにアップする - Qiita https://qiita.com/haruto167/items/0c9234d6ef77f3a5a09c Spring BootをElastic Beanstalk上で動かしてみた - Qiita https://qiita.com/takexi/items/3cc428e603653bbf2e8b Spring bootでMySQL接続 - Qiita https://qiita.com/uk-liverpool/items/5878d3c509c503ff5b29 Spring Boot MySQL を使用したデータへのアクセス - コードサンプル https://spring.pleiades.io/guides/gs/accessing-data-mysql/ 【Java】【AWS】Amazon EC2でJavaのWebアプリケーション動作環境を構築してデプロイするまで - 独り言 https://case10.hateblo.jp/entry/2020/10/06/165543 EC2-1インスタンスでnginx-SpringBoot-MySQL-redisを構築 - 【Spring Hack】 https://springhack.com/1%E5%B1%A4%E3%81%AE%E6%A7%8B%E7%AF%89/ SpringBootをサービス化(デーモン化)して常駐させる - 【Spring Hack】 https://springhack.com/springboot%e3%82%92%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e5%8c%96%ef%bc%88%e3%... EC2+RDS+Spring bootで簡単なAPIを作ってみる? - Qiita https://qiita.com/yseki_/items/81c84d78895b009c2aa6 AWS(EC2)上にSpringBootアプリをデプロイする - 好奇心の赴くままに https://writerman.hatenablog.jp/entry/2019/12/22/215749 Spring BootでMySQLに接続する | 株式会社CONFRAGE ITソリューション事業部 https://confrage.jp/spring-boot%E3%81%A7mysql%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B/ 以下はMinecraftの環境を作るための記事だが、Java環境の構築なので参考になるかも 【#Minecraft for AWS】EC2インスタンスでMinecraftサーバーを構築 Ver1.19 | DevelopersIO https://dev.classmethod.jp/articles/new-minecraft-for-aws_ec2-instance/ 【#Minecraft for AWS】EC2インスタンスでMinecraftサーバーを構築 Ver1.17 | DevelopersIO https://dev.classmethod.jp/articles/minecraft-for-aws_ec2-instance/ 第1回 AWS で Minecraft サーバー構築【1.19.2】〜バニラサーバー構築〜 https://staff-blog.faith-sol-tech.com/%E7%AC%AC%EF%BC%91%E5%9B%9E-aws-%E3%81%A7-minecraft-%E3%82%B5%...