20210419のJavaに関する記事は11件です。

debian10 に gradleをインストールする

前提 Java SE8以降がインストールされている gradleをダウンロード $ wget https://services.gradle.org/distributions/gradle-6.3-bin.zip -P /tmp 解凍する $ sudo unzip -d /opt/gradle /tmp/gradle-*.zip 中身を確認 $ ls /opt/gradle/gradle-* bin init.d lib LICENSE NOTICE README PATH環境変数の構成 $ touch /etc/profile.d/gradle.sh $ vi /etc/profile.d/gradle.sh 作成したgradle.shに追記 gradle.sh export GRADLE_HOME=/opt/gradle/gradle-6.3 export PATH=${GRADLE_HOME}/bin:${PATH} 実行可能にする $ sudo chmod +x /etc/profile.d/gradle.sh 環境変数を読み込み&インストール確認 下のようなメッセージが出れば完了 $ source /etc/profile.d/gradle.sh $ gradle -v Welcome to Gradle 6.3! Here are the highlights of this release: - Java 14 support - Improved error messages for unexpected failures For more details see https://docs.gradle.org/6.3/release-notes.html ------------------------------------------------------------ Gradle 6.3 ------------------------------------------------------------ Build time: 2020-03-24 19:52:07 UTC Revision: bacd40b727b0130eeac8855ae3f9fd9a0b207c60 Kotlin: 1.3.70 Groovy: 2.5.10 Ant: Apache Ant(TM) version 1.10.7 compiled on September 1 2019 JVM: 11.0.9.1 (Debian 11.0.9.1+1-post-Debian-1deb10u2) OS: Linux 5.4.72-microsoft-standard-WSL2 amd64 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

debianで環境変数JAVA_HOMEを設定する

インストール後 パスを通す $ cat >> ~/.bashrc <<'EOF' # set JAVA_HOME adn append PATH JAVA_HOME=$(readlink -f /usr/bin/javac | sed "s:/bin/javac::") export JAVA_HOME PATH=$PATH:$JAVA_HOME/bin export PATH EOF 適用 source ~/.bashrc 確認 echo $JAVA_HOME
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【プログラミングコンテスト】JAVA

AtCoderに初参加してボロボロだったので次回に向けて必要そうな知識をまとめてみた 適宜追加していく 標準入力の取得 これがないと何も出来ない import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in);     //標準出力の1行目取得 String first_row = sc.next();     //標準出力の2行目取得 String second_row = sc.next(); } } 文字型=>数値型に変換 標準出力を数値として使用したい場合等に使用 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in);     //標準出力の1行目取得 String first_row = sc.next();     //整数に変換 Integer num = Integer.parseInt(first_row); } } 文字のn番目の文字を取得 これについてはcharAtの方が良さそうだが、エラーが出て使えなかったのでsubstringで代用した。 (charAtの使い方教えて欲しい。。。) String test = "ABCDEFGHIJKLMNOPQRST"; //substring(k,n)で文字のk+1からn+1番目までの文字を取得できる。 //substring(k-1,k)でk番目の文字を取得できる。 String val = test.substring(2,3); 反省点 プログラミングコンテスト初参加の結果は0点だった。。。 原因としては問題を見て解けそうだと感じた問題に挑戦していたが、作ったプログラムが実行時間超過となってしまい点数にならなかった。 反省点としては、 ・参加前にトレーニング問題を解いとくべきだった。 ・事前にエディター環境を用意しとくべきだった。 分かったこと ・ネストでfor文やWhileが2回以上入ると実行時間を超過する恐れがある ・複雑な問題でも最初は小さい数字から考えるのが良い ・簡単そうな問題でも実行時間超過にさせない為に規則性を見つけなければいけない場合がある 参考記事 [Java]n番目の文字を取得する https://hacknote.jp/archives/17781/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

独習Javaを学びながらJavaをマスターする

背景 Javaが本当に気になるので・・・ やさしいとかスラスラ系を買いに行ったのだが・・・独習Javaを見かけて わかりやすいような気がしたので・・・ 目的 Java8を一通り触れれ・・・ 用語もわかればいいのでは・・・・ 完了条件 改訂版をつけた時です。 chap2 TakeAway 時間の測り方のテンプレート package selfLerning.chap3; public class ConcatBulder { public static void main(String[] args) { // 処理前の時刻を取得 long startTime = System.currentTimeMillis(); StringBuilder builder = new StringBuilder(); for (int i = 0; i < 100000; i++) { builder.append("いろは"); } // 処理後の時刻を取得 long endTime = System.currentTimeMillis(); System.out.println("開始時刻:" + startTime + " ms"); System.out.println("終了時刻:" + endTime + " ms"); System.out.println("処理時間:" + (endTime - startTime) + " ms"); } } chap3 用語 特に用語大事なような気がする。 chap4 用語
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java本格入門を学びながらJavaをマスターする 

背景 Javaが本当に気になるので・・・ やさしいとかスラスラ系を買いに行ったのだが・・色々あってJava本格入門を 使うことにします。 補足 プログラムソースはダウンロードしようとしたがよくわかりませんでした。 独習Javaは7から一読問題やってみることにする。 目的 Java8を一通り触ればと思います。・・・ 用語もわかればいいのでは・・・・ 完了条件 改訂版をつけた時です。 アーカイブ 独習Java chap2 TakeAway 時間の測り方のテンプレート package selfLerning.chap3; public class ConcatBulder { public static void main(String[] args) { // 処理前の時刻を取得 long startTime = System.currentTimeMillis(); StringBuilder builder = new StringBuilder(); for (int i = 0; i < 100000; i++) { builder.append("いろは"); } // 処理後の時刻を取得 long endTime = System.currentTimeMillis(); System.out.println("開始時刻:" + startTime + " ms"); System.out.println("終了時刻:" + endTime + " ms"); System.out.println("処理時間:" + (endTime - startTime) + " ms"); } } chap3 用語 特に用語大事なような気がする。 chap4 用語 chap5 用語 chap6 用語
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

独習Javaを学びながらJavaをマスターする Push編

背景 Javaが本当に気になるので・・・ やさしいとかスラスラ系を買いに行ったのだが・・・独習Javaを見かけて わかりやすいような気がしたので・・・そのため標準ライブラリとかコレクションは 一読のみとする。のちに、仕上げのPull編で扱います。 目的 Java8を一通り触れれ・・・ 用語もわかればいいのでは・・・・ 完了条件 改訂版をつけた時です。 chap2 TakeAway 時間の測り方のテンプレート package selfLerning.chap3; public class ConcatBulder { public static void main(String[] args) { // 処理前の時刻を取得 long startTime = System.currentTimeMillis(); StringBuilder builder = new StringBuilder(); for (int i = 0; i < 100000; i++) { builder.append("いろは"); } // 処理後の時刻を取得 long endTime = System.currentTimeMillis(); System.out.println("開始時刻:" + startTime + " ms"); System.out.println("終了時刻:" + endTime + " ms"); System.out.println("処理時間:" + (endTime - startTime) + " ms"); } } chap3 用語 特に用語大事なような気がする。 chap4 用語 chap5 用語 chap6 用語
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

独習Javaを学びながらJavaをマスターする オブジェクト指向編

背景 Javaが本当に気になるので・・・ やさしいとかスラスラ系を買いに行ったのだが・・・独習Javaを見かけて わかりやすいような気がしたので・・・Javaも範囲が広いので7章以降のオブジェクト思考以降に力を入れることにする。講座でもそういう風に分けていることも珍しくないようだ。 目的 Java8を一通り触れれ・・・ 用語もわかればいいのでは・・・・ 完了条件 改訂版をつけた時です。 chap2 TakeAway 時間の測り方のテンプレート package selfLerning.chap3; public class ConcatBulder { public static void main(String[] args) { // 処理前の時刻を取得 long startTime = System.currentTimeMillis(); StringBuilder builder = new StringBuilder(); for (int i = 0; i < 100000; i++) { builder.append("いろは"); } // 処理後の時刻を取得 long endTime = System.currentTimeMillis(); System.out.println("開始時刻:" + startTime + " ms"); System.out.println("終了時刻:" + endTime + " ms"); System.out.println("処理時間:" + (endTime - startTime) + " ms"); } } chap3 用語 特に用語大事なような気がする。 chap4 用語 chap5 用語 chap6 用語
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java アルゴリズム修行⑧】ハッシュ_チェイン法

ハッシュとは? これまではデータの集合から特定の値を見つける探索を主に扱ってきましたが データというのは探索だけでなく、追加や削除という操作を行うことも多く そんな追加と削除を効率的に行う方法がハッシュ法と呼ばれる考え方だそうです。 データが格納されている位置は配列のインデックスを前から順番に指定するのがベーシックでしたが このインデックスを指定するための演算を各値で行い、格納する場所を管理するという方法です。 例えば、配列の要素が13個数ある下記配列を考えてみましょう。 (実際には8要素しかありませんが、余分に空要素が5個あると考えます) このとき、それぞれの値を要素数13で割り、剰余をインデックスとして指定してみます。 18であれば 18÷13 の剰余が 5、42であれば 42 ÷ 13の剰余が 3 といった感じに 求められた剰余をそのまま配列のインデックスとして格納していきます。 こうすることによって、例えば33という値を見つけたければ、ハッシュ関数を通じてインデックスは7となるので そのまま[7]の要素を引っ張ってくれば良く、線形探索よりも効率的に探索を行うことができるということです。 格納位置を決定するハッシュ関数があれば、取り出す時も同じハッシュ関数を使って位置を割り出すことができるので、処理速度も上がるよねというお話ですね。。! ハッシュ法における独特の言い回しにおいてもまとめておきます。 ハッシュ値:要素を格納する配列の位置、インデックスのこと ハッシュ関数:ハッシュ値を求める関数のこと バケット:配列の各要素のこと 衝突という危険性 と、ここだけみると万能ハッシュ君と思いがちですが、ある危険性も存在します。。 仮に先の配列に14という値を加えたい! となったとき、14 ÷ 13 なので [1]に追加すればいいか となりますが、[1]は既に27で埋まっており、こういったバケットの重複が衝突と呼ばれたりします。 と、そんな衝突が発生した場合の対処方法

は既に決められており、下記2つが挙げられます。 チェイン法:同一のハッシュ値を持つ要素を線形リストで管理する
 オープンアドレス法:空きバケットを見つけるまで、ハッシュを繰り返す
 今回はその内のチェイン法について理解も兼ねて、書いてみたいと思います! チェイン法 チェイン法と呼ばれるくらいなので、その名の通り、同じハッシュ値で衝突したときに 同一のハッシュ値を持つデータを線形リストによって鎖状につないでいく方法です。 ※線形リスト リストというと、データが順序づけられて並んだデータ構造ですが 線形リストはその中でも単純なリスト構造の一種です。 線形リストは連結リストとも呼ばれ、A,B,Cという要素があれば、A→B→C という順にアクセスしていくので、 構造上どこかの要素を飛ばしてアクセスしたりすることはできません。 

リストの個々の要素はノードと呼ばれ、各ノードは、データと後続ノードを指すポインタで構成されています このノードという部分には、それよりも前にいた要素の参照を格納することによって、 左から読み込んだときに「自身の後ろに繋がれている要素の参照」を各ノードが持っているということになります。 nd3は要素が何もないnullの次に格納されたので、nullという参照を nd2はnd3の後に格納されたので、nd3の参照を。。という感じで、格納された順番的には右から左に繋がれていますが 矢印のように左から読み込んだ時は、自分の後続ノードの参照を持っているという言い方もできます (考え方としては分かりにくいですが、どんどん値を押し出して右に繋げていくみたいな感覚だと思います。) チェイン法ではこの線形リストというデータ型を使って衝突する値をうまく管理していきます。 例えば、以下のようなハッシュ表があったして、各要素には後続ノードの参照も含まれているとします。 (ハッシュ値が1の要素はnullが入っていましたが、その後に格納された27には nullという後続ノードが格納されているという構造です) ここに、32を追加したい!としたとき、ハッシュ値は 32%13 6なので 19と衝突してしまいます。 そこで。互いのハッシュ値は6なので、それらを連結した線形リストへの先頭ノードへの参照を[6]に格納することによって 同じ位置に別々の値を格納することができます。 [6]には 32という要素があり、ポインタには19という値が入っていて、 19という値にはポインタである nullが入っている。。という構造になります。 このように、各要素に線形リストの鎖がぶら下がっているような構造になってくのが特徴といえます。 コードで表現してみる まずは大元となるハッシュ表を一つのクラスで表現してみます。 ChainHash.java public class ChainHash<K,V> { private int size; // ハッシュ表の大きさ private Node<K,V>[] table; // ハッシュ表 //--- コンストラクタ ---// public ChainHash(int capacity) { table = new Node[capacity]; this.size = capacity; } //--- ハッシュ値を求める ---// public int hashValue(Object key) { return key.hashCode() % size; } ハッシュ表の大きさを表すsizeと、線形リスト(ノードで構成された配列)のtableをフィールドとして持っています。 コンストラクタでは、引数で持ってきたハッシュ表のサイズ数の要素数を持つNode型の配列を生成しており、 Nodeオブジェクトの具体的な中身は下記のような感じになります。 hashValue関数は実際にハッシュ値を求める関数で、指定の要素をハッシュ表の要素数で割ったときの剰余を返すようにしています。 Node.java class Node<K,V> { private K key; // キー値 private V data; // データ private Node<K,V> next; // 後続ポインタ(後続ノードにとっての先行ノードに自身を参照させる) //--- コンストラクタ ---// Node(K key, V data, Node<K,V> next) { this.key = key; this.data = data; this.next = next; } } Nodeクラスというオブジェクトですが、(実際はChainHashクラスの内部クラスとして定義しています)keyとdataと、後続の参照を持つnextというフィールドを持たせています。 実際に持てるキーとデータは、ジェネリクスにしてますが、 今回はint型の会員番号とString型の氏名をdataとして持ち、keyは氏名を設定しているというシンプルなオブジェクトで表現してみましょう。 Data.java //--- データ(会員番号+氏名) ---// static class Data { private Integer no; // 会員番号 private String name; // 氏名(キー値) //--- キー値として氏名を返す ---// String keyCode() { return name; } //--- 文字列表現を返す ---// public String toString() { return Integer.toString(no); } 大元のハッシュ表、ノードオブジェクト、扱うデータ、が準備できたので、具体的な要素の探索、追加、削除などをメソッドで表現していきます。 探索・追加・削除 search.java public V search(K key) { int hash = hashValue(key); // 探索するデータのハッシュ値(探索対象の値が格納されたインデックス) Node<K,V> p = table[hash]; // 着目ノード while (p != null) { if (p.getKey().equals(key)) { return p.getValue(); // 探索成功 } p = p.next; // 一致しなければ後続ノードの参照を探索対象にする } return null; // 探索失敗 } 引数のkeyという値を探索したい!というときのメソッドです。 今回扱うデータのkeyは氏名になるので、ここではString型の氏名が入ってきますが、 まずやるべきはhashValue関数でハッシュ値(インデックス)を求めることです。 ハッシュ値がでたら、今度は探索対象である値が入っているであろうノードに注目して、あとはそのノードに格納されている keyが一致するまで無限ループで線形探索を実施する。。という流れになります。 もしノードがnullであれば、指定のノードにはどの値も格納されていないか、値が見つからないまま、最後の要素まで探索してしまったということで、そのままnullを返し探索失敗としています。(while(p != null)という条件式が判定部分です。) もしnullでなければkeyが一致するか、nullになるまで繰り返し、一致しない場合は p = p.nextで後続ノードの参照を次の探索対象としています。(ここがnullだと最後まで探索したことになるということです。) 例えば、上記のハッシュ表似て、32 → 19 → null というノードが[6]という位置にあったとしたとき 19という値を探索する場合は、32という値とは一致しないので、後続の参照である19を返します。 すると次にくる19とは同値なので探索が完了するといった流れです。 次に値の追加を見てみましょう。 add.java public int add(K key, V data) { int hash = hashValue(key); // 追加するデータのハッシュ値 Node<K,V> p = table[hash]; // 着目ノード while (p != null) { if (p.getKey().equals(key)) { // このキー値は登録ずみ System.out.println("この名前は登録済みです"); return 1; } p = p.next; // 後続ノードに着目 } //table[hash]は自分の1個前のノードなのでポインタとしてその参照を入れておく Node<K,V> temp = new Node<K,V>(key, data, table[hash]); table[hash] = temp; // ノードを挿入 return 0; } まずは追加したいkey値のハッシュ値を求めて、格納先のノードを決めます。 格納先のノードが特定できれば、まずは探索と同様の方法で頭から同じ名前がないかを確認します。 もしなければ、現状のノードであるtable[hash]の参照を持った新しいノードを生成し、追加します。 同じNodeオブジェクトであるものの、中身は指定した要素の鎖が増えた線形リストであるということですね。。! (オブジェクトの中に自分の前にあった参照があり、その参照にもその前の参照が。。という再帰的な構造をイメージすると分かりやすいかもしれません。) 全体のハッシュ表の値が変わっておらず、ハッシュ表の同じ位置に値を再代入しているだけなので 一見すると値を追加したとは思いにくいですが、衝突する可能性がある値を一括してノード内で管理しているというのを意識するのが大事かと思います。(自分はここのイメージができなく、理解に戸惑いました。。) 最後に要素の削除を書いてみたいと思います。 remove.java public int remove(K key) { int hash = hashValue(key); // 削除するデータのハッシュ値 Node<K,V> p = table[hash]; // 着目ノード Node<K,V> pp = null; // 前回の着目ノード while (p != null) { if (p.getKey().equals(key)) { // 同じkey値を見つけて if (pp == null) { //先頭ノードであれば直後のノードをそのまま再代入する table[hash] = p.next; } else { // 先頭でなければ、1個前に探索したノードに自身の次の参照を代入し、自身の参照は無かったことにする pp.next = p.next; } return 0; } //現在の探索対象を、前回の探索ノードとして代入する pp = p; //現在の探索対象のnextを探索対象に移す p = p.next; } return 1; // そのキー値は存在しない } 探索、追加と同じように削除したい値のハッシュ値を求めて、指定の値が含まれているであろうノードに着目します。 削除対象が先頭ノードではない可能性もあるので、指定の値の直前にあるノードを格納するためにppという変数も用意しています。 もしノードに何かしらの値が格納されていれば削除する値まで線形探索を行います。 if (p.getKey().equals(key))で、削除したい値が見つかったときの処理がありますが、 もし、先頭ノードであった場合、(pp == null)はtrueとなるので、そのまま後続ノード(next)を再代入します。 先頭ノードでない場合は、自身の一個前のノードに自身の次に来る参照を再代入することで自身の参照を削除しています。 例えば 14 → 27 → 40 → nullという順番で値が右から格納されていたとして、 探索は左から行いますが、27を削除したいというときに、 14のnextに40の参照を入れる必要があるので、 先頭ノードの14でif (p.getKey().equals(key))がfalseとなった後に、 14を pp に再代入し、 14の次の参照である27を次の探索対象として、p に再代入しています。 次のノードである27と一致した場合、ppは!nullとして、14のnextに、27のnext(40)を代入しているので、 14のnextが40となり 、 14 → 40 → nullとして27が削除されたことになるという流れです。 先頭ではないノードを削除するさいは若干ややこしくはなりますが、基本的には線形探索を行い、値が一致したものを無かったことにするという流れになりますね。 学んだこと ハッシュ法では値が衝突する可能性があり、回避方法の一つとしてチェイン法が存在する 線形リストという、自身の参照を繋げた鎖状のデータ構造が存在する 同じハッシュ関数を使用して格納位置を決めているので、探索効率は高く、追加や削除も行える ハッシュ表と線形リストという配列の中に連続したオブジェクトが存在しているという 今までにないデータ構造と、その操作方法だったのでなかなか理解に苦しみましたが、 データを追加した順に鎖を繋げて、左から右に先頭~後続という流れでみると割とスッキリすることができました! まぁこんなデータ構造もあるんだなという理解ができたのでよしとして、引き続き頑張っていきます! ※ 記事内の画像は下記2サイトから拝借致しました。ありがとうございます。 C#によるアルゴリズムとデータ構造 アドバンスプログラミング
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Spring Boot + Azure AD B2C で認証を実装する

Spring Boot + Azure AD B2C で認証を実装する Azure 向けに Spring Boot Starterが提供されているのは以前の記事で触れましたが、今回はこの中から、Azure Active Directory用のライブラリを用いて、Azure Active Directory B2C にて認証を行う方法を解説したいと思います。これ以外にもいくつかライブラリがありますので、別記事で解説できたらと思います。 Azure 向けの Spring Boot Starter | Microsoft Docs Azure AD B2C Azure AD B2C とは名前のとおり B2C向けの認証などのID管理を提供してくれるサービスで、いわゆるIDaaS と呼ばれる物です。 Azure Active Directory B2C とは | Microsoft Docs 細かい話はドキュメントをあったっていただくとして、ソーシャルなアカウントと連携したり、任意のメールアドレスで、サインアップ、サインイン、プロファイル管理などができます。B2Cは、一定のユーザーまでは無料で使用できます。本記事では、B2C自体にはフォーカスしないので以下を参考に作成してください。 チュートリアル - Azure Active Directory B2C テナントを作成する | Microsoft Docs Spring Boot 用 Azure AD B2Cライブラリ 現時点で azure-spring-boot-starter-active-directory-b2c:3.3.0 が最新板です。バージョンが 3.0 系 になって、以前のライブラリ名 azure-active-directory-b2c-spring-boot-starter から変更されていますので注意してください。ググると古いチュートリアルに当たったりして、微妙に設定が異なります。 <dependency> <groupId>com.azure.spring</groupId> <artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId> <version>3.3.0</version> </dependency> Spring Boot プロジェクト ひな形は、 https://start.spring.io/ から、Web と Azure Active Directory 、Thymeleaf、Security を依存関係に指定して生成してください。 最終的に以下の依存関係が必要です。thymeleaf-extras-springsecurity5 はView側で独自のタグを利用するために追加してますが、この記事では解説しないです。最後の紹介するGitHubサンプルのViewを確認してください。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.azure.spring</groupId> <artifactId>azure-spring-boot-starter-active-directory</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency> 必要な設定 B2Cに以下の設定をしていきます。 アプリの登録 認証するアプリケーション情報を登録します。特にデプロイする必要がなければ、リダイレクトURLには、http://localhost:8080/login/oauth2/code/ を設定すればいいです。 以下の情報が手に入るはずです。 テナントサーバーのURL クライアントID クライアントシークレット ユーザーフロー B2Cでは、あらかじめどのような サインイン・サインアップ プロセスを行うかを定義しておく必要があります。あらかじめ定義されているものを「ユーザーフロー」と呼び、一般的なシナリオに基づくものはほぼ用意されており、ある程度カスタマイズもできますので、これを利用すると便利です。別途、詳細なカスタマイズもできますがここでは触れませんので、興味があれば調べてみてください。 B2C上でユーザーフローを定義しましょう。以下の3つのフローを定義して、名前を付けて保存します。 サインイン、サインアップ フロー名 プロファイル編集 フロー名 パスワードリセット フロー名(任意) Spring Boot Starter向けの設定 Spring Boot Starter が Confiurationを用意してくれているので、前述した情報を以下のプロパティを設定します。 azure: activedirectory: b2c: base-uri: ${your-tenant-authorization-server-base-uri} client-id: ${your-client-id} client-secret: ${your-client-secret} logout-success-url: ${you-logout-success-url} user-flows: password-reset: B2C_1_reset_password profile-edit: B2C_1_edit_profile sign-up-or-sign-in: B2C_1_signin user-name-attribute-name: ${your-user-name-attribute-name} アプリ側の実装 どのページに認証を設定するのかを、WebSecurityConfigurerAdapter を継承したクラスで定義します。以下では、/login 以外を認証必須に定義していますが、必要なように修正してください。 @EnableWebSecurity public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { private final AADB2COidcLoginConfigurer configurer; public WebSecurityConfiguration(AADB2COidcLoginConfigurer configurer) { this.configurer = configurer; } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .apply(configurer); } } 別途、コントローラとページを用意しておきますがここでは割愛します。 コントローラの引数に OAuth2AuthenticationToken を指定するとDIされるので、そこから認証情報を取り出すことが出来ます。以下、ちょっとしたサンプルです。 private void initializeModel(Model model, OAuth2AuthenticationToken token) { if (token != null) { final OAuth2User user = token.getPrincipal(); model.addAllAttributes(user.getAttributes()); model.addAttribute("grant_type", user.getAuthorities()); model.addAttribute("name", user.getName()); } } @GetMapping(value = { "/", "/home" }) public String index(Model model, OAuth2AuthenticationToken token) { initializeModel(model, token); return "home"; } 実行、確認 mvn clean spring-boot:run で ローカル実行し、http://locahost:8080 にアクセスすると、B2Cのログイン画面にリダイレクトされます。 WebAppsにデプロイする場合は、B2Cに正しくリダイレクトURLを設定した上でデプロイすれば動作すると思います。 まとめ B2C使うと簡単に認証できるのですが、B2C側の設定等々も理解する必要がるので、そこさえクリアすれば簡単に認証を実装できます。以前はもっと面倒くさかったのでライブラリが提供されるのは良いと思います。カスタマイズする上でも、どうB2C向けに実装しているか確認できるので。 最後にサンプルは以下のSDKページにもありますので、参考にしてください。 azure-sdk-for-java/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-b2c-oidc at azure-spring-boot-starter-active-directory-b2c_3.3.0 · Azure/azure-sdk-for-java
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Mybatisを使って、リストの要素で条件を絞り込む方法

はじめに サービス開発を行う中で、複数の条件で絞り込みを行なった結果をデータとして取得し一覧表示したい場面に遭遇した。そこで、複数条件を含めたリストを作成し、その要素をループで一つずつ取り出し、条件文に適用させる方法がないかと思い、調査を始めた。 実現したいこと DBからデータを取得するときに、リストに含めた全要素を条件に付加したい。 調査 公式ドキュメントを参照したところ、MybatisのforEachタグを用いることで実現できそう。 foreach 動的 SQL で良くあるもう一つの要件は、コレクションの要素をイテレーション処理したいというものです。多くの場合、IN 演算子を使った条件を構築するのが目的です。例: xml <select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select> 実装 @Mapper public interface MainListMapper { public List<ACCOUNT> getMainUpperList(List<Integer> hideList); } <select id="getMainUpperList" resultType="com.example.matching.entity.ACCOUNT"> SELECT * FROM ACCOUNT WHERE ID NOT IN <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> ORDER BY CREATED DESC </select> 躓いたところ 引数が一つの時は「collection="list"」の「list」の箇所に任意の名前が使用できたが、引数が二つ以上になった場合はinterfaceの引数で「@Param("hideList")」のように明示的に名前をつけてあげないと「collection="hideList"」をMybatis側で識別できない様子。 @Mapper public interface MainListMapper { public List<ACCOUNT> getMainLowerListMatchResidence(@Param("hideList") List<Integer> hideList, @Param("loginUserId") int loginUserId); } <select id="getMainLowerListMatchResidence" resultType="com.example.matching.entity.ACCOUNT"> SELECT * FROM ACCOUNT WHERE ID NOT IN <foreach item="item" index="index" collection="hideList" open="(" separator="," close=")"> #{item} </foreach> AND RESIDENCE = (SELECT RESIDENCE FROM ACCOUNT WHERE ID = #{loginUserId}) ORDER BY CREATED DESC </select> まとめ 引数の数による影響で躓いたが、無事にリストの要素で条件を絞り込むことができた。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java初学生が簡単な基礎から学び始めるまで

自己紹介 こんにちは。私は現在運用保守のエンジニアとして働こうとしている22歳都内在住エンジニア()です。 自分のための備忘録として簡単なjavaの基礎をまとめていこうと思います。少しでもかつての私のような入門者たちに役に立てば幸いです。 対象者 この記事の対象となる人はJavaで何ができるかなどの情報ではなく、主に出力方法や、配列や変数などの宣言の方法のまとめを知りたいというよう方向けになります。 文字及び数字の出力 //文字の場合 System.out.println("テスト"); //数字の場合 System.out.println(1); 基本的にSystem.out.printというものはコンソール上に出力結果を出すものになります。数字の場合は""がいらないと覚えてます。 ...端的すぎるのでもう少しわかりやすくしますね。 もう少しわかりやすくすると public class Sample01 { public static void main(String[] args) { // データ型や宣言方法のまとめ int age = 22; String name = "テスト太郎"; System.out.println(age); System.out.println(name); System.out.pritln(11111); System.out.println("適当な数字"); これでいかがでしょうか。 変数の宣言方法もついでに書いてしまいましたが、なんとなく把握できそうですね! int=数字 String=文字 という感じになり、変数ageやnameに指定しているデータ型の値を格納するといった感じですね。 いったんは初期的なところを記載させていただきましたが次回の記事からはもう少し処理的なところを書いていこうと思います。 備忘録といった感じで試験的にやっているものなので長続きするかわかりませんが、頑張ってみます!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む