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

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作成

アカウント登録後ログインします。

image-20201118230750232.png

Add Applicationで新しいアプリケーションを作成します。

image-20201118230830581.png

image-20201118230843069.png

image-20201118230853034.png

作成後にClient IDClient secretを確認できます。後でこれらを使います。

2.2 APIの設定

ヘッダーのAPI > Authorization Serversをクリックします。今回はdefaultを使います。

image-20201118231115603.png

スコープタブで新しいスコープを作成します。任意で大丈夫です。

image-20201118231143349.png

2.3 tokenを発行します

ここまでは準備作業が終わったので、実際にトークンを発行してみます。私はpostmanを使っています。

image-20201118231526009.png

↑は利用例です。各項目について説明します。

項目 説明
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で軽く検証します。

image-20201118232436308.png

image-20201118232604206.png

これで先ほど発行されたトークンは有効であることを確認できました。

3 Springで実装する

本題に入りますが、https://start.spring.io/にて新しいプロジェクトをダウンロードします。

3.1 初期化する

image-20201118233300830.png

必要な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

image-20201118234432509.png

正しくトークンを指定する場合にアクセスできます。
また、トークンが不正の場合に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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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ファクトリメソッドにしたらどうかな?」と検討してみる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

社内業務のシステムをWebで作ろう!

投稿の動機

@NP_Systemsさんの 製造業において、Pythonに加えてWebも活用して飛躍しよう の記事を見て正にキャッチ‐な話題でしたので、社内での活動状況を投稿しようと思いました。現在私は定年後の再就職先として広島市内の名盤製造業に嘱託として勤めています。仕事内容は社内業務システム「業務支援・改」の構築・保守です。

何故Webなのか

今のシステムは経理・給与・販売管理(移行開発中)を除く、製造業務のほぼ全般をWebシステムで運用しています。巷では業務システムはクライアント・サーバータイプ(VB, VC, Java 等)で作られているみたいですが、かなり早い段階からWebで開発している身としては、楽なのに何故Webで開発しないのかが不思議でした。実際WebでVBよりも高速な伝票入力画面を作ることができます。現役時代に納品したシステムはOSのバージョンアップを行っても問題無く使えていますし、カーソル移動も[Enter]キーで[tabIndex]順に移動できます。端末へのインストールも不要で遠地の端末が壊れても簡単に機器の入れ替えができます。ハードを更改してもシステムを更改する必要が無いのです。環境に依存しないので製造現場ではiPadで運用している部署も有ります。一度作ったシステムを要件が変わらないのに再度開発するのは、資産が残らないという意味で馬鹿らしいと感じています。

実運用画面のサンプル

実際に現場でどんな画面を使っているのかを見てみましょう。
■ 出荷計上一覧(出荷予定・実績の一覧)
出荷計上一覧画面.jpg
■ 出荷計上保守(俗に言う売上伝票、在庫出納と連動)
出荷計上保守画面.jpg
■ 納品書 先頭ページ (PDF出力)
納品書01.jpg
■ 納品書 最終ページ (PDF出力)
納品書02.jpg
■ 物品受領書 (PDF出力)
納品書03.jpg
■ 品目保守(製品の材料・工程と工数、他各種情報)
品目保守.jpg
■ 生産予定作成(生産オーダーより生産予定を作成)
生産予定作成画面.jpg
■ 生産状況一覧(生産ロットの進捗状況を把握)
生産状況一覧.jpg
■ 生産日程(カレンダー上で予定と進捗を確認)
生産日程画面.jpg
挙げれば切が無いのでこれぐらいにしておきますが、これらはたった一人で設計・施工・導入したものです。意外とWebシステムって簡単に作れるので皆さんもWebで開発する事を強くお勧めします。

開発環境

全てオープンソースです。Java8 (pdfBox), JavaScript, Tomcat9, mariaDB10, JQuery (ほんのチョットだけ), それと検索時に照合が出来ない事が有るので、入力時にANKは半角、カタカナは全角、濁音・半濁音は1文字に合成しています。殆どが手作りなので、皆さんも安価にリーズナブルなシステムを構築できる事請け合いです。生産計画作成画面はJavaScroptでコメントを入れて1,200行強位です。今日嵌って対応していた見積積算画面は少し凝っていて2,200行強でした (共通ライブラリ除く)。意外と手軽だと思いませんか。

まとめ

実は自分の周りに同じ様な事をしている人がいないので、最近疎外感を感じていたところでした。この投稿を切っ掛けにして多くの人にWebで業務システムを開発して貰いたいと思っています。本も買ったけどネットに転がっている情報でプログラムを作れているので、Webによる業務アプリケーション開発は決して敷居の高いものでは無いのです。みんなでWeb開発をやりましよう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

javaのラムダ式について理解する[入門]

普段から何気なくラムダ 式記法を使って実装をしていますが、ラムダとはそもそも、どういう仕組みになっているのか改めて調べてみました〜。

Javaのラムダ式とは

Javaのラムダ式とは、ざっくり言ってしまうと、メソッドが1つしかないインターフェイスを簡単に実装するための記法です。

色々記述を省略した結果として、ラムダ記法が生まれているので、
本来、ラムダ式を使わずに書くとしたらどうなるのか?というところから説明を始めます。

サンプル1

CalculatorInterface.java
public interface CalculatorInterface {
    public int calculate(int a, int b);
}
MultiplyCalculator.java
public class MultiplyCalculator implements CalculatorInterface {
    @Override
    public int calculate(int a, int b) {
        return a * b;
    }
}
Main.java
public 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.java
package sample2;

public interface CalculatorInterface {
    public int calculate(int a, int b);
}
Main.java
package 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.java
package sample3;

public interface CalculatorInterface {
    public int calculate(int a, int b);
}
Main.java
package 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;

これがいわゆるラムダ式というやつです。こんな感じで、記法の省略を重ねるとラムダ式に達するんですね〜!

説明はこれで終わりです。
分かりにくいところあればコメントください〜

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【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);

実行結果は要素数の5が表示されます。
image.png
オッケーです。

【インデックス】 配列の各要素の参照・更新

インデックスの指定の仕方

配列名の直後に[ ] をつけ、インデックス(添字)と呼ばれる数字を指定することで、要素の参照や更新をすることが出来ます。
※ 当然ながら、インデックスも0から順番に数えます。

配列変数[数字(インデックス)]

下記はscore配列の3番めの要素を引っ張り出すときの例です。

int[] score = {80, 90, 100, 85, 90};
System.out.println(score[2]);

この場合は100が出力されるはずです。
image.png
オッケーでした。

配列の全要素を表示する(for文を使用)

配列に入ってる要素をすべて出力してみます。
この書き方だと、「0〜score配列の要素数だけ1つずつ出力する」というというのをfor文を使って書いています。

要素のインデックス番号をすべて抽出

下記は要素のインデックス番号をすべて抽出する場合です。

int[] score = {80, 90, 100, 85, 90};
// インデックス番号をすべて表示
for (int i = 0; i < score.length; i++) {
    System.out.println(i);
}

実行結果
image.png

配列の中の要素の値をすべて抽出

下記は配列の中の要素の値をすべて抽出する場合です。

int[] score = {80, 90, 100, 85, 90};
// 要素の値をすべて表示
for (int i = 0; i < score.length; i++) {
    System.out.println(score[i]);
}

実行結果
image.png

合計点を求めるプログラム

すべてのscoreを合計して出力するプログラムを書きました。
処理の流れは..

  1. int[]型の変数scoreの宣言と初期化
  2. 合計スコアを宣言し、0で初期化する
  3. scoreの要素数だけ計算をおこなう
  4. 計算された得点を表示する

という流れになります。

// 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);

実行結果
image.png

for文の内容は実質、80 + 90 + 100 + 85 + 90を行ったということなので、出力結果は上記のようになりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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ファイルのダウンロードが始まります。
スクリーンショット 2020-10-19 23.43.00.png
ダウンロードしたzipファイルを解凍します。
以下の画面が表示されたらSpringToolSuite4.appをApplicationsファイルにドラッグアンドドロップしてください。
スクリーンショット 2020-10-20 0.58.49.png
以上でインストール完了です。

Pleiadesのインストール

STSに日本語化プラグインを入れます。
Pleiadesダウンロードサイトにアクセスします。
スクリーンショット 2020-10-20 1.14.48.png
Pleiades プラグイン・ダウンロードからMacOSをクリックし、Preparing to download Eclipse Pleiades pluginの下のリンクからzipファイルをダウンロードします。
zipファイルを解凍し、setup.appを起動(クリック)します。
※「“setup.app”は、開発元を検証できないため開けません。」とエラーが出た場合は以下の記事を参照してみてください。
https://github.com/ko-ichi-h/khcoder/issues/100
以下の画面が表示されたら「選択」をクリックしてアプリケーションファイルに移したSTSを選択します。
スクリーンショット 2020-10-20 3.08.54.png
「日本語化する」をクリックします。
以上でインストール完了です。

Lombokのインストール

Lombokとは、setterやgetterを自動的に実装してくれる便利ツールです。
現場でよく使われるらしいので、入れておきましょう。
Lombokダウンロードサイトにアクセスします。
ダウンロードしたlombok.jarを/Applications/SpringToolSuite4.app/Contents/MacOSにコピーします。
lombok.jarを起動し、Specify location...をクリックします。
/Applications/SpringToolSuite4.app/Contents/Eclipse/にあるSpringToolSuite4.iniを選択します。
スクリーンショット 2020-10-20 3.28.13.png
「install/Update」「Quit Installer」と順にクリックします。
インストールが完了すると、STSのフォルダ内にlombokが入ります。
以上でインストール完了です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【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に置き換えられている。
 

参考文献

【Java入門】GUIの開発フレームワークまとめ(Swing、JavaFx、AWT)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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);
    }
}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【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
xaze

import 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);
                }
            }
        }
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 julia

OpenCV build errorlog

log
z.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 \
..
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む