LoginSignup
1
0

More than 1 year has passed since last update.

【Angularアプリケーション開発 #8】フロントエンドとバックエンドを繋げてみよう

Posted at

目的

フロントエンドとバックエンドを疎通させること。
実際の開発現場に近い環境を再現し、経験と知識を増やすこと。

今回やること

なんちゃって従業員管理を作ります。
従業員一覧をDBから取得して、webページで表示するといった内容になります。
↓今回作ったwebページです。
image.png

開発言語とフレームワーク

フロントエンド:javascript、typescript
フロントエンドフレームワーク:angular
バックエンド:java
バックエンドフレームワーク:spring boot
DB:mysql
※DBはdockerのコンテナに構築しています。ローカルに直でインストールしていても問題はありません。

フロントエンド

MenbersComponentを作成します。
ngOnInitでバックエンドにリクエストを送る処理を行っています。
レスポンスとして返ってくるのは従業員のidとnameです。
それをmembersに設定しています。
html側ではmembersをループさせてメンバーリストを作成しています。

members.component.ts
import { Component, OnInit } from '@angular/core';
import { Member } from '../member';
import { MEMBER } from '../mock-member';

@Component({
  selector: 'app-members',
  templateUrl: './members.component.html',
  styleUrls: ['./members.component.css']
})
export class MembersComponent implements OnInit {

  members;
  selectedMember: Member;

  constructor() { }

  ngOnInit(): void {
    const myAsync = async (url) => {
      const response = await fetch(url); //await で fetch() が完了するまで待つ
      const data = await response.json(); //await で response.json() が完了するまで待つ
      return data;
    }
    myAsync('http://localhost:8080/api/getUserInfo').then(value => this.members = value).catch((err) => console.log("データ取得に失敗"));
  }

  onSelect(member:Member): void{
    this.selectedMember = member;
  }

}
members.component.html
<h2>従業員一覧</h2>

<ul class="members">
  <!-- (click)はイベントバインディング -->
  <li
   *ngFor="let member of members"
   [class.selected]="member === selectedMember"
    (click)="onSelect(member)"
  >
    <span class="badge">{{member.id}}</span> {{member.name}}
  </li>
</ul>
<app-member-detail [member] = "selectedMember"></app-member-detail>

バックエンド

プロジェクト構成

spring bootのプロジェクト作成については今回は省略します。
image.png

srcの説明

UserInfoApi.java

@GetMapping("api/getUserInfo")
⇒フロントでリクエストに使用するエンドポイントを定義しています。
jdbcTemplate.queryForList("select id,name from userinfo");
⇒DBへ投げるsqlです。
@CrossOrigin
⇒これをつけておかないとレスポンスが返ってきません。
 詳細は省略しますが、要は異なるオリジン間の通信を許可しています。
 オリジンとはhttp://~/api/get〇〇:8080のようなurlのことです。
 フロントエンドとバックエンドは使用しているportが異なるので、
 こちらのアノテーションが必要になります。

UserInfo.java

役割としてはDBから取得した値とjava側からフロントエンドでの返却値を格納する箱になります。

ApitestApplication.java

main関数があるので、javaを起動するためには必要なクラスになるのだと思っています。

ServletInitializer.java

こちらは何をしているのかわかりませんが、必要になったら調べます。

UserInfoApi.java
package com.example.demo.api;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.entity.UserInfo;

@RestController
@CrossOrigin
public class UserInfoApi {

	@Autowired
	JdbcTemplate jdbcTemplate;

    @GetMapping("api/getUserInfo")
    public List<UserInfo> getHoge() {
    	List<Map<String,Object>> userInfoListMap;
    	List<UserInfo> userInfoList = new ArrayList<UserInfo>();
        userInfoListMap = jdbcTemplate.queryForList("select id,name from userinfo");
        //listの中のmapを取り出す
        for(Map<String,Object> map:userInfoListMap) {
        	UserInfo info = new UserInfo();
        	info.setId((int) map.get("id"));
        	info.setName((String) map.get("name"));
        	userInfoList.add(info);
        }
        return userInfoList;
    }
}
UserInfo.java
package com.example.demo.entity;

public class UserInfo {

    private int id;
    private String name;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
ApitestApplication.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ApitestApplication {

	public static void main(String[] args) {
		SpringApplication.run(ApitestApplication.class, args);
	}
}
ServletInitializer.java
package com.example.demo;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(ApitestApplication.class);
	}
}

DB

userinfoでテーブルを作成しています。
image.png

詰まった部分

spring bootでDBを使用するのであれば、DBは疎通できる状態で待機しておく必要があります。
というのもpom.xmlでDBに関するライブラリを定義しているのですが、DBに接続できる状態でないとビルドは通りますが、実行時にエラーになります。ちなみにDB接続情報はapplication.propertiesにあるので、こちらもdb名やら間違わないように書く必要があります。
私はjavaのバージョンが異なるのかと思い込んで苦戦しました。
エラー内容の抜粋↓
CommunicationsException: Communications link failure

まとめ

今回は、従業員情報を取得するだけでしたが、改良すれば登録、削除、更新等もできそうです。
一連の疎通ができたわけですが、細かい部分をあまり追及せず、まずは目的を達成することが大事だと感じました。
仕事で実際に作業をする場合は、既に開発環境が出来上がっている状態が多いので、今回のように一から作っていくのは貴重な体験でした。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0