JavaのStream APIを触ってみた
読み込んだテキストファイルのうち「#」で始まる行と空行を除外するという処理を、せっかくだからStream APIで実装してみた。
Stream APIを使わなかった場合は以下の通り。
List<String> result = new ArrayList<>(); // 対象のテキストファイルを読み込んで、各行の内容を含んだListを受け取る List<String> lines = readAllLines(); for (String line: lines) { // #から始まる行は読み飛ばす if (line.trim().startsWith("#")) { continue; } // 空行も読み飛ばす if (line.trim().length()==0) { continue; } result.add(line); }
これがStream APIを使うと以下の通り。
// 対象のテキストファイルを読み込んで、各行の内容を含んだListを受け取る List<String> lines = readAllLines(); List<String> result = lines.stream() .filter(line -> !(line.trim().startsWith("#"))) // #から始まる行は読み飛ばす .filter(line -> !(line.trim().length()==0)) // 空行も読み飛ばす .collect(Collectors.toList());
実にシンプル。
これは気持ち良いかも。
for文禁止にしたい気持ちが、今更ながらわかってきた。
Gitの設定ファイル
以下のサイトを見ながら自分の言葉でまとめてみた。
Git - Git の設定
Gitの設定方法
下記のようにgitコマンドを使ってGitの設定を変更することが出来る。
git config [設定先] [設定項目] [設定値]
例えばユーザー名として「John Doe」を設定するなら、設定項目が「user.name」、設定値が「John Doe」となり、コマンドは以下のようになる。
git config --global user.name "John Doe"
これでグローバル域にユーザー名「John Doe」を設定したことになる。
あとは、設定先を切り替えることで使いやすい設定にカスタマイズすれば良い。
続いてその設定先についてまとめる。
3段構えの設定先
Gitの設定先は3段構えとなっている。
- システム:インストールしたGit本体に対する設定
- グローバル:ユーザー単位での設定
- ローカル:リポジトリ単位での設定
上から順にスコープが狭くなる。
それぞれを掘り下げてみてみる。
システム
インストールしたGit本体に対する設定で、Linux系だと下記のファイルに設定内容が書き込まれる。
/etc/gitconfig
Windowsの場合はGitのインストールフォルダの下記のファイルに設定内容が書き込まれる。
[インストールフォルダ]/etc/gitconfig
gitコマンドはまずこのファイルに記載した設定を読み込む。
[設定先]に使用するパラメータは「--system」となり、以下のように設定する。
git config --system core.autocrlf true
まとめ
3つの設定をまとめると下記のようになる。
git config --system [システムへの設定] git config --global [グローバルへの設定] git config --local [ローカルへの設定]
設定できる項目や設定に関することについては冒頭のGitのサイトや下記コマンドで表示するマニュアルページに詳しくあるので、そちらを参照。
git config --help
GitBucket 3.2 を試す
「Scalaで実装されたオープンソースのGitHubクローン」のGitBucketのインストールが予想以上に簡単だったので、メモを残す。
今回入れるGitBucketの3.2。
GitBucketのサイトは下記の通り。
https://github.com/takezoe/gitbucket
事前準備
Scalaで実装されているので、Javaが入っていないとならない。
今回はJava8(Update31)で試した。
(Javaのインストールフォルダのbinフォルダにパスを通しておきましょう)
続いてGitBucket本体のダウンロード。
GitBucketのwarファイルをGitBucketのサイトからダウンロードする。
GitBucket 3.2は下記URLでダウンロードできる。
https://github.com/takezoe/gitbucket/releases/download/3.2/gitbucket.war
準備に必要なのはこの2点。
GitBucketの実行
GitBucketの実行は下記のコマンドで行う。
java -jar gitbucket.war
これだけ。
GitBucketには組み込みWebサーバのJettyを使っているため、上記のようにJARファイルを実行するとGitBucketをデプロイ済みのWebサーバーが起動する。
GitBucketへアクセスする
ブラウザを起動して、起動したサーバーもしくはローカルホストのポート8080にアクセスする。
http://localhost:8080/
以下のようなログイン画面が表示されれば正常に起動したことになる。
あとは初期ユーザroot(パスワードもroot)でログインして、ユーザ追加やグループの追加等の設定を行う。
その他
GitBucketのサイトにある通り、javaコマンドで起動する際にパラメータを与えることが出来る。
自分が真っ先に行ったのは「--gitbucket.home」の設定。
初期状態では実行ユーザのホームディレクトリにGitBucketの設定とリポジトリが作成される。
ホームディレクトリ以外をGitBucketの作業場所とするには、下記のように起動パラメータを与える。
java -jar gitbucket.war --gitbucket.home=D:\GitBucket
起動すると、D:\GitBucketに設定内容を保存したデータベースファイル(H2かな?)とリポジトリフォルダなどが作成される。
ここまでが初期設定。
さて、Git使ってみるぞ。
Spring Boot/第五回 Spring Bootで Web (一覧表示)
Spring BootでWebの画面を作ってみる。
まずは顧客一覧画面から。
Contrller
ブラウザからのリクエストを受け取ってビジネスロジック呼んでブラウザにレスポンスを返すのがコントローラの役目。
コントローラは以下のようになる。
package tools.springsample.springsample05.web; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import tools.springsample.springsample05.domain.Customer; import tools.springsample.springsample05.service.CustomerService; @Controller // a @RequestMapping("customer") // b public class CustomerContrller { @Autowired private CustomerService customerService; @RequestMapping(method=RequestMethod.GET) // c public String list(Model model) { // d List<Customer> customers = customerService.findAll(); model.addAttribute("customers", customers); // e return "customer/list"; // f } }
a -> コントローラであることを記すアノテーション。
b -> コントローラがリクエストを受け取るURLを「customer」と定義する。
c -> URLの「customer」にGETメソッドが送られたときに実行するメソッドであることを記すアノテーション。
d -> 画面に値を渡すModelを引数に受け取る。
e -> ビジネスロジックの顧客一覧取得結果をモデルにセットする。
f -> 画面のテンプレート「customer/list.html」を呼び出す。
@Controllerアノテーションでコントローラであることを宣言して、@RequestMapping("customer")アノテーションで受け取るURLを定義して、@RequestMapping(method=RequestMethod.GET)アノテーションでHTTPメソッドの何を受け取って処理するメソッドかを宣言すると、そのメソッド(今回だとCustomerContrllerクラスのlistメソッド)が呼ばれる。
リクエスト処理(listメソッド)内では処理結果をモデルにセットして結果を表示するURLを戻り値で返せば、後のテンプレートへ処理結果を引き継げる。
今回は処理結果として、CustomerServiceで提供している顧客リスト取得メソッド(findAllメソッド)の結果をModelに「customers」という名前でセットした。
テンプレート
動的なページの作成に「Thymeleaf」(タイムリーフ)というテンプレートエンジンを使用する。
HTMLに「th:xxx」や「data-th:xxx」などのタグを入れるとThymeleafが適切な値に置き換えてくれる。
HTMLのテンプレートは下記のフォルダに置く。
src/main/resources/template
コントローラで「customer/list」と返しているので、対象のテンプレートは下記のファイルとして記述する。
src/main/resources/template/customer/list.html
まず普通のHTMLとして表示する画面を下記のようにする。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>顧客一覧</title> <style type="text/css"> .list th { background-color: #cccccc; padding: 5px; } .list td { padding: 5px; } </style> </head> <body> <table class="list"> <tr> <th>ID</th> <th>氏名</th> <th>アドレス</th> </tr> <tr> <td>xx</td> <td>name</td> <td>address</td> </tr> </table> </body> </html>
このHTMLをブラウザで開くと下記の通り。
続いてHTMLにThymeleafで処理を書いて動的な結果を出力するように変える。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org/"> <!-- a --> <head> <meta charset="UTF-8"/> <title>顧客一覧</title> <style type="text/css"> .list th { background-color: #cccccc; padding: 5px; } .list td { padding: 5px; } </style> </head> <body> <table class="list"> <tr> <th>ID</th> <th>氏名</th> <th>アドレス</th> </tr> <tr th:each="customer:${customers}"> <!-- b --> <td th:text="${customer.id}">xx</td> <!-- c --> <td th:text="${customer.name}">name</td> <!-- d --> <td th:text="${customer.email}">address</td> <!-- e --> </tr> </table> </body> </html>
a -> Thymeleafの名前空間を宣言。
b -> コントローラでModelにセットしたリスト「customers」を取得して「th:each」で件数分ループさせる。
ループ中の要素へアクセスするキーとして「customer」を指定する。
c -> 上で要素へのアクセスキー「customer」からIDを取得。
customersはCustomerクラスのリストなので、Customerクラスのフィールドidのゲッターメソッド結果をTDタグの値として当てはめる。
d -> Customerクラスのフィールドnameのゲッターメソッド結果をTDタグの値として当てはめる。
e -> Customerクラスのフィールドemailのゲッターメソッド結果をTDタグの値として当てはめる。
Thymeleafの処理を追記したこのHTMLをブラウザで開くと下記の通り。
追記前と変わらない。
つまりThymeleafの記述はブラウザには影響しない。
そのため、WebデザイナーとWebデベロッパーが分業して作業を進めることができる。
WebデザイナーがHTMLを書いて、そのあとWebデベロッパーがThymeleafの記述を追記する。
そのあとでもWebデザイナーはHTMLをブラウザで開いて表示内容を確認できるのでデザインを変更することもできる。
コンパイルして実行
以下のようにコンパイルする。
mvn package
続いて起動
mvn spring-boot:run
ブラウザで下記のアドレスにアクセスする。
http://localhost:8080/customer
するとデータベースの内容を読み込んで下記のように結果を表示する。
まとめ
コントローラとテンプレートを作って動的な画面を表示してみた。
次回はフォームを使って更新系の画面を試してみる。
■ 参考文献 ■
この記事で参考にしたのは「はじめての Spring Boot」です。
はじめてのSpring Boot―「Spring Framework」で簡単Javaアプリ開発 (I・O BOOKS)
- 作者: 槇俊明
- 出版社/メーカー: 工学社
- 発売日: 2014/11
- メディア: 単行本
- この商品を含むブログ (5件) を見る
Spring Boot/第四回 Spring Bootで REST(POST時のLocation設定)
RESTではPOSTでデータを新規作成した時は、そのデータにアクセスするURLをLocationヘッダーで返すのが一般的とのことで、それを試してみる。
新規にデータを登録して、オートインクリメントに設定したプライマリキー「ID」が「5」として登録できたら、以下のURLを返すということ。
api/customer/5
CustomerRestController の postCustomer メソッドを以下のように修正する。
@RequestMapping(method=RequestMethod.POST) public ResponseEntity<Customer> postCustomer(@RequestBody Customer customer, UriComponentsBuilder uriBuilder) { // a Customer createdCustomer = service.create(customer); // b // Locationで設定するURLを作成する URI location = uriBuilder.path("api/customer/{id}") // c .buildAndExpand(createdCustomer.getId()) // d .toUri(); // レスポンスのHTTPヘッダー HttpHeaders headers = new HttpHeaders(); headers.setLocation(location); // e // レスポンス情報を作成 return new ResponseEntity<>( createdCustomer, headers, HttpStatus.CREATED); // f }
a -> URI作成用クラスを引数で受け取る。
b -> 顧客情報の登録。
c -> プレースホルダ付の作りたいURLを指定する。
d -> プレースホルダに登録したIDを当てはめる。
e -> HTTPヘッダーにLocationのURLを設定。
f -> HTTPボディに createdCustomer の内容、
HTTPヘッダーに headers の内容、
HTTPステータスに CREATED を指定。
ビルドして Spring Boot を起動して curl で以下のように登録をする。
curl http://localhost:8080/api/customer -v -X POST -H "Content-Type: application/json" -d "{\"name\":\"name04\", \"email\":\"name04@test\"}"
実行結果は下記の通り。
# curl http://localhost:8080/api/customer -v -X POST -H "Content-Type: application/json" -d "{\"name\":\"name04\", \"email\":\"name04@test\"}" * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > POST /api/customer HTTP/1.1 > User-Agent: curl/7.41.0 > Host: localhost:8080 > Accept: */* > Content-Type: application/json > Content-Length: 40 > * upload completely sent off: 40 out of 40 bytes < HTTP/1.1 201 Created < Server: Apache-Coyote/1.1 < Location: http://localhost:8080/api/customer/4 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Fri, 03 Apr 2015 16:09:41 GMT < {"id":4,"name":"name04","email":"name04@test"}* Connection #0 to host localhost left intact
レスポンスヘッダーに今までなかった下記が追加されている。
< Location: http://localhost:8080/api/customer/4
うまく出来たようだ。
ちなみに、プレースホルダを解決する buildAndExpand メソッドには Map を引数に指定もできる。
// プレースホルダ解決用Map Map<String, Integer> map = new HashMap<>(); map.put("id", createdCustomer.getId()); // Locationで設定するURLを作成する URI location = uriBuilder.path("api/customer/{id}") // c // .buildAndExpand(createdCustomer.getId()) // d .buildAndExpand(map) // d .toUri();
プレースホルダの「{id}」を Map のキーにして値を当てはめてくれる。
■ 参考文献 ■
この記事で参考にしたのは「はじめての Spring Boot」です。
はじめてのSpring Boot―「Spring Framework」で簡単Javaアプリ開発 (I・O BOOKS)
- 作者: 槇俊明
- 出版社/メーカー: 工学社
- 発売日: 2014/11
- メディア: 単行本
- この商品を含むブログ (4件) を見る
Spring Boot/第四回 Spring Bootで REST
Spring Bootを使うと、RESTの実装が簡単に出来るので試してみる。
試しに簡単な顧客管理のシステムを実装する。
REST
REST について、詳しい説明は他のサイトを参照してほしいが、要は CRUD のそれぞれを HTTP メソッドで表現するWebサービスの考え方のこと。
CRUD | HTTPメソッド |
---|---|
Create | POST |
Read | GET |
Update | PUT |
Delete | DELETE |
何に対する CURD 操作なのかは URL で表す。
たとえば /api/customer に対して GET を送ると「顧客情報の取得」といった具合。
今回は下記の実装を試してみる。
API名 | HTTPメソッド | リソースパス | 正常時HTTPレスポンスステータス |
---|---|---|---|
顧客全件取得 | GET | /api/customer | 200 OK |
顧客一件取得 | GET | /api/customer/{id} | 200 OK |
顧客一件作成 | POST | /api/customer | 201 CREATED |
顧客一件更新 | PUT | /api/customer/{id} | 200 OK |
顧客一件削除 | DELETE | /api/customer/{id} | 204 NO CONTENT |
{id}の部分にユニークなIDを渡して特定の顧客を取得したり更新したり削除したりする。
Maven
pom.xmlに追加する依存関係は下記の通り。
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <!-- a --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <!-- b --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <!-- c --> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> <dependency> <!-- d --> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.14.0</version> <scope>provided</scope> </dependency> </dependencies>
a -> Spring BootでWebアプリを作成するための依存関係。
b -> Spring BootでJPAを扱うための依存関係。
c -> H2の依存関係。
d -> Lombokの依存関係。
Repository
階層の一番下。
Repositoryから実装する。
まずは顧客情報を入れるデータベースの設定から。
pom.xmlに書いた依存関係の通り、データベースはH2を使用する。
プロジェクトがあるフォルダから相対パスで testdb フォルダ内に H2 のデータベースを作成する。
src/main/resources/application.yml に下記を記載。
spring: datasource: driverClassName: org.h2.Driver url: jdbc:h2:file:testdb/testdb username: sa password: jpa: hibernate: ddl-auto: none
データソースの URL の通り、testdb フォルダ内に testdb というデータベースファイルを指定する。
JPA プロバイダは Hibernate を使用するので、その設定も併せて行う。
続いてテーブル定義。
DDL は下記の通りで src/main/resources/schema.sql に記載する。
create table if not exists customer ( id int primary key auto_increment, name varchar(50) not null, email varchar(50) not null );
id -> プライマリキー。オートインクリメントで一意の値を自動で割り当てる。
name -> 名前を格納。
email -> メールアドレスを格納。
Hibernate はエンティティクラスからテーブルを自動作成する機能があるが、application.yml の「ddl-auto: none」の通り作成は行わない。
そのかわり、Spring Boot の機能で schema.sql に DDL を書いて、そちらでテーブルを作ってもらう。
続いてエンティティ定義。
src/main/java/toolsspringsample/springsample04/domain/Customer.java に記載する。
package tools.springsample.springsample04.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Entity // a @Table(name="customer") // b @Data // c @AllArgsConstructor // d @NoArgsConstructor // e public class Customer { @Id // f @GeneratedValue // g private Integer id; @Column(nullable=false) // h private String name; @Column(nullable=false) // h private String email; }
JPAの記述とLombokの記述が入り乱れているので注意が必要。
a -> JPA: エンティティクラスであることを記すアノテーション。
b -> JPA: どのテーブルとマッピングするのか指定する。
c -> Lombok: すべてのフィールドに対するsetter/getterメソッド、equalsメソッド、hashCodeメソッド、toStringメソッドが生成される。
d -> Lombok: すべてのフィールドを初期化する引数を持つコンストラクタが生成される。
e -> Lombok: 引数なしのデフォルトコンストラクタが生成される。
f -> JPA: フィールドidがエンティティの主キーであることを表す。
g -> JPA: 自動採番する主キーであることを表す。
h -> JPA: テーブルに該当するカラムであることを表す。nullでの更新を抑制する。
最後にリポジトリ定義。
src/main/java/toolsspringsample/springsample04/repository/CustomerRepository.java に記載する。
package tools.springsample.springsample04.repository; import tools.springsample.springsample04.domain.Customer; import org.springframework.data.jpa.repository.JpaRepository; public interface CustomerRepository extends JpaRepository<Customer, Integer> { // a }
a -> JpaRepositoryを拡張したインターフェースを定義。
まだ複雑な実装がないので、定義はとてもシンプル。
JpaRepositoryを拡張すると、実行時に実装クラスが自動生成される。
ジェネリクスで永続化対象のクラス「Customer」を指定し、キー項目の型を「Integer」と指定する。
Service
サービスはビジネスロジックを書くが、今回は処理らしい処理は書かずに下位層のリポジトリの呼び出しのみを行う。
src/main/java/toolsspringsample/springsample04/service/CustomerService.java に記載する。
package tools.springsample.springsample04.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import tools.springsample.springsample04.domain.Customer; import tools.springsample.springsample04.repository.CustomerRepository; @Service // a @Transactional // b public class CustomerService { @Autowired // c CustomerRepository repository; // d // 顧客全件取得 public List<Customer> findAll() { // e return repository.findAll(); } // 顧客一件取得 public Customer findOne(Integer id) { // f return repository.findOne(id); } // 顧客一件作成 public Customer create(Customer customer) { // g return repository.save(customer); } // 顧客一件更新 public Customer update(Customer customer) { // h return repository.save(customer); } // 顧客一件削除 public void delete(Integer id) { // i repository.delete(id); } }
a -> サービスクラスであることを記すアノテーション。
b -> トランザクションを扱うクラスであることを記すアノテーション。
DIからの CustomerService クラスのメソッド呼び出し時に自動的にトランザクション処理を行う。
つまり例外が発生したらロールバックし、発生しなかったらコミットする。
c -> DIコンテナからインスタンスを取得する。
d -> リポジトリクラスの参照。
e -> 顧客全件取得処理。
f -> 顧客一件取得処理。
g -> 顧客一件作成処理。
h -> 顧客一件更新処理。
i -> 顧客一件削除処理。
このように今回は下位層のリポジトリの呼び出しのみを行う。
RestController
RestController は、URLと処理をマッピングし、そこからサービスの呼び出しを行う。
src/main/java/toolsspringsample/springsample04/api/CustomerRestController.java に記載する。
package tools.springsample.springsample04.api; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import tools.springsample.springsample04.domain.Customer; import tools.springsample.springsample04.service.CustomerService; @RestController // a @RequestMapping("api/customer") // b public class CustomerRestController { @Autowired // c CustomerService service; // d // 顧客全件取得 @RequestMapping(method=RequestMethod.GET) // e public List<Customer> getCustomer() { return service.findAll(); } // 顧客一件取得 @RequestMapping(method=RequestMethod.GET, value="{id}") // f public Customer getCustomer(@PathVariable Integer id) { return service.findOne(id); } // 顧客一件作成 @RequestMapping(method=RequestMethod.POST) // g @ResponseStatus(HttpStatus.CREATED) // h public Customer postCustomer(@RequestBody Customer customer) { return service.create(customer); } // 顧客一件更新 @RequestMapping(method=RequestMethod.PUT, value="{id}") // i public Customer putCustomer(@PathVariable Integer id, @RequestBody Customer customer) { customer.setId(id); return service.update(customer); } // 顧客一件削除 @RequestMapping(method=RequestMethod.DELETE, value="{id}") // j @ResponseStatus(HttpStatus.NO_CONTENT) // k public void deleteCustomer(@PathVariable Integer id) { service.delete(id); } }
a -> RESTコントローラクラスであることを記すアノテーション。
b -> URL(api/customer)とマッピングさせることを定義。
c -> DIコンテナからインスタンスを取得する。
d -> サービスクラスの参照。
e -> 顧客全件取得処理を HTTP の GET メソッドとマッピングする。
f -> 顧客一件取得処理を HTTP の GET メソッドとマッピングする。
URLの最後に付加したIDを取得し、@PathVariable でその URL の ID と引数をマッピングする。
g -> 顧客一件作成処理を HTTP の POST メソッドとマッピングする。
POST 時の HTTP ボディを @RequestBody で引数とマッピングする。
h -> 正常時のレスポンスコードを CREATED (201) とする
i -> 顧客一件更新処理を HTTP の PUT メソッドとマッピングする。
URLの最後に付加したIDを取得し、@PathVariable でその URL の ID と引数をマッピングする。
PUT 時の HTTP ボディを @RequestBody で引数とマッピングする。
j -> 顧客一件削除処理を HTTP の DELETE メソッドとマッピングする。
URLの最後に付加したIDを取得し、@PathVariable でその URL の ID と引数をマッピングする。
テスト用HTTPクライアント
REST を試すのに各種 HTTP メソッドをブラウザから送信するのは大変なので、コマンドラインから動作する HTTP クライアントの「curl」を使用する。
http://www.paehl.com/open_source/?Welcome
ブラウザでページを表示し、左側の「CURL」からダウンロード。
ZIPを解凍してコマンドにパスを通して動作できるようにする。
コンパイルして実行
以下のようにコンパイルする。
mvn package
続いて起動
mvn spring-boot:run
顧客一件作成
まずはcurlを使って顧客一件作成。
curl http://localhost:8080/api/customer -v -X POST -H "Content-Type: application/json" -d "{\"name\":\"name01\", \"email\":\"name01@test\"}"
curl コマンドのすぐ後で指定する URL が RestController の @RequestMapping の通りであることを確認。
-X で HTTP メソッドの「POST」を送り、CustomerRestControllerクラス の postCustomer メソッドを呼ぶ。
-H でボディの内容をJSONで送ることを指定。
-d でボディの内容を記載。
実行結果は下記の通り。
# curl http://localhost:8080/api/customer -v -X POST -H "Content-Type: application/json" -d "{\"name\":\"name01\", \"email\":\"name01@test\"}" * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > POST /api/customer HTTP/1.1 > User-Agent: curl/7.41.0 > Host: localhost:8080 > Accept: */* > Content-Type: application/json > Content-Length: 40 > * upload completely sent off: 40 out of 40 bytes < HTTP/1.1 201 Created < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Thu, 02 Apr 2015 17:28:06 GMT < {"id":1,"name":"name01","email":"name01@test"}* Connection #0 to host localhost left intact
最後の行に返ってきた JSON が出力されている。
読みやすくすると以下の通り。
{ "id":1, "name":"name01", "email":"name01@test" }
顧客一件更新
続いて顧客一件更新。
curl http://localhost:8080/api/customer/1 -v -X PUT -H "Content-Type: application/json" -d "{\"name\":\"name01_\", \"email\":\"name01_@test\"}"
URLの最後に更新対象のID「1」を指定する。これは先ほど追加したID。
-X で HTTP メソッドの「PUT」を送り、CustomerRestControllerクラス の putCustomer メソッドを呼ぶ。
-H でボディの内容をJSONで送ることを指定。
-d でボディの内容を記載。
「name01」の部分を「name01_」に変更するリクエストになる。
実行結果は下記の通り。
# curl http://localhost:8080/api/customer/1 -v -X PUT -H "Content-Type: application/json" -d "{\"name\":\"name01_\", \"email\":\"name01_@test\"}" * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > PUT /api/customer/1 HTTP/1.1 > User-Agent: curl/7.41.0 > Host: localhost:8080 > Accept: */* > Content-Type: application/json > Content-Length: 42 > * upload completely sent off: 42 out of 42 bytes < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Fri, 03 Apr 2015 03:08:44 GMT < {"id":1,"name":"name01_","email":"name01_@test"}* Connection #0 to host localhost left intact
最後の行に返ってきた JSON が出力されている。
読みやすくすると以下の通り。
{ "id":1, "name":"name01_", "email":"name01_@test" }
顧客一件削除
続いて顧客一件削除。
curl http://localhost:8080/api/customer/1 -v -X DELETE
URLの最後に削除対象のID「1」を指定する。これは先ほど追加したID。
-X で HTTP メソッドの「DELETE」を送り、CustomerRestControllerクラス の deleteCustomer メソッドを呼ぶ。
今回はボディは不要なので -H も -d もなし。
実行結果は下記の通り。
# curl http://localhost:8080/api/customer/1 -v -X DELETE * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > DELETE /api/customer/1 HTTP/1.1 > User-Agent: curl/7.41.0 > Host: localhost:8080 > Accept: */* > < HTTP/1.1 204 No Content < Server: Apache-Coyote/1.1 < Date: Fri, 03 Apr 2015 03:12:59 GMT < * Connection #0 to host localhost left intact
deleteCustomer メソッドで @ResponseStatus を NO_CONTENT にしているので戻り値のボディはなし。
顧客全件取得
実際に削除できたのか、顧客全件取得する。
curl http://localhost:8080/api/customer -v -X GET
全件取得なのでURLの最後にIDは指定しない。
-X で HTTP メソッドの「GET」を送り、CustomerRestControllerクラス の引数なしの getCustomer メソッドを呼ぶ。
実行結果は下記の通り。
# curl http://localhost:8080/api/customer -v -X GET * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > GET /api/customer HTTP/1.1 > User-Agent: curl/7.41.0 > Host: localhost:8080 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Fri, 03 Apr 2015 03:17:41 GMT < []* Connection #0 to host localhost left intact
テーブルに一件も入っていなので空のボディが返ってくる。
わかりにくいので下記を実行して 2 件追加する。
curl http://localhost:8080/api/customer -v -X POST -H "Content-Type: application/json" -d "{\"name\":\"name02\", \"email\":\"name02@test\"}" curl http://localhost:8080/api/customer -v -X POST -H "Content-Type: application/json" -d "{\"name\":\"name03\", \"email\":\"name03@test\"}"
もう一度、顧客全件取得する。
curl http://localhost:8080/api/customer -v -X GET
実行結果は下記の通り。
# curl http://localhost:8080/api/customer -v -X GET * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > GET /api/customer HTTP/1.1 > User-Agent: curl/7.41.0 > Host: localhost:8080 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Fri, 03 Apr 2015 03:28:03 GMT < [{"id":2,"name":"name02","email":"name02@test"},{"id":3,"name":"name03","email":"name03@test"}]* Connection #0 to host localhost left intact
読みやすくすると以下の通り。
{ "id":2, "name":"name02", "email":"name02@test" }, { "id":3, "name":"name03", "email":"name03@test" }
顧客一件取得
まだ実行していない処理、顧客一件取得を試す。
curl http://localhost:8080/api/customer/2 -v -X GET
URLの最後に取得対象のID「2」を指定する。これは先ほど追加したID。
-X で HTTP メソッドの「GET」を送り、CustomerRestControllerクラス の今度は引数ありの getCustomer メソッドを呼ぶ。
URLの最後に付加したIDを、@PathVariable で引数 id にマッピングする。
実行結果は下記の通り。
# curl http://localhost:8080/api/customer/2 -v -X GET * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > GET /api/customer/2 HTTP/1.1 > User-Agent: curl/7.41.0 > Host: localhost:8080 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Fri, 03 Apr 2015 03:36:28 GMT < {"id":2,"name":"name02","email":"name02@test"}* Connection #0 to host localhost left intact
読みやすくすると以下の通り。
{ "id":2, "name":"name02", "email":"name02@test" }
うん。
確かに 1 件だけ取得できた。
まとめ
RestController で REST のリクエストを取得し、
Service でビジネスロジックを書いて(今回は処理らしい処理は書いていないが)、
Repository で永続化をする。
ここまでを一気にまとめた。
次回は Controller と UI まわりをやってみよう。
■ 参考文献 ■
この記事で参考にしたのは「はじめての Spring Boot」です。
はじめてのSpring Boot―「Spring Framework」で簡単Javaアプリ開発 (I・O BOOKS)
- 作者: 槇俊明
- 出版社/メーカー: 工学社
- 発売日: 2014/11
- メディア: 単行本
- この商品を含むブログ (4件) を見る
Groovyにプロキシ設定
groovyコマンドに下記の引数を追加してプロキシサーバーを指定できる。
groovy -DproxyHost=xxx.xxx.xxx.xxx -DproxyPort=xxx
ただし、コマンドを実行するたびに引数を指定するのは面倒なので、ホームディレクトリに下記フォルダとファイルを作成して、そこに記述すると良い。
Windowsの場合
.groovy/preinit.bat
下記のように記述する。
set JAVA_OPTS=-DproxyHost=xxx.xxx.xxx.xxx -DproxyPort=3128
バッチファイルとして記述する。
UNIX/Linux系の場合
.groovy/startup
下記のように記述する。
JAVA_OPTS="-DproxyHost=xxx.xxx.xxx.xxx -DproxyPort=3128"
シェルとして記述する。
根拠
この辺りのパラメータはstartGroovyを見ると分かる。
Windowsの場合はstartGroovy.batの下記の記述。
if exist "%USERPROFILE%/.groovy/preinit.bat" call "%USERPROFILE%/.groovy/preinit.bat"
UNIX/Linux系の場合はstartGroovyの下記の記述。
GROOVY_STARTUP="$HOME/.groovy/startup" if [ -r "$GROOVY_STARTUP" ] ; then . "$GROOVY_STARTUP" fi
sourceしているのでstartupには実行権限はいらない。
(たぶん。Windowsでしか試していない・・・)