taiPyのお悩み解決ブログ

日々の発見をまとめます!

Gradleを使用:Springの入力値検証機能を使いたい。spring-boot-starter-validation

はじめに

自分用の備忘録です。 Springの入力値検証機能を使いたいってなりましたが、自分のプロジェクトに必要なライブラリというか機能が備わっていなかったんですよね。

なので、Gradleで依存関係を整理して使えるようにしました!

環境

  • エクリプス
  • Windows
  • Spring

手順

大きく分けて次の2つ。

  1. Spring Boot Starter Dependencyを追加する: Spring Boot Starter Dependencyには、必要な依存関係が含まれています。build.gradleファイルに次のような依存関係を追加します:
   dependencies {
       implementation 'org.springframework.boot:spring-boot-starter-validation'
       // 他の依存関係も追加する場合はここに記述します
   }

これにより、Spring Bootが提供するバリデーション機能がプロジェクトに追加されます。

  1. 入力値の検証を行うクラスを作成する

今回はFormクラスを使っています。入力値を受け取るときにFormクラスを使う方法とModelクラスを使う方法の2種類があると思いますが、Formクラスを使っています。入力値検証をしたい、バリエーションをしたいってなったら基本Formクラスを作成することになるかと存じ上げますが。

入力値の検証を行うクラスを作成します。通常は、入力値を持つDTO(Data Transfer Object)クラスや、コントローラー内で使用されるフォームクラスが対象となります。以下は例です:

   import javax.validation.constraints.NotBlank;

   public class MyForm {
       @NotBlank(message = "名前を入力してください")
       private String name;

       // getterとsetterを省略
   }

ここでは、@NotBlankアノテーションを使用して名前が空でないことを検証しています。

これらの手順を実行することで、GradleプロジェクトでSpringの入力値検証機能を使用できるようになります。

Thymeleafの`[*{birth}]`と`[${birth}]`の違いについて。

Thymeleafの[*{birth}][${birth}]の違い

  1. [*{birth}]:

    • [*{...}]は、プレースホルダー式(Placeholder Expression)として知られています。
    • プレースホルダー式は、Thymeleafがデータをテンプレートに表示する際に、対応するモデルオブジェクトから属性を動的に解決します。
    • この式は、コンテキスト内のオブジェクトのプロパティを参照するために使用されます。*は現在のオブジェクトを指します。
    • 例えば、[*{birth}]は、現在のオブジェクトのbirthプロパティを取得し、それを表示します。
  2. [${birth}]:

    • ${...}は、変数式(Variable Expression)として知られています。
    • 変数式は、明示的にモデルに追加された属性を参照します。モデル内のオブジェクトに直接アクセスするのではなく、モデル内の属性を参照します。
    • 例えば、[${birth}]は、モデル内でbirthという名前の属性が定義されている場合、その値を表示します。

したがって、[*{birth}]は現在のオブジェクトのプロパティを参照し、[${birth}]はモデル内の属性を参照します。どちらを使用するかは、テンプレート内のデータの出所によって異なります。

Spring Framework 超入門, 4種類のDIのアノテーションを使用タイミングと意味について

はじめに

いま、Spring Framework 超入門という本を読んでいます。アマゾンへのリンクはこちら。Spring Framework 超入門

学んだことの備忘録としてブログにメモしておこうと思います。 今回書くことは、 「DIのアノテーション」 について書きます!

Springの勉強をしていると必ずDIという機能をマスターする必要があります。これがSpingの中心的な機能ですので。その時に、アノテーション(例:@Service)をつけるんですよね。私が学習をしていて結構困ったのがいつどんなアノテーションをつけたらいいのかっていうことに困っていたんですよ。今日はこのDI関連のアノテーションというのが、4種類ぐらいあるんですよね。じゃあそれぞれの種類の意味とかいつつけたらいいのとかそこら辺が結構あいまいでした。

今回、DIのアノテーションについて勉強したので説明していきます。 まずは、DIとアノテーションについての概要を説明してから、4種類それぞれのアノテーションの意味とタイミングを説明する流れで本記事は構成されています。

目次

DIとは?

DIとは英語でDependence Injectionと呼ばれ、日本語訳すると「依存性を注入する」ということです。これをすることでJavaのクラスとクラスを疎結合にすることが出来ます。たとえば、AクラスとBクラスがあったとして、AクラスはBクラスがないと生きていけない(恋愛っぽい)をなくすことが出来るんですよね。クラスとクラスを疎結合にすることが出来る。これがDI(Dependence Injection)のメリットです。

デメリットを上げるとすれば、まあ、慣れるまでは少しめんどくさいってことですね。

アノテーションとは?

アノテーションについての概要は次の通りです。

  • アノテーション=annotation=注釈
  • @hogehogeみたいなやつ
  • 外部のソフトウェアにやってほしいことです

import lombok.Data;

// ここ
@Data
public class Cake {
    private String Name;
    private Integer Number;
}

上の例の場合だと、@Dataを使っています。で、import lombok.Data;が外部のソフトウェアを表していて、lombok.Dataを使いますよー。それをインポートしてきますよーって言っています。これを書くことで、このCakeクラスにgetter, setter, equals(), hashCode(), toString()メソッドを自動で作成してくれます。(lombokが勝手にしてくれます。lombok様様です。)

4種類、DIのアノテーション概要とタイミング

DIとあとはアノテーションについて抑えられたところで、実際にDIのアノテーションについて説明していきます。DDのアノテーションは次の4種類があります。

  • @Component
  • @Controller
  • @Service
  • @Repository

それでそれぞれのアノテーションの意味は次のようになっています。

No アノテーション 意味
1 @Component 特定の役割を持たない。なんでも屋さん。
2 @Controller Webのリスクエストを処理します。例えば、GetやPost等を処理して、このページにデータがPostされたから、この処理していこーみたいな。
3 @Service ビジネスロジック。根幹。本質的なプログラムに付与される
4 @Repository データをやり取りするときに使用される。

とりあえず@Componentつけといて、MVCフレームワーク(Webアプリ開発でよく出てくるやつ)のコントローラーを作成したいときは@Controllerをつけて.

じゃあビジネスロジックとか本当に大切なところ、あんまり変わらないところには@Serviceつけといて、データベースとやり取りするところには@Repositoryをつけておくそんな感覚で大丈夫かと思います。

これらのアノテーションたちをつけておくことでコンピューターに、このクラスはこういう意味で使うよって伝えることができる。裏側でいろいろやってくれているので、便利だし、必要だからつけておきましょう!

参考文献

(編集中)学習記録:Java:C - Airport Code , AtCoder Beginner Contest 349

問題と解説へのリンク

問題 C - Airport Code https://atcoder.jp/contests/abc349/tasks/abc349_c

解説へのリンク

問題のポイントとメモ

  • 正規表現でも求めることが出来る!
  • T の最後の文字が X でない場合, T が S の部分列であるかどうか判定すればよいです.T の最後の文字が X である場合, T の最初の2文字が S の部分列であるかどうか判定すればよいです.

解答例

import java.util.Scanner;

public class Main {
    public static boolean check(String S, String T) {
        int i = 0;
        for (char t : T.toCharArray()) {
            while (i < S.length() && S.charAt(i) != t) {
                i++;
            }
            if (i == S.length()) {
                return false;
            }
            i++;
        }
        return true;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String S = scanner.nextLine().toUpperCase();
        String T = scanner.nextLine();
        scanner.close();

        System.out.println(check(S, T.charAt(T.length() - 1) != 'X' ? T : T.substring(0, T.length() - 1)) ? "Yes" : "No");
    }
}

正規表現バージョン

ChatGPTに変換してもらったがTLEだった。うん。他のコードを参考にするか?C++など。




    
    
  

学習記録:Java:B - Commencement , AtCoder Beginner Contest 349

問題と公式の解答へのリンク

問題 B - Commencement https://atcoder.jp/contests/abc349/tasks/abc349_b

公式の解答へのリンク https://atcoder.jp/contests/abc349/editorial/9778

解答例 自分の

Javaの解答例(自作)

Point

  • 文字が何文字出てきてますかー
  • 1回の繰り返しの文字の種類は、、2回の繰り返しの文字の種類は、、って100回の繰り返しの文字の種類は?ってforループさせます。
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        int sLength = s.length();

        Map<Character, Integer> map = new HashMap<>();

        for (int i = 0; i < sLength; i++) {
            map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);
        }


        for (int i = 1; i <= 101; i++) {
            int count = 0;
            for (Integer num : map.values()) {
                if (num == i) {
                    count ++;
                }
            }

            if (! (count == 0 || count == 2)) {
                System.out.println("No");
                return;
            }
            
        }

        System.out.println("Yes");

        sc.close();
    }
}

公式の解答(Python)をJavaに変換

公式の解答(Python)をJavaに変換

Point

  • アルファベットは26文字
  • char型の'a'は97、'b'は98というように、char型のアルファベットの持つ数値は連続している。

アルファベットを出力するコード

        char c = 'a';
        for (int i = 0; i < 26; i++) {
            System.out.println(c++);
        }

解答例

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String S = scanner.nextLine();
        int[] cnt = new int[26];
// 文字が出てきたら数えている
// 配列のindex=0が1文字目、つまりaを意味している。
        for (char c : S.toCharArray()) {
            cnt[c - 'a']++;
        }

// 1文字連続、2文字連続・・・100文字連続が何種類あるかを数える
        int[] cnt2 = new int[101];
        for (int c : cnt) {
            if (c > 0) {
                cnt2[c]++;
            }
        }

// 判定
        boolean isAllZeroOrTwo = true;
        for (int c : cnt2) {
            if (c != 0 && c != 2) {
                isAllZeroOrTwo = false;
                break;
            }
        }
        System.out.println(isAllZeroOrTwo ? "Yes" : "No");
    }
}

学習記録:Java:A31 - Divisors , 競技プログラミングの鉄則 演習問題集

はじめに

競技プログラミングの鉄則 演習問題集 の A31 - Divisors を解いたので、その備忘録を!

ポイントとミスったポイント

ポイント

  • 包除原理を使う。高校数学で学ぶ集合的なイメージ。重なり合っている部分は重複して数えちゃうから引こうね!ってこと!
  • 3の倍数が何個あるか?という問題だから、普通に3で割った数が3の倍数の個数だよね。
  • 5の倍数も3の倍数と一緒。

ミスったポイント

  • 数え上げちゃった。計算量がバカでかい。O(3N)
    • 正解は4回計算するだけで行けちゃう。
  • long使っていない。intじゃ、小さすぎて正しく表示できないよ。

目次

問題と公式の解答

A31 - Divisors https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_ae

公式の解答へのリンク https://github.com/E869120/kyopro-tessoku/blob/main/codes/java/chap05/answer_A31.java

解答例

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long n = sc.nextLong();

        // 数える用の変数を用意するよー
        // 正直用意しなくてもいいよ。公式見てみて。すっきりしている。
        long threeCnt = 0, fiveCnt = 0, fifteenCnt = 0;

        threeCnt = n / 3;
        fiveCnt = n / 5;
        fifteenCnt = n / (5 * 3);


        System.out.println(threeCnt + fiveCnt - fifteenCnt);
        sc.close();
    }
}

誤った回答例(TLE)

時間超過しちゃうよー。計算量がバカでかいからねー。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long n = sc.nextLong();

        // 数える用の変数を用意するよー
        int threeCnt = 0, fiveCnt = 0, fifteenCnt = 0;

        for (int i = 1; i <= n; i++) {
            if (i % 3 == 0) {
                threeCnt ++;
            }

            if (i % 5 == 0) {
                fiveCnt ++;
            }

            if (i % (3 * 5) == 0) {
                fifteenCnt ++;
            }
        }

        System.out.println(threeCnt + fiveCnt - fifteenCnt);
        sc.close();
    }
}

学習記録:Java:A29 - Power , 競技プログラミングの鉄則 演習問題集

はじめに

Javaで解答例を書いています。自分用のメモです。問題としては、競技プログラミングの鉄則 演習問題集 の A29 - Power という問題です!○○乗を素早く計算するアルゴリズムが使われています!あとは、割り算の余りの性質を使っていますね。

問題のポイントと自分がミスったポイント

問題のポイント

  • ○○乗って分解できますよね。5乗なら1乗と4乗に。高校の時に習った指数法則。

ミスしたポイント

  • if ((b / wari) % 2 == 1)の意味が分からなかった。2のi乗の時に、二進数に直したときに1になっているポイントでanswerに2のi乗を掛け合わせるために用意していたんだなー。

目次

問題と公式の解答例

問題 A29 - Power

A29 - Power , https://atcoder.jp/contests/tessoku-book/tasks/math_and_algorithm_aq

公式の解答例

https://github.com/E869120/kyopro-tessoku/blob/main/codes/java/chap05/answer_A29.java

解答例

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long a = sc.nextLong();
        long b = sc.nextLong();

        System.out.println(Power(a, b, 1000000007));
    }

    static long Power(long a, long b, long m) {

        long p = a;
        long answer = 1;
// n が 30 未満なのは問題の制約から
// 制約に応じて変える必要アリ
        for (int i = 0; i < 30; i++) {
// 計算を2進数で考えよう
            int wari = (1 << i);
// bを2進数で表したとき、1になっているところでpをかけるよ
            if ((b / wari) % 2 == 1) {
                answer = (answer * p) % m;
            }
// pのi乗を計算
            p = (p * p) % m;
        }

        return answer;
    }
}