- 投稿日:2020-11-18T23:56:34+09:00
Springを使ってトークンをイントロスぺクトしてみる
Oauth2のClient Credentials Grantという認証方法があります
サーバー間の通信を行い、また認証したい場合に基本的にUIがないので、
Client Credentials Grant方式で認証を行うケースが多いです。
例えばリソースサーバーと認証サーバーが分離している場合に、
リソースサーバーは認証サーバーに問い合わせ、トークンの有効性を確認する必要があります。
今回はこのトークンの有効性を確認する
という行為をどうやって実現できるかについて紹介します。1 RFC7662
実は、
トークンの有効性を確認する
の規定はすでにRFC7662で定義されています。
有効性をチェックするときのエンドポイントは/introspect
になります。
いくつかの概念について紹介します1.1 introspect request
リソースサーバーが認証サーバーにイントロスぺクトする際に必要な情報。
項目 値 HTTPメソッド POST Content-Type application/x-www-form-urlencoded Authorization リソースサーバー自身の身分(BearerやBasicなど) Request Body token=xxx, token_type_hint=yyy イントロスぺクトしたいトークンはリクエストボディに入れます。
1.2 introspect response
認証サーバーはリクエストを受け付け、確認結果を返します。
1.2.1 response body
レスポンスボディの各項目について軽く説明します。
項目 説明 active 必須。もしトークンが有効の場合にtrue scope トークンが利用できるスコープ。https://tools.ietf.org/pdf/rfc6749.pdfのSection 3.3を参照 client_id クライアントIDがある場合のみ username 人間が読める名前 token_type トークンの種類。https://tools.ietf.org/pdf/rfc6749.pdfのSection 7.1を参照 exp トークンのエクスパイアの日時 iat トークンの発行の日時 nbf トークンがこの時間前に利用できない sub トークンの利用目的 aud トークンの利用対象 iss トークンの発行者 jti トークンのユニークID 基本的にJWT自体の定義が多いので、
もっと知りたい方はIDトークンが分かれば OpenID Connect が分かるを読んでください。
1.2.2 エラー処理
もしリソースサーバー自身が提供している認証情報が不正の場合に401を返します。
イントロスぺクト対象のトークンが不正の場合には401ではなく、レスポンスボディのactiveをfalseに設定するのでご注意ください。2 oktaでAuthサーバーを使ってみる
Spring-bootで認証サーバーを実装したいですが、
Spring-bootの認証サーバープロジェクトは非推奨になったので今回は紹介しません。
また、Springチームは新しい認証サーバーのプロジェクトを実装しているので、
まだ実験プロジェクトとしてインキュベート中です。
興味ある方はご確認ください。
今回は自分で実装する代わりにoktaを利用して認証サーバーを立ち上げます。
まず事前準備としてoktaのアカウントを自分で登録してください。2.1 Application作成
アカウント登録後ログインします。
Add Application
で新しいアプリケーションを作成します。作成後に
Client ID
とClient secret
を確認できます。後でこれらを使います。2.2 APIの設定
ヘッダーのAPI > Authorization Serversをクリックします。今回はdefaultを使います。
スコープタブで新しいスコープを作成します。任意で大丈夫です。
2.3 tokenを発行します
ここまでは準備作業が終わったので、実際にトークンを発行してみます。私はpostmanを使っています。
↑は利用例です。各項目について説明します。
項目 説明 URL Authorization ServersタブでIssuer URIを確認できると思います。
${Issuer URI}/v1/tokenは今回利用するURLですgrant_type アプリケーション作成時にマシンツーマシンを選択したので、ここは client_credentials
になりますclient_id アプリケーションのGeneralタブで確認できます client_secret アプリケーションのGeneralタブで確認できます application_type service scope スコープタブで追加したスコープ レスポンスボディの
access_token
は発行されたトークンになります。
これからこのトークンをイントロスぺクトします。2.4 introspectを検証
後でSpringを実装してintrospectを検証しますが、とりあえずpostmanで軽く検証します。
これで先ほど発行されたトークンは有効であることを確認できました。
3 Springで実装する
本題に入りますが、https://start.spring.io/にて新しいプロジェクトをダウンロードします。
3.1 初期化する
必要なdependencyを追加します。
- Spring Web
- Spring Security
- Oauth2 Resource Server
3.2 Authに関する設定
package com.demo.security.config; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer; @EnableWebSecurity public class AuthConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests( ar -> ar.antMatchers("/hello").authenticated()) .oauth2ResourceServer(OAuth2ResourceServerConfigurer::opaqueToken); } }3.3 シンプルなコントローラ―
package com.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello World"; } }3.4 application.yml
spring: security: oauth2: resourceserver: opaquetoken: introspection-uri: https://dev-7571110.okta.com/oauth2/default/v1/introspect client-id: 0oa13xsm1CsN8v6uq5d6 client-secret: ****************************3.5 pom.xml
下記のdependencyを追加します。
<dependency> <groupId>com.nimbusds</groupId> <artifactId>oauth2-oidc-sdk</artifactId> </dependency>3.6 検証
まずSpring-bootを起動します。
$ mvn spring-boot:run
正しくトークンを指定する場合にアクセスできます。
また、トークンが不正の場合に401を返します。参考
https://developer.okta.com/
https://github.com/spring-projects/spring-security
https://tools.ietf.org/html/rfc7662
https://oauth.net/2/grant-types/client-credentials/
https://qiita.com/TakahikoKawasaki/items/8f0e422c7edd2d220e06
- 投稿日:2020-11-18T21:42:35+09:00
Effective Java 項目1 「コンストラクタの代わりにstaticファクトリメソッドを検討する」
自分用メモなので雑です。
コンストラクタはこういうの
public Human
の部分
(フィールド持たない場合は、何も書かなくてもデフォルトのコンストラクタが生成される)class Human { String name; public Human(String name) { this.name = name; } }コンストラクタを呼ぶ = クラスのインスタンスを生成しても取得する
Human human = new Human("yamada");staticファクトリメソッドを用意してコンストラクタからはHumanを生成できないようにするとこうなる
class Human { String name; // クライアントが、createHumanからしかHumanを作れないようコンストラクタはprivateにしている。 private Human(String name) { this.name = name; } // staticなファクトリメソッド static Human createHuman(String name) { return new Human(name); } }(コンストラクタではなく、)staticファクトリメソッドを使わせるメリット
- 1 名前がわかりやすい
- 2 呼び出しごとに新たなオブジェクトを作らなくて済むようになる 呼び出しによって作られるオブジェクトの数なども簡単にコントロールできるようになる。シングルトンパターンがその一例。
public class RegisterNote { private static RegisterNote registerNote = new RegisterNote(); private RegisterNote(){} public static RegisterNote getInstance() { return registerNote; } }上の例では、RegisterNoteがたった一つしか存在しえないことを保証している。
- 3 返す型を柔軟に選べる
例えば、
java.util.Collections
はCollection型のオブジェクトを返すファクトリメソッドがたくさん入っている。public static final <T> List<T> emptyList() { return (List<T>) EMPTY_LIST; }このemptyList()が返しているEMPTY_LISTは
EmptyList<E>
というクラスで、
EmptyListは抽象クラスAbstractListを継承し、AbstractListはインターフェースListを実装し、ListはインターフェースCollectionを拡張したものである。
慣習として、Hogeという名前のインターフェースのstaticファクトリメソッドはHogesというシングルトンのクラスに入れる。
(個人的に、これでライブラリの命名の規則についてかなり合点がいった。sついてるのとついてないのなんだろうって思ってたので)でもあまり他の例が思いつかない、、、
- 4 引数によって、返すオブジェクトの型を自由に決められる。 例
EnumSet
クラスenum型が64個以下で構成されている場合は、RegularEnumSetInstanceを返し、64個を超える場合は、JumboEnumSetを返す。
これはパフォーマンス上を考えてこうなっているだけで、特にクライアントには知ってほしくない。混乱を招くだけなので。
なので、staticファクトリメソッドの戻り値の型は単にEnumSetで、使う側は自分が作ったのがRegularEnumSetInstanceなのかそれともJumboEnumSetなのかを全く考えず、EnumSetに用意されたAPIを利用すればよい。public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) { Enum<?>[] universe = getUniverse(elementType); if (universe == null) throw new ClassCastException(elementType + " not an enum"); if (universe.length <= 64) return new RegularEnumSet<>(elementType, universe); else return new JumboEnumSet<>(elementType, universe); }
- 5 返されるオブジェクトのクラスは、staticファクトリメソッドを書いている時点で存在する必要さえない ちょっとよくわからなかった。Service Provider Interfaceについてちょっとドキュメント読んだが、なかなか難しい。 ただ、「リフレクションを使わずに」、とあるので、まだ宣言していないクラスも返すようにすることができる的なことだろう() そういう意味では4を拡大したような話だと思う。たぶん。 java.util.spi.CurrencyNameProviderについてちょっと見たが、おそらく通貨単位の略称("JPY", "USD"など)をもとに、円マークやドル記号をStringとして返してくれるようなサービス(を作るのに?)使われている?あまりわかっていないが、、
staticファクトリメソッドを使うことによって生まれる制約
- 1 コンストラクタがprivateだと、サブクラスが作れない
例: 下記は当然コンパイルエラーとなる。
interface Writable { void write(String txt); } class Paper implements Writable{ private Paper() { new Paper(); } public static Paper createPaper() { return new Paper(); } @Override public void write(String txt) { System.out.println("write to Paper."); } } class RichPaper extends Paper implements Writable { public RichPaper() { super(); // 親クラスPaperのコンストラクタはprivateなので、コンパイルエラーとなる } }しかし、これにより、継承よりもコンポジション(親クラスへの委譲によってメソッドを実装すること)を促すことのになるので、これはこれでよいとのこと。
(全然いい感じの例が思いつかなかった)class RichPaper implements Writable{ private Paper paper; private RichPaper() {} RichPaper createRichPaper() { return new RichPaper(); } @Override public void write(String txt) { paper.write(txt); } }
- 2 staticファクトリメソッドだと、探すのが大変 確かに、これは自分も経験がある。とりあえずこのクラスを作りたい!っていうときに、コンストラクタがprivateで、「じゃあどこから作ればいいんだよ」とイラつく。
しかし、staticファクトリメソッドの一般的な命名規則を把握すればあんまり苦労しないかもなと思った。
下記のメソッドのニュアンスの違いは、本に載ってるので省略。from of valueOf instance getInstance create newInstance // ここからは、クラス名がHogeの場合 getHoge newHoge hogeまとめ
それぞれのメリット、デメリットを意識して使い分ける。「staticファクトリメソッドにしたらどうかな?」と検討してみる。
- 投稿日:2020-11-18T20:45:13+09:00
社内業務のシステムをWebで作ろう!
投稿の動機
@NP_Systemsさんの 製造業において、Pythonに加えてWebも活用して飛躍しよう の記事を見て正にキャッチ‐な話題でしたので、社内での活動状況を投稿しようと思いました。現在私は定年後の再就職先として広島市内の名盤製造業に嘱託として勤めています。仕事内容は社内業務システム「業務支援・改」の構築・保守です。
何故Webなのか
今のシステムは経理・給与・販売管理(移行開発中)を除く、製造業務のほぼ全般をWebシステムで運用しています。巷では業務システムはクライアント・サーバータイプ(VB, VC, Java 等)で作られているみたいですが、かなり早い段階からWebで開発している身としては、楽なのに何故Webで開発しないのかが不思議でした。実際WebでVBよりも高速な伝票入力画面を作ることができます。現役時代に納品したシステムはOSのバージョンアップを行っても問題無く使えていますし、カーソル移動も[Enter]キーで[tabIndex]順に移動できます。端末へのインストールも不要で遠地の端末が壊れても簡単に機器の入れ替えができます。ハードを更改してもシステムを更改する必要が無いのです。環境に依存しないので製造現場ではiPadで運用している部署も有ります。一度作ったシステムを要件が変わらないのに再度開発するのは、資産が残らないという意味で馬鹿らしいと感じています。
実運用画面のサンプル
実際に現場でどんな画面を使っているのかを見てみましょう。
■ 出荷計上一覧(出荷予定・実績の一覧)
■ 出荷計上保守(俗に言う売上伝票、在庫出納と連動)
■ 納品書 先頭ページ (PDF出力)
■ 納品書 最終ページ (PDF出力)
■ 物品受領書 (PDF出力)
■ 品目保守(製品の材料・工程と工数、他各種情報)
■ 生産予定作成(生産オーダーより生産予定を作成)
■ 生産状況一覧(生産ロットの進捗状況を把握)
■ 生産日程(カレンダー上で予定と進捗を確認)
挙げれば切が無いのでこれぐらいにしておきますが、これらはたった一人で設計・施工・導入したものです。意外とWebシステムって簡単に作れるので皆さんもWebで開発する事を強くお勧めします。開発環境
全てオープンソースです。Java8 (pdfBox), JavaScript, Tomcat9, mariaDB10, JQuery (ほんのチョットだけ), それと検索時に照合が出来ない事が有るので、入力時にANKは半角、カタカナは全角、濁音・半濁音は1文字に合成しています。殆どが手作りなので、皆さんも安価にリーズナブルなシステムを構築できる事請け合いです。生産計画作成画面はJavaScroptでコメントを入れて1,200行強位です。今日嵌って対応していた見積積算画面は少し凝っていて2,200行強でした (共通ライブラリ除く)。意外と手軽だと思いませんか。
まとめ
実は自分の周りに同じ様な事をしている人がいないので、最近疎外感を感じていたところでした。この投稿を切っ掛けにして多くの人にWebで業務システムを開発して貰いたいと思っています。本も買ったけどネットに転がっている情報でプログラムを作れているので、Webによる業務アプリケーション開発は決して敷居の高いものでは無いのです。みんなでWeb開発をやりましよう!
- 投稿日:2020-11-18T17:21:01+09:00
javaのラムダ式について理解する[入門]
普段から何気なくラムダ 式記法を使って実装をしていますが、ラムダとはそもそも、どういう仕組みになっているのか改めて調べてみました〜。
Javaのラムダ式とは
Javaのラムダ式とは、ざっくり言ってしまうと、
メソッドが1つしかないインターフェイスを簡単に実装するための記法
です。色々記述を省略した結果として、ラムダ記法が生まれているので、
本来、ラムダ式を使わずに書くとしたらどうなるのか?というところから説明を始めます。サンプル1
CalculatorInterface.javapublic interface CalculatorInterface { public int calculate(int a, int b); }MultiplyCalculator.javapublic class MultiplyCalculator implements CalculatorInterface { @Override public int calculate(int a, int b) { return a * b; } }Main.javapublic class Main { public static void main(String[] args) { CalculatorInterface multiplyCalculator = new MultiplyCalculator(); int result = multiplyCalculator.calculate(2, 5); System.out.println(result); // 10が表示 } }掛け算を行うメソッドを持つ
MultiplyCalculator
クラスがCalculatorInterface
を実装する形です。これは基本的な形ですね!!ただ、実はわざわざ
MultiplyCalculator
クラスを作らずに実装する方法があります。それが次のサンプル2です。
サンプル2
CalculatorInterface.javapackage sample2; public interface CalculatorInterface { public int calculate(int a, int b); }Main.javapackage sample2; public class Main { public static void main(String[] args) { CalculatorInterface multiplyCalculator = new CalculatorInterface() { @Override public int calculate(int a, int b) { return a * b; } }; int result = multiplyCalculator.calculate(2, 5); System.out.println(result); // 10が表示 } }
MultiplyCalculator
クラスを作らず、mainメソッド内で上記のように書くことで実装できます。CalculatorInterface multiplyCalculator = new CalculatorInterface() { @Override public int calculate(int a, int b) { return a * b; } };この部分ですが、これは
CalculatorInterface
をimplementsする無名クラス(名前を持たないクラス)を生成し、その場でメソッドの実装を行っている形となります。でも、実はもっと簡単に書けるんです、、!それが次のサンプル3になります。
サンプル3
CalculatorInterface.javapackage sample3; public interface CalculatorInterface { public int calculate(int a, int b); }Main.javapackage sample3; public class Main { public static void main(String[] args) { CalculatorInterface multiplyCalculator = (a, b) -> {return a * b;}; int result = multiplyCalculator.calculate(2, 5); // returnだけなら、{}も省略できます CalculatorInterface multiplyCalculator2 = (a, b) -> a * b; int result2 = multiplyCalculator2.calculate(3, 4); System.out.println(result); // 10が表示 System.out.println(result2); // 12が表示 } }もっとすっきりしましたね!
CalculatorInterface
はメソッドが1つしかないので、どのメソッドをオーバーライドするのかが明白です。そんな場合、下記のような形で簡単にメソッドの実装内容を記述することができます。CalculatorInterface multiplyCalculator2 = (a, b) -> a * b;これがいわゆるラムダ式というやつです。こんな感じで、記法の省略を重ねるとラムダ式に達するんですね〜!
説明はこれで終わりです。
分かりにくいところあればコメントください〜
- 投稿日:2020-11-18T14:18:44+09:00
【Java】配列について
配列
勉強のメモとして、配列について学んだことをメモります。
配列とは
プログラミング言語には、「いくつかの関係のあるデータをグループにして、まとめて1つの変数として扱う」仕組みががあり、それを配列と呼ぶ。
配列操作
配列にはその変数が保持する特定の値や値全体に対して行える機能があり、
- 取り出し
- 書き換え
- 削除
これらを総称して「配列操作」と呼ぶ。
配列の作り方
書き方
結論からいうと配列の作り方は以下です。
要素の型[] 配列変数名 = new 要素の型[要素数];なぜそういう書き方になるかというと、配列を作るためには、
配列の宣言
、要素の代入
の2つ手順が必要です。
例として得点という意味の「score」を配列変数名にして配列を宣言する場合はこうなります。int[] = score; score = new int[100];1. 配列の宣言
配列の宣言の仕方はこちら。
要素の型[] = 配列変数名;scoreという配列を宣言するとこうなります。
int[] = score;2. 要素の代入
要素の代入の仕方はこちら
配列変数名 = new 要素の型[要素数]要素数の部分は、たとえばポケモン(初代)だったら151、学校のテストで五教科の得点を入れたい場合は5がはいるといえばわかりやすいかもです。
scoreという配列に「5」という要素を代入するとこうなりますscore = new int[5];【つまり配列はこう書く】 一連の流れを短く書く
丁寧な書き方(手順を分けた書き方)をすると上記のような形になるが、これらをひとまとめにして書くことでコードがスッキリする。
とりあえず「配列の書き方はこう書く」というのだけ叩き込んでおけばオッケーです。要素の型[] 配列変数名 = new 要素の型[要素数];scoreを短く書いてみます。
int[] score = new int[5];初期化
変数の値を取り出すには、必ずまず初期化を行う必要があり、値を代入して初期化していないとエラーが発生してしまいます。
まずは配列の宣言同様、手順を分けた長い書き方をするとこうなります。
int[] score = new int[5]; //配列scoreの宣言 score[0] = 80; // 1番目(先頭)の要素に 80 を代入 score[1] = 90; // 2番目の要素に 90 を代入 score[2] = 100; // 3番目の要素に 100 を代入 score[3] = 85; // 4番目の要素に 85 を代入 score[4] = 90; // 5番目の要素に 90 を代入【つまり配列はこう書く】 宣言と初期化を同時に行う
それでは上記のスッキリした書き方をしてみましょう。
以下は要素の数が 3つの場合の配列の宣言と初期化の方法です。要素の型[] 配列変数名 = {値, 値, 値};80、90、100、85、90 の要素の値(初期値)とする、要素数が 5 の score という名前のint型配列を宣言する場合はこうなります。
int[] score = {80, 90, 100, 85, 90};length
Javaの配列におけるlength
Javaの配列には
length
という、その配列の要素数を調べることができる いうフィールド(情報)があります。
length
を使用することにより、プログラマが配列の要素数を別の変数に保持するなどの管理をする必要がなくなるため、配列がとても利用しやすくなる。length 値の参照方法
下記のように配列の変数に対してドット「.」で繋いで記述します。
配列変数.lengthこちらを用いてscoreの要素の数を調べてみたいと思います。
int[] score = {80, 90, 100, 85, 90}; System.out.println(score.length);【インデックス】 配列の各要素の参照・更新
インデックスの指定の仕方
配列名の直後に[ ] をつけ、インデックス(添字)と呼ばれる数字を指定することで、要素の参照や更新をすることが出来ます。
※ 当然ながら、インデックスも0から順番に数えます。配列変数[数字(インデックス)]下記はscore配列の3番めの要素を引っ張り出すときの例です。
int[] score = {80, 90, 100, 85, 90}; System.out.println(score[2]);配列の全要素を表示する(for文を使用)
配列に入ってる要素をすべて出力してみます。
この書き方だと、「0〜score配列の要素数だけ1つずつ出力する」というというのをfor文を使って書いています。要素のインデックス番号をすべて抽出
下記は要素のインデックス番号をすべて抽出する場合です。
int[] score = {80, 90, 100, 85, 90}; // インデックス番号をすべて表示 for (int i = 0; i < score.length; i++) { System.out.println(i); }配列の中の要素の値をすべて抽出
下記は配列の中の要素の値をすべて抽出する場合です。
int[] score = {80, 90, 100, 85, 90}; // 要素の値をすべて表示 for (int i = 0; i < score.length; i++) { System.out.println(score[i]); }合計点を求めるプログラム
すべてのscoreを合計して出力するプログラムを書きました。
処理の流れは..
- int[]型の変数scoreの宣言と初期化
- 合計スコアを宣言し、0で初期化する
- scoreの要素数だけ計算をおこなう
- 計算された得点を表示する
という流れになります。
// int[]型の変数scoreの宣言と初期化 int[] score = {80, 90, 100, 85, 90}; // 合計スコアを宣言し、0で初期化する int sum = 0; //scoreの要素数だけ計算をおこなう for (int i = 0; i < score.length; i++) { sum = sum + score[i]; } //計算された得点を表示する System.out.println(sum);for文の内容は実質、
80 + 90 + 100 + 85 + 90
を行ったということなので、出力結果は上記のようになりました。
- 投稿日:2020-11-18T13:29:31+09:00
Spring開発環境構築 For Mac
はじめに
Springの開発環境の構築方法をまとめました。
流れは以下になります。①STSのインストール
②Pleiadesのインストール
③LombokのインストールSTS(Spring Tool Suite 4)のインストール
STSダウンロードサイトにアクセスします。
Spring Tools 4 for Eclipseの欄から「4.8.0-MACOS 64-BIT」をクリックしてください。
※バージョンは2020年10月時点で最新の4.8.0を利用します。
するとSTSが入ったzipファイルのダウンロードが始まります。
ダウンロードしたzipファイルを解凍します。
以下の画面が表示されたらSpringToolSuite4.appをApplicationsファイルにドラッグアンドドロップしてください。
以上でインストール完了です。Pleiadesのインストール
STSに日本語化プラグインを入れます。
Pleiadesダウンロードサイトにアクセスします。
Pleiades プラグイン・ダウンロードからMacOSをクリックし、Preparing to download Eclipse Pleiades pluginの下のリンクからzipファイルをダウンロードします。
zipファイルを解凍し、setup.appを起動(クリック)します。
※「“setup.app”は、開発元を検証できないため開けません。」とエラーが出た場合は以下の記事を参照してみてください。
https://github.com/ko-ichi-h/khcoder/issues/100
以下の画面が表示されたら「選択」をクリックしてアプリケーションファイルに移したSTSを選択します。
「日本語化する」をクリックします。
以上でインストール完了です。Lombokのインストール
Lombokとは、setterやgetterを自動的に実装してくれる便利ツールです。
現場でよく使われるらしいので、入れておきましょう。
Lombokダウンロードサイトにアクセスします。
ダウンロードしたlombok.jarを/Applications/SpringToolSuite4.app/Contents/MacOSにコピーします。
lombok.jarを起動し、Specify location...をクリックします。
/Applications/SpringToolSuite4.app/Contents/Eclipse/にあるSpringToolSuite4.iniを選択します。
「install/Update」「Quit Installer」と順にクリックします。
インストールが完了すると、STSのフォルダ内にlombokが入ります。
以上でインストール完了です。
- 投稿日:2020-11-18T12:39:10+09:00
【Java】GUIの開発フレームワーク
プログラミング勉強日記
2020年11月18日
swingを使っているが、他にGUIのフレームワークがないか気になったのでまとめる。GUIとは
Graphical User Interfaceの頭文字をとったもので、操作対象が画像や図形などで、キーボードからの入力やマウスのクリックといった直感的にコンピュータを操作できる。
コマンドプロンプトを使ってjavacやjavaのコマンドでコンパイルや実行するのをCUIといい、CUIの場合はコマンドを覚える必要があるが、GUIの場合はコマンドを知らなくても画像や図形を使うことで直感的に操作できる。GUIはEclipseといった統合開発環境(IDE)を使って開発する。(統合開発環境(IDE)についてはこちらの記事で扱った)GUIのフレームワーク
GUIを開発するためにはフレームワークを使用する。
AWT
AWTはAbstract Window Toolkitの頭文字をとったもので、Java 1.0のころから使用されているGUIフレームワーク。ボタンなどの部品はウィンドウシステムのネイティブ部品が使われているので、Windows上ではネイティブなWindowsアプリと似ていて、Mac上ではネイティブなMacintoshに似ていて、OSに依存する。
JavaFX
JavaFXはJava8以降でJava SEの標準GUIフレームワークで、FMXLと呼ばれるXMLとCSSを併用してデザインを記述し、デザイン処理と処理クラスの記述を分離できる。
Swing
Javaで書かれたGUIのフレームワークで、どのOSで動かしても見栄えが同じになる。AWTに起因する限界もあって、Java8以降はJavaFXに置き換えられている。
参考文献
- 投稿日:2020-11-18T08:26:40+09:00
26進数シーケンス作成
package practice; import java.io.FileWriter; import java.io.IOException; public class ChipIdCreate { static char[] hexList = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; static String str = "AAA"; public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ try{ FileWriter fileWriter = new FileWriter("chipID.csv"); fileWriter = create(fileWriter); fileWriter.flush(); fileWriter.close(); }catch(IOException ex) { ex.printStackTrace(); }catch(Exception ex) { ex.printStackTrace(); } } public static FileWriter create(FileWriter fileWriter) throws IOException{ // int kurai = str.length(); StringBuilder sb = new StringBuilder(str); for(int i1 = 0; i1 <=25; i1++) { // if(i1 != 0) { sb.setCharAt(0,hexList[i1]); // } for(int i2 =0; i2<=25; i2++) { // if(i2 != 0) { sb.setCharAt(1,hexList[i2]); // } for(int i3=0; i3<=25; i3++) { sb.setCharAt(2,hexList[i3]); System.out.println(sb); fileWriter.append(sb); fileWriter.append("\r\n"); } } } return fileWriter; } }package practice; import java.io.FileWriter; import java.io.IOException; import java.util.*; public class HexTestCreate { static String[] hexList = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; static String hexStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static void main(String[] args) { Scanner sc = new Scanner(System.in); String str = sc.nextLine(); sc.close(); int number = Integer.parseInt(str); // convert10(str); try{ FileWriter fileWriter = new FileWriter("hex.csv"); for(int i =1;i<=number;i++) { convert(i,fileWriter); } try { fileWriter.flush(); fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } }catch(IOException ex) { ex.printStackTrace(); } } static FileWriter convert(int number,FileWriter fileWriter) { int[] outDat = new int[10]; for(int i = 0; i<10 ; i++) { outDat[i] = -1; } int index = 0; double data = 0; while(true) { data = Math.floor(number /26); outDat[index] = number % 26; if(data == 0) { break; } number = (int) data; index++; } String outStr = ""; for(int ii = index; ii>=0; ii--) { outStr += hexList[outDat[ii]]; } System.out.println(outStr); try { fileWriter.append(outStr); fileWriter.append("\r\n"); }catch(IOException ex) { ex.printStackTrace(); }catch(Exception ex) { ex.printStackTrace(); } return fileWriter; } static void convert10(String str) { int data = 0; int data2 = 0; for(int i =0; i<str.length();i++) { data = hexStr.indexOf(str.charAt(i)); data2 = data + data2 * 26; } System.out.println(data2); } }
- 投稿日:2020-11-18T07:24:40+09:00
【Java】変更可能文字列の操作(AOJ15 - 文字列変換)
変更可能文字列の操作を行う
- StringBuilderクラスのメソッド
- サンプルコードです
- 追加・挿入・置換・削除・反転
public class Main { public static void main(String[] args) { StringBuilder sb1 = new StringBuilder("MohuMohuNekoSan"); StringBuilder sb2 = new StringBuilder("MohuiNekoSanMohui"); StringBuilder sb3 = new StringBuilder("あめんぼ赤いな"); //末尾に"***"を追加 System.out.println(sb1.append("^・ェ・^"));//MohuMohuNekoSan^・ェ・^ //インデックス番号1(2文字目)に"***"を挿入 System.out.println(sb1.insert(1, "ooo")); //MoooohuMohuNekoSan^・ェ・^ //インデックス番号15~18を Sama に置換する System.out.println(sb1.replace(15, 18, "Sama")); //MoooohuMohuNekoSama^・ェ・^ //インデックス番号3を'-'に置換 //setCharAtは戻り値voidなのでそのままplintlnしないよう注意! sb1.setCharAt(3, '-'); System.out.println(sb1); //Moo-ohuMohuNekoSama^・ェ・^ //System.out.println(sb1.setCharAt(3, '*')); //Main.java:30: error: void cannot be dereferenced //インデックス番号0~7を削除 System.out.println(sb1.delete(0,7)); //MohuNekoSama^・ェ・^ //インデックス番号3を削除する System.out.println(sb1.deleteCharAt(3)); //MohNekoSama^・ェ・^ //インデックス番号3を取得 System.out.println(sb1.charAt(3)); //N //"CD"が一番最初に出現するインデックス番号を取得する System.out.println(sb2.indexOf("Mohui"));//0 System.out.println(sb2.indexOf("hoge")); // -1 //インデックス番号5以降で"Mohui"が最初に出現するインデックス System.out.println(sb2.indexOf("Mohui", 5)); //12 //"Mohui"が一番最後に出現するインデックス番号を取得する System.out.println(sb2.lastIndexOf("Mohui")); //12 //インデックス番号10(11文字目)以前で"CD"が最後に出現するインデックス番号を取得する System.out.println(sb2.lastIndexOf("Mohui", 5)); //0 //文字数を取得する System.out.println(sb3.length());// 7 //文字列を反転 System.out.println(sb3.reverse()); //ない赤ぼんめあ //インデックス番号3以降の文字列を取得 System.out.println(sb3.substring(3)); //ぼんめあ //インデックス番号0~3の文字列を取得 System.out.println(sb3.substring(0, 3)); //ない赤 //StringBuilderをString型に変換 System.out.println(sb3.toString()); //ない赤ぼんめあ } }文字列変換(ITP1-9)
文字列 str に対して、与えられた命令の列を実行するプログラムを作成してください。命令は以下の操作のいずれかです:
* print a b: str の a 文字目から b 文字目までを出力する。
* reverse a b: str の a 文字目から b 文字目までを逆順にする。
* replace a b p: str の a 文字目から b 文字目までを p に置き換える。
ここでは、文字列 str の最初の文字を 0 文字目とします。
-- Input
1 行目に文字列 str が与えられます。str は英小文字のみ含みます。2 行目に命令の数 q が与えられます。続く q 行に各命令が上記の形式で与えられます。
-- Output
各 print 命令ごとに文字列を1行に出力してください。
-- Constraints
* 1≤strの長さ≤1000
* 1≤q≤100
* 0≤a≤b<strの長さ0≤a≤b<strの長さ
* replace 命令では 長さb−a+1=pの長さ
-- Sample Input 1
abcde
3
replace 1 3 xyz //axyze
reverse 0 2 //yxaze
print 1 4 //xaze
-- Sample Output 1
xazeimport java.util.*; class Main { public static void main(String args[]) { try (Scanner sc = new Scanner(System.in)) { StringBuilder S = new StringBuilder(sc.next()); int N = sc.nextInt(); for (int i = 0; i < N; i++) { String operator = sc.next(); int a = sc.nextInt(), b = sc.nextInt() + 1; if (operator.equals("print")) { System.out.println(S.substring(a, b)); } else if(operator.equals("reverse")) { S.replace(a, b, (new StringBuilder(S.substring(a, b))).reverse().toString()); } else { String x = sc.next(); S.replace(a, b, x); } } } } }
- 投稿日:2020-11-18T03:38:45+09:00
Note Book : Build Error OpenCV v4.5.0 with Julia
- Run
import Pkg; Pkg.add("CxxWrap")
to install the CxxWrap package.Install julia on ubuntu by apt-get
sudo apt-get -yV install juliaOpenCV build errorlog
logz.so;/usr/lib/x86_64-linux-gnu/libdl.so;/usr/lib/x86_64-linux-gnu/libm.so (found version "1.10.4") -- Registering hook 'STATUS_DUMP_EXTRA': /usr/local/src/opencv_contrib/modules/julia/cmake/hooks/STATUS_DUMP_EXTRA.cmake -- Found Julia executable: /usr/bin/julia -- Julia_VERSION_STRING: 1.4.1 -- Julia_INCLUDE_DIRS: /usr/include/julia -- Julia_LIBRARY_DIR: /usr/lib/x86_64-linux-gnu -- Julia_LIBRARY: /usr/lib/x86_64-linux-gnu/libjulia.so.1 -- JULIA_HOME: /usr/bin -- Julia_LLVM_VERSION: v8.0.1 -- Julia_WORD_SIZE: 64 -- Found Julia: /usr/lib/x86_64-linux-gnu/libjulia.so.1 (found version "1.4.1") ERROR: ArgumentError: Package CxxWrap not found in current path: - Run `import Pkg; Pkg.add("CxxWrap")` to install the CxxWrap package. )$ Julia julia> import Pkg julia> Pkg.add("CxxWrap") Cloning default registries into `~/.julia` Cloning registry from "https://github.com/JuliaRegistries/General.git" Added registry `General` to `~/.julia/registries/General` Resolving package versions... Installed libcxxwrap_julia_jll q v0.8.0+0 Installed CxxWrap qqqqqqqqqqqqqq v0.11.0 Installed MacroTools qqqqqqqqqqq v0.5.6 Downloading artifact: libcxxwrap_julia Updating `~/.julia/environments/v1.4/Project.toml` [1f15a43c] + CxxWrap v0.11.0 Updating `~/.julia/environments/v1.4/Manifest.toml` [1f15a43c] + CxxWrap v0.11.0 [1914dd2f] + MacroTools v0.5.6 [3eaa8342] + libcxxwrap_julia_jll v0.8.0+0 [2a0f44e3] + Base64 [ade2ca70] + Dates [b77e0a4c] + InteractiveUtils [76f85450] + LibGit2 [8f399da3] + Libdl [56ddb016] + Logging [d6f4376e] + Markdown [44cfe95a] + Pkg [de0858da] + Printf [3fa0cd96] + REPL [9a3f8284] + Random [ea8e919c] + SHA [9e88b42a] + Serialization [6462fe0b] + Sockets [cf7118a7] + UUIDs [4ec0a83e] + Unicode julia>cmake
cmake \ -DWITH_JULIA=ON \ -DJlCxx_DIR=~/.julia/registries/General \ ..