- 投稿日:2020-10-25T22:17:07+09:00
Javaで自作アノテーションを作成し値を取得する方法
Javaで自作アノテーションを作成し、アノテーションの値を取得するサンプルプログラムを紹介します。
環境
- jdk1.8.0_231
C:\>java -version java version "1.8.0_231" Java(TM) SE Runtime Environment (build 1.8.0_231-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode) C:\>1. 自作アノテーションを作成
自作アノテーションのサンプルです。ここではメンバに「name」と「value」を持たせています。
MyAnnotation.javapackage test01; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) // (1) @Retantionでアノテーション情報をどの段階まで保持するかを制御 @Target({ // (2) @Targetどのようなタイプの要素に対して、そのアノテーションを付加できるのかを制御 ElementType.TYPE, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD }) public @interface MyAnnotation { // (3) MyAnnotationを作成 String name(); int value() default 0; }(1) の
@Retention
でアノテーション情報をどの段階まで保持するかを指定します。
@Retention
には主に以下を設定することができます。
値 説明 RetentionPolicy.SOURCE アノテーションはソースレベルでのみ保持され、コンパイラによって無視されます。 RetentionPolicy.CLASS アノテーションはコンパイル時にコンパイラーによって保持されますが、Java仮想マシン(JVM)によって無視されます。 RetentionPolicy.RUNTIME アノテーションはJVMによって保持されるため、ランタイム環境で使用できます。 ここでは
RetentionPolicy.RUNTIME
を指定します。(2) の
@Target
でアノテーションを適用可能な場所を指定します。
@Target
には主に以下を設定することができます。
値 説明 ElementType.TYPE クラス、インターフェース、アノテーション、enum型に適用可能にします。 ElementType.FIELD フィールドに適用可能にします。 ElementType.CONSTRUCTOR コンストラクタに適用可能にします。 ElementType.METHOD メソッドに適用可能にします。 ここでは
@Target
にElementType.TYPE
、ElementType.FIELD
、ElementType.CONSTRUCTOR
、ElementType.METHOD
を指定します。(3) で
MyAnnotation
の名前でアノテーションを作成します。メンバにname
とvalue
を設定します。2. クラスにアノテーションを付与
Sample
クラスのクラス、フィールド、コンストラクタ、メソッドに自作のMyAnnotation
を付与します。Sample.javapackage test01; @MyAnnotation(name="class", value=100) // (1) クラスにMyAnnotationを付与 public class Sample { @MyAnnotation(name="field", value=200) // (2) フィールドにMyAnnotationを付与 private String name; @MyAnnotation(name="constructor", value=300) // (3) コンストラクタにMyAnnotationを付与 public Sample() {} @MyAnnotation(name="method", value=400) // (4) メソッドにMyAnnotationを付与 public void execute() { System.out.println("execute"); } }(1) クラスに自作アノテーション(
MyAnnotation
)を付与します。
(2) フィールドに自作アノテーション(MyAnnotation
)を付与します。
(3) コンストラクタに自作アノテーション(MyAnnotation
)を付与します。
(4) メソッドに自作アノテーション(MyAnnotation
)を付与します。3. アノテーションを取得して参照
Main.javapackage test01; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Main { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, SecurityException { // (1) クラスについているアノテーション(MyAnnotation)を取得 Class<?> clazz = Class.forName("test01.Sample"); MyAnnotation annoClass = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class); System.out.println("class annotation : name=" + annoClass.name() + ", value=" + annoClass.value()); // (2) フィールドについているアノテーション(MyAnnotation)を取得 Field field = clazz.getDeclaredField("name"); MyAnnotation annoField = (MyAnnotation) field.getAnnotation(MyAnnotation.class); System.out.println("field annotation : name=" + annoField.name() + ", value=" + annoField.value()); // (3) コンストラクタについているアノテーション(MyAnnotation)を取得 Constructor<?> cons = clazz.getConstructor(); MyAnnotation annoCons = (MyAnnotation) cons.getAnnotation(MyAnnotation.class); System.out.println("constructor annotation : name=" + annoCons.name() + ", value=" + annoCons.value()); // (4) メソッドについているアノテーション(MyAnnotation)を取得 Method method = clazz.getMethod("execute"); MyAnnotation annoMethod = (MyAnnotation) method.getAnnotation(MyAnnotation.class); System.out.println("method annotation : name=" + annoMethod.name() + ", value=" + annoMethod.value()); } }(1)
Sample
クラスに付いているアノテーション(MyAnnotation
)の内容を取得し表示します。
(2)Sample
クラスのフィールドname
に付いているアノテーション(MyAnnotation
)の内容を取得し表示します。
(3)Sample
クラスのコンストラクタに付いているアノテーション(MyAnnotation
)の内容を取得し表示します。
(4)Sample
クラスのexecute
メソッドに付いているアノテーション(MyAnnotation
)の内容を取得し表示します。参考
Lesson: Annotations (The Java™ Tutorials < Learning the Java Language)
以上
- 投稿日:2020-10-25T21:04:55+09:00
【Java】楽曲ファイルからタグ情報を取得する
はじめに
楽曲ファイルのタグ情報(楽曲名、アルバム名、アーティスト名など)は各種メディアプレイヤーから簡単に編集が可能です。
特にiTunesではGracenote
を使ってCDからのインポートと同時にタグ情報の自動取得まで行ってくれてとても便利です。
しかし、中には取得してきたタグ情報が 自分好みじゃない 場合もあるかと思います。
例をあげると
- 楽曲名がCD表記と異なる
- アーティスト名が表記揺れしている
- ジャンルが異なる(ここは個人の主観もあると思いますが...)
などなど...
これらを1曲ずつポチポチ編集するのは面倒なので、システムからタグ情報を操作できればいいなーと常々思ってました。(そのためには上記の要件を満たすCDDBも必要になりますが...)
今回はシステムからタグ情報を操作する
のうちタグ情報を取得する
処理に関して、Java言語
とSpringBoot
の組み合わせでJAudioTagger
というライブラリを検証した結果を備忘録として残します。pom.xmlの編集
pom.xml
のdependencies
に以下の依存関係を追加します<dependency> <groupId>org</groupId> <artifactId>jaudiotagger</artifactId> <version>2.0.3</version> </dependency>タグ情報の読み込み
まずはiTunesにインポートされている適当な曲のタグ情報を確認します
それでは実際にJavaコードからタグ情報を読み込んでみます(コードは以下を参照)
AudioFile audioFile = AudioFileIO.read(楽曲ファイルを読み込んだファイルオブジェクト); Tag tag = audioFile.getTag(); System.out.println(tag.getFirst(FieldKey.TITLE)); System.out.println(tag.getFirst(FieldKey.ARTIST)); System.out.println(tag.getFirst(FieldKey.ALBUM_ARTIST)); System.out.println(tag.getFirst(FieldKey.ALBUM)); System.out.println(tag.getFirst(FieldKey.YEAR)); System.out.println(tag.getFirst(FieldKey.COMPOSER)); System.out.println(tag.getFirst(FieldKey.GENRE));出力結果は以下となりました。
誰がその鐘を鳴らすのか? 欅坂46 欅坂46 誰がその鐘を鳴らすのか? 2020 辻村有記 J-POPちなみに
FieldKey
は以下のようなものが取得できるようです
FieldKey 取得できるタグ情報 TITLE 楽曲名 TITLE_SORT 楽曲名(よみ) ARTIST アーティスト名 ARTIST_SORT アーティスト名(よみ) ALBUM_ARTIST アルバムアーティスト ALBUM_ARTIST_SORT アルバムアーティスト(よみ) ALBUM アルバム名 ALBUM_SORT アルバム名(よみ) YEAR アルバム発売年 COMPOSER 作曲者 COMPOSER_SORT 作曲者(よみ) GENRE ジャンル この他にも色々なフィールドが取得できるようです(参考:マッピング表)
おわりに
今回は
タグ情報の取得
を検証しましたが、次はタグ情報の書き込み
も検証してみたいと思います。
また、Java
以外の言語でのタグ情報の操作も、時間がある際に検証してみたいと思います。
最後になりますが、サブスクが主流となりつつある昨今、ローカルの楽曲ファイルを操作すること自体がナンセンスかもしれません(笑)
- 投稿日:2020-10-25T17:04:24+09:00
JavaでTODOアプリを制作しよう12 使われていないHttpMethodでリクエストが来た時の処理・サーバー内でエラーが起きた時の処理
こんにちは。
前回までに引き続き例外処理の実装を進めていきましょう!
TODOアプリ作成リンク集
1: [超基礎の理解] MVCの簡単な説明
2: [雛形を用意する] Spring Initializrで雛形を作ってHello worldしたい
3: [MySQLとの接続・設定・データの表示] MySQLに仮のデータを保存 -> 全取得 -> topに表示する
4: [POST機能] 投稿機能の実装
5: [PATCH機能] TODOの表示を切り替える
6: [JpaRepositoryの簡単な使い方] 検索機能の実装
7: [Thymeleaf テンプレートフラグメントで共通化] Headerの作成
8: [PUT機能] 編集機能の実装
9: [微調整]TODOの表示を作成日時が新しい順にソートする + 期日のデフォルトを今日の日付にする
10: [springで例外処理] 例外処理についての簡単なまとめ
11: [springで例外処理] 存在しないIDのTODOにアクセスした時の例外処理
12: [springで例外処理] 使われていないHttpMethodでリクエストが来た時の処理・サーバー内でエラーが起きた時の処理HttpMethodに関する簡単な説明
HTTPメソッドって一体何?と思われる方も多いと思うので今回はまずざっくりですがどういうものなのかを説明してみようと思います。
ウェブサイトにアクセスするとはどういう事なのかを軽く理解する
まず理解して頂きたいのが
インターネットのサイトにアクセスする = ネット上にあるサーバーにアクセスする
ということです。
このサーバー内にはHPを表示させたり色々な機能(例えばTODO機能とか)が置いてあり、アクセスされれば製作者の想定通りに動くはずです。
ちなみに現在作成しているTODOアプリはウェブ上には公開されていませんが、私たちのローカル上に仮のサーバーを作っているので、アプリをRunするとlocalhost:8080にアクセスできるようになっているのです。
URLとHttpMethod
さてサーバーにアクセスする事によってHPを利用できるということが分かりましたが
アクセスする際には何が必要でしょうか?
まずはそのサイトのアドレスが必要になりますね!
サイトが家みたいなものだとしたらアドレスは住所(番地)になるでしょう!
普通にHPを利用するだけでしたらアドレスだけを知っていれば良いのですが、実際にウェブ製作者としてHPを作るとなると、もう一つの概念HttpMethodを理解しなければなりません。
実はサイトにアクセスする際にはHttpMethodというものをつかってアクセスをリクエストしています。
サイトのURL + HttpMethodの同時をリクエストすることで、サイト側はユーザーがどのページにアクセスしたいのかを判別しています!
例えば以下の例を見てみます。
com/example/todo/TodoController.java@Controller public class TodoController { @GetMapping("/top") public String top(Model model){ return "top"; }これはTODOアプリのトップページを表示する部分ですが注目したいのが
@GetMapping("/top")
の部分です。このアノテーションはユーザーが
サイトのURL/top
にGETメソッド
でリクエストしてきた時に行いたい処理というのを明記する役割があります。よってユーザーがそのようなリクエストをしてきた場合は関数
top
が走るというわけです。サイトが家でアドレスが住所であればHttpMethodは鍵のようなものかもしれません。
家の中のトップページを表示させる部屋に入るのに必要な鍵といった感じです。
同じURLでもHttpMethodを変えてアクセスすることもできる
例えば下記の例をみてましょう
com/example/todo/TodoController.java@Controller public class TodoController { @GetMapping("/top") public String top(Model model){ return "top"; } @PostMapping("/top") public String top(Model model){ //投稿処理 }
POSTメソッド
で/topにアクセスした時の処理を追加してみました。アクセスするURL自体は同じですがリクエスト時のHTTPメソッドを変更することで違う処理を実現することができます。
様々なHttpMethod
さてHttpMethodにはいろいろな種類がありますが、代表的な物とその役割をまとめてみます。
- GET
- サイト内のリソースを取得する際に使われる(例:トップページにDBから取得したTODO(リソース)を表示する)
- POST
- 何かを投稿したりする際に使われる(例:TODO投稿時」)
- PUT
- データの内容を置換する(例:ファイルをアップロードして丸々中身を変える)
- PATCH
- データの一部もしくは全体を更新、修正して保存する(例:TODO編集時」)
使われていないHttpMethodでリクエストされた時の例外処理
com/example/todo/exception/TodoControllerAdvice.java@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public String badMethod() { log.warn("Bad Request"); return "error/405.html"; }templates/error/405.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>405</title> </head> <body> 405! </body> </html>上記2つを追加してあげましょう。
ControllerAdviceについては前回の記事を見れば書き方がわかると思います。
ここでは
HttpRequestMethodNotSupportedException
(存在しないHttpMethodのリクエストが投げられた時に起こる例外クラスです。)が起きた時に405.htmlを表示するようにしています。せっかくなので実際に存在しないHttpMethodを
Curlコマンド
を使って投げてみましょう!Todoアプリを起動してターミナルで
$ curl -X POST "http://localhost:8080/top"と打ちます。これは本来は
GET
でしか処理を実装していない/top
に対してPOST
でアクセスリクエストを投げています。この様になるはずです!想定通り405が表示されていることがわかります。
ついでサーバー内でエラーが起きた時の設定もしておく
com/example/todo/exception/TodoControllerAdvice.java@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Exception.class) public String otherErrors() { log.error("Something went wrong"); return "error/500.html"; }templates/error/500.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>500</title> </head> <body> 500! </body> </html>これらを追加することで
Exceptionクラス
が起きた際に500エラーのページを表示できるようになりました!
- 投稿日:2020-10-25T12:38:17+09:00
【Java】Thymeleaf基本 (SpringBoot)
Thymeleafとは
- SpringBootで標準で使われるテンプレートエンジン
- テンプレートエンジンを使うことでWebアプリケーション(MPA)を作るのに必要な機能が追加される
- 例えばHTMLファイルの中に
[[]]
でJavaの変数名[[${modelValue}]]
を書くことができる- これで画面が表示される時に、HTMLファイルがテンプレートとなって、Placefolder(=置き換わる場所)をSpringフレームワークが書き換えてくれる
- テンプレートの機能を果たすものをThymeleafという
使用方法
- build.gradleファイルのdependenciesにThymeleafが定義がされていることを確認
dependencies { compile('org.springframework.boot:spring-boot-starter-thymeleaf') }テンプレートファイルの呼び出し
- デフォルト設定では
/resources/templates/【Controller の戻り値】.html
配下にテンプレートファイルを記述- 以下の例はMain.javaで
HelloController
を呼び出し、クラスパス以下のテンプレートファイルが探索されsrc/main/resources/templates/hello.html
がテンプレートファイルとして利用される。main.javapackage sample; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Main { public static void main(String[] args) { SpringApplication.run(Main.class, args); } }HelloController.javapackage sample.thymeleaf.web; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @Controller public class HelloController { @GetMapping("/hello") public String hello(Model model) { model.addAttribute("message", "Hello Thymeleaf!!"); return "hello"; } }hello.html<html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>Hello Thymeleaf</title> </head> <body> <h1 th:text="${message}"></h1> </body> </html>テンプレートファイルでテキストを埋め込み
th:text=【出力する値】
そのタグのテキスト要素を出力<h1 th:text="'hello world'"></h1>
<h1>[['hello world!!']]</h1>
で直接テンプレート上に値を出力することもできるHelloController.javapackage sample.thymeleaf.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class HelloController { @GetMapping("/hello") public String hello() { return "hello"; } }hello.html<!doctype html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>Hello Thymeleaf</title> </head> <body> <h1 th:text="'hello world'"></h1> </body> </html>
- 投稿日:2020-10-25T12:06:18+09:00
Eclipse Pleiades All in One を使って Tomcat プロジェクトを作成する
はじめに
- Eclipse Pleiades All in One を使って Tomcat プロジェクト(Java Servlet)を作成する方法についてまとめました。Eclipse Pleiades All in One は Eclipse の日本語化対応がされており、JDK や TOMCAT など Java Servlet を作成するために必要なソフトウェアがパッケージ化されているので環境構築がしやすい点がメリットです。
概要
Java Servlet とは、Java で実装された WEB アプリケーションにおいて、動的 WEB ページを生成するプログラムです。WEB アプリケーションは、サーバ・クライアントシステムになっており、以下の図のように、クライアントがサーバにリクエストを送信し、サーバがクライアントにレスポンスを返して動作します。
Java Servlet は単体で動作するのではなく、サーブレットコンテナと呼ばれるソフトウェアと一緒に動作します。Tomcat とは、このサーブレットコンテナに該当します。WEB ブラウザから WEB サーバにリクエストを送信すると、Tomcat がこのリクエストを受信します。サーブレットは、リクエストの種類に応じた動的 WEB ページを生成し、Tomcat は、この動的 WEB ページをWEB ブラウザにレスポンスとして送信します。WEB ブラウザには、この動的 WEB ページをが表示されます。
動作環境
- Windows 10 (64bit)
- Eclipse Pleiades All in One(Windows 64bit Full Edition Java Version 2020-06)
- Tomcat 9
開発環境構築:Eclipse インストール
Eclipse Pleiades All in One は、Eclipse の日本語対応がされており、JDK や Tomcat など Java Servlet 開発に必要なソフトウェアが含まれています。
まず、Eclipse Pleiades All in One をダウンロードして起動し、Tomcaat Plagin をインストールします。
以下の Pleiades(Java アプリを日本語化するツール)のサイトに移動し、「Eclipse 2020」をクリックします。
⇒「Download」ボタンの一覧が並んだページに移動します。
https://mergedoc.osdn.jp/「Windows 64bit」、「Full Edition」、「Java」の組み合わせ上の「Download」ボタンをクリックします。
⇒pleiades-2020-06-java-win-64bit-jre_20200702.zip がダウンロードされます。
ダウンロード完了したら、任意のフォルダに解凍し、eclipse\eclipse.exe をダブルクリックして、Eclipseを起動します。
(起動時に、workspaceフォルダのパスの入力が必要ですが、デフォルト設定のままにします。)Eclipse のメインメニュー「ヘルプ」>「Eclipse マーケットプレース」を実行して、「Eclipse マーケットプレース」ダイアログを起動します。
「検索」欄に、「Tomcat」と入力して、「Go」ボタンを押します。
「Eclipse Tomcat Plugin 9.1.4」を選択して、「インストール」ボタンを押します。
「使用条件の条項に同意します」を選択して「完了」ボタンを押す。
証明証ダイアログ「これらの証明証を信頼しますか?」が表示されたら、証明書発行元にチェックして「選択を受け入れる」ボタンを押します。
Eclipse を再起動すると、Eclipseのメインメニューのアイコンに Tomcat のアイコンがメニューに表示されます。
Eclipse 初期設定
プロジェクト作成の前に Eclipse の初期設定を行います。最初に一度設定しておけば次回からは設定不要です。
メインメニュー「ウィンドウ」>「設定」を実行して、「設定」ダイアログを起動します。
まず、Tomcat の設定をします。左側のツリーから「Tomcat」を選択します。
「Tomcat」ホームに Tomcat のフォルダを設定します。
(pleiades-2020-06-java-win-64bit-jre_20200702.zip を解凍したフォルダ下の「tomcat\9」を設定します。)「コンテキスト宣言モード」で「Server.xml」をチェックし、「設定ファイル」欄に Server.xml のパスを設定します。
(pleiades-2020-06-java-win-64bit-jre_20200702.zip を解凍したフォルダ下の「tomcat\9\conf\server.xml」を設定します。)次に、デプロイする環境が Linux であることを想定して、Linux 上で動作するように設定します。左側のツリーから「一般」>「ワークスペース」を選択します。
「テキスト・ファイル・エンコード」で「その他」をチェックし、「UTF-8」を選択します。
「新規テキスト・ファイルの行区切り文字」で「その他」をチェックし、「Unix」を選択します。
「適用して閉じる」ボタンを押します。
プロジェクト作成
プロジェクトの新規作成時と Server.xml の設定を行います。
メインメニュー「ファイル」>「新規」>「プロジェクト」を実行して、「新規プロジェクト」ダイアログを起動します。
ツリー内の「Java」>「Tomcatプロジェクト」ノードをクリックします。
「プロジェクト名」を入力して、「次へ」ボタンを押します。
「コンテキスト名」欄のパスを確認して、「Finish」ボタンを押します。(「コンテキスト名」欄のパスが、WEB サーバにアクセスするときの URL パスのルート部分になります。)
http://localhost:8080/{「コンテキスト名」欄のパス}
Tomcat のインストールフォルダ下の「conf\server.xml」に以下の行が追加されていることを確認します。この行が Server.xml に登録されていない場合、WEB サーバにアクセスしても、WEB 画面は表示されません。
(【例】C:\apache\apache-tomcat-9.0.37\conf\server.xml)<Context path="{プロジェクト名}" reloadable="true" docBase="{プロジェクトのパス}" workDir="{プロジェクトのパス}\\work" />デフォルトでは、8080 番ポートを使用する設定になっています。8080 番ポート以外に設定したい場合は、以下の部分を変更します。
<Connector port="8080" protocol="HTTP/1.1" ★"8080"の部分を設定したいポート番号に変更 connectionTimeout="20000" redirectPort="8443" useBodyEncodingForURI="true" />サーブレット作成
サーブレットの処理を実装します。
「パッケージ・エクスプローラー」上のツリーのトップノードを選択して右クリックし、ポップアップメニュー「新規」>「クラス」をクリックします。
「名前」欄にクラス名、「スーパークラス」欄に「javax.servlet.http.HttpServlet」を入力して「完了」ボタンを押します。
(ここでは、「名前」欄に「SampleServlet」と入力し、「名前」欄と「スーパークラス」欄以外の設定はデフォルトのままとします。)
⇒「パッケージ・エクスプローラー」上のツリーに「sample」>「SampleServlet.java」ノードが追加されます。
SampleServlet.javapackage sample; import javax.servlet.http.HttpServlet; public class SampleServlet extends HttpServlet { }「パッケージ・エクスプローラー」上のツリーノード「SampleServlet.java」を選択して、メインメニュー「ソース」>「メソッドのオーバーライド/実装」をクリックし、「メソッドのオーバーライド/実装」ダイアログを起動します。
「HttpServlet」>「doGet」をチェックして「OK」ボタンを押して、doGet() と doPost() を生成します。doGet() は GET メソッドを受信したときに動作します。GET メソッドは、クライアントの WEB ブラウザから、WEB サーバにアクセスがあったときに動作します。また、doPost() は POST メソッドを受信したときに動作します。POST メソッドは、クライアントの WEB ブラウザのフォームから WEB サーバにデータが送信されたときに動作します。
SampleServlet.javapackage sample; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class SampleServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO 自動生成されたメソッド・スタブ super.doGet(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO 自動生成されたメソッド・スタブ super.doPost(req, resp); } }以下の import 処理を追加します。
SampleServlet.javapackage sample; import java.io.IOException; import java.io.PrintWriter; // 追加doGet() の実装を以下のように変更します。クライアントから WEB サーバにアクセスしたときに、クライアントの WEB ブラウザに表示される WEB ページを作成しています。
SampleServlet.java@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO 自動生成されたメソッド・スタブ //super.doGet(req, resp); // コメントアウト // ↓ ここから追加 // 日本語の文字化け対策のため、文字エンコーディングを行う resp.setContentType("text/html; charset=UTF-8"); // クライアントの WEB ブラウザに表示する WEB 画面を作成する PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>sample</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Hello こんにちは</h1>"); out.println("</body>"); out.println("</html>"); out.close(); // ↑ ここまで追加 }web.xml 作成
web.xml を作成します。web.xml はサーブレットコンテナの設定をするファイルです。
「パッケージ・エクスプローラー」上のツリーノード「WEB-INF」を選択して右クリックし、ポップアップメニュー「新規」>「その他」をクリックして、「新規」ダイアログを起動します。
「XML」>「XML ファイル」をクリックして、「新規 XML ファイル」ダイアログを起動します。
「ファイル名」欄に「web.xml」と入力して「完了」ボタンを押します。
⇒「パッケージ・エクスプローラー」上に、ツリーノード「web.xml」が追加されます。
「パッケージ・エクスプローラー」上のツリーノード「web.xml」を選択して右クリックし、ポップアップメニュー「次へ開く」>「汎用テキスト・エディター」をクリックします。
web.xml<?xml version="1.0" encoding="UTF-8"?>
web.xml に以下のコードを追加します。
web.xml<?xml version="1.0" encoding="UTF-8"?> <!-- ↓ここから追加 --> <web-app> <servlet> <servlet-name>sample</servlet-name> <!-- Servlet name --> <servlet-class>sample.SampleServlet</servlet-class> <!-- Class name --> </servlet> <servlet-mapping> <servlet-name>sample</servlet-name> <!-- Servlet name --> <url-pattern>/servlet</url-pattern> <!-- URL pattern --> </servlet-mapping> </web-app> <!-- ↑ここまで追加 -->ビルド
ビルドを行います。
「パッケージ・エクスプローラー」上のツリーのトップノードを選択して右クリックし、ポップアップメニュー「リフレッシュ」をクリックします。
⇒「パッケージ・エクスプローラー」上のツリーのファイル構成が現在の状態に自動的に更新されます。「パッケージ・エクスプローラー」上のツリーのトップノードを選択して右クリックし、ポップアップメニュー「プロジェクトのビルド」をクリックして、ビルドします。
※メインメニュー「プロジェクト」>「自動的にビルド」をチェックすると、自動的にビルドされ、このポップアップメニューは消えます。実行
ビルドができたら実行します。まずは、Eclipse を使用して、Windows 上に WEB サーバを起動して、WEB ブラウザからアクセスします。
ブラウザを起動して以下の URL にアクセスすると、クライアントからサーバに GET メソッドが送信され、以下のような WEB ページが表示されます。
http://localhost:8080/sample/sevlet
デバッグ
デバッグしたい場合は、以下のようにします。
右クリックしてポップアップメニュー「ブレークポイントの切り替え」をクリックしてブレークポイントを設定し、F8 キー(実行)を押します。
ブラウザを起動して以下の URL にアクセスすると、ブレークポイントを設定した場所でブレークします。また、 F6 キーでステップアウト、F5 キーでステップインできます。
http://localhost:8080/sample/sevlet
WAR ファイル作成
デプロイ(利用可能な状態にする)するために、WAR ファイル(WEB アプリの動作に必要なファイルをまとめたもの)を作成します。
メインメニュー「Project」>「Properties」をクリックして、「Properties」ダイアログを起動します。
ツリーノード「Tomcat」を選択し、「WARエクスポート設定」タブを開き、「参照」ボタンを押して、「開く」ダイアログを起動します。
「ファイル名」欄に保存する WAR ファイル名を入力して、「開く」ボタンを押します。
「エクスポートするWARファイル」欄に保存する WAR ファイルのパスが反映されたら、「適用して閉じる」ボタンを押します。
「Package Explorer」上のツリーのトップノードを選択して右クリックし、「Tomcatプロジェクト」>「プロジェクト設定に従いWARファイル作成」を実行します。
「エクスポートするWARファイル」欄に設定したパスに WAR ファイルが生成されます。
プロジェクトのエクスポート
プロジェクト削除前にプロジェクトのバックアップを取得します。
Tomcat を停止します。
「パッケージ・エクスプローラー」上のツリーのトップノードを選択して右クリックし、ポップアップメニュー「エクスポート」をクリックして、「エクスポート」ダイアログを起動します。
「一般」>「ファイルシステム」を選択して「次へ」ボタンを押します。
プロジェクトのチェックボックスをチェックします。
「宛先ディレクトリー」欄にエクスポート先のパスを入力して「完了」ボタンを押します。
プロジェクト削除
プロジェクトの削除と Server.xml の設定削除を行います。
Tomcat を停止します。
「パッケージ・エクスプローラー」上のツリーのトップノードを選択して右クリックし、ポップアップメニュー「削除」をクリックして、「リソースの削除」ダイアログを起動します。
「ディスク上からプロジェクト・コンテンツを削除(元に戻せません)」をチェックして「OK」ボタンを押します。
「プロジェクトのコンテキスト定義を Server.xml から除去」ダイアログが起動したら「OK」ボタンを押します。
プロジェクトのインポート
プロジェクトをインポートする場合はバックアップしたプロジェクトをインポートします。
『プロジェクト作成』項目にしたがって、プロジェクトを作成します。
「パッケージ・エクスプローラー」上のツリーのトップノードを選択して右クリックし、ポップアップメニュー「インスポート」をクリックして、「インスポート」ダイアログを起動します。
「一般」>「ファイルシステム」を選択して「次へ」ボタンを押します。
プロジェクトのチェックボックスをチェックします。
「次のディレクトリーから」欄にインポート先のパスを入力して「完了」ボタンを押します。
「上書きしますか?」と質問されたら、「すべていいえ」を選択します。
デプロイ環境
ここから、デプロイの準備をします。ここでは、Ubuntu にデプロイします。
- Ubuntu 20.04 LTS
- OpenJDK 11
- Tomcat 9
デプロイ環境構築①:OpenJDK 11 インストール
まず、Java をインストールします。
OpenJDK 11 をインストールします。
$ sudo apt-get install openjdk-11-jdkインストールした Java のバージョンを確認します。
$ java --version openjdk 11.0.8 2020-07-14 OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu120.04) OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu120.04, mixed mode, sharing)デプロイ環境構築②:TOMCAT インストール
次に、TOMCAT をインストールします。
下記のサイトにアクセスし、左側の「Download」項目の「Tomcat9」をクリックします。
http://tomcat.apache.org/download-80.cgi
「Binary Distributions」内の「Core」下の「tar.gz」をクリックします。
⇒「apache-tomcat-9.0.37.zip」がダウンロードされます。
https://tomcat.apache.org/download-90.cgi
ダウンロードが完了したら任意のディレクトリに解凍します。ここでは、/opt に解凍します。
$ sudo tar zxvf apache-tomcat-9.0.37.tar.gz -C /opt/opt に解凍されたことを確認します。
$ ls /opt/apache-tomcat-9.0.37/ BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs temp webapps workデプロイ
デプロイ環境が準備できたら、デプロイします。
tomcat の デフォルト設定では、root ユーザ以外のユーザに実行権限がないため、root ユーザになります。
$ sudo su作成した WAR ファイルを TOMCAT の webapps 下のフォルダにコピーします。
# mv sample.war /opt/apache-tomcat-9.0.37/webappsTOMCAT を起動します。
# cd /opt/apache-tomcat-9.0.37/bin # sh startup.shWEB ブラウザを起動して以下の URL にアクセスすると、クライアントからサーバに GET メソッドが送信され、以下のような WEB ページが表示されます。
http://{デプロイしたPCのIPアドレス}:8080/sample/servlet
TOMCAT を終了します。
# sh shutdown.sh
- 投稿日:2020-10-25T11:50:14+09:00
【WIP】Java変数
記事を書いた目的:Javaの基本、変数について調べ知識を整理する。
変数とは?
- データ値を格納するための入れ物です。(コンテナとも呼ばれます)
Javaには、たとえば次のようなさまざまなタイプの変数があります。
String:"Hello "のようなテキストを格納する。文字列の値は二重引用符で囲まれている。
int:123 や -123 のような小数を含まない整数 (整数) を格納する。
float:19.99や-19.99のような小数を含む浮動小数点数を格納します。
char:は 'a' や 'B' のような単一の文字を格納します。文字値は単一引用符で囲まれています。
boolean:値を格納し、2つの状態: true または false を指定します。
- 投稿日:2020-10-25T11:26:03+09:00
Migration Toolkit for Application Binariesを使ってみた
IBMから出ているMigration Toolkit for Application Binariesは無料のツールでJavaアプリケーションのバージョン間の移行やLibertyへのマイグレーションを診断してくれるツールです。診断を行うためにはJavaアプリケーションのwar/earファイルが必要です。
https://developer.ibm.com/wasdev/downloads/#asset/tools-Migration_Toolkit_for_Application_Binaries
手順は
- JDKのインストール
- このMigration Toolkitのダウンロード、インストール
- war/earファイルの準備
- 診断の実行
* 私はWindows 10の環境でやってみました。JavaがあればMac, Linuxでも同じようにできるはずです。(コマンドはPowerShellで実行)マイグレーションオプション
このツールでサポートしているマイグレーション元、ソースのアプリケーションサーバーは
JBoss, Liberty, Liberty Core, Apache Tomcat, WebSphere, WebLogic
- デフォルトはWebSphere Application Server traditional V8.5.5
マイグレーション先、ターゲットのアプリケーションサーバーは
Liberty, Liberty Core, WebSphere Application Server traditional V8.5.5, WebSphere Application Server traditional V9.0
- デファルトはWebSphere Application Server Liberty
またJavaのバージョンも指定できるようで。元、ソースのJavaのバージョンは
Java (11,14), IBM Java (5,6,7,8), Oracle Java (5,6,7,8)
ターゲットのJavaのバージョンは
Java (11,14), IBM Java (7,8), Oracle Java (7,8)
IBM Cloudへのマイグレーションの際の診断もできるようで以下のオプションがあります。
`
--targetCloud=[containers|cfIBMCloud|thirdParty|vmIBMCloud]
指定したターゲット・クラウド・ランタイム環境へのマイグレーションに関する規則を
組み込みます。 デフォルトはありません。 ソースまたはターゲットのアプリケーション・サーバーを
指定せずにこのオプションを指定した場合、クラウド規則のみが組み込まれます。
以下のオプションが有効です。
* containers - コンテナー (IBM Cloud Pak for Applications、Kubernetes)
* cfIBMCloud - IBM Cloud ランタイム (CF PaaS)
* thirdParty - サード・パーティー PaaS (CF)
* vmIBMCloud - 仮想マシン (IBM Cloud)
JDKのインストール
こちらからJDKをダウンロード、インストールしました。
https://www.oracle.com/java/technologies/javase-downloads.html
以下のコマンドが動けばいいです。> java --versionMigration Toolkitのダウンロード、インストール
こちらのページからダウンロードをクリックしてダウンロードしてください。
https://developer.ibm.com/wasdev/downloads/#asset/tools-Migration_Toolkit_for_Application_Binaries
binaryAppScannerInstaller.jarというファイルがダウンロードされます。PCの任意の場所に保存しました。
次に保存したフォルダーに移動して次のコマンドでインストール> java -jar binaryAppScannerInstaller.jarインストール後にwamtというフォルダーが作成されます。そこで以下のようにコマンドをいれて動作確認してください。
> cd wamt java -jar binaryAppScanner.jar --help --allwar/earファイルの準備
診断の実行
準備したwarファイルに対して以下のコマンドを入れればしばらくすると診断が始まります。そのあとブラウザーが起動して診断結果が表示されます。ここではHelloServelet.warを診断
> java -jar binaryAppScanner.jar HelloServlet.war上記アプリは名前の通りHelloを出すだけのものなので問題がないのは当然ですが、ぜひいろいろなアプリで試してみてください。
- 投稿日:2020-10-25T09:13:13+09:00
Javaサーブレット 14 - 提出課題 社員情報管理ツール - 05
7. Class#forName再考
7.1. Class#foName処理
ロジックの生成にClass.forName()を使うべきか。このメソッドは何をしているのか。
クラスを取得する。ここでいうクラスとは、Javaコンパイラーが生成するclass拡張子付きのクラスファイルがJVMのメモリに読み込まれ、利用可能な状態に構成されたもの。まず、クラスは、クラスローダーによってメモリに読み込まれる。次に、利用可能な状態にするために、クラスの静的な(static)メンバーの初期化、静的初期化子の実行を一度だけ行う。 以下の例はClass#forNameを使用してorg.h2.Driverクラスをメモリーにロードする。
Class.forName("org.h2.Driver");org.h2.Driverのソースコードを一部引用する。このクラスがメモリーにロードされると、staticで修飾された静的変数の初期化と、staticブロック(静的初期化子)が一度だけ実行される。その後、このクラスのインスタンスをnewしたり、静的メソッドを呼べるようになる。クラスがメモリに読み込まれた後はClass#forNameを実行しても意味がない。理由はすでにクラスがメモリに存在するから。ところが、Class#forNameを何度も実行すると、最悪の場合はスレッドの競合が発生して処理が遅延することがあることが知られている。
クラスのロードはクラスローダーが行う。クラスローダーの構成には階層がある。クラスローダーがクラスを発見できないときは上位のクラスローダーにクラスのロードを委譲する。
package org.h2; public class Driver implements java.sql.Driver, JdbcDriverBackwardsCompat { private static final Driver INSTANCE = new Driver(); private static final String DEFAULT_URL = "jdbc:default:connection"; private static final ThreadLocal<Connection> DEFAULT_CONNECTION = new ThreadLocal<>(); private static boolean registered; static { load(); }7.2. Class#foNameを利用する意味
利点として考えられるもの。
- クラス名(String)を指定してクラスをロードできるのでクラスがなくてもコンパイルできる
- 言い換えると、開発時点で存在しないクラスを実行時に名前でロードできる
- これが働くためには、あらかじめインターフェイスや抽象クラスを用意しておき
- 実行時にインターフェイスや抽象クラスを継承した具象クラスをクラス名でロードする
- 用途はフレームワーク作成
欠点として考えられるもの。
- 業務ロジックで利用する問題点
- アプリケーションの初期化で一度だけ実行するべき機能、繰り返し実行するものではない
- 最悪の場合は、性能低下、セキュリティの脆弱化を招く恐れがある
Class#foNameは、Webアプリケーションの初期化でフレームワークやDIコンテナが一度だけ実行すべき。通常処理で繰り返し使うべきではない。特にクラス名がインターネットに晒されるような実装は避けること。
7.3. ファクトリ機能
本来の要件は、利用者クラスにLogicインターフェイスだけを見せて、ポリモーフィズムを働かせることにあった。ファクトリ機能に、Logicを実装する具象クラスのインスタンスの生成を分離する。ファクトリ機能としてClass.forName()を使用したわけである。ファクトリ機能は、マーチン・ファウラー著、『新装版 リファクタリング』オーム社にswitch文の除去例として紹介されている。
JSPは、HTTPパラメータのactionに処理内容を表す文字を格納してサーブレットに送る。ファクトリメソッドを以下のように引数付きで定義する。引数のactionの内容に応じてLogicクラスを生成する。クラスが追加されてもファクトリメソッドのインスタンス生成部分を変更すれば、利用するクラスに影響を及ぼさない。
public static Logic getLogic(HttpServletRequest request) throws ServletException, IOException { String action = request.getParameter("action"); if (action == null) { return null; } switch(action) { case "編集": return new EditEmployeeLogic(); break; case "削除": return new DeleteEmployeeLogic(); break; defalut: } return null; }
- 投稿日:2020-10-25T01:44:23+09:00
Java GradleからのDocker利用
この記事はこのシリーズの第一弾です。
今回に限らず巨人の肩に乗ってパッケージを便利にしてきますか。
シリーズ冒頭からパッケージをさっくり作ったところでのスタートです。
なお、繰り返しですがソースコードあります。
適宜ご覧ください(READMEの口調が荒いですがお許しくだされ)。導入プラグイン
今回利用するのは、米Palantir Technologies(データ分析業)の開発している、
docker pluginたちです。
「たち」というのは、docker, docker-run, docker-composeそれぞれに独立のプラグインがあるからですね。
https://github.com/palantir/gradle-docker
composeは今回はいいかなぁ...
ひとまずはgradleからcontainer起動までこぎつける、ここまでを扱います。各手順
1. Dockerfile作成
まぁこれなければ動きませんよね...
今回作ったのはこんな感じです。DockerfileFROM amazonlinux:latest RUN yum update -y &&\ yum upgrade -y &&\ yum install java-11-amazon-corretto-headless -y COPY ./build/libs/gradle-docker.jar /tmp/app.jar ENTRYPOINT ["java", "-jar", "/tmp/app.jar"]私はクラウド環境としてAmazon ECS / Fargate / EKS想定なのでamazonlinuxです(思考放棄)。
イメージサイズが重要であればubuntuやalpineでというのもありよりのありです。
alpineにcorretto突っ込むという荒業もできないことはないです...
Javaは11、LTSが無料で使えるのはありがたいですね。
ともかく、まずCOPYとENTRYPOINTはコメントアウトして、ちゃんと動くかまで確認します。2. docker起動をビルドスクリプトに記述
ここが難所ですね。
まずプラグインを記入します。build.gradleplugins { id 'java' id 'application' id 'idea' id 'eclipse' id 'com.palantir.docker' version '0.25.0' id 'com.palantir.docker-run' version '0.25.0' }それから、プラグインが持っているtask:dockerに対し、いろいろオプションを加えていくわけです。
copySpecの下りはわかりにくいですので後述します。build.gradledocker { // name: これはbuildされたコンテナイメージの名前になります。 // コロンで区切った右側はタグとして認識されます。 name "${project.name}:${project.version}" // いわずもがなDockerfileです。 // パスは.\つけても素でも動きます。 dockerfile file('Dockerfile') // Gradleのコピースペックを使って、ビルドした資材をpluginの利用先に持っていきます。 copySpec.from('build/libs').into('build/libs') // docker buildのキャッシュ利用off noCache true // 依存関係定義:gradle dockerしたら、その前段でgradle buildが走ります dependsOn tasks.build }これで、基本command lineで"gradle docker"としたら、走るはずです。
※DockerfileのCOPY/ENTRYPOINTはコメントアウトから戻してください。まぁせっかくなので、ええいままよとcontainer起動まで行きますか。
プラグインはもう入っているのでタスクのオプションを追加するだけです。
コンテナ起動オプションは、特に人それぞれ異なるので、
ドキュメントをきっちり読んでくださいね。build.gradledockerRun { //コンテナ名です。 name project.name // 起動するイメージ(dockerタスクで作ったやーつ) image "${project.name}:${project.version}" // コンテナをデーモン起動?:docker run "-d" <- こいつ daemonize false // 否、我顕現す // 君はマグロか?(stopしたらauto terminate) clean true // いかにも、マグロだ。 }と、これで以下のコマンドをたたけばひとまずものになるはずです。
$ ./gradlew docker $ ./gradlew dockerRun Hello World.ただ、もう少しやるべきことはあります。
3. fatJarをつくる
現在はライブラリがないのでちゃんと動きますが、
フレームワーク・ライブラリを突っ込むと、classNotFoundで落ちます。
かくなる上は、buildするjarファイルにライブラリjarを突っ込むしかない(わけではないが楽)。
これもpluginを使えば楽です。
ShadowJar、今回はこれを使いましょう。
まずプラグイン追加して、build.gradleplugins { id 'java' id 'application' id 'idea' id 'eclipse' id 'com.palantir.docker' version '0.25.0' id 'com.palantir.docker-run' version '0.25.0' id 'com.github.johnrengelman.shadow' version '6.1.0' // <-こいつ }それからタスクのオプションを追加します。
中にfinalizedByとあります。
これはdockerタスクを追加したときには伝えておりませんでしたが、
ちゃんとこのタスクが終わってから次のタスクに移るための明示です。
つまりこの場合、shadowJarタスクでjarを作り終わってからdockerタスクをさせたいということです。
後続するタスクのdependsOnをつけることで、確かにshadowJar->dockerで実行されます。
ただ、dockerタスクが動く前にshadowJarが完了することは保証されません。
正直ちょっと詰まりました...タスク依存ムズイ...build.gradleshadowJar { // jarタスクのを参照してくれないので、ここでもarchiveファイルは指定 archiveFileName = "${project.name}.jar" // 依存関係 finalizedBy tasks.docker }そして、前述のgradle docker/dockerRunコマンドでちゃんとイメージ作成・起動までこぎつけられたことでしょう。
内部での動き
dockerプラグイン君ですが、keyはイメージに突っ込むファイルです。
プラグインは/build/docker配下に資材(Dockerfile含)をため込み、
それをimageビルドに利用しています。
なので、dockerタスクのオプションでそれをしなければなりません。
プラグインはGradleの"copySpec"というAPIを使っています。
それで、
from /build/libs/*
to /build/docker/build/libs/*
こんな形でファイルをコピーさせているということですね。
それで、build/docker配下に同じくコピーされたDockerfileは、
その置き場所から./build/libs/your.jarを見つけ、COPYでイメージに突っ込んでいます。
ちなみに、task dockerのオプション file, copySpecを組み合わせて同様のことができます。build.gradledocker { name "${project.name}:${project.version}" dockerfile file('Dockerfile') files shadowJar.archiveFile.get() copySpec.into('build/libs') noCache true dependsOn tasks.shadowJar }filesオプションを事前に突っ込むことで、それもcopySpecに載せられます。
これを利用し、jarに梱包しない環境ファイルが別にある場合もイメージに突っ込めます。開発に利用するなら
釈迦に説法かもしれませんが、
Dockerfileは書き換えての開発をお勧めします。
毎回gradle dockerでイメージビルドするのに、jdk落としてインスコしては萎えますので。
いっそjava環境まで作ったイメージをつくり、
以降はその部分をコメントアウトしてFROMを作ったイメージに向けるほうが圧倒的コスパです。だそく
しかしこのプラグイン群すさまじいですね、やれることが多くて。
それこそimage pushやcompose利用など、いろいろできます。
こうしたものがあり、利用できるからエンジニアやれているのだと常々感じます。ところで、話変わりますが「巨人の肩に乗る」って比喩でなくほんとに巨人なんですね。
SFの話です。
テューリアンは優しい。
それから、ちょっと面倒なので、docker rmiもgradleタスクで作ろうと思います。
プラグインに期待するのも1つですが、まぁできないことはないだろうと。
- 投稿日:2020-10-25T01:01:39+09:00
Javaジャーニー:快適なパッケージを求めて
ほぼ動的型付け言語しか使用しないチームに転職し、
┌( ^o^┌ )┐ <- これのごとく型付けェ型付けェと禁断症状に...
欲求不満に任せ、いつのまにか理想のGradleパッケージのジャーニーへと旅立っていました。
せっかくなので情報整理がてらやりたいこと・過程を紹介します。
あと、Githubにpublicのrepositoryを作っているので、
それをご覧いただくもよし、そのまま流用するもよし(そんな価値があればよいですが...)。
Github Link: gradle-docker
※本記事はJava/Gradle/Dockerなど基礎知識はすでにある前提でお読みください。やりたいこと
- Dockerにすんなり疎通できる
- テストのフローはきっちり(Junit*Matcher - Jacocoでカバレッジ)(YET)
- Logも今風(slf4j*logback - Jsonized Log)(YET)
- 書き方も統制しよう(formatter, linter)(YET)
ここまでやれば、まぁ禁断症状は治まるかと...
あと、これをベースにAWSのコンソール操作を自動化するツールも作るつもりなので...プロローグ
生まれたての小鹿パッケージ、作るだけ、作りますか。
gradle initの時の選択肢は、まぁオーソドックスですね。
javaですし、DSLはgroovyですし、テストはJUnitですし?。$ cd '任意のディレクトリ' $ mkdir 'project name' $ cd 'project name' $ gradle init --type java-application $ gradle wrapperこれで、よくある、ローカルにjavaさえ入っていれば
- maven,gradleなくともできますよ、
- gradleは固定ですよ
の環境が出来上がりですね。
あとは最低限のプロジェクト・パッケージ情報をシコシコ仕込みますか。gradle.buildplugins { id 'java' id 'application' id 'idea' id 'eclipse' } repositories { mavenCentral() } // パッケージのバージョン指定 project.version = '0.1.1' // javaランタイムは11(15はそのうち...) sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 dependencies { testImplementation 'junit:junit:4.13' } // Runするとき、Appのmain関数を起点に指定 application { mainClassName = 'info.akotadakura.App' } // UTF-8強要します。 tasks.withType(JavaCompile).all { options.encoding = "UTF-8" } // java -jarするとき、Appのmain関数を起点に指定 // あとjarファイル名にバージョンつくの嫌だ! jar { archiveFileName = "${project.name}.jar" manifest { attributes 'Main-Class' : 'info.akotadakura.App' } }実に初々しい...
と、ここにいろいろ付け加えていくことになります。
まずはコンテナ対応、Docker Nativeな時代ですからね。P.S.
初投稿なので、まさかりはお手柔らかに.....
- 投稿日:2020-10-25T01:01:39+09:00
Gradleジャーニー:快適なパッケージを求めて
ほぼ動的型付け言語しか使用しないチームに転職し、
┌( ^o^┌ )┐ <- これのごとく型付けェ型付けェと禁断症状に...
欲求不満に任せ、いつのまにか理想のGradleパッケージのジャーニーへと旅立っていました。
せっかくなので情報整理がてらやりたいこと・過程を紹介します。
あと、Githubにpublicのrepositoryを作っているので、
それをご覧いただくもよし、そのまま流用するもよし(そんな価値があればよいですが...)。
Github Link: gradle-docker
※本記事はJava/Gradle/Dockerなど基礎知識はすでにある前提でお読みください。やりたいこと
- Dockerにすんなり疎通できる
- テストのフローはきっちり(Junit*Matcher - Jacocoでカバレッジ)(YET)
- Logも今風(slf4j*logback - Jsonized Log)(YET)
- 書き方も統制しよう(formatter, linter)(YET)
ここまでやれば、まぁ禁断症状は治まるかと...
あと、これをベースにAWSのコンソール操作を自動化するツールも作るつもりなので...プロローグ
生まれたての小鹿パッケージ、作るだけ、作りますか。
gradle initの時の選択肢は、まぁオーソドックスですね。
javaですし、DSLはgroovyですし、テストはJUnitですし?。$ cd '任意のディレクトリ' $ mkdir 'project name' $ cd 'project name' $ gradle init --type java-application $ gradle wrapperこれで、よくある、ローカルにjavaさえ入っていれば
- maven,gradleなくともできますよ、
- gradleは固定ですよ
の環境が出来上がりですね。
あとは最低限のプロジェクト・パッケージ情報をシコシコ仕込みますか。gradle.buildplugins { id 'java' id 'application' id 'idea' id 'eclipse' } repositories { mavenCentral() } // パッケージのバージョン指定 project.version = '0.1.1' // javaランタイムは11(15はそのうち...) sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 dependencies { testImplementation 'junit:junit:4.13' } // Runするとき、Appのmain関数を起点に指定 application { mainClassName = 'info.akotadakura.App' } // UTF-8強要します。 tasks.withType(JavaCompile).all { options.encoding = "UTF-8" } // java -jarするとき、Appのmain関数を起点に指定 // あとjarファイル名にバージョンつくの嫌だ! jar { archiveFileName = "${project.name}.jar" manifest { attributes 'Main-Class' : 'info.akotadakura.App' } }実に初々しい...
と、ここにいろいろ付け加えていくことになります。
まずはコンテナ対応、Docker Nativeな時代ですからね。P.S.
初投稿なので、まさかりはお手柔らかに.....