20210727のJavaに関する記事は5件です。

Spring Bootにおけるページング

本日行うこと テーブルから一覧全件表示を行い、1ページ10件ずつの表示にする。 上限数を超過した分は別ページに出力させるページング機能を実装する 画面イメージ ①画面遷移時(ページ番号1) ②ページ番号2 ③ページ番号3 ページングを実装する際に必要なこと Pageableというページングに必要な情報を管理するインターフェースを利用する コントローラーのメソッドにPageableの引数を指定することで利用できる Pageableを利用することで、画面ごとに表示件数などを指定できる 全てのコントローラーのメソッドでもページングの表示件数を同じにする(10件など)はWebMvcConfigurerインターフェースを実装したクラスを定義する Configurationクラス package jp.co.ttt.employee.config; import java.util.List; import org.springframework.context.annotation.Configuration; import org.springframework.data.domain.PageRequest; import org.springframework.data.web.PageableHandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; // 全てのコントローラーに対して共通処理を行う @Configuration public class EmployeeConfig implements WebMvcConfigurer { // 設定を補完する情報のことをリゾルバ(resolver)と呼ぶ @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { // Pageableに対して設定を行うためのクラスであり、リゾルバ PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver(); // ページ単位に表示する件数を追加(第一引数:ページ番号、第二引数:1ページあたりの表示件数) resolver.setFallbackPageable(PageRequest.of(0, 10)); // 具体的な設定をリゾルバに追加後、リストに追加 argumentResolvers.add(resolver); } } ページングを実装するために コントローラでページ情報付きの検索を行う ビューで検索結果を出力する Controller package jp.co.ttt.employee.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import jp.co.ttt.employee.entity.Employee; import jp.co.ttt.employee.repository.EmployeeRepository; @Controller public class EmployeePagingController { @Autowired EmployeeRepository repository; @RequestMapping("/findAllPaging") // 引数Pageableの中に「ページ番号」、「1ページあたりの表示件数」などの設定情報が含まれる。 // ConfigurationクラスでPageable型の引数に関数情報を設定した場合、それらの設定値が含まれる // ページ番号「0」と1ページあたりの表示件数「10」 public String showEmployeePagingList(Model model, Pageable pageable) { // 従業員情報を検索(ページ情報つきの検索) Page<Employee> pageList = repository.findAll(pageable); // 検索結果を保存するためのリストを用意(レコード情報のみを取得) // ビューに渡す際、Page型の変数をそのまま渡しても実装可能だが、記載が複雑になるのでレコード情報だけを別にわたすことで可読性があがる。 List<Employee> employeeList = pageList.getContent(); // コンソール確認用 for(Employee employee : employeeList) { System.out.println(employee); } // 従業員情報をリクエストスコープに保存 model.addAttribute("pages", pageList); model.addAttribute("employees", employeeList); return "employee/employee_paging_list"; } } ビューの実装 レコード、ページリンクを出力するためのビューを作成する ページリンクはコントローラから渡されたページ情報を基に作成する HTML <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Insert title here</title> <link th:href="@{/css/style.css}" rel="stylesheet"> </head> <body> <div>従業員一覧</div> <table> <tr> <th>従業員番号</th> <th>従業員名</th> <th>部署番号</th> </tr> <tr th:each="employee:${employees}"> <td th:text="${employee.id}"></td> <td th:text="${employee.name}"></td> <td th:text="${employee.deptNo}"></td> </tr> </table> <!-- ページリンク --> <ul class="paging"> <li> <span th:if="${pages.first}">&lt;&lt;</span> <a th:if="${not pages.first}" th:href="@{${url}(page=0)}">&lt;&lt;</a> </li> <!-- 中間のページリンク --> <li th:each="i:${#numbers.sequence(0, pages.totalPages-1)}"> <span th:if="${i}==${pages.number}" th:text="${i+1}"></span> <a th:if="${i}!=${pages.number}" th:href="@{${url}(page=${i})}"> <span th:text="${i+1}"></span> </a> </li> <!-- 末尾のページリンク --> <li> <span th:if="${pages.last}">&gt;&gt;</span> <a th:if="${not pages.last}" th:href="@{${url}(page=(${pages.totalPages-1}))}"> &gt;&gt; </a> </li> </ul> </body> </html> pagesはEmployeePagingControllerで作成された情報の変数名 firstはページ情報が持つフィールド。現在出力されているページが先頭であるか(true or false) "@{${url}(page=0)}"はhttp://localhost:8888/employee/findAllPaging?page=0の意味。page=0が1ページ目 #numbersは数値形式のデータに対する操作を行える。 #numbersのsequence()メソッドで第一引数から第二引数で指定した数値までの連番を配列形式で作成 if文では現在出力されているページ番号と配列の要素の値を比較し、同じならリンクは消して数字のみにする(リンクをつけない) ページ情報で管理されている番号は0からなので、出力する際は+1する必要あり 画面の装飾 リンクの>>や<<の位置などを簡易に位置調整 CSS /** ページリンクのレイアウト **/ .paging { text-align: center; margin: 15px 0; font-size: 1rem; list-style-type: none; } .paging li { display: inline-block; } .paging.current, .paging a { padding: 0 3px; } .paging a { display: block; } ソースコード ふりかえり ページングの設定もPageableを利用すると簡単に設定することができる
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MLflowのProductionのモデルのバージョンの確認方法

記載内容 MLflowで管理しているモデルについて、実行時のログに、バージョン番号も記録したい。 Productionのステージにあるモデルのバージョン番号の確認方法を調査する。 MLflowのProductionのモデルのバージョンの確認方法 REST APIで実行したら、レスポンスヘッダーにモデルバージョン番号が入ってないかな、 モデルをロードした場合は、そのモデルがバージョン番号持ってないかな、 と期待したのですが、ありませんでした。 MLflowに対して、モデル名でModelVersionを検索して、ステージがProductionのモデルのバージョン番号を確認する必要があるようです。 REST APIで確認する方法 Search ModelVersionsが使えます。 mlflow document > Search ModelVersions リクエストデータのfilterに、"name='my-model-name'"といったように、モデル名を絞り込み条件に入れてリクエストすると、[ModelVersion]の配列が返ってきます。current_stageがProductionのModelVersionのバージョン番号を確認します。 残念ながら、ステージでの絞り込みは現状対応していないようです。 String filter condition, like “name=’my-model-name’”. Must be a single boolean condition, with string values wrapped in single quotes. Python APIで確認する方法 mlflow.tracking.MlflowClient.search_model_versionsが使えます。 mlflow document > mlflow.tracking.MlflowClient.search_model_versions REST APIと同じ要領です。メソッドの引数に、"name='my-model-name'"と入れて実行します。 filter_string – A filter string expression. Currently, it supports a single filter condition either a name of model like name = 'model_name' or run_id = '...'.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】APIでGoogleカレンダーの予定登録+取得+更新

虎の穴ラボのH.Hです。 Googleカレンダーに自動で予定を登録取得更新するプログラムを作ったので、手順をまとめました。 1.準備 1.1 APIの有効化する 1.1.1 GoogleCoudPlatformにアクセスする 下記のURLにアクセスする https://console.cloud.google.com/ 1.1.2 初回アクセスした際には利用規約に同意する 1.1.3 APIを画面上部の検索枠で検索する 「CalendarAPI」と検索すると「Google Calendar API」が見つかる 1.1.4 APIを有効にする 「Google Calendar API」のリンクをクリックするとAPIの詳細画面に遷移するので「有効にするボタン」をおす 1.2 認証情報の設定 1.2.1 認証情報を作成するプロジェクトを作成する 初回の場合は「My First Project」が作成されている。そのままでも問題はありません。(専用のプロジェクトを作成しても良い) 1.2.2 プロジェクトのダッシュボードを開く プロジェクトの設定に移動する 1.2.3 メニューからサービスアカウントを選択 1.2.4 サービスアカウントの作成 サービスアカウント名は任意の値で問題はありません。 プロジェクトへのアクセスの許可などは不要です。 完了すると以下のような画面になります。 1.2.5 操作の中から「鍵を管理」を選択する 選択すると下のような画面になります。 1.2.6 鍵を追加から「新しい鍵を生成」する キーのタイプはJSONを選択する。成功するとjsonファイルがダウンロードされる。 1.3 連携するGoogleカレンダーの設定 1.3.1 今回は新しいカレンダーを作る。 1.3.2 設定から「特定のユーザーとの共有」にユーザーを追加する 追加するユーザーは「サービスアカウントの作成」の画面に表示されたメールアドレスを入力し、権限は「変更及び共有の管理権限」に変更する。 設定はここまでです。 2.プログラム 2.1 jarファイルの取得 認証部分のライブラリーはカレンダーAPI用など様々なライブラリーが必要です。 今回使用したライブラリーは以下の場所やファイルです。 1)api-client-library https://developers.google.com/api-client-library/java/google-api-java-client/download 2)認証関連のライブラリ appengine-api-1.0-sdk-1.9.88.jar google-auth-library-appengine-0.25.3.jar google-auth-library-credentials-0.25.3.jar google-auth-library-oauth2-http-0.25.3.jar 3)Googleカレンダーのライブラリ google-api-services-calendar-v3-rev411-1.25.0.jar 2.2 登録 認証を行い予定情報作成し、登録を行う。 例) 2021/4/17 15:00~15:10の予定の登録 final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); Credentials credentials =AppEngineCredentials.fromStream(new FileInputStream(jsonファイルのパス)) .createScoped(Collections.singleton(CalendarScopes.CALENDAR_EVENTS)); Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JacksonFactory.getDefaultInstance(), new HttpCredentialsAdapter(credentials)) .setApplicationName(任意の文字列) .build(); EventDateTime startEventDateTime = new EventDateTime().setDateTime(new DateTime("2021-04-17T15:00:00.000+09:00")); // イベント開始日時 EventDateTime endEventDateTime = new EventDateTime().setDateTime(new DateTime("2021-04-17T15:10:00.000+09:00")); // イベント終了日時 String summary = "タイトル"; String description = "詳細"; Event event = new Event() .setSummary(summary) .setDescription(description) .setStart(startEventDateTime) .setEnd(endEventDateTime); event = service.events().insert("XXXXXXXXXXXXXXXXXXXXX@group.calendar.google.com", event).execute(); //カレンダーの設定画面にあるカレンダーIDをいれる 終日の予定の登録はイベント開始と終了日時を以下のように設定します。 EventDateTime startEventDateTime = new EventDateTime().setDate(new DateTime("2021-04-17")); // イベント開始日時 EventDateTime endEventDateTime = new EventDateTime().setDate(new DateTime("2021-04-17")); // イベント終了日時 2.3 取得 予定の取得する。 基本は下記の処理で取得できる。 final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); Credentials credentials =AppEngineCredentials.fromStream(new FileInputStream(jsonファイルのパス)) .createScoped(Collections.singleton(CalendarScopes.CALENDAR_EVENTS)); Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JacksonFactory.getDefaultInstance(), new HttpCredentialsAdapter(credentials)) .setApplicationName(任意の文字列) .build(); Events events = service.events().list("XXXXXXXXXXXXXXXXXXXXX@group.calendar.google.com").execute(); 期間指定する場合(以下の例は4/17~4/18の予定の取得)は以下の通り Events events=service.events().list("XXXXXXXXXXXXXXXXXXXXX@group.calendar.google.com") .setTimeMax(new DateTime("2021-04-18T00:00:00.000+09:00")) .setTimeMin(new DateTime("2021-04-17T00:00:00.000+09:00")).execute(); 2.4 更新 予定の更新は予定個別に設定されるeventIDを指定してAPIを実行する。 以下の例はタイトルの変更した場合 final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); Credentials credential =AppEngineCredentials.fromStream(new FileInputStream(jsonファイルのパス)) .createScoped(Collections.singleton(CalendarScopes.CALENDAR_EVENTS)); Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JacksonFactory.getDefaultInstance(), new HttpCredentialsAdapter(credential)) .setApplicationName(任意の文字列) .build(); Event event=null; //イベントの登録や検索から更新するEventを取得する event.setSummary("更新後タイトル"); event = service.events().update("XXXXXXXXXXXXXXXXXXXXX@group.calendar.google.com",event.getId(), event).execute(); 注意点 作成するにあたり以下の点に気をつける必要があります。 1)タイムゾーンの指定が必要になる 予定登録の際に「+09:00」を付けないと、カレンダーが日本時間の設定だとしても時間がずれて登録されます。 2)取得された予定の順序が決まっていない 予定の取得にはorderByの変数の指定をしないと、順序は確定されません。 今回は特定期間の予定の取得を行っただけなので設定はしませんでした。 3)認証に使用するクラスの非推奨化 過去のバージョンで使用されていた認証部分のクラスが最新のライブラリでは非推奨になっていました。非推奨のクラスでも認証は可能ですが、今後のことを考えると推奨されているクラスで実装が必要だと思います。 クラス名 非推奨 GoogleCredential 推奨 AppEngineCredentials
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エラー:この文字は、エンコーディングMS932にマップできません

メモ程度に。 IntelliJ IDEAを使っている人向け。 UTF-8でエンコードされていないのが原因 下記をConfigrationに追加すると解決する javac -encoding utf-8
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

独習Java新版まとめ(第2章)

2-1 変数 変数を複数宣言するときは原則として1つ1つ個別の文として宣言 変数はCamelCaseで戦闘箱文字にしてそれ以降は大文字スタートだが、クラスはPascal記法で頭から大文字 定数の宣言 final データ型 定数名 = 値 2-2 データ型 データ型は基本型と参照型に分けることができる Javaの基本型はbyte/short/int/long/float/double/boolean/charのみ また数値を示すときは基本的にint型を採用 浮動小数点も目メモリに特に制限がない限りはdoubleを使用 booleanはfalseを0やtrueを1などをみなすことはできない Java10以降ではvarキーワードを使用することで変数を宣言するときにデータ型を省略できる varは初期値から型推論をするのでいきなり使うことはできない 2-3 リテラル リテラルとはデータ格納できる値そのもの、また、値の表現方法 浮動小数点リテラルは<仮数部>10符号<指数部> データ型が勝手に決められて困る場合にはlomgの時はLでfloatはFでdoubleはDを用いる 2-4 型変換 狭い方から広い方に変更するのはOkだが、逆はだめ 型キャストは(データ型)変数 2-5 参照型 Javaの参照型はクラス型/インターフェイス型/配列型と分別できる newキーワード クラス名 変数名 = new クラス名(引数....) メゾットはインスタンスを作成して.メゾット名(引数) 参照型はオブジェクトが参照の値を持たない状態 配列の宣言はデータ型[] 配列名 = {要素1, 要素2....} 要素の追加等はできない 多次元配列はデータ型[][]配列名 = new データ型[要素数1][要素数2] しかし長さがそろわないときもあるのでその際にはどちらかだけ固定してその行ごとに後で指定していく var list = new int[3][]; list[0] = new int[2];のように また、この時宣言する数は要素数なので注意が必要
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む