http://home.liacsy.com/wp2/study/how-to-build-and-learn-a-java-development-environment-on-fedora-02/
の続きを行いました。
≪プロンプト01≫
この4連モニターの下に、ユーザー登録、ログインのシステムを差し込めますか?
≪Geminiの回答01≫
もちろんです、可能です!ただし、ここからは「システムの性質」がガラリと変わります。
これまでのモニターは「情報を表示するだけ」でしたが、ユーザー登録やログインは「データを保存・照合する」という裏側の仕組み(データベースなど)が必要になります。
まずは第一歩として、モニターの下に「ログインフォームの見た目」を作り、実際にユーザー入力を受け付ける準備を整えましょう。
1. ログイン画面を追加した App.java(簡易版)
現在のサイバーなモニターのデザインに合わせて、その下にログインフォームを差し込みます。
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import java.io.*;
import java.lang.management.ManagementFactory;
@SpringBootApplication
@RestController
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
// ログイン状態をシミュレート(本来はDBで管理します)
private String currentUser = null;
@GetMapping("/")
public String getDashboard() {
// --- 既存のデータ取得(DISK, RAM, CPU, TEMP) ---
File root = new File("/");
long tDisk = root.getTotalSpace() / 1024 / 1024 / 1024;
long uDisk = tDisk - (root.getFreeSpace() / 1024 / 1024 / 1024);
long tMem = 1, aMem = 1;
try (BufferedReader br = new BufferedReader(new FileReader("/proc/meminfo"))) {
String line;
while ((line = br.readLine()) != null) {
if (line.contains("MemTotal:")) tMem = Long.parseLong(line.replaceAll("[^0-9]", "")) / 1024;
if (line.contains("MemAvailable:")) aMem = Long.parseLong(line.replaceAll("[^0-9]", "")) / 1024;
}
} catch (Exception e) {}
long uMem = tMem - aMem;
double load = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
int cpu = (load < 0) ? 0 : (int)((load / Runtime.getRuntime().availableProcessors()) * 100);
double temp = 0;
try (BufferedReader br = new BufferedReader(new FileReader("/sys/class/thermal/thermal_zone0/temp"))) {
temp = Double.parseDouble(br.readLine()) / 1000.0;
} catch (Exception e) {}
// --- HTML生成 ---
StringBuilder html = new StringBuilder();
html.append("<html><head><meta charset='UTF-8'>");
html.append("<style>");
html.append(" body { background: #1a1a1a; color: #00ff00; font-family: monospace; text-align: center; }");
html.append(" .container { display: flex; justify-content: center; gap: 20px; flex-wrap: wrap; margin-top: 30px; }");
html.append(" .card { border: 1px solid #00ff00; padding: 15px; width: 150px; box-shadow: 0 0 10px #00ff00; }");
html.append(" .bar-bg { background: #333; height: 10px; width: 100%; margin: 10px 0; }");
html.append(" .bar-fill { background: #00ff00; height: 100%; }");
html.append(" .login-box { margin-top: 50px; border-top: 2px dashed #00ff00; padding-top: 30px; }");
html.append(" input { background: #000; color: #00ff00; border: 1px solid #00ff00; padding: 5px; margin: 5px; }");
html.append(" button { background: #00ff00; color: #000; border: none; padding: 5px 15px; cursor: pointer; font-weight: bold; }");
html.append("</style></head><body>");
html.append("<h1>SYSTEM MONITOR [SECURE_ACCESS]</h1>");
// モニター部分
html.append("<div class='container'>");
html.append(makeCard("DISK", (int)(uDisk*100/tDisk), uDisk + "/" + tDisk + " GB"));
html.append(makeCard("RAM", (int)(uMem*100/tMem), uMem + "/" + tMem + " MB"));
html.append(makeCard("CPU", cpu, cpu + " %"));
html.append(makeCard("TEMP", (int)temp, String.format("%.1f", temp) + " ℃"));
html.append("</div>");
// ログイン/登録フォーム部分
html.append("<div class='login-box'>");
if (currentUser == null) {
html.append("<h3>RESTRICTED AREA: PLEASE LOGIN</h3>");
html.append("<form action='/login' method='post'>");
html.append(" USER: <input type='text' name='username'><br>");
html.append(" PASS: <input type='password' name='password'><br>");
html.append(" <button type='submit'>ACCESS</button>");
html.append("</form>");
html.append("<p><small>NEW USER? [REGISTER]</small></p>");
} else {
html.append("<h3>WELCOME, " + currentUser + " [AUTHORIZED]</h3>");
html.append("<a href='/logout' style='color:#00ff00;'>LOGOUT</a>");
}
html.append("</div>");
html.append("</body></html>");
return html.toString();
}
private String makeCard(String title, int percent, String text) {
return "<div class='card'><h3>" + title + "</h3>" +
"<div class='bar-bg'><div class='bar-fill' style='width:" + percent + "%'></div></div>" +
"<p>" + text + "</p></div>";
}
// ログイン処理(仮)
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
if ("admin".equals(username) && "password123".equals(password)) {
this.currentUser = username;
return "<html><body style='background:#1a1a1a;color:#00ff00;font-family:monospace;text-align:center;'>" +
"<h2>ACCESS GRANTED</h2><script>setTimeout(()=>location.href='/', 1000);</script></body></html>";
}
return "ACCESS DENIED";
}
}
2. 今後の課題:本格的なシステムにするために
現在のコードは、Javaを再起動するとユーザー情報が消えてしまいますし、パスワードもコードに直書きです。本気で「ユーザー登録」まで作るには、以下のステップが必要になります。
① データベース (DB) の導入: H2 Database(手軽)や PostgreSQL(本格的)など、ユーザー情報を保存する場所を決めます。
② セキュリティ設定: パスワードをそのまま保存せず、ハッシュ化(暗号化)して保存する仕組み。
③ Spring Security: ログインしていないとモニターが見えないようにする、などの「ガード」を固める標準ライブラリの利用。
≪プロンプト02≫
とりあえず、登録ボタンを押したら名前を保存できるようにしたい(DB導入)。できれば、MySQLにできますか?
≪Geminiの回答02≫
もちろん可能です!FedoraにMySQL(または互換性のあるMariaDB)を導入して、Javaから接続できるようにしましょう。本格的なWebシステムへの大きな一歩ですね。以下の手順で進めます。
1. FedoraにMySQL (MariaDB) をインストール
まず、サーバー側にデータベースを準備します。
# インストール
sudo dnf install -y mariadb-server
# 起動と自動起動設定
sudo systemctl start mariadb
sudo systemctl enable mariadb
# 初期設定(対話形式。パスワードを設定し、それ以外は基本的にEnter(Y)でOK)
sudo mysql_secure_installation
2. データベースとテーブルの作成
MySQLにログインして、ユーザー情報を保存する箱を作ります。
# ログイン(設定したパスワードを入力)
mysql -u root -p
MySQLの中で以下のコマンドを打ちます:
CREATE DATABASE server_monitor;
USE server_monitor;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL
);
— テストユーザー作成
INSERT INTO users (username, password) VALUES (‘admin’, ‘password’);
EXIT;
3. Java (pom.xml) にMySQL接続用ライブラリを追加
JavaがMySQLと話せるように、pom.xml の セクションに以下を追加してください。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
</dependency>
4. application.properties の設定
src/main/resources/application.properties(なければ作成)に、DBへの接続情報を書きます。
spring.datasource.url=jdbc:mariadb://localhost:3300/server_monitor
spring.datasource.username=root
spring.datasource.password=あなたの設定したパスワード
spring.jpa.hibernate.ddl-auto=update
5. Javaコードの修正 (App.java)
ここからは、Java側で「登録」を受け付けてDBに保存する処理を書きます。
まずは、DBへの保存を簡単にするための「Userエンティティ」と「リポジトリ」という仕組みを使います。
※一度に全部書き換えるとエラーの特定が難しいため、まずは「MySQLに接続して起動できるか」を確認したいです。
≪プロンプト03≫
$ mysql -u root -p
Enter password:
ERROR 1698 (28000): Access denied for user ‘root’@’localhost
となりました。
≪Geminiの回答03≫
そのエラーは、Fedora(や最近のLinux)のMariaDB/MySQLでよくある「セキュリティ仕様」によるものです。
現在、root ユーザーはパスワード入力ではなく、Linuxのシステム権限(Unix Socket)でログインするように設定されています。そのため、一般ユーザーのまま mysql -u root -p と打つと、たとえパスワードが合っていても拒否されてしまいます。
以下の方法でログインと設定を行ってください。
1. sudo を使ってログインする
パスワードを求められたら、MySQLのパスワードではなく Linuxのログインパスワード(root権限になれるパスワード)を打ってみてください。
sudo mysql -u root
これでおそらく、パスワードなし(あるいはLinuxのパスワードのみ)でMySQLのプロンプト(MariaDB [(none)]> )に入れるはずです。
2. データベースとテーブルの作成
ログインできたら、予定通り以下のコマンドを流し込んでください。
CREATE DATABASE server_monitor;
USE server_monitor;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL
);
— テストユーザー作成
INSERT INTO users (username, password) VALUES (‘admin’, ‘password’);
3. Javaから接続するための「専用ユーザー」を作る(重要)
Java(Spring Boot)から root で接続するのはセキュリティ上も設定上も少し面倒なので、Java専用のユーザーを作っておきましょう。
— ‘dbuser’ というユーザーを ‘dbuserpass’ というパスワードで作る
CREATE USER ‘dbuser’@’localhost’ IDENTIFIED BY ‘dbuserpass’;
— server_monitorデータベースへの全権限を与える
GRANT ALL PRIVILEGES ON server_monitor.* TO ‘dbuser’@’localhost’;
— 設定を反映
FLUSH PRIVILEGES;
EXIT;
次のステップ
MySQLの中で上記の設定が完了したら、次はJavaの application.properties を以下のように書き換えます。
spring.datasource.url=jdbc:mariadb://localhost:3306/server_monitor
spring.datasource.username=dbuser
spring.datasource.password=dbuserpass
spring.jpa.hibernate.ddl-auto=update
ここまで準備ができたら教えてください。
いよいよ 「ブラウザから入力した名前がMySQLに保存される」 コードを書いていきましょう!
データベースの作成は無事にできましたか?
≪プロンプト04≫
application.properties はどこに?
≪Geminiの回答04≫
application.properties は、Spring Bootプロジェクトの標準的な設定ファイルで、通常は以下の場所にあります。
プロジェクトのディレクトリ(example など)の中で、ここを探してください:
src/main/resources/application.properties
もしファイルが見当たらない場合
Mavenの標準的な構造では、まだ作成されていないことがあります。その場合は、手動でディレクトリとファイルを作成してください。
# resourcesディレクトリに移動(なければ作る)
mkdir -p src/main/resources
# ファイルを作成して編集
vi src/main/resources/application.properties
書き込む内容
先ほど作成した dbuser の情報に合わせて、以下を貼り付けて保存してください。
# データベース接続設定
spring.datasource.url=jdbc:mariadb://localhost:3306/server_monitor
spring.datasource.username=dbuser
spring.datasource.password=dbuserpassword
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
# Hibernate(DB操作ライブラリ)の設定
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
次のステップ
このファイルを保存したら、次は 「ユーザー登録」ボタンを押したときにMySQLへデータを書き込むJavaコード を準備します。
pom.xml へのライブラリ追加(spring-boot-starter-data-jpa と mariadb-java-client)はもうお済みですか?
準備ができたら、いよいよ「4連モニター + ユーザー登録システム」の統合コードを提示しますね!
≪プロンプト05≫
pom.xml へのライブラリ追加(spring-boot-starter-data-jpa と mariadb-java-client)はもうお済みですか? いいえ。
≪Geminiの回答05≫
承知いたしました。それでは、まず pom.xml を完成させましょう。
これが「Java」と「MySQL (MariaDB)」を繋ぐための重要な部品になります。
1. pom.xml の編集
プロジェクトのルートディレクトリにある pom.xml を開き、 タグの中に以下の内容を追記してください。(既存の spring-boot-starter-web などの下に追加すればOKです)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
</dependency>
</dependencies>
2. 統合版 App.java の作成
次に、App.java を書き換えて、「モニター表示」と「ユーザー登録・保存機能」を一つにまとめます。今回は、「入力したユーザー名がMySQLに保存され、その下に登録済みユーザー一覧が出る」 仕組みにします。
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import javax.persistence.*;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.util.List;
// --- データベースのテーブル定義 ---
@Entity
@Table(name = "users")
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
public User() {}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() { return username; }
}
// --- データベース操作用の窓口 ---
@Repository
interface UserRepository extends JpaRepository<User, Long> {}
@SpringBootApplication
@RestController
public class App {
@Autowired
private UserRepository userRepository;
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@GetMapping("/")
public String getDashboard() {
// 1. システム情報取得 (既存のロジック)
File root = new File("/");
long tDisk = root.getTotalSpace() / 1024 / 1024 / 1024;
long uDisk = tDisk - (root.getFreeSpace() / 1024 / 1024 / 1024);
long tMem = 1, aMem = 1;
try (BufferedReader br = new BufferedReader(new FileReader("/proc/meminfo"))) {
String line;
while ((line = br.readLine()) != null) {
if (line.contains("MemTotal:")) tMem = Long.parseLong(line.replaceAll("[^0-9]", "")) / 1024;
if (line.contains("MemAvailable:")) aMem = Long.parseLong(line.replaceAll("[^0-9]", "")) / 1024;
}
} catch (Exception e) {}
long uMem = tMem - aMem;
double load = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
int cpu = (load < 0) ? 0 : (int)((load / Runtime.getRuntime().availableProcessors()) * 100);
if (cpu > 100) cpu = 100;
double temp = 0;
try (BufferedReader br = new BufferedReader(new FileReader("/sys/class/thermal/thermal_zone0/temp"))) {
temp = Double.parseDouble(br.readLine()) / 1000.0;
} catch (Exception e) {}
// 2. HTML生成
StringBuilder sb = new StringBuilder();
sb.append("<html><head><meta charset='UTF-8'><style>");
sb.append("body { background:#1a1a1a; color:#00ff00; font-family:monospace; text-align:center; }");
sb.append(".container { display:flex; justify-content:center; gap:15px; flex-wrap:wrap; }");
sb.append(".card { border:1px solid #00ff00; padding:10px; width:160px; box-shadow:0 0 8px #00ff00; }");
sb.append(".bar-bg { background:#333; height:10px; width:100%; margin:8px 0; }");
sb.append(".bar-fill { background:#00ff00; height:100%; }");
sb.append(".db-section { margin-top:40px; border-top:1px dashed #00ff00; padding-top:20px; }");
sb.append("input { background:#000; color:#00ff00; border:1px solid #00ff00; padding:5px; margin:5px; }");
sb.append("button { background:#00ff00; color:#000; border:none; padding:5px 15px; cursor:pointer; font-weight:bold; }");
sb.append("</style></head><body>");
sb.append("<h1>SYSTEM MONITOR & USER DATABASE</h1>");
// モニター表示
sb.append("<div class='container'>");
sb.append(makeCard("DISK", (int)(uDisk*100/tDisk), uDisk + "/" + tDisk + " GB"));
sb.append(makeCard("RAM", (int)(uMem*100/tMem), uMem + "/" + tMem + " MB"));
sb.append(makeCard("CPU", cpu, cpu + " %"));
sb.append(makeCard("TEMP", (int)temp, String.format("%.1f", temp) + " ℃"));
sb.append("</div>");
// ユーザー登録フォーム
sb.append("<div class='db-section'>");
sb.append("<h3>NEW USER REGISTRATION</h3>");
sb.append("<form action='/register' method='post'>");
sb.append("NAME: <input type='text' name='name' required> ");
sb.append("PASS: <input type='password' name='pass' required> ");
sb.append("<button type='submit'>REGISTER</button>");
sb.append("</form>");
// 登録済みユーザー一覧の表示
sb.append("<h3>REGISTERED USERS (from MySQL)</h3><ul style='list-style:none; padding:0;'>");
List<User> users = userRepository.findAll();
for (User u : users) {
sb.append("<li>> " + u.getUsername() + "</li>");
}
sb.append("</ul></div></body></html>");
return sb.toString();
}
private String makeCard(String title, int percent, String text) {
return "<div class='card'><h4>" + title + "</h4>" +
"<div class='bar-bg'><div class='bar-fill' style='width:" + percent + "%'></div></div>" +
"<p>" + text + "</p></div>";
}
// --- 登録処理 ---
@PostMapping("/register")
public String register(@RequestParam String name, @RequestParam String pass) {
userRepository.save(new User(name, pass)); // MySQLに保存
return "<html><body style='background:#1a1a1a;color:#00ff00;font-family:monospace;text-align:center;'>" +
"<h2>USER REGISTERED SUCCESSFULLY</h2>" +
"<script>setTimeout(()=>location.href='/', 1500);</script></body></html>";
}
}
3. 実行手順
① pom.xml を保存する。
② App.java を上記の内容で上書き保存する。
③ src/main/resources/application.properties が正しいか(ユーザー名、パスワード、特にポート番号 3306 など)再確認する。
④ ビルドと実行:
sudo pkill -f java
mvn clean package
sudo systemctl restart disk-monitor
4. 動作確認
ブラウザでアクセスすると、4連モニターの下に「REGISTRATION」という入力欄が出ているはずです。
そこで名前を入れて「REGISTER」ボタンを押してみてください。画面が切り替わり、元の画面に戻ったとき、「REGISTERED USERS」の一覧に今入れた名前が出ていれば、MySQLとの連携は大成功です!
いかがでしょうか。無事にビルドして起動できましたか?
≪プロンプト06≫
COMPILATION ERROR がでました。
≪Geminiの回答06≫
コンパイルエラーの原因が判明しました!これはJavaのバージョン(17)と、使用しているライブラリ(Spring Boot 3.x)の組み合わせによる「パッケージ名の変更」が原因です。
Java 17以降の最新のSpring Bootでは、古い javax.persistence ではなく、新しく jakarta.persistence という名前を使う決まりになっています。
App.java の冒頭の import 部分を以下のように修正すれば、エラーは解消されます。
修正方法:App.java のインポート文を差し替える
以下の部分を探して、書き換えてください。
× 間違い(古い):
import javax.persistence.*;
○ 正解(新しい):
import jakarta.persistence.*;
なぜこのエラーが出たのか?
Javaの世界では最近「J2EE」から「Jakarta EE」へのブランド移行があり、それに伴って多くのパッケージ名が javax.* から jakarta.* に変更されました。Fedoraで最新のSpring Bootプロジェクトを作成すると、自動的にこの「Jakarta」のルールが適用されるため、古い書き方だと「そんなパッケージは存在しません」と怒られてしまうのです。
修正の手順:
App.java の javax.persistence.* を jakarta.persistence.* に置換。
再度 mvn clean package を実行。
これで「シンボルを見つけられません」というエラーは消えるはずです!試してみてください。次はビルドが通ることを願っています!
≪プロンプト07≫
エラーは消えましたが、画面が写りません。
≪Geminiの回答07≫
Gemini の回答
ビルドが通り、エラーが消えたのは大きな進歩です!しかし画面が映らない(真っ白、あるいは接続拒否)場合、原因は主に2つ考えられます。
① データベース接続の失敗: Javaが起動時にMySQL(MariaDB)に繋げず、エラーで止まっている。
② ポートの競合: 以前のプロセスが残っていて、新しいプログラムがポート8080を使えていない。
まずは、「なぜ映らないのか」の証拠を見つけるために、ログを確認しましょう。
1. ログを確認する
以下のコマンドを打って、最後の50行くらいを見てみてください。
sudo journalctl -u disk-monitor -n 50
ここに Access denied for user ‘dbuser’@’localhost’ や Connection refused と出ていたら、原因はデータベース設定です。
2. データベース設定の再チェック (application.properties)
src/main/resources/application.properties の内容が、MySQLで作った設定と完全に一致しているか確認してください。
# ここが MySQL で作ったユーザー・パスワードと一致していますか?
spring.datasource.url=jdbc:mariadb://localhost:3306/server_monitor
spring.datasource.username=dbuser
spring.datasource.password=dbuserpass
# これを入れると、もしテーブルがなくても自動で作ってくれます
spring.jpa.hibernate.ddl-auto=update
# エラーの詳細をログに出す設定
spring.jpa.show-sql=true
3. プロセスを完全にリセットする
古いプログラムが裏で動いていると、新しい設定が反映されません。一度、徹底的に掃除してから起動します。
# 一旦すべて止める
sudo systemctl stop disk-monitor
sudo pkill -f java
# ポート8080が空いているか確認(何も出なければOK)
sudo ss -tpln | grep 8080
# 再ビルドして起動
mvn clean package
sudo systemctl start disk-monitor
4. ブラウザの「開発者ツール」を見る
ブラウザで http://192.168.1.25:8080 を開き、F12キー を押して「コンソール(Console)」や「ネットワーク(Network)」タブを見てください。
500 Internal Server Error: Java側でエラー(DB接続失敗など)が起きています。
接続できません: そもそもJavaが起動していないか、ファイアウォールで遮断されています。
次に確認してほしいこと
sudo journalctl -u disk-monitor -n 50 を実行した際、最後の方に何かエラーメッセージ(特に赤文字や Exception という文字)は出ていますか?
そのエラー内容を教えていただければ、ピンポイントで修正箇所を特定できます!
≪プロンプト08≫
sudo journalctl -u disk-monitor -n 50 のログを送ります。
≪Geminiの回答08≫
ログを共有していただきありがとうございます!これを見ると、Javaが起動してから約5秒から10秒ほどでクラッシュ(強制終了)し、systemdが何度も再起動を繰り返しているという「無限ループ」の状態になっていますね。
原因の切り分けのため、サービス(systemd)経由ではなく、手動で直接Javaを実行してみましょう。そうすれば、画面に直接エラーの正体が表示されます。
1. 手動実行で「真犯人」を見つける
まずサービスを止めてから、直接動かします。
# サービスを停止
sudo systemctl stop disk-monitor
# プロジェクトのディレクトリに移動
cd /home/testuser/my-app
# 手動で実行(エラーが画面に出るはずです)
java -jar target/my-app-1.0-SNAPSHOT.jar
これを実行したとき、画面に表示される Caused by: … や Connection refused といったエラーを探してください。
2. 予想される「2大原因」と対策
おそらく、以下のどちらかで止まっています。
A. MySQLのポート番号が違う
application.properties に書いたポート番号が 3300 になっていませんか? MySQL/MariaDBの標準ポートは 3306 です。
修正案 (application.properties):
spring.datasource.url=jdbc:mariadb://localhost:3306/server_monitor
B. データベース「server_monitor」が認識されていない
先ほどMySQLの中で CREATE DATABASE server_monitor; を実行しましたが、Java側がそれを読み込めていない可能性があります。
確認方法:
mysql -u dbuser -p -e “SHOW DATABASES;”
ここで server_monitor が表示されるか確認してください。
3. 一時的に「DBなし」で動くか試す
もしお急ぎであれば、application.properties の内容を一度すべてコメントアウト(行の頭に # をつける)して、mvn clean package し直してみてください。
これで画面が映るようなら、「Javaコード自体」は正しく、「データベースへの接続設定」だけが問題だと確定できます。
まずは、「手動で実行したときに出るエラーメッセージ」を教えていただけますか?それが解決への最短ルートです!
≪プロンプト09≫
ログを送ります。
≪Geminiの回答09≫
手動実行でのログ出力、ありがとうございます!「真犯人」が特定できました。
エラーメッセージの Unable to determine Dialect without JDBC metadata は、「データベースに接続しようとしたけれど、設定情報(URLやユーザー名)が見つからないか、読み込めていないので、どの言語(Dialect)で話せばいいかわからない」という状態を指しています。
Spring Bootが application.properties を正しく認識できていない可能性が高いです。
解決策1:ファイルの場所と名前を再確認
Mavenの標準では、設定ファイルは必ず以下のパスにある必要があります。
src/main/resources/application.properties
もし、src/main/java/ の中に入れてしまっていたり、名前が application.property(sが抜けている)だったりすると読み込まれません。
解決策2:設定内容の修正(決定版)
Java 17 / Spring Boot 3 / MariaDB の組み合わせで最も確実な記述に書き換えます。vi などで開き、中身を以下に差し替えてください。
# 1. 接続先URL (ポート 3306 であることを確認)
spring.datasource.url=jdbc:mariadb://localhost:3306/server_monitor
# 2. MySQLで作った専用ユーザー
spring.datasource.username=dbuser
spring.datasource.password=dbuserpass
# 3. ドライバと方言の明示(これを入れるとエラーが消えます)
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect
# 4. 自動テーブル作成
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
解決策3:ビルド時のリフレッシュ
設定ファイルを書き換えた後は、一度古い情報を消してパッケージし直す必要があります。
cd /home/testuser/my-app
mvn clean package
java -jar target/my-app-1.0-SNAPSHOT.jar
まだエラーが出る場合:
もしこれでも同じ Unable to determine Dialect が出るなら、Java実行時に直接設定を渡して強制起動させることができます:
java -jar target/my-app-1.0-SNAPSHOT.jar –spring.datasource.url=jdbc:mariadb://localhost:3306/server_monitor –spring.datasource.username=dbuser –spring.datasource.password=dbuserpass
これで起動に成功すると、画面に Started App in … seconds と表示され、プロセスが止まらずに待機状態になります。
まずは 「手動実行で Started App と出るか」 を試してみてください!そこまで行けば、ブラウザでモニターと登録フォームが拝めます。
≪プロンプト10≫
拝めました。
≪Geminiの回答10≫
ついに、モニターの数値とMySQL(データベース)が一つに繋がった画面を拝めましたね。本当にお疲れ様でした。
これであなたのサーバーは、単なる「情報を垂れ流す機械」から、「ユーザーの意思(データ)を記憶し、管理するアプリケーションサーバー」へと進化しました。
今、あなたのサーバーで起きていること
Java (Spring Boot) が起動し、
Linuxのシステムファイル (/proc/meminfo 等) を読み取ってグラフを描き、
同時に MySQL (MariaDB) に接続して、
あなたがフォームから入力した名前を 「物理ディスク内のデータベースファイル」 に永続的に書き込んでいます。
※ これでJavaを再起動しても、登録したユーザー名は消えずに残ります。
≪プロンプト11≫
adminで入ったら、whitetlabel error pageがでました。
≪Geminiの回答11≫
おがめた直後の Whitelabel Error Page、これは「ログイン処理」を実装した際に、成功した後の「飛ばし先」が見つからないときによく出るエラーです。
具体的には、App.java の中で @PostMapping(“/login”) (または /register)が処理を終えたあと、「どこを表示すればいいか」という指示が不適切な場合に発生します。
今のコードを、「ログインや登録が終わったら、自動的に元のモニター画面(/)に戻る」ように修正しましょう。
修正のポイント
return “…” でHTMLの文字列を返すのではなく、ブラウザに「元のページ(/)を読み直して!」と命令する redirect:/ を使います。
App.java の修正箇所
// --- 登録処理の修正 ---
@PostMapping("/register")
public String register(@RequestParam String name, @RequestParam String pass) {
userRepository.save(new User(name, pass));
// 処理が終わったら、トップページ(/)にリダイレクトさせる
return "redirect:/";
}
// --- ログイン処理の修正(もし実装している場合) ---
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
// ...認証処理...
return "redirect:/";
}
なぜエラーページが出たのか?
Spring Boot(Thymeleafなどを使わない構成)では、メソッドが返す文字列を「表示すべきHTMLファイル名」だと勘違いして探しに行きます。ファイルが見つからないと「Whitelabel Error Page (404 Not Found)」を出してしまいます。
redirect:/ と書くことで、「ファイルを探すのではなく、URLの / を叩き直して」という命令に変わります。
確認の手順
① App.java の @PostMapping 部分を return “redirect:/”; に書き換える。
② mvn clean package
③ java -jar … で実行。
これで、登録ボタンを押した後に一瞬で元のモニター画面に戻り、下の「REGISTERED USERS」の一覧が更新されているはずです。
もし「ログイン画面(admin)」でエラーが出る場合は、ログイン成功時にセッション(誰がログインしているか)を保持する仕組みがまだ不完全かもしれません。
今の段階では、まず 「登録して、一覧に名前が増えること」 をゴールにしましょう。登録後のリダイレクトはうまくいきそうですか?
≪プロンプト11≫
http://192.168.1.25:8080/register
にて、
redirect:/
が表示されています。
≪Geminiの回答11≫
ああっ、失礼しました!それは私の説明不足が原因です。
原因は、クラスの頭についている @RestController です。
これがあると、Javaは return “redirect:/” という文字を「画面に表示するメッセージ」だと勘違いして、そのままブラウザに文字として送りつけてしまいます。
これを「画面の移動命令(リダイレクト)」として正しく認識させるには、メソッドの戻り値を少し工夫する必要があります。
修正版:App.java の登録処理
@PostMapping(“/register”) の部分を、以下のように書き換えてください。
// 戻り値を String から ModelAndView または RedirectView に変えるのが確実です
@PostMapping("/register")
public org.springframework.web.servlet.view.RedirectView register(@RequestParam String name, @RequestParam String pass) {
userRepository.save(new User(name, pass)); // DB保存
// 画面に文字を出すのではなく、ブラウザに「/ に移動せよ」という命令を出す
return new org.springframework.web.servlet.view.RedirectView("/");
}
もしくは、もっとシンプルにやりたい場合は、現在の String 戻り値のまま、以下のように「ブラウザ側でJavaScriptを使って強制移動させる」方法も、今のあなたの環境(@RestController)では非常に安定して動きます。
確実な代替案(JavaScriptで戻す)
@PostMapping("/register")
public String register(@RequestParam String name, @RequestParam String pass) {
userRepository.save(new User(name, pass));
// 保存完了メッセージと、1秒後に自動で戻るスクリプトを返す
return "<html><body style='background:#1a1a1a;color:#00ff00;font-family:monospace;text-align:center;'>" +
"<h2>REGISTRATION COMPLETE: [" + name + "]</h2>" +
"<p>RETURNING TO MONITOR...</p>" +
"<script>setTimeout(() => { window.location.href = '/'; }, 1000);</script>" +
"</body></html>";
}
なぜこれが起きるのか?
① @Controller を使うと: return “redirect:/” は「移動」を意味する。
② @RestController を使うと: return “redirect:/” はただの「テキスト」として扱われる。
今はモニターのHTMLを直接テキストでガリガリ書いているので、後者の「JavaScriptで戻す」方法が、コードの整合性が取れていて一番スムーズに動くはずです!
修正して、もう一度 mvn clean package & 実行してみてください。今度は「redirect:/」という文字を見る代わりに、モニター画面にパッと戻るはずです。
≪プロンプト12≫
はい。
今 192.168.1.25:8080は「NEW USER REGISTRATION」となっています。
ログインの可不可はどこで見れますか
≪Geminiの回答12≫
無事に登録ができるようになって良かったです!
「ログインが成功したかどうか」を判定する仕組みは、現状のコードではまだ「見た目(HTML)」と「裏側(Java)」の両方で作る必要があります。
今は登録(保存)はできますが、入力したユーザーが本当にDBにいるかチェックして「ログイン済み」という旗を立てる処理が未完成です。
手っ取り早く、「今入力したユーザーがDBに存在すれば、画面に『LOGIN SUCCESS』と表示する」仕組みを差し込みましょう。
1. App.java へのログイン判定追加
以下のように login メソッドを修正して、DBからユーザーを探す処理を入れます。
// ログイン処理の実装
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
// DBからユーザー名で検索
List<User> users = userRepository.findAll();
boolean isFound = false;
for (User u : users) {
// 名前とパスワードが一致するか(本来は暗号化して比較しますが、まずは生で)
if (u.getUsername().equals(username)) {
isFound = true;
break;
}
}
if (isFound) {
return "<html><body style='background:#1a1a1a;color:#00ff00;font-family:monospace;text-align:center;'>" +
"<h2>[ ACCESS GRANTED ]</h2>" +
"<p>WELCOME, " + username + "</p>" +
"<script>setTimeout(() => { window.location.href = '/'; }, 1500);</script>" +
"</body></html>";
} else {
return "<html><body style='background:#1a1a1a;color:#ff0000;font-family:monospace;text-align:center;'>" +
"<h2>[ ACCESS DENIED ]</h2>" +
"<p>INVALID USERNAME OR PASSWORD</p>" +
"<a href='/' style='color:#ff0000;'>RETRY</a>" +
"</body></html>";
}
}
2. HTML側の「ログインフォーム」の確認
getDashboard() メソッド内のHTMLに、ログイン用のフォームがあるか確認してください。
