mavenプロジェクトを構築する

This commit is contained in:
ry.yamafuji 2025-10-11 18:09:02 +09:00
parent 68d4ccbc4c
commit cd3aae30ce
18 changed files with 661 additions and 8 deletions

View File

@ -4,7 +4,10 @@ JAVA Basic Code
## 実行方法
### JDK
```sh
cd dockerfile/jdk
docker compose up -d
docker compose exec -it app bash
```
@ -14,4 +17,11 @@ docker compose exec -it app bash
```sh
javac Hello.java
java Hello
```
```
### Maven
```sh
docker compose up -d
docker compose exec -it dev bash
```

View File

@ -1,12 +1,14 @@
version: "3.9"
# compose.yaml
services:
app:
image: eclipse-temurin:21-jdk
working_dir: /app
dev:
image: maven:3.9-eclipse-temurin-21
working_dir: /workspace
volumes:
- ./src:/app # ← bind mountホストの ./src を /app に)
- ./:/workspace
- m2:/root/.m2 # 依存キャッシュ
tty: true
stdin_open: true
command: bash
# # command: bash -lc "javac Hello.java && java Hello"
# command: bash -lc "mvn -DskipTests package && bash"
volumes:
m2:

View File

@ -0,0 +1,12 @@
version: "3.9"
services:
app:
image: eclipse-temurin:21-jdk
working_dir: /app
volumes:
- ./src:/app # ← bind mountホストの ./src を /app に)
tty: true
stdin_open: true
command: bash
# # command: bash -lc "javac Hello.java && java Hello"

222
docs/java_construction.md Normal file
View File

@ -0,0 +1,222 @@
# Java SE構文8〜21の主要差分まとめ
この文書は、Java SE 8から21までに追加・変更された主要な言語仕様とAPIをまとめたものです。
バージョン間の差分を理解することで、最新のJavaコードを正しく書き分けることができます。
---
## Java 82014年
**モダンJavaの基礎となるアップデート**
- **ラムダ式**
```java
list.forEach(x -> System.out.println(x));
```
匿名クラスを簡潔に書ける。
- **Stream API**
```java
list.stream().filter(x -> x > 10).map(x -> x * 2).toList();
```
コレクションを関数的に操作可能。
- **Optional<T>**
```java
Optional.ofNullable(value).orElse("default");
```
Null安全のためのラッパー型。
- **Date and Time API (java.time)**
```java
LocalDate.now(); Instant.now();
```
新しい日付時刻API旧java.util.Dateの置換
- **Defaultメソッドinterface**
```java
interface A {
default void log() { System.out.println("log"); }
}
```
---
## Java 92017年
**モジュール化とAPI整備**
- **モジュールシステムProject Jigsaw**
```java
module com.example.app {
requires java.sql;
exports com.example.app;
}
```
大規模プロジェクト向け依存管理。
- **try-with-resources改良**
```java
try (var br = Files.newBufferedReader(path)) {
...
}
```
既存変数もtryリソースとして扱える。
- **Stream API追加メソッド**
`takeWhile`, `dropWhile`, `iterate`(predicate付き)
- **`var` はまだ導入されていないJava 10以降**
---
## Java 102018年
**ローカル変数型推論**
- **var キーワード**
```java
var list = new ArrayList<String>();
```
コンパイル時に型を推論。ただしローカル変数限定。
---
## Java 112018年LTS
**安定版LTS・実用性の向上**
- **新HTTPクライアントjava.net.http**
```java
HttpClient.newHttpClient()
.send(HttpRequest.newBuilder(URI.create("https://example.com")).build(),
HttpResponse.BodyHandlers.ofString());
```
- **文字列ユーティリティ**
- `" text ".strip()`
- `"a\nb\n".lines()`
- `"abc".repeat(3)`
- **ファイル読み書きの簡略化**
```java
String s = Files.readString(Path.of("a.txt"));
```
- **var in lambda**
```java
(var x, var y) -> x + y
```
---
## Java 12〜152019〜2020年
**構文改善と新機能の試験導入**
- **switch式Java 14で正式導入**
```java
int num = switch (day) {
case MON, TUE -> 1;
default -> 0;
};
```
- **テキストブロックJava 15**
```java
String json = """
{
"id": 1,
"name": "test"
}
""";
```
---
## Java 162021年
**record と sealed の前段階**
- **recordクラスデータ専用クラス**
```java
public record Point(int x, int y) {}
Point p = new Point(1, 2);
```
- **Stream.toList()**
Java 8までは `collect(Collectors.toList())` が必要だった。
---
## Java 172021年LTS
**構造的な制約とパターンマッチング**
- **sealedクラス**
```java
public sealed class Shape permits Circle, Square {}
public final class Circle extends Shape {}
```
- **instanceofパターンマッチング**
```java
if (obj instanceof String s) {
System.out.println(s.length());
}
```
---
## Java 18〜202022〜2023年
**テスト的・プレビュー的な改良**
- **Simple Web Server**
```bash
jwebserver -p 8080
```
簡易HTTPサーバを起動できる。
- **Recordパターンプレビュー**
```java
if (p instanceof Point(int x, int y)) { ... }
```
---
## Java 212023年LTS
**軽量スレッドVirtual Threadとパターンマッチの完成形**
- **Virtual Thread**
```java
Thread.startVirtualThread(() -> System.out.println("Hello"));
```
数百万スレッドを軽量に扱える。
- **Pattern Matching for switch**
```java
static String format(Object o) {
return switch (o) {
case Integer i -> "int " + i;
case String s -> "str " + s;
default -> "unknown";
};
}
```
- **Record Pattern正式採用**
```java
record Point(int x, int y) {}
if (obj instanceof Point(int x, int y)) { ... }
```
---
## まとめ
| バージョン | 主な特徴 |
| ---------- | ------------------------------------------- |
| 8 | Lambda, Stream, Optional, 新Date/Time |
| 9 | Module System |
| 10 | var型推論 |
| 11 | 新HTTP, String/Files改善 |
| 14 | switch式 |
| 15 | テキストブロック |
| 16 | record |
| 17 | sealed, instanceof pattern |
| 21 | virtual thread, pattern matching for switch |
この流れを理解しておくと、古いコードと新しいコードの混在環境でもスムーズに対応できる。

229
docs/java_maven.md Normal file
View File

@ -0,0 +1,229 @@
# Mavenとは
Maven(メイヴン)は、Javaプロジェクトのビルド・依存管理・実行を自動化するツールです。
* Node.js の npm
* Python の pip + venv
## Install
### Windows
wingetでインストール
```sh
# JDK
winget install EclipseAdoptium.Temurin.21.JDK
# Maven
winget install Apache.Maven
# 確認
java -version
mvn -v
```
Chocolatey(管理者 PowerShell)でインストール
```powershell
choco install temurin21
choco install maven
```
永続的に設定(PowerShell管理者)
```powershell
# JDK のインストール先に応じてパスを調整
setx JAVA_HOME "C:\Program Files\Eclipse Adoptium\jdk-21"
setx MAVEN_HOME "C:\ProgramData\chocolatey\lib\maven\apache-maven-3.9.9"
setx PATH "%PATH%;%JAVA_HOME%\bin;%MAVEN_HOME%\bin"
```
プロジェクト作成・実行
```powershell
mvn archetype:generate -DgroupId=com.example -DartifactId=hello-maven `
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
cd hello-maven
mvn -q -DskipTests package
```
### Mac
Homebrewでインストール
```sh
brew install maven
# 確認
mvn -v
# 出力例
# Apache Maven 3.9.9
# Java version: 21.0.2
```
### Linux
Debian/Ubuntu
```sh
sudo apt update
sudo apt install -y temurin-21-jdk maven || sudo apt install -y openjdk-21-jdk maven
java -version
mvn -v
```
Fedora/RHEL/CentOS Stream
```sh
sudo dnf install -y java-21-openjdk java-21-openjdk-devel maven
```
### Dockerで実行する場合
公式イメージ: maven:3.9-eclipse-temurin-21
```sh
mkdir hello-maven && cd hello-maven
docker run --rm -it -v "$PWD":/app -w /app maven:3.9-eclipse-temurin-21 \
mvn -q archetype:generate -DgroupId=com.example -DartifactId=hello-maven \
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
cd hello-maven
docker run --rm -it -v "$PWD":/app -w /app maven:3.9-eclipse-temurin-21 mvn -q -DskipTests package
```
# 生成物: target/*.jar はホスト側にも残る
## How To Setup
プロジェクト作成
```sh
mvn archetype:generate -DgroupId=com.example -DartifactId=hello-maven \
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
```
以下の構築が作成されます
```txt
hello-maven/
├─ pom.xml
├─ src/
│ ├─ main/java/com/example/App.java
│ └─ test/java/com/example/AppTest.java
```
| オプション | 意味 |
| -------------------------------------------------- | --------------------------------------------------- |
| `archetype:generate` | |
| `-DgroupId=com.example` | グループID(Javaのパッケージ階層にも使われる) |
| `-DartifactId=hello-maven` | アーティファクトID(生成されるプロジェクト名) |
| `-DarchetypeArtifactId=maven-archetype-quickstart` | 使用するテンプレートの種類(標準の“最小構成”の1つ) |
| `-DinteractiveMode=false` | 対話モードをオフ(すべて自動) |
### 基本的なコマンド
* `mvn compile`
* ソースをコンパイル(`target/classes`へ)
* `mvn exec:java -Dexec.mainClass="com.example.App"`
* 実行(後述のplugin必要)
* `mvn test`
* テスト実行
* `mvn package`
* jarファイル作成(`target/hello-maven-1.0-SNAPSHOT.jar`)
* `mvn clean`:
* `target`ディレクトリ削除
直接`mvn exec:java`で動かす場合はpluginが必要です。
pom.xml
```xml
<project>
<!-- add -->
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>com.example.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<!-- /add -->
</project>
```
直接実行する場合は以下です
```sh
java -cp target/classes com.example.App
```
* `-cp`: はクラスパス指定(classpath)
* `com.example.App`は完全修飾クラス名
* 拡張子`.class`は書かない
### パッケージ化する場合
1. Jarファイルを作成する
2. Jarから実行する
```sh
# java -cp target/xxx.jar com.example.App
java -cp target/hello-maven-1.0-SNAPSHOT.jar com.example.App
```
Javaは通常、.class(target/classes/)と他のライブラリ(.jar)を別々に管理しています。そのままだと実行時に依存jarが必要です。
```sh
java -cp target/classes:~/.m2/repository/gson-2.10.jar com.example.App
```
`fat jar`にまとめることにより全部ひとつのjarにパッキングできます。
maven-assembly-pluginが必要になります
```xml
<project>
<!-- add -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- /add -->
</project>
```
コマンド
```sh
mvn clean package
java -jar target/hello-maven-1.0-SNAPSHOT-jar-with-dependencies.jar
```

32
hello-maven/pom.xml Normal file
View File

@ -0,0 +1,32 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>hello-maven</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>hello-maven</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>com.example.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,13 @@
package com.example;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}

View File

@ -0,0 +1,38 @@
package com.example;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

View File

@ -0,0 +1,3 @@
artifactId=hello-maven
groupId=com.example
version=1.0-SNAPSHOT

View File

@ -0,0 +1 @@
/workspace/hello-maven/src/main/java/com/example/App.java

View File

@ -0,0 +1 @@
/workspace/hello-maven/src/test/java/com/example/AppTest.java

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report-3.0.xsd" version="3.0" name="com.example.AppTest" time="0.275" tests="1" errors="0" skipped="0" failures="0">
<properties>
<property name="java.specification.version" value="21"/>
<property name="sun.jnu.encoding" value="UTF-8"/>
<property name="java.class.path" value="/workspace/hello-maven/target/test-classes:/workspace/hello-maven/target/classes:/root/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar:"/>
<property name="java.vm.vendor" value="Eclipse Adoptium"/>
<property name="sun.arch.data.model" value="64"/>
<property name="java.vendor.url" value="https://adoptium.net/"/>
<property name="os.name" value="Linux"/>
<property name="java.vm.specification.version" value="21"/>
<property name="sun.java.launcher" value="SUN_STANDARD"/>
<property name="user.country" value="US"/>
<property name="sun.boot.library.path" value="/opt/java/openjdk/lib"/>
<property name="sun.java.command" value="/workspace/hello-maven/target/surefire/surefirebooter-20251011085740477_3.jar /workspace/hello-maven/target/surefire 2025-10-11T08-57-37_548-jvmRun1 surefire-20251011085740477_1tmp surefire_0-20251011085740477_2tmp"/>
<property name="jdk.debug" value="release"/>
<property name="surefire.test.class.path" value="/workspace/hello-maven/target/test-classes:/workspace/hello-maven/target/classes:/root/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar:"/>
<property name="sun.cpu.endian" value="little"/>
<property name="user.home" value="/root"/>
<property name="user.language" value="en"/>
<property name="java.specification.vendor" value="Oracle Corporation"/>
<property name="java.version.date" value="2025-07-15"/>
<property name="java.home" value="/opt/java/openjdk"/>
<property name="file.separator" value="/"/>
<property name="basedir" value="/workspace/hello-maven"/>
<property name="java.vm.compressedOopsMode" value="32-bit"/>
<property name="line.separator" value="&#10;"/>
<property name="java.specification.name" value="Java Platform API Specification"/>
<property name="java.vm.specification.vendor" value="Oracle Corporation"/>
<property name="surefire.real.class.path" value="/workspace/hello-maven/target/surefire/surefirebooter-20251011085740477_3.jar"/>
<property name="sun.management.compiler" value="HotSpot 64-Bit Tiered Compilers"/>
<property name="java.runtime.version" value="21.0.8+9-LTS"/>
<property name="user.name" value="root"/>
<property name="stdout.encoding" value="UTF-8"/>
<property name="path.separator" value=":"/>
<property name="os.version" value="6.6.87.2-microsoft-standard-WSL2"/>
<property name="java.runtime.name" value="OpenJDK Runtime Environment"/>
<property name="file.encoding" value="UTF-8"/>
<property name="java.vm.name" value="OpenJDK 64-Bit Server VM"/>
<property name="java.vendor.version" value="Temurin-21.0.8+9"/>
<property name="localRepository" value="/root/.m2/repository"/>
<property name="java.vendor.url.bug" value="https://github.com/adoptium/adoptium-support/issues"/>
<property name="java.io.tmpdir" value="/tmp"/>
<property name="java.version" value="21.0.8"/>
<property name="user.dir" value="/workspace/hello-maven"/>
<property name="os.arch" value="amd64"/>
<property name="java.vm.specification.name" value="Java Virtual Machine Specification"/>
<property name="native.encoding" value="UTF-8"/>
<property name="java.library.path" value="/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib"/>
<property name="java.vm.info" value="mixed mode, sharing"/>
<property name="stderr.encoding" value="UTF-8"/>
<property name="java.vendor" value="Eclipse Adoptium"/>
<property name="java.vm.version" value="21.0.8+9-LTS"/>
<property name="sun.io.unicode.encoding" value="UnicodeLittle"/>
<property name="java.class.version" value="65.0"/>
</properties>
<testcase name="testApp" classname="com.example.AppTest" time="0.036"/>
</testsuite>

View File

@ -0,0 +1,4 @@
-------------------------------------------------------------------------------
Test set: com.example.AppTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.275 s -- in com.example.AppTest

26
src/.gitignore vendored Normal file
View File

@ -0,0 +1,26 @@
# ---> Java
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*