■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%...