読者です 読者をやめる 読者になる 読者になる

ぺーぺーSEのブログ

備忘録・メモ用サイト。

Angular入門

Angular TypeScript JavaScript npm Sass

フロントエンドMVCフレームワーク Angular (所謂Angular2)を触ってみた。
ここでは Angular CLI を使う。
なお、 ndenv が入ってるテイで書く。導入は下記記事参照。

blog.pepese.com

Angular CLI

インストール

$ npm install -g @angular/cli
$ ndenv rehash
$ ng version
                             _                           _  _
  __ _  _ __    __ _  _   _ | |  __ _  _ __         ___ | |(_)
 / _` || '_ \  / _` || | | || | / _` || '__|_____  / __|| || |
| (_| || | | || (_| || |_| || || (_| || |  |_____|| (__ | || |
 \__,_||_| |_| \__, | \__,_||_| \__,_||_|          \___||_||_|
               |___/
@angular/cli: 1.0.0-beta.32.3
node: 7.5.0
os: darwin x64
@angular/common: 2.4.8
@angular/compiler: 2.4.8
@angular/core: 2.4.8
@angular/forms: 2.4.8
@angular/http: 2.4.8
@angular/platform-browser: 2.4.8
@angular/platform-browser-dynamic: 2.4.8
@angular/router: 3.4.8
@angular/cli: 1.0.0-beta.32.3
@angular/compiler-cli: 2.4.8

以降、 ng コマンドでいろいろできるようになる。

プロジェクト作成と起動

$ ng new angular-sample
$ cd angular-sample
$ ng serve

プロジェクト構成

.
├── README.md
├── .angular-cli.json                * Angular CLI 設定ファイル
├── .editorconfig                    * エディタの設定ファイル
├── .gitignore
├── e2e                              * エンドツーエンドテストディレクトリ
│   ├── app.e2e-spec.ts
│   ├── app.po.ts
│   └── tsconfig.json
├── karma.conf.js                    * karma(テストランナー)の設定ファイル
├── package.json                     * npmの設定ファイル
├── protractor.conf.js               * e2eテストの設定ファイル
├── tslint.json                      * TypeScriptのLinter設定ファイル
└── src                              * ソースファイルディレクトリ
    ├── app                          * アプリケーションコードディレクトリ
    │   ├── app.component.css
    │   ├── app.component.html
    │   ├── app.component.spec.ts
    │   ├── app.component.ts
    │   └── app.module.ts
    ├── assets
    ├── environments
    │   ├── environment.prod.ts
    │   └── environment.ts
    ├── favicon.ico
    ├── index.html                    * トップ画面、ルートコンポーネントを記載
    ├── main.ts                       * ルートモジュールのロード(メイン)
    ├── polyfills.ts
    ├── styles.css
    ├── test.ts
    └── tsconfig.json                 * TypeScriptの設定ファイル

.ditorconfigEditorConfigというプロジェクトの設定ファイルで、エディタへプラグインなどを入れることにより様々なエディタの設定をプロジェクト単位で可能にする。
テストは Jasmine (テスティングフレームワーク)と Karma (テストランナー)の組み合わせで実行される。
e2e(エンドツーエンド)テストは protractor

主要なコマンド

  • ng new
    • 新規にAngularプロジェクトを作成する
  • ng build
    • src 配下をビルドして dist へ出力する
  • ng serve
    • Webサーバを起動してアプリケーションを実行する
  • ng generate
    • blueprints から選択して新たにコードを生成する
  • ng eject
    • ng generate などで作成したコードを取り除き、webpackの設定やスクリプトを変更する
  • ng get
    • 設定(key-value)から値(value)を取得する
  • ng set
    • 設定(key-value)に値(value)を追加する
  • ng lint
    • Linterを実行する
  • ng test
    • テストを実行する
  • ng e2e
    • e2eテストを実行する
  • ng xi18n
    • コードからi18nメッセージを抜く

上記以外や詳細なオプションは ng help を参照。

blueprints の種類

  • module
    • ng generate module sample
    • モジュール( sample/sample.module.ts )が作成される。
    • 自動で指定したモジュール名でディレクトリが切られることに注意
  • component
    • ng generate component sample
    • コンポーネント(以下)を作成し、 app.module.ts に自動登録(importおよびメタデータ declarations への追加)される。
      • sample.component.tssample.component.spec.tssample.component.htmlsample.component.scss
    • なお、既に存在するモジュール名で作成すると、そのモジュール名のディレクトリ内に作成される。
  • directive
    • ng generate directive sample
    • ディレクティブ(以下)を作成し、 app.module.ts に自動登録(importおよびメタデータ declarations への追加)される。
      • sample.directive.tssample.directive.spec.ts
  • pipe
    • ng generate pipe sample
    • パイプ(以下)を作成し、 app.module.ts に自動登録(importおよびメタデータ declarations への追加)される。
      • sample.pipe.tssample.pipe.spec.ts
  • service
    • ng generate service sample
    • サービス(以下)を作成する。
      • sample.service.tssample.service.spec.ts
  • class
    • ng generate class sample
    • 普通のクラス( sample.ts )が作成される。
  • interface
    • ng generate interface sample
    • 普通のインターフェース( sample.ts )が作成される。
  • enum
    • ng generate enum sample
    • 普通の列挙型( sample.enum.ts )が作成される。

ディレクトリを切りたい場合は / を加えて、 ng generate service sample/sample-service のようにする。

Angular CLI のバージョンアップ方法

グローバルでは以下。

$ npm uninstall -g @angular/cli
$ npm cache clean
$ npm install -g @angular/cli@latest
$ ndenv rehash

ローカルプロジェクトでは以下。

$ rm -rf node_modules dist # use rmdir on Windows
$ npm install --save-dev @angular/cli@latest
$ npm install

Angularの基本

Angularのアーキテクチャは以下の要素から構成される。

  • モジュール(@NgModule)
  • コンポーネント(@Components)
  • テンプレート(Templates)
  • メタデータ(Metadata)
  • データバインディング(Data Binding)
  • ディレクテイブ(@Directive)
  • パイプ(@Pipe)
  • サービス(Services)・DI(Dependency injection / @Injectable)
  • フォームとバリデータ
  • Angularライブラリ

上記の各々について後述する。

モジュール(@NgModule)

Angularのアプリケーションはモジュール単位で機能を管理する。
モジュールは後述の コンポーネントテンプレート を包含する。

Angularアプリケーションは少なくとも1つ ルートモジュール を持ち、AppModule と命名する。
ルートモジュールは、 src/main.ts からロードされる。
通常のアプリケーションの場合、ルートモジュールは1つだが、巨大なアプリケーションの場合、複数のルートモジュールを持つこともある。

モジュールは以下のように作成する。

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ Logger ],
  declarations: [ AppComponent ],
  exports:      [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

AppModule クラスに @NgModule デコレータ (Javaでいうアノテーション)を付与した形になっている。
デコレータにAngularに則した設定を行い、クラスには何も書かない(たぶん)。
@NgModule の代表的なプロパティは以下の通り。ちなみにデコレータに設定するプロパティを メタデータ という。

  • imports
    • このモジュールに他のモジュールを取り込み、このモジュール内で定義されているコンポーネントやテンプレートが他のモジュールのクラスを使用できるようになる。
    • 他のモジュールの providersexports に定義されたものを使用できるようになる。
  • providers
    • このモジュールおよび関係するコンポーネント・サービスへインジェクトするためのサービスクラスを定義・インスタンス化する。
  • declarations
    • このモジュールに所属させるビュークラスを指定する。Angularのビュークラスには、 コンポーネントディレクティブパイプ がある。
  • exports
    • このモジュール内のクラスを他のモジュールのコンポーネント・テンプレートで使用可能にする。
    • imports の逆。
  • bootstrap
    • ルートコンポーネント を定義する。ルートコンポーネントはアプリケーションのメインビュー。
    • ルートモジュールにだけbootstarp プロパティを設定する。

以下が ルートモジュール を指定する方法( src/main.ts )。

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

また、モジュール内では以下のようにライブラリから他のモジュールをロードすることもできる。

import { Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

ロードしたライブラリモジュールは、 @NgModuleimports プロパティに指定することにより使用できるようになる。

imports:      [ BrowserModule ],

コンポーネント(@Component)

コンポーネントはビューの役割を担う。
コンポーネントクラス内で定義したフィールド変数やメソッドは、テンプレートから直接使用できる。
ロジックは基本的にコンポーネント内に記載し、サービスクラスをDIしたりする。

@Component({
  moduleId: module.id,
  selector:    'hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

@Component の代表的なメタデータプロパティは以下。

  • moduleId
    • このモジュールが定義されるファイルのES/CommonJSモジュールID
  • selector
    • このコンポーネントのHTMLタグ名を定義する。
  • template
    • テンプレートを直接記載する。
  • templateUrl
    • テンプレートファイルのパスを指定する。
  • styles
    • スタイルシート(CSSやSass)を直接記載する。このコンポーネント外には影響が無い。
  • styleUrls
    • スタイルシートファイルのパスを指定する。このコンポーネント外には影響が無い。
  • providers
    • このコンポーネントがDI経由で使用するサービスクラスを指定する。
    • コンポーネントクラスの constructor の引数でも指定する必要がある。

その他の @Component のメタデータはここで確認できる。

テンプレート(Templates)

テンプレートはコンポーネントのDOMとして使われるHTML。
コンポーネントクラスの @Component デコレータのメタデータに直接記載( template )することも、別ファイルとして作成して読み込む( templateUrl )ことも可能。
テンプレート内では、HTMLの属性として ディレクティブ*ngFor など)、コンポーネントとのデータ・機能のやりとりに データバインディング を使用することができる。

  • コンポーネントフィールドへのアクセス
    • *ngFor : コレクションフィールドの値にアクセス
    • *ngFor="let hero of heroes" : コレクションheroesの各要素をheroへ代入
  • コンポーネントのメソッド呼び出し
    • (click)="onClickMe()" : クリック時に onClickMe() メソッドを呼び出す
    • (keyup)="onKey($event)" : キーアップ時にイベントを引数に onKey() メソッドを呼び出す

また、テンプレートにはスタイルシート(CSS、Sassなど)を指定することができ、@Component デコレータのメタデータ( stylesstyleUrls )で指定することができる。

メタデータ(Metadata)

メタデータは デコレータ@ から始まるJavaでいうアノテーション)に設定するプロパティ。
Angularにクラスがどのように挙動するか知らせる役割。
@Injectable@Input@Output など様々なデコレータにメタデータを設定できる。
もう十分前述しているのでこの程度で。

データバインディング(Data Binding)

テンプレートとコンポーネント間のデータ・機能のやりとりを行う機能。
以下のように4種類ある。

  • 単方向バインド(interpolation)
    • <li>{{hero.name}}</li>
    • コンポーネントの hero.name プロパティの値を <li> 表示する
  • プロパティバインド(property binding)
    • <hero-detail [hero]="selectedHero"></hero-detail>
    • 親コンポーネントの selectedHero の値を、子コンポーネントの hero へ渡している
  • イベントバインド(event binding)
    • <li (click)="selectHero(hero)"></li>
    • ユーザのクリックにより selectHero() メソッドが呼び出される。
  • 双方向バインド(Two-way data binding)
    • <input [(ngModel)]="hero.name">
    • ngModel を用いて 参照と更新 を両方同時に実現する。

ngModel のようにテンプレートのHTMLタグの属性として記述できるAngularの機能を ディレクティブ という。

イベント

<button (click)="onClickButton()">ボタン1</button>
<button (click)="onClickButtonWithEvent($event)">ボタン2</button>

(click) のように、イベント名をカッコで囲んだ属性に、イベントを処理するメソッドを記述する。
引数なしの記述と、イベントオブジェクト $event を指定する記述ができる。
コンポーネントクラス内では以下のようにメソッド定義する。

onClickButtonWithEvent(event:any) {
   // targetプロパティでイベントを発生させたオブジェクトを取得
   var button = event.target;
   // ボタンのラベルをtextContentプロパティから取得して表示
   alert("ボタン「" + button.textContent + "」が押下されました");
 }

ディレクテイブ(@Directive)

ディレクティブは前述の通り、テンプレートのHTMLタグの属性として指定できるAngularの機能。
モジュール・コンポーネント間のデータの授受や、ループ・条件分岐といった動的なDOMの機能を提供する。

<li *ngFor="let hero of heroes"></li>
<hero-detail *ngIf="selectedHero"></hero-detail>

@Directive デコレータでディレクティブを自作できる。
ここでは割愛。参考

パイプ(@Pipe)

Pipeはテンプレート内で文字列操作の機能を提供する。
例えば、Dateオブジェクトをあるフォーマットに整形して表示できる。

// コンポーネントクラスのフィールド
let birthday = new Date(1985,3,1); // これで1985年4月1日 なことに注意

上記をテンプレードで以下のように指定することにより yy/MM/dd 形式で表示できる。

<p>{{ birthday | date:"yy/MM/dd" }}</p> <!-- 1985/04/01 と表示される -->

他にも下記のようなパイプがある。

  • DatePipe
    • 上記例。日付を整形する。
    • date_expression | date[:format]
  • UpperCasePipe
    • 文字列を大文字にする。
    • expression | uppercase
  • JsonPipe
    • 入力値にJSON.stringfyを実行して返す。
    • expression | json

また、パイプはこんな {{ birthday | date | uppercase}} 感じでチェーンできる。

さらに、@Pipe デコレータでパイプを自作できる。
ここでは割愛。参考

サービス(Services)・DI(Dependency injection / @Injectable)

サービスは export された通常のtypescriptクラス。
DIを使用してコンポーネントや他サービスクラスにサービスクラスをインジェクトできる。

作成例

$ ng generate service sample/sample
installing service
  create src/app/sample/sample.service.spec.ts
  create src/app/sample/sample.service.ts
  WARNING Service is generated but not provided, it must be provided to be used

上記で作成した src/app/sample/sample.service.ts をDIするには、使用するモジュール・コンポーネントにimport、メタデータ providers およびコンストラクタへの指定を行う。
以下コンポーネントへの導入例。

...
import { SampleService } from './sample/sample.service' // インポート

@Component({
  ...
  providers: [SampleService], // providers に追加
  ...
})
export class AppComponent {
  title: string;

  constructor(
    private sampleService: SampleService // コンストラクタに設定
  ){
    this.title = sampleService.getTitle();
  }
}

DI・インジェクタ

サービスをモジュールやコンポーネントで使用できるようにインジェクトする機能。
前述の通り、モジュール・コンポーネントにimport、メタデータ providers およびコンストラクタへの指定を行う。

@Injectable デコレータがついたサービスクラスは多段Inject(DIのDI)することが可能になる。
一段Injectはデコレータが無しでもOKだがつけておいても問題ない。

フォームとバリデータ

http://codezine.jp/article/detail/9596?p=4

Angularライブラリ

Angularのライブラリには様々用意されており、APIリファレンスはここ
リファレンスではクラスの前に記号がついており、それぞれ以下の意味。

記号 意味
D Directive。ディレクティブ。
P Pipe。パイプ。
@ Decorator。デコレータ。Javaでいう所謂アノテーション。
C Class。普通のTypeScriptのクラス。
I Interface。普通のTypeScriptのインターフェース。
F Function。関数。
E Enum。普通の列挙型。
T Type Alias。なんかわからん。
K Const。定数クラス。

その他話題、メモ

TypeScriptの型解決について

解決方法には以下がある。

  • tsd
  • typings
  • @types

Angularは型定義が含まれているため、上記3つは不要。ただし、他のライブラリを用いる場合 @types を使用する。

Spring Security / Spring Session入門

Java Spring Spring Security Spring Session Maven

Spring Securityは認証・認可の機能を持つSpringのライブラリ。
Spring Sessionを用いて Redis にセッションを格納する設定も試してみる。

ここでは、簡単なログイン画面でログインする機能を作成する。
以下の構成で記載する。

  • Java Configで設定する方法
    • Springの設定をJavaベースで設定する方法
  • XML Configで設定する方法
    • Springの設定をXMLベースで設定する方法
  • 共通作成物
    • Java Config、XML Configによらない共通の作成物

また、ここで紹介の作成物については以下参照のアプリケーションに対して、Thymeleaf画面・Spring Securityによる認証・Spring SessionによるRedisセッション管理機能を追加する。

blog.pepese.com

blog.pepese.com

Java Configで設定する方法

pom.xml

  • org.springframework.boot:spring-boot-starter-security を使用しているのがポイント

com.pepese.sample.config.WebSecurityConfig

  • org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter を継承し、 @EnableWebSecurity アノテーションを付与する
  • configure メソッドの引数により設定対象を変更できる
    • WebSecurity web : Spring Security Filter Chain (springSecurityFilterChain) に関する設定が可能
      • web.Xxx() で様々設定できる。詳細はここ
    • HttpSecurity http : XML Configの http タグと同じ設定が可能
      • http.Xxx() で様々設定できる。詳細はここ
  • configureGlobal メソッドで認証処理ロジックのサービスクラスをSpring Securityの認証マネージャに設定している

com.pepese.sample.config.SessionConfig

  • クラスに @EnableRedisHttpSession アノテーションを付与するとSpring Sessionの設定はほぼ完了
  • connectionFactory メソッドで Redis へセッションを格納する設定
  • ホスト名やポートは application.properties に設定する

XML Configで設定する方法

pom.xml

spring-mvc.xml

ThymeleafのView Resolverを設定。

spring-security.xml

  • <sec:http pattern="/resources/**" security="none" />
    • Spring Session処理対象外の設定
  • <sec:http>
    • 認証周りの設定
  • ユーザ認証処理ロジックのサービスクラス( UserDetailsServiceImpl )のBean定義
  • <sec:authentication-manager>
    • UserDetailsServiceImpl を認証マネージャに登録

spring-session.xml

  • RedisHttpSessionConfiguration のBean定義でSpring Sessionの設定
  • LettuceConnectionFactory のBean定義でRedis接続の設定

web.xml

  • contextConfigLocationspring-security.xmlspring-session.xml を追加。
  • Spring Securityの設定として springSecurityFilterChain という名前で org.springframework.web.filter.DelegatingFilterProxy をFilter定義しているのがポイント。
  • Spring Sessionの設定として springSessionRepositoryFilter という名前で org.springframework.web.filter.DelegatingFilterProxy をFilter定義しているのがポイント。
    • さらに Spring SecurityのFilter定義より上 に設定する必要がある

共通作成物

com.pepese.sample.model.User

  • 認証するユーザクラス
    • パスワードを固定にしているのはサンプルなので

com.pepese.sample.service.security.UserDetails

  • Spring Securityが提供するユーザ認証用のクラス( org.springframework.security.core.userdetails.User )を継承して作成
  • 自作のUserクラスを認証対象のクラスとして設定する

com.pepese.sample.service.security.UserDetailsServiceImpl

  • Spring Securityが提供するユーザ認証用サービスクラス( org.springframework.security.core.userdetails.UserDetailsService )を継承して作成
  • 本来なら認証対象のユーザデータをDBなどから取得して突合するが、サンプルということで new してる

application.properties

com.pepese.sample.controller.HelloController

  • @AuthenticationPrincipal でログイン済みのユーザ情報を取得できる
  • なお、 /logout のパス・ロジックは Spring Security にてもつ

index.html

Viewは、Java Configの場合は resources/templates 配下、XML Configの場合は WEB-INF/templates 配下に配置する。

login.html

error.html

Git入門

Git Github

Gitのメモ。

環境構築

GitHubのアカウントを作成

下記でGitHubのアカウントを作成。

Gitクライアント環境の作成

Windowsへのインストール

Macへのインストール

以下を参照。

blog.pepese.com

Gitクライアント設定

  • ユーザ名とメールアドレスを登録( コミットログに残るユーザ名なので必ず設定する!
    • git config --global user.name "hoge"
    • git config --global user.email "hoge@email.sample.com"
  • プロキシがある環境の場合は下記を叩く
    • git config --global http.proxy http://[FQDN]:[PORT]
    • git config --global https.proxy http://proxy.example.com:8080
  • プロキシがある環境の場合は下記を叩く(ID、Passwordが必要な場合)
    • git config --global http.proxy http://[ID]:[Password]@[FQDN]:[PORT]
    • git config --global https.proxy http://[ID]:[Password]@[FQDN]:[PORT]
  • プロキシがある環境の場合は下記を叩く
    • git config --global url."https://".insteadOf git://
    • これでgitスキームを使えるようになる
  • Windowsのgitではデフォルトで改行コードがCR+LFへ変換されてしまうのでオフにする
    • git config --global core.autocrlf false
  • 設定が反映されていることを確認 git config --global -l

グローバル設定ではなく、単一Gitプロジェクトにのみ反映させたい場合は、 --global を外してコマンドを打つ。

core.symlinks=false
core.autocrlf=true
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
pack.packsizelimit=2g
help.format=html
http.sslcainfo=/bin/curl-ca-bundle.crt
sendemail.smtpserver=/bin/msmtp.exe
diff.astextplain.textconv=astextplain
rebase.autosquash=true
http.proxy=http://[ID]:[Password]@proxy.example.com:8080
https.proxy=http://[ID]:[Password]@proxy.example.com:8080
url.https://.insteadof=git://

使い方

リモートリポジトリを作って、ローカルリポジトリにコピーして編集して更新するパターン

  1. リモートリポジトリをローカルリポジトリへコピー(clone)
  2. GitHub用のローカルリポジトリ領域を作成してカレントを移動
    • cd /d C:\Git\GitHub
  3. リモートリポジトリ(GitHub)をローカルリポジトリへコピー(初回のみ)
    • git clone https://github.com/pepese/Sample.git
    • C:\Git\GitHub\Sample」と「C:\Git\GitHub\Sample\.git ができる
  4. ローカルリポジトリへファイルを登録(add/commit)
  5. コピーしたローカルリポジトリへ移動
    • cd /d C:\Git\GitHub\Sample
  6. ファイルを作成
    • touch sample.txt
      • C:\Git\GitHub\Sample\sample.txt
    • このままだとファイルを作っただけでまだローカルリポジトリへは反映されていない
  7. ステージング領域へ反映
    • git add sample.txt
    • 全ての変更ファイルをaddしたい場合は git add --all
  8. ローカルリポジトリへコミット
    • git commit
    • Vimが起動してコミットコメントを求められるので適当に編集
    • コメント付きでコミットする場合は下記
      • git commit -m "コミットコメント"
  9. ローカルリポジトリの内容をリモートリポジトリへ反映(push)
  10. ローカルリポジトリの内容をリモートリポジトリ(GitHubのMasterブランチ)へ反映
    • git push origin master
  11. 確認
  12. ファイルを更新する
  13. 下記のファイルをエディタで更新
    • C:\Git\GitHub\Sample\sample.txt
  14. ステージング領域へ反映
    • git add sample.txt
  15. ローカルリポジトリへコミット
    • git commit
  16. ローカルリポジトリの内容をリモートリポジトリ(GitHub)へ反映
    • git push origin master
    • GitHubアカウントのIDとPasswordを求められるので入力
  17. 確認

ローカルリポジトリを作ってリモートリポジトリへ反映するパターン

リモートリポジトリが存在している前提で。

  • cd /d C:\Git\GitHub
  • mkdir Sample2
  • cd Sample2
  • git init
  • git remote add origin https://github.com/pepese/Sample2.git
    • リポジトリの参照先(origin)の設定
    • もちろんGithub上にあらかじめリポジトリを作成しておく必要がある
  • touch sample2.txt
  • git add sample2.txt
  • git commit
  • git push origin master

ブランチの作成からPull Request完了まで

$ git branch <branchname>

<branchname> を指定せずに実行すると現在のブランチ(*がついてる)が確認できる。
また、ブランチの切り替えは以下。

$ git checkout <branchname>

一連の流れは以下。

$ git branch issue1
$ git branch
  issues1
* master
$ git checkout issue1
$ git branch
* issues1
  master

Pull Requestマージ後の作業。

$ git checkout master
$ git branch -d issue1      #ローカルブランチの削除
$ git push origin issue1   #リモートブランチの削除

ファイルの変更を戻す

以下でコミットログのハッシュ値を取得。

git log [ファイルパス]

以下でコミットのハッシュ値を指定して戻す。

$ git checkout [コミット番号] [ファイルパス]

特定のコミットをマージする

以下でリモートリポジトリの変更をローカルリポジトリへ持ってくる。(ワーキングディレクトリの変更は行われない)

$ git fetch

コミットログのハッシュ値を指定してマージする。

$ git cherry-pick [ハッシュ値]

ブランチをマージする

issue1ブランチにmasterをマージしたい場合。

$ git checkout issue1
$ git merge master

ファイル、ディレクトリをgitの管理対象から外す

ファイルをgitの管理対象から外して且削除

$ git rm [削除したいファイル]

ファイルをgitの管理対象から外すがファイルを削除しない

$ git rm —-cached [削除したいファイル]

ディレクトリをgitの管理対象から外して且削除

$ git rm -r [削除したいディレクトリ]

もうちょっと知りたい人は以下を参照。

blog.pepese.com

JenkinsでMavenレポートを出力する

JenkinsでMavenレポートを出力する。

MavenとJenkinsを使ってJavaのレポート出力をやってみた。
下記を読んだテイで書く。

blog.pepese.com

Maven

mvn clean test site をたたいてHTML形式のレポートを出力する親POMを下記に作った。

親POM

※2017年2月17日時点での最新バージョンにしている。
javancss-maven-plugin はJava8未対応だったためコメントアウト。

プラグインの概要

reporting タグの部分だけ記載する。

  • org.apache.maven.plugins:maven-site-plugin
    • mvn site コマンドの実装
    • 以下の「Project Information」を出力する
      • Dependencies :依存ライブラリの一覧
      • Dependency Convergence :同一依存ライブラリの全てのバージョンを集約して表示
      • Dependency Information :このプロジェクトの依存の書き方
      • Dependency Management :最終的に適用される依存ライブラリの一覧
      • Distribution Management :配布するリポジトリの情報
      • About :POMのdescriptionの記載
      • Plugin Management :最終的に適用されるプラグインの一覧
      • Project Plugins :buildおよびreportingに使用されるプラグインの一覧
      • Project Summary :プロジェクト情報のサマリ
  • org.apache.maven.plugins:maven-javadoc-plugin
    • Project Reports の「JavaDocs」および「Test JavaDocs」を出力する
  • org.apache.maven.plugins:maven-surefire-report-plugin
    • Project Reports の「Surefire Report」を出力する
      • テストの件数、エラー数、失敗数等を出力する
  • org.apache.maven.plugins:maven-jxr-plugin
    • Project Reports の「Source Xref」および「Test Source Xref」を出力する
      • JavaソースコードをHTML形式で出力する
  • org.apache.maven.plugins:maven-pmd-plugin
    • Project Reports の「PMD」を出力する
      • PMDはJavaコードを分析して潜在的なバグを探すツール
  • org.apache.maven.plugins:javancss-maven-plugin
    • Project Reports の「JavaNCSS」を出力する
      • JavaNCSSはJavaコードの品質や複雑度に関するメトリクスを出力する
  • org.jacoco:jacoco-maven-plugin
    • Project Reports の「JaCoCo」を出力する
      • JaCoCo による単体試験のカバレッジ測定結果
  • org.apache.maven.plugins:maven-checkstyle-plugin
    • Project Reports の「Checkstyle」を出力する
  • org.codehaus.mojo:findbugs-maven-plugin
    • Project Reports の「FindBugs」を出力する
  • org.apache.maven.plugins:maven-project-info-reports-plugin
    • プロジェクトの情報を出力する
      • cim、help、issue-tracking、license等

以上の情報がHTML形式で target/site 配下へ出力される。

testFailureIgnore について

親POMのbuild⇒plugins⇒pluginのmaven-surefire-pluginの設定で testFailureIgnoretrue にするとテストでコケてもレポート出力するようになる。
と、同時に mvn test でコケてもSUCCESS となってしまう。
こうなってくると、Jenkinsで DailyTestで失敗しても気づかない ことになってしまう。
なので、 testFailureIgnore はPOMで設定せず、以下のようにするといい。

  • JenkinsによるDailyTest
    • mvn test -Dmaven.test.failure.ignore=false
      • これでテストでコケたら FAILURE になる(ちなみにデフォルトfalse)
  • Jenkinsによるレポート出力
    • mvn clean test site -Dmaven.test.failure.ignore=true
      • これでテストでコケても SUCCESS になり、レポートが出力される

Jenkins

Jenkinsのジョブで mvn clean test site をした後、Jenkinsの HTML Publisher Plugin で下記のように設定すればJenkinsのジョブのページにSiteで出力したレポートへのリンクが作成される。

  • Publish HTML reports :チェックボックスをオン
    • HTML directory to archive
      • 例) target/site/
    • Index page[s]
      • 例) index.html
    • Report title
      • 例) HTML Report

レポートの表示が崩れている(CSS/JSが適用されていない様子)場合は下記を参照。

blog.pepese.com

また、今回Mavenで出力しなかったJavaコード解析情報について、下記のJenkinsプラグインを使用するとカバーできる。

  • DRY Plugin
    • コピペコードのような重複したコードをチェックしてくれる
  • Task Scanner Plugin
    • ソースコードを任意の文字列で検索するチェックをかけることができる
      • FIXME、TODO、XXX、deprecated、System.out.printlnとかスキャンしてくれる
  • Warnings Plugin
    • コンパイラの警告をチェックしてくれる
  • Step Counter Plugin
    • ファイル行数をカウントしてくれる

Express入門

Express.js Node.js JavaScript npm

Node.jsのWebフレームワーク Express 触ってみた。
下記の記事を読んだテイで書く。

blog.pepese.com

インストール

Expressのインストール

$ npm install express --save

Express単体を入れる時はこれ。
以降の説明は express-generator を使うので上記はやらなくていい。

express-generatorのインストール

express-generator は Expressベースのアプリ雛形を作成するツール。
RailsのScaffoldのようなもの。

$ npm install -g express-generator
$ ndenv rehash # ndenvを使っている人は

サンプルアプリの作成

以下の順で記載する。

  • express-generatorの使い方
  • express-generatorで雛形作成
  • ディレクトリ構造
  • 実行と確認
  • コードを見てみる

express-generatorの使い方

$ express --help

  Usage: express [options] [dir]

  Options:

    -h, --help           output usage information
        --version        output the version number
    -e, --ejs            add ejs engine support
        --pug            add pug engine support
        --hbs            add handlebars engine support
    -H, --hogan          add hogan.js engine support
    -v, --view <engine>  add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
    -c, --css <engine>   add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
        --git            add .gitignore
    -f, --force          force on non-empty directory

express-generatorで雛形作成

ExpressのデフォルトのView Template Engine は Jade だが、 Jadeは Pug にリネームされた。
今後、ExpressのデフォルトのView Template EngineはPugに置き換えられるため、ここでは Pug を使用する。

$ express express-sample --view=pug --git

   create : express-sample
   create : express-sample/package.json
   create : express-sample/app.js
   create : express-sample/.gitignore
   create : express-sample/public
   create : express-sample/public/javascripts
   create : express-sample/public/stylesheets
   create : express-sample/public/stylesheets/style.css
   create : express-sample/public/images
   create : express-sample/routes
   create : express-sample/routes/index.js
   create : express-sample/routes/users.js
   create : express-sample/views
   create : express-sample/views/index.pug
   create : express-sample/views/layout.pug
   create : express-sample/views/error.pug
   create : express-sample/bin
   create : express-sample/bin/www

   install dependencies:
     $ cd express-sample && npm install

   run the app:
     $ DEBUG=express-sample:* npm start

$ cd express-sample/
$ npm install

express <プロジェクト名> コマンドでExpressの雛形プロジェクトが作成される。
npmのpackage.jsonが作成されているので「npm install」でモジュールをインストールする。
npm start コマンド(package.jsonにて定義)で node ./bin/www が実行され、サービスが起動する。
「./bin/www」には、Express.jsでHTTPサービス(3000番ポート)が起動するJavaScriptがコーディングされており、「app.js」に記述されたサービスが実行される。

ディレクトリ構造

$ tree
.
├── app.js           # メインJavaScript
├── bin/             # サービス起動JavaScript(www)置き場
├── node_modules/    # npmモジュール置き場
├── package.json
├── public/          # 公開ディレクトリ
│   ├── images/
│   ├── javascripts/
│   └── stylesheets/
├── routes/          # ルーティング先のスクリプト置き場(MVCのCとロジックに相当)
│   ├── index.js
│   └── users.js
└── views/           # View用のコード置き場(MVCのVに相当)
    ├── error.pug
    ├── index.pug
    └── layout.pug

実行と確認

# 実行
$ npm start
# 確認
$ curl localhost:3000
<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>
$ curl localhost:3000/users
respond with a resource

コードを見てみる

app.js

  • 各種ライブラリのロード( var xxx = require('xxx');
  • ルーティング先コントローラ層ロジックのロード( var xxx = require('./routes/xxx');
  • Express本体オブジェクトの作成と設定( var app = express();
    • View Template Engine( Pug ) の設定
    • ロガー、パーサー、公開ディレクトリの設定
    • ルーティン部先ロジックの設定( app.use('/xxx', xxx);
    • エラーハンドリングの設定

index.js

users.js

Node.js(npm)入門

Node.js JavaScript npm

Node.js(npm)についてまとめる。

npm(Node Packege Manager)は、Node.js用のパッケージ管理コマンド。
JavaScriptエコシステムツール・ライブラリはnpmで導入できるものが多い。
npmはNode.jsと同時にインストールされるので、Node.jsを入れておけばいい。
また、Node.jsはJavaScriptの実行エンジン。

ちなみにここでNode.jsのES6対応状況がわかる。
v7.5.0で 99% カバーしている。

インストール

Node.jsのインストール方法は以下の「anyenv」を参照。

blog.pepese.com

プロキシの設定が必要な場合は以下。

$ npm config set proxy http://<username>:<password>@<proxy-host>:<proxy-port>
$ npm config set https-proxy http://<username>:<password>@<proxy-host>:<proxy-port>

ndenv

上記の手順でNode.jsを導入した場合、Node.jsのバージョンを ndenv でコントロールする。

$ ndenv install -l # インストールできるNode.jsのバージョン確認
$ ndenv install v7.5.0 # バージョンを指定してインストール
$ ndenv versions # インストールされたことを確認
$ ndenv global v7.5.0 # バージョンを切り替え
$ ndenv local v7.5.0 # 今いるプロジェクトだけバージョンを指定したい場合はこっち
$ node -v # 確認

npmの使い方

公式ドキュメントはここ

プロジェクトの作成

任意のディレクトリを作成して npm init を実行すると package.json が作成され、プロジェクトとなる。
いろいろ聞かれるが、全部Enterで問題無い。あとで変更可能。

$ mkdir nodejs-sample
$ cd nodejs-sample
$ npm init

package.json はMavenでいう pom.xml みたいなもの。(Javaの人向けでごめん)

パッケージのインストール

グローバルインストール

npm install -g <package_name>@<version> でパッケージのインストールが可能。
-g オプションがついてるのがポイント。
アンインストールは npm uninstall -g <package_name>
インストールパッケージ一覧の確認は npm list -g

インストール先は以下で確認できる。

# グローバルインストール先のディレクトリ
$ npm root -g

# グローバルインストール先の、コマンドディレクトリ
$ npm bin -g

ローカルインストール

npm install <option> <package_name>@<version> でパッケージのインストールが可能。
インストールしたパッケージは package.json に追記され、 node_modules/ 配下に配備される。
オプションは以下の通り。

  • --save-S
    • package.jsondependencies に追記される
    • npm install --production した時に mode_modules/ に配備される
    • 開発したソフトウェアを動かすのに必要な依存ライブラリ
  • --save-dev-D
    • package.jsondevDependencies に追記される
    • npm install --dev した時に mode_modules/ に配備される
    • ソフトウェアを開発する際に必要になるツール・ライブラリ
  • --save-optional-O
    • package.jsonoptionalDependencies に追記される
    • npm install した時に mode_modules/ に配備される(失敗してもスルーされる)

デフォルト設定の場合、 npm install (オプション無)すると、 dependenciesdevDependenciesoptionalDependencies の全てがインストールされる。
アンインストールは npm uninstall <package_name>
インストールパッケージ一覧の確認は npm list

パッケージの使い方

npmで導入したJavaScriptライブラリ( node_modules/ 配下にある)は、JavaScriptのソースコードからほぼ以下の形式で呼び出すことができる。

var req = require('request')

上記は request モジュールを呼び出して req 変数へ代入している例。

npmスクリプト

package.jsonscripts にスクリプトを登録することにより簡易に実行することができる。
例えば以下。

"scripts": {
  "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/",
  "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/",
  "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
  "test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/"
  }

上記のようにスクリプトを定義することにより npm testnpm test-ci といった具合で登録したスクリプトを実行することができる。

Node.jsの使い方

Node.jsのAPIリファレンスはここ

シンプルに動かしてみる

まず、Node.jsをJavaScriptエンジンとしてシンプルに動かしてみる。

■hello.js

■main.js

上記JSファイルを作成して下記を実行。

$ node main.js
Hello World !

node <JSファイル> コマンドで実行できる。

HTTPサーバ

Node.jsでHTTPサービスを立ち上げてみる。

■app.js

下記を実行してブラウザで http://127.0.0.1:1337/ へアクセスすると「Hello World !」と表示される。

$ node app.js

Ctr+C でサービスを停止できる。
この方法でHTTPサービスを起動した場合、ロジックでエラーが発生するとプロセスが終了する。
エラーが発生してもプロセスが終了しないようにする方法の1つとして forever の導入がある。

■foreverのインストール、起動、停止

$ npm install -g forever
$ forever start app.js
$ forever stop app.js

Node.jsに関する話題

Spring BootでJUnitテスト

Java Spring SpringBoot JUnit Maven

Spring Bootのテストについて書く。
spring-boot-starter-testを使用するとコントローラのJUnitテストも可能になる。
テストやコードインスペクションレポートのMaven設定は以下を参照。

blog.pepese.com

テスト対象アプリ

以下の記事で紹介した入門アプリをテスト対象とする。

blog.pepese.com

テストの作成

以下を作成する。

  • com.pepese.sample.service.HelloServiceTest
    • コントローラへDIされるサービスクラスのテスト
  • com.pepese.sample.controller.HelloControllerTest
    • コントローラのテスト

サービスのテスト(com.pepese.sample.service.HelloServiceTest)

ポイントは以下。

  • @RunWith(SpringRunner.class) アノテーション
    • Spring BootでJUnitテストするときはコレをつける
  • @SpringBootTest アノテーション
    • SpringのJava/XML Based Configurationなどの設定を読み込んでくれる

Springの設定(Java/XML Based Configuration)を読み込んでいるのでDIでテスト対象のインスタンスを取得できる。

コントローラのテスト(com.pepese.sample.controller.HelloControllerTest)

ポイントは以下。

  • @AutoConfigureMockMvc アノテーションをつけるとコントローラ層のモック( MockMvc )を作成でき、これでコントローラのJUnitテストが可能になる
    • @WebMvcTest(HelloController.class) としてコントローラクラスを指定することもできる
  • @MockBean でコントローラ内でDIされるモジュールのモック(Mockito)を作成できる
  • when メソッド等(Mockito)を使用してコントローラ内にDIされたモジュールの挙動を指定できる
  • HamcrestのMatchersを使用してassertする

テストの実行

基本的には mvn test で実行可能だが、特定のクラスを指定してテストしたい場合は mvn clean test -Dtest=*.HelloControllerTest のように指定して実行できる(正規表現の指定可能)。
また、 mvn clean test -Dtest=*.HelloControllerTest,*HelloServiceTest のようにカンマ区切りで複数指定することもできる。