★ はじめに
Springの勉強と並行してNode.jsとReactの学習も進めているのですが、フロント側は苦手意識があるせいか進捗が悪いです。
例のごとく作業メモ兼勉強記録の記事になります。
★ やりたいこと
掲題ママ。
◆ SpringBoot+gradle REST+JSON形式のAPIを呼び出してみる
で作成したAPIをフロント側でコールする処理の実装を行います。
ところで業務では基本サーバサイド、独自のフレームワークを使ったAPI開発をメインで行っています。バッチからAPIをコールする処理を実装した経験はあっても、フロント側、画面からAPIをコールする処理を実装をする経験はなかなかないので、いい勉強になりました。
★ API側(SpringBoot)
package com.example.sample.app.controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.sample.app.resource.BirthStone;
@RestController
@CrossOrigin(origins = "*") // ★変更点
@RequestMapping("api/sample")
public class RestApiController {
@RequestMapping(value = "/getBirthStone", method = RequestMethod.GET)
@ResponseBody
public BirthStone getBirthStone() {
BirthStone birthStone = new BirthStone("2月", "アメジスト", "紫");
return birthStone;
}
}
実際に画面から呼んだ際に、
「クロスオリジン要求をブロックしました: 同一生成元ポリシーにより、【※APIのURL】 にあるリモートリソースの読み込みは拒否されます (理由: CORS ヘッダー ‘Access-Control-Allow-Origin’ が足りない)。[詳細]」
なんてエラーメッセージがコンソールに出力されたのでなんじゃそりゃ、と思ったらCORSでエラーになっていたみたいです。
不勉強のためまずCORSという言葉を初めて知りました。
いまだに把握しきれていないので、後日勉強予定。余力があれば記事にしたいです。
@CrossOrigin
アノテーションをつけることで、CORSを制御できるとのこと。
origins
(Access-Control-Allow-Origin)は"*"(ワイルドカード)を設定。
ローカルで起動します。ポートはデフォルトの8080。
★ 画面側(React)
// プロジェクト作成
create-react-app call_api_sample
// プロジェクトに移動
cd call_api_sample
// node-fetchのインストール
npm install --save node-fetch
// サーバ起動
npm start
プロジェクトを作成し、FetchAPIを使いたかったのでインストールしました。
サーバを起動します。ポートはデフォルトの3000。
import React, { Component } from 'react';
import fetch from 'node-fetch';
import './App.css';
class App extends Component {
constructor (props) {
super(props)
this.state = {
month: '',
name: '',
color: ''
}
}
componentWillMount () {
const URL = 'http://localhost:8080/api/sample/getBirthStone'
fetch(URL, {mode: 'cors'})
.then(res => res.json())
.then(json => {
this.setState({
month: json['month'],
name: json['name'],
color: json['color']
})
});
}
render() {
return <div className='App'>
month: {this.state.month} <br />
name: {this.state.name} <br />
color: {this.state.color} <br />
</div>
}
}
export default App;
別のjsファイル作ろうかと思いましたが簡単な疎通確認程度でしたので、App.jsを書き換えました。
constructor
でmonth、name、colorの初期化(空)を行っています。
componentWillMount
(コンポーネント作成前に実行される処理)でAPIを呼び出し、レスポンス値をmonth、name、colorに詰めています。
CORS対応するため、mode
には'cors'を設定。
★ 実行結果
http://localhost:3000/
にアクセスすると...
APIのレスポンス値が画面に表示されました。
★ 参考
本記事の執筆にあたり、以下書籍・記事を参考にさせていただきました。
いまどきのJSプログラマーのための Node.jsとReactアプリケーション開発テクニック
CORSまとめ
【JavaScript基礎】Fetch APIの基礎 - KDE BLOG
Node.jsでfetchを使えるようにする
お疲れさまXMLHttpRequest、こんにちはfetch