Java
Node.js
spring-boot
React

◆ Spring Bootで作成したAPIをReactからGETする


★ はじめに

Springの勉強と並行してNode.jsとReactの学習も進めているのですが、フロント側は苦手意識があるせいか進捗が悪いです。

例のごとく作業メモ兼勉強記録の記事になります。


★ やりたいこと

掲題ママ。

◆ SpringBoot+gradle REST+JSON形式のAPIを呼び出してみる

で作成したAPIをフロント側でコールする処理の実装を行います。

ところで業務では基本サーバサイド、独自のフレームワークを使ったAPI開発をメインで行っています。バッチからAPIをコールする処理を実装した経験はあっても、フロント側、画面からAPIをコールする処理を実装をする経験はなかなかないので、いい勉強になりました。


★ API側(SpringBoot)


RestApiController.java

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という言葉を初めて知りました。

いまだに把握しきれていないので、後日勉強予定。余力があれば記事にしたいです。

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/CrossOrigin.html

@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。


App.js

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/

にアクセスすると...

WS000006.JPG

APIのレスポンス値が画面に表示されました。


★ 参考

本記事の執筆にあたり、以下書籍・記事を参考にさせていただきました。

いまどきのJSプログラマーのための Node.jsとReactアプリケーション開発テクニック

CORSまとめ

【JavaScript基礎】Fetch APIの基礎 - KDE BLOG

Node.jsでfetchを使えるようにする

お疲れさまXMLHttpRequest、こんにちはfetch