20210425のJavaに関する記事は10件です。

setterを書くな高校校歌

setterを書くな高校校歌 作詞作曲:わたくし 迷光が巡る丘の上 値を代入するためにsetterを書こうとするな 若きアプリだとあなどらず ロジックを持つクラスはコンストラクタで値を与えなさい SetterDame.java public class SetterDame { String value; //好き public SetterDame(String input) { this.value = input; } //よくない public setValue(String input) { this.value = input; } } 大空へと今飛び立とう Listの場合はreturn new コンストラクタで命を与えてやれ SetterDame.java public class SetterDame { List<String> values; //可視性好き private SetterDame(List<String> input) { this.values = input; } //好き(staticでも良い) public create(List<String> input) { return new SetterDame(input); } } setterはアプリがでかくなるとマジで追えなくなるぞ おぉ 我らがsetterを書くな高校 setterを書くな高校 参考書籍 現場で役立つシステム設計の原則 ~変更を楽で安全にするオブジェクト指向の実践技法~ 増田亨 著(技術評論社 2017年)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EclipseにSpring Tool Suiteのプラグインをインストールする方法

手っ取り早くEclipseとpring Tool Suiteのプラグインをインストールする方法を紹介します。 1. Eclipseのインストール 1.1. Eclipseのダウンロード 「Pleiades - Eclipse 日本語化プラグイン」のページを開き、「Eclipse 2021(最新版)」をクリックします。 自分の環境に合うものを選択し、ダウンロードします。 ここでは、「Java」-「Windows 64bit」-「Full Edition」の「Download」をクリックします。 ダウンロードのリンクをクリックします。 1.2. ファイルの解凍 ダウンロードしたファイル(ここでは「pleiades-2021-03-java-win-64bit-jre_20210328.zip」)をインストールしたいフォルダ(ここでは「C:\DK\pleiades-2021-03-java」)に解凍します。 ※「Windows では 7-Zip で解凍してください。それ以外で解凍した場合、パス長 260 文字制限により正常動作しません。」とあるので、ここでは7-Zipを使用して解凍します。 海洋すると「pleiades」というフォルダができます。 以上で、Eclipseのインストールは完了です。 2. Eclipseを起動 「pleiades\eclipse」配下の「eclipse.exe」をダブルクリックし起動します。 ワークスペースは「../workspace」のままで、「起動」をクリックします。 Eclioseが起動します。 3. Spring Tool Suiteプラグインをインストール メニューの「ヘルプ」から「Eclipse マーケットプレース」を選択します。 検索の欄に「Spring Tool Suite」と入力し、「Go」をクリックします。 「Spring Tools 4 (aka Spring Tool Suite 4) 4.10.0.RELEASE」の「インストール」をクリックします。 と思ったら、既に「インストール済み」となっています。 「Pleiades All in One Eclipse ダウンロード」のページに Full Edition には Eclipse 実行用の Java が付属しているため、Java のインストールや環境変数の設定は不要です。また、Java Full Edition は STS と Lombok が設定済みのため、すぐに Spring Boot での開発ができます。 (Spring Boot 入門) と記載がありますね。 「Pleiades All in One Eclipse」のページを見ると、確かに設定済みのようです。 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Android】srcとbackgroundの違い

ImageViewやImageButtonで画像リソースを設定するときに用いる 基本的にはbackgroundでリソースを指定していたが、他人の実装ソースではsrcを使用していたので把握している限りの違いを確認する。 Stack Overflowで同じ質問がヒットしたのだがそこから抜粋すると background指定 リソースのオリジナルサイズ関係なしに指定したwidthとheightに調整される <ImageButton android:id="@+id/button" android:layout_width="60dp" android:layout_height="60dp" android:background="@drawable/resource_button"/> ※実際の細かい調整は省略 src指定 リソースのオリジナルサイズで表示される <ImageButton android:id="@+id/button" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/resource_button" android:background="#00000000"/> ※実際の細かい調整は省略 この場合だと、縦横は60dpで指定しているもののリソースサイズはそれより大きいため途中で切られてしまう。もしbackgroundの時のようにサイズ調整したい場合はandroid:scaleType="fitCenter"を指定するとOK Stack Overflowに戻るが The src to an ImageView has additional features: different scaling types adjustViewBounds for setting bounds to match image dimensions some transformations such as alpha-setting とあるように、srcの方が様々な設定ができる様子。 またbackgroundは動的に変えることができ、Javaだと private ImageView view; /* * 中略 */ view.setBackgroundResource(R.drawable.resource_button); //画像リソースを指定する場合 Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.btn, null); view.setBackground(drawable); //drawableファイルを設定する場合 view.setBackground(null); //リソースをクリアする場合 と変えられるが、レイアウトファイルでsrc指定すると上の処理を実行しても反映されない。background指定内容の前面にsrc指定内容が表示されている様子。 以下はbackgroundを黒色指定して、srcにリソースを指定した場合。 <ImageView android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/ic_launcher_foreground" android:background="@color/black"/> 結論 オリジナルリソースの縦横の比率を維持したいならsrc指定がベスト 動的に変えたいならbackground指定(src指定したリソースを動的に変える方法があるのか不明) 試した環境 Android Studio4.1.2 Android10
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Sparkについて(Python,Java,JVM,RDD)

Hadoop,Sparkの分散処理について 巨大データの取り扱いを目的とした分散処理のフレームワーク 分散処理によってビッグデータを高速に処理することが可能 Hadoopの利用者は自作したデータ処理のプログラムや他者が開発したツールプログラムをHadoop内に組み込んでビッグデータ処理が可能 Hadoop上で稼動するデータベースマネージメントシステム(DBMS) Hive Impala Hadoop上で稼動するスクリプト環境 Pig Hadoop連携ソフトウェアの存在がビックデータ処理環境をより便利にしている。 SparkもHadoopと同じく分散処理のフレームワーク adoopがJava言語で作られているのに対してSparkはJavaの派生言語であるScalaで作られています。 Sparkの内部処理方式 データをメモリに保存することで入出力の高速化を図り処理全体の実行速度を向上させようとする取り組みがある。 利用可能メモリが枯渇した場合にはデータをストレージに保存するケースも勘案 機械学習の計算処理に効果を発揮する 実際特定のアプリケーションに関する実行性能は、HadoopのMapReduce処理と比べた場合の100倍 「データの格納場所」に関する選択肢の広さ Sparkで処理を行うデータは「いろいろな種類のデータ置き場」に格納可能 Sparkは様々なデータ格納場所からのデータ入出力に対応している Hadoopがデータの格納場所として基本的には「Hadoop Distributed File System (HDFS)」という独自のファイル格納場所を必要 Hadoop Distributed File System (HDFS) Cassandra OpenStack Swift Amazon S3 上記などが対応可能なストレージ プログラム手法に関する選択肢の広さ Java(直接Hadoopを制御する事からこの方法を生Hadoopと呼んだりします) HiveQL(Hadoop+Hive) Pig(Hadoop+Pig) Hadoop Streamingを使用することで標準入出力を介してPythonなどから制御 「Hadoopとは別のソフトウェア」を介してプログラミングを行う事が一般的 SparkはSpark自身はScalaでプログラムされているものの、他のプログラム言語に対してより緊密なアプローチが採用されています。すなわち、Sparkを制御するための機能が、Scalaだけでない。 Java Python R言語 Spark SQL 各プログラム言語用のAPIとして提供されている。 SparkとHadoopの関係は競合というよりは共存。ユーザには広い選択肢が与えられている *「Hadoop+Spark」の構成も現実的である(Hadoop内のYarn制御下でSparkを利用する) * Sparkはデータの入出力場所としてHDFSにも対応している * 現段階ではSparkとHadoopは共存関係 SparkがHDFS上のデータをその制御の対象としていることは、既存データの再利用性も含めて二者の親和性の高さをより緊密なものにしています。競合関係という意味では「Spark式処理方法とMapReduce式処理方法の競合」という表現が適切 Apache Sparkについて 半構造化データ(https://jp.drinet.co.jp/blog/datamanagement/semi-structured-data) 構造化データ ストリーミングデータ 機械学習 データサイエンス マスターノード上の1つのドライバプロセス(複数のジョブを持てる)から立ち上げられる。 数多くのワーカーノードに分散配置されたエグゼキュータプロセス(複数タスク)に指示を送る。 ・有行非循環グラフ Sparkはそれらのタスクスケジューリングや実行を最適化する。 RDD(耐障害性分散データセット) イミュータブルなJava仮想マシン(JVM)のオブジェクトの分散コレクションを中心として構成されている。 pythonのデータがJVMオブジェクトの中に保存される。 これらのオブジェクトを使うことでいかなるジョブにおいても高速に演算処理可能 RDDはメモリを有効に利用し計算、キャッシュ、保存される。 このおかげで、Apache Hadoopのような他の旧来フレームワークに比べて何桁も演算処理が高速になっている。 RDDの機能 map() reduce() filter() ...etc RDDはデータへの変換の適用と記録を並列に行う。そのため、速度も耐障害性も向上している。 変換を登録しておくことでRDDはデータリネージを提供可能。 何か問題が生じて、一部のデータが失われて場合にフォールバックを行います。失われた場合は再計算が可能。 RDDの操作 変換(新しいRDDポインターを返す。) → 遅延処理 アクション(演算処理を行い、値をドライバーに返す。)矢印戻り値のこと? Sparkの最大の利点は並列に処理が実行されること データセットの様子を掴むために分析の際によく使われる手順。 * ある列中に現れるそれぞれの値の登場回数をカウントする。 * Aで始まる値だけを選択する * その結果を画面に表示させる データのフォーマットもテキスト、parquet、JSON、Hiveのテーブルといった複数のフォーマットがサポートされている。 リレーショナルデータベースからJDBCドライバを使用してデータを読み取ることが可能。 Sparkは圧縮されたデータセットを自動的に扱える。などほとんどあらゆるものを混在させることが可能。 * スキーマレスなデータ構造(tuple、dict、list) メタデータ [https://jp.drinet.co.jp/blog/datamanagement/metadata_management_3minutes] * メタデータとは一言でいうと「データに関するデータ」 * データ:「構造化データ」と「非構造化データ」に分類される。 * 構造化データ:構造化データはデータの内容や形式が定められており、RDBMSで実装 * 非構造化データ:非構造化データは内容や形式に決まりが無く、あらゆるデータが当てはまる。 (映像、音声、テキストデータなども非構造化データ) Pysparkでのpythonの使い方 クラスたモードとローカルモードが存在する。 ローカルモードでの実行 通常のpythonの実行と同じコードでも問題ない。 構造上の変化が生じやすいのは、データとコードが独立したワーカープロセス間でコピーされるようなひねりが加わる場合。 クラスタモードでの実行 ジョブが投入されて実行される時、そのジョブはドライバノードに送られる。 ドライバノードはそのジョブにあるDAGを生成しそれぞれのエグゼキュータノードを決定する。 そして、ドライバはワーカーに対してそれぞれのタスクを実行し、処理が終了すれば結果をドライバに返すよう指示をする。 RDMSについて データを管理・活用するためのシステムとして代表的なのがMySQL、OracleなどのRDBMS(リレーショナルデータベース管理システム)です。 RDBMSは複雑なデータをリアルタイムで取り扱える半面、大量のデータ処理に際して能力が低下してしまうという弱点があります。 DBでの処理では追いつかないデータ量を高速処理するために導入された概念が分散処理 複数のサーバーもしくはCPUでデータを分割し、大量のデータを高速で処理できるようにします。たくさんのパソコンが作業を分けあって処理している様子を思い浮かべるとわかりやすい それがマスターノードとコアノード 分散処理は気象・災害予測や遺伝子解析、SNSのリアルタイム解析、サイトのユーザー行動分析など大量のデータ処理を必要とする作業に用いられます。ビッグデータの取り扱いにおいて分散処理は欠かせない要素であり、昨今その需要は高まり続けています。 分散処理の機能を組み込む際に使えるフレームワークの代表格がHadoopとSpark Docker for Jupyternotebook pyspark
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azure FunctionのJavaでFailed to start Worker Channel. Process fileName: %JAVA_HOME%/bin/javaエラーが出た時の対処法

Azure FunctionsをJavaで実装するため、Mavenのazure-functions-archetypeを使ってプロジェクトを作成しました。動作環境はDocker上のDebian 10.9です。手元で実行できるように .NET Core 3.1.408とAzure Functions Core Toolsもインストールしました。 ドキュメントどおりに実行したところ mvn azure-functions:run 以下のエラーになりました。 Failed to start Worker Channel. Process fileName: %JAVA_HOME%/bin/java Javaのパスに関連する問題に見えます。ちなみにwhich javaの結果は以下です。 which java /usr/bin/java エラーメッセージを調べると以下のStackOverflowがひっかかりました。どうやらazure-functions-core-toolsの設定ファイル「worker.config.json」に関するもので、自分の環境に合わせて修正が必要なようです。 worker.config.jsonは以下にありました。 /usr/lib/azure-functions-core-tools-3/workers/java/worker.config.json 開いてみると以下の内容で、defaultExecutablePathで%JAVA_HOMEが使われています。 { "description": { "language": "java", "extensions": [".jar"], "defaultExecutablePath": "%JAVA_HOME%/bin/java", "defaultWorkerPath": "azure-functions-java-worker.jar", "arguments": ["-XX:+TieredCompilation -XX:TieredStopAtLevel=1 -noverify -Djava.net.preferIPv4Stack=true -jar", "%JAVA_OPTS%", "%AZURE_FUNCTIONS_MESH_JAVA_OPTS%"] } } StackOverflowにあるとおり、defaultExecutablePathを環境に合わせて適切なパスにするとエラーが解消しました。 修正前 "defaultExecutablePath": "%JAVA_HOME%/bin/java", 修正後 "defaultExecutablePath": "/usr/bin/java", StackOverflowの情報からはファイルがどこにあるのか読み取れなかったので、解決に少し手間取りました。同じエラーでハマった方の解決方法になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者】Spring Boot で骨組みだけの CRUD アプリを作ってデータの流れを確認する

はじめに Spring Boot のデータの流れをイメージで捉えるために、次のような骨組みだけのサンプルアプリを作って、データの受け渡しを一つ一つ確認していきます。 サンプルアプリには、Create(登録)、Read(閲覧)、Update(更新)、Delete(削除)の主要4機能を全て入れるようにしますが、本記事の趣旨とは関係のない余計なコードは排除して、最小限のコード量にします。 Service や Repository は作らず、データの処理は Controller のみで手短に済ませます。 そして、次のように簡略化した MVC のイメージ図に当てはめて、CRUD のそれぞれの機能を確認していきます(下図の詳細は後述)。 実際に動かして確認できるように、全てのソースコードを掲載してから、各機能におけるデータの流れを追っていきますので、ソースコードが不要な方は、そのあたりは適当に読み飛ばしてください。 使用する環境は次のとおりです。 項目 内容 IDE Spring Tool Suite4 OS Windows 10 データベース MySQL DB接続のAPI JDBC API ビルドツール Gradle 学習のアウトプットとして書いている記事なので、記述内容に間違いなどがあるかもしれません。 お気づきのことなどあれば、ご指摘などいただけると幸いです。 <目次> 1. データベースの用意(MySQL) 2. プロジェクト作成時の設定内容 3. 作成するファイルとソースコード 4. Spring MVC のイメージ 5. 機能ごとのデータの流れのイメージ 1. データベースの用意(MySQL) 先に、MySQL のデータベースを用意しておきます。 MySQL の部分は要点のみを書きますので、詳細については MySQLの使い方 という記事を参考にしてください。 <データベースの作成> CREATE DATABASE 文で spring_test という名前のデータベースを作成しておきます。 mysql> create database spring_test; Query OK, 1 row affected (0.33 sec) <ユーザーの作成> CREATE USER 文で yama3@localhost という名前のデータベースを作成しておきます(ユーザー名とパスワードは何でもいいです)。 mysql> create user 'yama3'@'localhost' identified by '123456'; Query OK, 0 rows affected (0.32 sec) GRANT 文で、データベース(spring_test)に対する全ての権限を設定しておきます。 mysql> grant all on spring_test.* to 'yama3'@'localhost'; Query OK, 0 rows affected (0.23 sec) 2. プロジェクト作成時の設定内容 プロジェクト作成については、設定内容を中心に書いていきます。 細かいことは前回記事に書きましたので、必要に応じて参照してみてください。 Spring Tool Sweet(STS)を使用してプロジェクトを作成していきます。 メニューから「File」→「New」→「Spring Starter Project」の順で選択して、次の画面を表示します。 ここでは、ビルドツール(Type)は Gradle を、Java バージョン(Java Version)は 11 を選択しています。 プジェクト名(Name)は適当に付けておきます。 「Next」ボタンを押すと、下図のライブラリを選択する画面になります。 選択するのは、「JDBC API」「MySQL Driver」「Spring Boot DevTools」「Spring Web」「Thymeleaf」の5つとなります(細かいことはこちらを参照)。 「Finish」をクリックすれば、プロジェクトが作成されます。 3. 作成するファイルとソースコード 以下、作成するファイルの全体図と、ソースコードの全体を一通り掲載しておきます。 個々のメソッドにおけるデータの受け渡しの流れについては、後から「5. 機能ごとのデータの流れのイメージ」のところで確認していきます。 3-1. ファイルのディレクトリ プロジェクトのディレクトリ構成は、下図のとおりです。 青枠の2つのファイルは、ファイルもコードも自動生成されるので、そのまま使います。 緑枠の1つのファイルは、ファイルのみ作成されているので、そこにコードを書き込みます。 赤枠の7つのファイルは、所定のディレクトリにファイルを作成の上、コードを書いていきます。 ※注意点 3つのHTMLファイルは、src/main/resources/templatesの下にsampleというフォルダを作成した上で、その中に格納していますのでご注意ください。 3-2. アプリケーションクラス(自動生成) プロジェクト作成時に、CrudSampleApplication.javaというファイルが自動生成されています(プロジェクト名によって名前は異なります)。 特に変える必要もないので、このままにしておきます。 mainメソッドの中身は SpringApplication の run メソッドが記載されているだけです。 これにより、アプリケーションが起動されます。 /src/main/java/com/example/demo/CrudSampleApplication.java package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class CrudSampleApplication { public static void main(String[] args) { SpringApplication.run(CrudSampleApplication.class, args); } } 3-3. ビルドスクリプト(自動生成) ビルドスクリプト(build.gradle)も自動生成されます。 プロジェクトで設定したライブラリなどが反映されています。 これも、そもままにしておきます。 /build.gradle plugins { id 'org.springframework.boot' version '2.4.5' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'mysql:mysql-connector-java' testImplementation 'org.springframework.boot:spring-boot-starter-test' } test { useJUnitPlatform() } 3-4. アプリケーションプロパティ ここにデータベースに関する設定を、以下のように記述します(ファイルは src/main/resources のフォルダに入っています)。 /src/main/resources/application.properties spring.datasource.url=jdbc:mysql://localhost:3306/spring_test spring.datasource.username=yama3 spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.initialization-mode=always spring.datasource.schema=classpath:schema.sql spring.datasource.data=classpath:data.sql spring.datasource.sql-script-encoding=utf-8 以下、個別の設定が必要なところに触れておきます。 spring.datasource.url の末尾の spring_test は MySQL のデータベース名です。 spring.datasource.username には MySQL のユーザー名を記載します。 spring.datasource.password には MySQL のユーザーパスワードを記載します。 その他は、上記のままで大丈夫だと思います。設定内容の詳細はこちらを参照してください。 3-5. SQLスクリプト SQLスクリプトには、プロジェクト起動時に実行されるSQL文を記載します。 schema.sqlおよびdata.sqlには、次のような初期設定を書いておきます。 (細かいことはこちらを参照してください) 3-5-1. schema.sql /FormTest/src/main/resources/schema.sql DROP TABLE IF EXISTS test_table; CREATE TABLE test_table ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, old INT NOT NULL, PRIMARY KEY(id) ); 3-5-2. data.sql /FormTest/src/main/resources/data.sql INSERT INTO test_table(name, old) VALUES('Taro', 30), ('Jiro', 25), ('Saburo', 22); 3-6. コントローラー コントローラーには、データベースからのデータの取得も含めた処理を書いておきます(邪道ですが)。 こうすることで、データベースとのデータのやりとりが一目瞭然になります。 本来は、ビジネスロジック(Service)とデータアクセス(Repository)を作成して分担して処理すべきところですが、ここでは作成していません。 (コントローラー作成に関する細かいことはこちらを参照してください) /src/main/java/com/example/demo/TestController.java package com.example.demo; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/sample") public class TestController { private JdbcTemplate jdbcTemplate; //コンストラクタ @Autowired public TestController(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } //一覧画面の表示 @GetMapping public String index(Model model) { String sql = "SELECT * FROM test_table"; List<Map<String, Object>> list = jdbcTemplate.queryForList(sql); model.addAttribute("testList", list); return "sample/index"; } //新規入力フォームの表示 @GetMapping("/form") public String form(@ModelAttribute TestForm testForm) { return "sample/form"; } //新規入力データの保存 @PostMapping("/form") public String create(TestForm testForm) { String sql = "INSERT INTO test_table(name, old) VALUES(?, ?);"; jdbcTemplate.update(sql, testForm.getName(), testForm.getOld()); return "redirect:/sample"; } //編集フォームの表示 @GetMapping("/edit/{id}") public String edit(@ModelAttribute TestForm testForm, @PathVariable int id) { String sql = "SELECT * FROM test_table WHERE id = " + id; Map<String, Object> map = jdbcTemplate.queryForMap(sql); testForm.setId((int)map.get("id")); testForm.setName((String)map.get("name")); testForm.setOld((int)map.get("old")); return "sample/edit"; } //編集データの保存 @PostMapping("/edit/{id}") public String update(TestForm testForm, @PathVariable int id) { String sql = "UPDATE test_table SET name = ?, old = ? WHERE id = " + id; jdbcTemplate.update(sql, testForm.getName(), testForm.getOld()); return "redirect:/sample"; } //データの削除 @PostMapping("/delete/{id}") public String delete(@PathVariable int id) { String sql = "DELETE from test_table WHERE id = " + id; jdbcTemplate.update(sql); return "redirect:/sample"; } } 3-6-1. コンストラクタについての補足 上記では、コンストラクタを書いています。 コンストラクタの上にあるアノテーション@Autowiredがなくとも、このサンプルアプリは動きます。 なお、フィールド部分を下記のように書けば、コンストラクタは無くとも動きます。 参考 @Autowired private JdbcTemplate jdbcTemplate; <参考サイト> ・Spring FrameworkでDIする3つの方法 3-6-2. リクエストマッピングについて リクエストマッピング(RequestMapping)には、クライアントから受け付けたリクエスト URL 及び HTTP メソッドによって、Controller 内のどのメソッドに処理を渡すかを決める役割があります。 上記の TestController の create メソッドを例に、ルールを見てみます。 まず、クラスの頭に付けているアノテーション @RequestMapping("/sample") では、ベースパスを /sample と指定しています。 そして、create メソッドの頭に付いている @PostMapping("/form") では、HTTPメソッドは Post、相対パスは /form という指定をしています。 この場合、リクエストURLが /sample/form で、HTTPメソッドが POST であれば、update メソッドに処理が渡されるということになります。 以上のルールに基づいて、クライアントからのリクエストと、それに対応する TestController のメソッドをまとめると次のようになります。 HTTPメソッド リクエストURL Controller 処理内容 Get /sample index 一覧画面表示 Get /sample/form form 入力画面表示 Post /sample/form create 入力データ保存 Get /sample/edit/{id} edit 編集画面表示 Post /sample/edit/{id} update 編集データ保存 Post /sample/delete/{id} delete データ削除 3-7. フォームクラス 入力値を保持するためのフォームクラスを作成します。 このフォームクラスを入れ物にして、ビュー、コントローラー、クライアントの間のデータのやり取りを行います。 次のように、入力値(ここでは test_tableのカラム)と対応させたフィールドを作成します。 フォームクラスには、コンストラクタがなくても大丈夫ですが、getter と setter は必須となりますので、作成しておきます。 /src/main/java/com/example/demo/TestForm.java package com.example.demo; public class TestForm { private Integer id; private String name; private Integer old; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getOld() { return old; } public void setOld(Integer old) { this.old = old; } } 3-8. HTMLファイル HTMLファイルは、最低限の内容を書いておきました。 3つのHTMLファイルは、src/main/resources/templatesの下にsampleというフォルダを作成した上で、その中に格納しています。 なお、オブジェクト(Map)から要素を取り出すのに "${testForm.name}" という書き方をしていますが、これは "*{name}" というように簡単に書くこともできます。 ここでは、イメージのし易さを優先して、あえて前者の書き方をしています。 3-8-1. index.html これは一覧表示の画面です。 /src/main/resources/templates/sample/index.html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>CRUD Sample</title> </head> <body> <h2>一覧ページ</h2> <table> <tr><th>id</th><th>name</th><th>old</th></tr> <tr th:each="test : ${testList}"> <td th:text="${test.id}"></td> <td th:text="${test.name}"></td> <td th:text="${test.old}"></td> <td> <a href="#" th:href="@{'/sample/edit/' + ${test.id}}"><button>編集</button></a> </td> <td> <form action="#" th:action="@{'/sample/delete/' + ${test.id}}" method="post"> <button>削除</button> </form> </td> </tr> </table> <div><a href="#" th:href="@{/sample/form}">入力フォーム</a></div> </body> </html> 3-8-2. form.html 新規入力フォームの画面です。 /src/main/resources/templates/sample/form.html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>CRUD Sample</title> </head> <body> <h2>入力フォーム</h2> <form method="post" action="#" th:action="@{/sample/form}" th:object="${testForm}"> <label for="name">名前</label> <input type="text" id="name" name="name" th:value="${testForm.name}"><br> <label for="old">年齢</label> <input type="text" id="old" name="old" th:value="${testForm.old}"><br> <input type="submit" value="送信"> </form> <div><a href="#" th:href="@{/sample}">トップページ</a></div> </body> </html> 3-8-3. edit.html 編集フォームの画面です。新規入力フォームとほとんど同じ内容です。 共通化する方法もありますが、分かりやすさのために、別途作成しています。 /src/main/resources/templates/sample/edit.html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>CRUD Sample</title> </head> <body> <h2>編集フォーム</h2> <form method="post" action="#" th:action="@{'/sample/edit/' + ${testForm.id}}" th:object="${testForm}"> <label for="name">名前</label> <input type="text" id="name" name="name" th:value="${testForm.name}"><br> <label for="old">年齢</label> <input type="text" id="old" name="old" th:value="${testForm.old}"><br> <input type="submit" value="送信"> </form> <div><a href="#" th:href="@{/sample}">トップページ</a></div> </body> </html> 3-9. アプリケーションの起動 アプリケーションを起動してみます(起動方法の細かいことはこちらを参照してください)。 Package Explorer上のプロジェクト名(ここではCRUDSample)を右クリックして、「Run As」→「Spring Boot App」を選択します。 Console 画面に次のような表示がされていきます。 アプリケーションが起動したら http://localhost:8080/sample にアクセスします。 次のような画面が表示されたら成功です。 4. Spring MVC のイメージ データの流れを見るには、Spring MVC の構造を何となく把握しておく必要がありますが、「Spring MVC」という文言で画像検索すると、多種多様な画像が出てきます。 それぞれ内容が異なるので、なかなかイメージが掴みにくいところです。 4-1. 理論上のMVC Spring MVC の図を確認する前に、まず、理論上のMVCの図を見てみます。 一般的な MVC はだいたい次のような構造として説明されています。 項目 説明 Model データの管理・処理を行う(DBへのアクセスなども含む)。 View ユーザーへのへの表示・出力を行う。 Controller ユーザーからのリクエストを受け付け、Model 及び View に伝達する。 4-2. Spring MVC 数多のサイトに掲載されている Spring MVC の図が多種多様なのは、結局、簡単に図式化できるような構造ではないからだろうと思います。 とはいえ、Spring MVC のイメージを掴まないとデータの流れが見えてこないので、簡単に作図しておきます。 (このあたりのサイトを参考にしています) 図で見ると、Model の存在がいまいちよく分かりません。 個人的には、右側の Business Class と Data Access が Model に見えて仕方ないのですが、あくまでイメージの問題なので、深く考えないようにします。 上記のモデル図のままだと、データの流れのイメージを把握するのが難しくなってしまうため、Front Controller と Controller を一体のものとみなして、次のようなシンプルなモデルとして捉えておきます。 以下では、上記の構造を更に簡略化して、データの流れを追っていきます。 <参考サイト> ・Web MVC framework ・Spring Framework Learning 05 5. 機能ごとのデータの流れのイメージ 前置きが長くなりましたが、ここからが本題です。 データの流れがイメージできると、コードを書く際にも迷いが少なくなります。 大事なのは、次のところだと思います。 ① Controller と View の間のデータのやり取りは、Model を介して行われていること ② やり取りするデータは、Controller にあるメソッドの引数に入れて、取得したり更新したりすること このあたりに注目していただけると、分かりやすいのではないかと思います。 5-1. 一覧表示機能(READ) まずは、CRUD の Read(読み込み)から確認していきます。 次の画面を表示するには、データベースから、登録されているデータの一覧を取得する必要があります。 関係する Controller と View のコードは次のとおりです。 ① Controller のソースコード(抜粋) 一覧表示をする場合は、ユーザーは、リクエストURLは「/sample」、HTTPメソッドは「GET」でアクセスしてきます。 この場合は、index メソッドに処理が渡されます(対応関係のルールは「3-6-2. リクエストマッピングについて」に書いたとおりです)。 TestController.java(抜粋) @Controller @RequestMapping("/sample") public class TestController { //中略 @GetMapping public String index(Model model) { String sql = "SELECT * FROM test_table"; List<Map<String, Object>> list = jdbcTemplate.queryForList(sql); model.addAttribute("testList", list); return "sample/index"; } } index メソッド の中身を見てみると、最初の2行で次の処理を行っています。 ・JdbcTemplateクラスを使用してデータベースに接続(使用メソッドは queryForList) ・SQL文の実行により取得した一覧データを、List オブジェクトである list に格納(参考) 次の1行で、list に testList という名前を付けた上で、Model に格納しています(Model は引数に設定するだけで使えます)。 この Model が View にデータを渡してくれます。 最後の return では、一覧表示に使用するテンプレートを sample/index.html と指定しています。 ② View のソースコード(抜粋) Controller から命令を受けた View は、/src/main/resources/templates フォルダから sample/index.html を探し出します。 データベースから取得している一覧データ list は、Model に testList という名前で格納されてますので、View 側ではこれを ${testList} という記述で呼び出します(Thymeleaf を使用)。 /sample/index.html(抜粋) <table> <tr th:each="test : ${testList}"> <td th:text="${test.id}"></td> <td th:text="${test.name}"></td> <td th:text="${test.old}"></td> </tr> </table> th:eachの記述で、for each 文のように1レコード分ずつデータを取り出して、画面を作成します。 ③ データの流れのイメージ 一覧表示(READ)におけるデータの流れを図にすると、次のようになります。 ここでは、index メソッドの引数である Model がデータ受け渡しの役割を担っています。 Controller が直接 View にデータを渡しているのではなく、 Controller が Model にデータを格納して、View は Model にデータを取りに行くというイメージです。 5-2. 登録機能(CREATE) 次に、CRUD の Create(登録)についてです。 まず、最初に入力フォームを表示する必要があるので、その部分から確認していきます。 5-2-1. 入力フォームの表示 次の入力フォームの表示では、データベースからデータを取得する必要はありません。 ここでは、フォームの入力データを保持するためのフォームクラス(TestForm.java)の使用が必要になります。 ① Controller のソースコード(抜粋) 入力フォームを表示する場合、ユーザーは、リクエストURL「/sample/form」、HTTPメソッド「GETメソッド」でアクセスすることになります。 この場合は、form メソッドに処理が渡されます。 TestController.java(抜粋) @Controller @RequestMapping("/sample") public class TestController { //中略 @GetMapping("/form") public String form(@ModelAttribute TestForm testForm) { return "sample/form"; } } form メソッド の中身は、return の1行のみです。 この1行で、View に対して一覧表示に使用するテンプレートを sample/form.html と指定しています。 なお、引数に指定しているフォームクラスには、@ModelAttributeというアノテーションが付いています。 これにより、Model にフォームクラスのインスタンス testForm が追加されることになります(厳密なことはこちらの記事を参照してください)。 testForm には何らの値を入れていませんので、中身は空っぽのままです。View は、この空の testForm を Model を介して取得することになります。 なお、@ModelAttribute を付けずに、次のように記載しても動作します。 TestController.java(参考) public String form(TestForm testForm) { return "sample/form"; } これは、「ハンドラメソッドの引数に、フレームワーク側がサポートしていないクラスがあると自動的に @RequestParam または @odelAttribute とみなされるため」とのことです(「ModelAttributeでフォームパラメータをオブジェクトにマッピングする」より)。 <参考サイト> ・Spring MVC についてまとめてみるよ!!! ・はじめてのSpring MVCアプリケーション ・ModelAttributeでフォームパラメータをオブジェクトにマッピングする ・@ModelAttribute を使う ② View のソースコード(抜粋) Controller から命令を受けた View は、/src/main/resources/templates フォルダから sample/form.html を探し出します。 Model から取得した、フォームクラスのインスタンス testForm を、以下のようにセットして画面を作成します(Thymeleaf を使用)。 /sample/form.html(抜粋) <form method="post" action="#" th:action="@{/sample/form}" th:object="${testForm}"> <label for="name">名前</label> <input type="text" id="name" name="name" th:value="${testForm.name}"><br> <label for="old">年齢</label> <input type="text" id="old" name="old" th:value="${testForm.old}"><br> <input type="submit" value="送信"> </form> ③ データの流れのイメージ データの流れを図にすると、次のようになります。 ここでは、form メソッドの引数である testForm が受け渡しされています。 5-2-2. データベースへの登録 次に、ユーザーからの新規登録のリクエストを受けた場合の処理になります。つまり、CRUD の Create の部分となります。 ユーザーが、フォームにデータを入力して送信ボタンを押すと、次のように、リクエストURLは「/sample/form」、HTTP メソッドは「POST」でデータが送信されます。 /sample/form.html(抜粋) <form method="post" action="#" th:action="@{/sample/form}" th:object="${testForm}"> ① Controller のソースコード(抜粋) データの送信を受けると、Controller の create メソッドに処理が渡されます。 TestController.java(抜粋) @Controller @RequestMapping("/sample") public class TestController { //中略 @PostMapping("/form") public String create(TestForm testForm) { String sql = "INSERT INTO test_table(name, old) VALUES(?, ?);"; jdbcTemplate.update(sql, testForm.getName(), testForm.getOld()); return "redirect:/sample"; } } create メソッド の中身を見てみると、最初の2行で、次の処理を行っています。 ・JdbcTemplateクラスを使用してデータベースに接続(使用メソッドは update) ・Client から受け取った testForm のデータを元に SQL 文を実行して、データベースに新たなレコードを登録 どういう仕組みで Client から送信されたデータが testForm に格納されるのかはいまいち分かりませんが、引数に設定することでデータの取得ができます。 最後の return では、リダイレクト先として /sample を指定しています。 これにより、クライアントから自動的にリクエストURL /sample(HTTP メソッドは GET) へのアクセスが実行され、Controller の index メソッドが実行され、一覧ページが表示されることになります。 ② データの流れのイメージ 登録(CREATE)におけるデータの流れを図にすると、次のようになります。 ここでは、create メソッドの引数である testForm がデータ受け渡しの役割を担っています。 5-3. 更新機能(UPDATE) 次に、CRUD の Update(更新)についてです。 まず、最初に編集フォームを表示する必要があるので、その部分から確認していきます。 5-3-1. 編集フォームの表示 編集フォームの表示するには、ユーザーが編集を行うデータを、データベースから取得する必要があります。 データを特定するために、リクエスト URL の一部(id の部分)を使用し、フォームの表示するデータを受け渡すために、フォームクラス(TestForm.java)を使用します。 ① Controller のソースコード(抜粋) 編集フォームを表示する場合、ユーザーは、リクエストURL「/sample/edit/{id}」、HTTPメソッド「GETメソッド」でアクセスすることになります。 この場合は、edit メソッドに処理が渡されます。 TestController.java(抜粋) @Controller @RequestMapping("/sample") public class TestController { //編集フォームの表示 @GetMapping("/edit/{id}") public String edit(@ModelAttribute TestForm testForm, @PathVariable int id) { String sql = "SELECT * FROM test_table WHERE id = " + id; Map<String, Object> map = jdbcTemplate.queryForMap(sql); testForm.setId((int)map.get("id")); testForm.setName((String)map.get("name")); testForm.setOld((int)map.get("old")); return "sample/edit"; } } アノテーション@GetMapping("/edit/{id}") のパスのうち、波括弧で囲んだ {id} の部分は、@PathVariable を使用することで変数として受け取ることができます。 引数に指定しているフォームクラス testForm には、アノテーション@ModelAttributeを付けて Model に追加しています。 edit メソッド の中身を見てみると、最初の2行で次の処理を行っています。 ・JdbcTemplateクラスを使用してデータベースに接続(使用メソッドは queryForMap) ・リクエスト URL に付された {id} を元に編集対象となるレコードを取得し map に格納 次の3行で、map のデータの要素を1つずつ testForm に格納しています。 この testForm に格納されたデータが、Model を介して View に渡されることになります。 最後の return では、一覧表示に使用するテンプレートを sample/edit.html と指定しています。 ② View のソースコード(抜粋) Controller から命令を受けた View は、/src/main/resources/templates フォルダから sample/edit.html を探し出します。 Model から取得したフォームクラスのインスタンス testForm を、以下のようにセットして画面を作成します(Thymeleaf を使用)。 /sample/edit.html(抜粋) <form method="post" action="#" th:action="@{'/sample/edit/' + ${testForm.id}}" th:object="${testForm}"> <label for="name">名前</label> <input type="text" id="name" name="name" th:value="${testForm.name}"><br> <label for="old">年齢</label> <input type="text" id="old" name="old" th:value="${testForm.old}"><br> <input type="submit" value="送信"> </form> ③ データの流れのイメージ データの流れを図にすると、次のようになります。 ここでは、edit メソッドの引数である id 及び testForm が、データの受け渡しを担っています。 5-3-2. データベースの更新 次に、ユーザーからのデータ更新のリクエストを受けた場合の処理になります。これは、CRUD の Update の部分となります。 ユーザーが、フォーム上でデータを修正して送信ボタンを押すと、次のように、リクエストURLは「/sample/edit/{id}」、HTTP メソッドは「POST」でデータが送信されます。 /sample/edit.html(抜粋) <form method="post" action="#" th:action="@{'/sample/edit/' + ${testForm.id}}" th:object="${testForm}"> ① Controller のソースコード(抜粋) データの送信を受けると、Controller の update メソッドに処理が渡されます。 TestController.java(抜粋) @Controller @RequestMapping("/sample") public class TestController { //編集データの保存 @PostMapping("/edit/{id}") public String update(TestForm testForm, @PathVariable int id) { String sql = "UPDATE test_table SET name = ?, old = ? WHERE id = " + id; jdbcTemplate.update(sql, testForm.getName(), testForm.getOld()); return "redirect:/sample"; } } update メソッド の中身を見てみると、最初の2行で次の処理を行っています。 ・JdbcTemplateクラスを使用してデータベースに接続(使用メソッドは update) ・Client から受け取った id 及び testForm のデータを元に SQL 文を実行してデータベースのレコードを更新 最後の return では、リダイレクト先として /sample を指定しています。 これにより、一覧ページが表示されることになります。 ② データの流れのイメージ 更新(UPDATE)におけるデータの流れを図にすると、次のようになります。 ここでは、update メソッドの引数である id 及び testForm がデータ受け渡しの役割を担っています。 5-4. 削除機能(DELETE) 最後に、ユーザーからのデータ削除のリクエストを受けた場合の処理になります。これは、CRUD の Delete の部分となります。 ユーザーが、一覧表示画面(/sample)の削除ボタンを押すと、次のように、リクエストURLは「/sample/delete/{id}」、HTTP メソッドは「POST」でリクエストが送信されます。 /sample/index.html(抜粋) <form action="#" th:action="@{'/sample/delete/' + ${test.id}}" method="post"> <button>削除</button> </form> ① Controller のソースコード(抜粋) データの送信を受けると、Controller の delete メソッドに処理が渡されます。 TestController.java(抜粋) @Controller @RequestMapping("/sample") public class TestController { //データの削除 @PostMapping("/delete/{id}") public String delete(@PathVariable int id) { String sql = "DELETE from test_table WHERE id = " + id; jdbcTemplate.update(sql); return "redirect:/sample"; } } delete メソッド の中身を見てみると、最初の2行で次の処理を行っています。 ・JdbcTemplateクラスを使用してデータベースに接続(使用メソッドは update) ・リクエスト URL から取得した id を元に SQL 文を実行して、データの削除を実行 最後の return では、リダイレクト先として /sample を指定しています。 これにより、一覧ページが表示されることになります。 ② データの流れのイメージ 削除(DELETE)におけるデータの流れを図にすると、次のようになります。 ここでは、delete メソッドの引数である id がデータ受け渡しの役割を担っています。 さいごに 以上、学習のアウトプットとして書いてみましたが、謎は深まるばかりです。 お気づきのことがあれば、ご教示いただけると幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】ArrayListのremoveIf()メソッドの使い方

ArrayListのremoveIf()メソッドは、引数として渡された条件でリストのアイテムを削除します。 条件に合致するものは削除され、そうでないものはリストに残ります。 removeIf()メソッドの使い方 removeIf()メソッドは引数として Predicate を受け取ります。 Predicateはラムダ式に渡すことができ、リストからアイテムをフィルタリングする条件を表しています。 public boolean removeIf(Predicate<? super E> filter) 使用例 // 数値を格納するリスト ArrayList<Integer> Numbers = new ArrayList<Integer>(); // 数値をリストに追加 Numbers.add(33); Numbers.add(8291); Numbers.add(182930); Numbers.add(182); // 3で割り切れる数をリストから削除 Numbers.removeIf(n -> (n % 3 == 0)); // 出力 Numbers.forEach(s -> { System.out.println(s); }); 出力 8291 182930 182 参照 Java Platform SE 10 #removeIf(java.util.function.Predicate)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaでCoincheckのpublicAPIを呼び出す

呼び出したいAPI このpublicAPIのtickerを試しに呼び出してみる。 呼び出す情報は次の通り。  ticker情報 last 最後の取引の価格 bid 現在の買い注文の最高価格 ask 現在の売り注文の最安価格 high 24時間での最高取引価格 low 24時間での最安取引価格 volume 24時間での取引量 timestamp 現在の時刻 Javaで実装 以下のコードでAPIの疎通チェックを行っています。 まだいくつかのAPIがありますが、apiUrlを変更するだけで疎通確認ができます。 qiita sample.java  //CoinCheckのAPIの接続チェック String apiUrl = "https://coincheck.com/api/ticker"; URL connectUrl = new URL(apiUrl); HttpURLConnection con = (HttpURLConnection) connectUrl.openConnection(); System.out.println("レスポンスヘッダ:"); System.out.println("レスポンスコード[" + con.getResponseCode() + "] " + "レスポンスメッセージ[" + con.getResponseMessage() + "]"); resultにGETの結果をJSON形式で格納する qiita sample.java  //GETした結果をjson形式で出力する InputStream in = con.getInputStream(); String encoding = con.getContentEncoding(); if (null == encoding) { encoding = "UTF-8"; } StringBuffer result = new StringBuffer(); final InputStreamReader inReader = new InputStreamReader(in, encoding); final BufferedReader bufReader = new BufferedReader(inReader); String line = null; // 1行ずつテキストを読み込む while ((line = bufReader.readLine()) != null) { result.append(line); } bufReader.close(); inReader.close(); in.close(); System.out.println(result); JSONから抽出したデータをリストに格納して出力する qiita sample.java  JSONObject json = new JSONObject(result.toString()); int last = json.getInt("last"); int bid = json.getInt("bid"); int ask = json.getInt("ask"); int low = json.getInt("low"); double volume = json.getDouble("volume"); int timestamp = json.getInt("timestamp"); List<Object> ticker = new ArrayList<Object>(Arrays.asList(last,bid,ask,low,volume,timestamp)); System.out.println(ticker); 分析に使う為にCoinCheckのAPIを取得する実装を試しに書きました。とても冗長なのでまた綺麗にしておきます。 Github:https://github.com/YUJIjs/get-coincheck-api-value
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SpringJdbc】ConversionServiceを用いてRowMapperによるマッピング時に値を変換する

TL;DR BeanPropertyRowMapper/DataClassRowMapper/SingleColumnRowMapperはConversionServiceを登録することで値の変換ができる1 何も指定していない状態でも、DefaultConversionService.getSharedInstance()の取得結果が利用されている 本文 SpringFrameworkにはConversionServiceを用いた型変換の仕組みがデフォルトで用意されており、RowMapperの中でもそれを利用した型変換を行うことができます。 以下のように、数値で年月を表したカラムをjava.time.YearMonthに変換して取得する場面を例にします。 取得対象テーブル CREATE TABLE IF NOT EXISTS `foo_table` ( `year_month` MEDIUMINT UNSIGNED NOT NULL, PRIMARY KEY (`year_month`) ); 以下のように、何も設定せずに取得処理を行うとエラーが発生します。 SingleColumnRowMapper<YearMonth> mapper = new SingleColumnRowMapper<>(YearMonth.class); // この取得処理でTypeMismatchDataAccessExceptionが発生する YearMonth actual = template.queryForObject("SELECT year_month FROM foo_table", mapper); ConversionServiceを設定することで、この取得処理を行えるようにします。 今回はDefaultConversionServiceにConverterを設定し、更にそれをRowMapperに登録することでこれを行う例を示します2。 SingleColumnRowMapper<YearMonth> mapper = new SingleColumnRowMapper<>(YearMonth.class); // Converterの登録処理 DefaultConversionService defaultConversionService = new DefaultConversionService(); defaultConversionService.addConverter(new Converter<Integer, YearMonth>() { @Override public YearMonth convert(@NotNull Integer source) { return YearMonth.of(source / 100, source % 100); } }); mapper.setConversionService(defaultConversionService); YearMonth actual = template.queryForObject("SELECT year_month FROM foo_table", mapper); assertEquals(YearMonth.of(2021, 1), actual); 補足: DefaultConversionServiceについて Spring全体で、ConversionServiceを設定しなかった場合はDefaultConversionService.getSharedInstance()で取得されるstaticなConversionServiceが利用されます。 このインスタンスにConverterを設定すれば、デフォルトではアプリケーション全体でそれを使い回すことができます。 DefaultConversionServiceに設定する例 DefaultConversionService sharedInstance = (DefaultConversionService) DefaultConversionService.getSharedInstance(); sharedInstance.addConverter(new Converter<Integer, YearMonth>() { @Override public YearMonth convert(@NotNull Integer source) { return YearMonth.of(source / 100, source % 100); } }); また、SpringFramework内でString -> Enumのような変換が行われるのはこのsharedInstanceの働きによるものです。 どのような変換が行われるかはソースコードから読み取ることができます。 タイトルが長くなりすぎるため省きましたが、org.springframework.jdbc.coreに定義されたRowMapperでもConversionServiceを登録できないものが存在します。 ↩ ConverterはFunctionalInterfaceであるためラムダでも書くことができますが、Generics関連の問題により自分の環境では実行時エラーになったため、例では匿名クラスを用いた書き方をしています。 ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MicronautでLombokを利用する

やりたいこと MicronautでLombokを利用して開発する. Java16でRecordが正式対応したのですが、まだ11を使っているし、Lombokはなんだかんだで便利なので使いたい. 設定方法 基本的なことは、公式サイトに記載されています. 13.1.3 Using Project Lombok 私は、Mavenを使っているので、Mavenでの説明します. lombokをdependency追加 pom.xml <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> <scope>provided</scope> </dependency> lombokのannotationの処理をmaven-compiler-pluginに追加 pom.xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <annotationProcessorPaths combine.self="override"> <path> <!-- must precede micronaut-inject-java --> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </path> <path> <groupId>io.micronaut</groupId> <artifactId>micronaut-inject-java</artifactId> <version>${micronaut.version}</version> </path> <path> <groupId>io.micronaut</groupId> <artifactId>micronaut-validation</artifactId> <version>${micronaut.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin> あとは、LombokをIDEで使うための設定をします. 私は、Java開発もVS Codeを使うようになったので以下の拡張機能をインストールすることで対応可能です。 Lombok Annotations Support for VS Code
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む