WINGSプロジェクト様より献本いただいてのレビューとなります。

 

独習C#はじめ、数多くの技術書を執筆されている著者によるJavaの入門書となります。

入門書といっても、およそ600ページと、なかなかの分量があり、プログラミングの初心者がプログラムというものを学ぶために、最初に手に取る本としては若干ハードルが高いかもしれません。

しかしながら、現在職業としてJavaを使っている立場として、これから職業としてJavaを使う必要があるプログラマーの初学者にはにオススメできる書籍だと思います。

なぜかと言うと、Javaという言語自体だけではなく、文字コード、浮動小数点数、コーディング規約、正規表現などについて若干踏み込んで解説されているということが最初に、挙げられます。

プログラムそのものをまず学ぼうとする初心者には、これらのテーマはJava言語の基本から少し遠いところにあるため、Javaの文法の説明に混ぜ込まれると、混乱してしまうかもしれません。

しかしながら、これらのテーマは、業務アプリケーションを開発するプログラマーを職業とするものにとっては、頻出、かつはまりやすいテーマであり、知っておくことが必須だと言えます。

次に、この著者の著作に共通するのですが、文章が平易で論理的であり文書の構造が理解しやすい、また、詳細に説明する部分と省略する部分のさじ加減が絶妙であることも文章の理解を助けるのに役立っていると思います。

実は、自分自身は本書の記述は教科書的で、熱量が足りない、もっと物語性とか知的好奇心をくすぐるような踏み込んだ記述が欲しいと思うところもあるのですが、これは、私が、Javaに関わって既に20年ほど経っているので、本書に記述されている内容について、既に理解している部分が多くあるため、新しく得る知識が少し物足りなく感じてしまったというのが理由です。

海外本の翻訳物には、物語性とか踏み込んだ詳細の記述など、読ませものが多いですが、初学者が全体像を論理的に学ぶには本書のスタイルが効率が良いと感じます。

というのも、Javaについては経験がありますが、初めて学ぶような言語、フレームワークなどについては、著者の他の書籍にも共通のこのスタイルに助けられているからです。

一つ残念なのは、まさに自分がこの書籍に期待していた点なのですが、言及されている機能が、Javaのどのバージョンから実装されたかが、本文中で触れられてはいるのですが、例えば、タイトルなどで一目でわかるようにはなっていなかったことです。

職業Javaプログラマーであればこそ、業務で使用するJavaのバージョンが古かったり、常に最新バージョンをキャッチアップしているわけではないと思われるため、本書のような最新のJavaの全体像がわかる書籍を手に取った時に、言及されている機能が、Javaどのバージョンから実現された機能かが、視認しやすくなっていると、よかったかと思います。

そうなっていれば、わかっているところは読み飛ばして、差分だけ読み進める、写経することが効率よくできたかと思います。(もしくはわかっていると読み飛ばした中に、差分の技術が紛れ込んでいたかもしれません)

繰り返しになりますが、Javaを職業とする初学者プログラマは手元に本書を一冊置いておくことをオススメします。

600ページと分量はありますが、これだけでは足りません。

ただ、本書を教科書にすることで、他の書籍を読むための土台を作ることができることは間違い無いと思います。

Vuex で状態管理

  1. Google App Engine Java Standard + Spring Boot 環境構築
  2. Spring Bootのテンプレートエンジン Thymeleafを適用

  3. Spring BootにVue.jsを利用する

  4. Spring BootにVuetify導入からクロスドメインAjax通信

  5. Spring Boot+Vuetify GAEへデプロイ、動作確認

  6. Xamarin.FormsアプリをiOS用にビルド

  7. Xamarin.Forms ポップアップの表示と Http通信

  8. Spring Boot+Vuetify ファイルのアップロードとJSONで結果を返す

  9. Google Google Cloud Vision でOCR。VuetifyからSpringBoot経由で呼び出し

  10. Xamarin ファイル選択

  11. Xamarin ファイルのアップロード

  12. Vue Router を導入し画面遷移

  13. Firebaseでログイン機能

1.Vuex

Firebase を使用して、ログイン機能を追加できた。

つぎは、コンポーネント間で、データのやり取りを行いたい。

状態管理を行う手法の記述があるが、Fluxライクな公式実装ということで、Vuex を素直に使用する。

https://vuex.vuejs.org/ja/

動画チュートリアル

1.1 インストール

npm install vuex --save

2.実装

2.1 main.js

  • Vue.user(Vuex) で使用準備
  • Vuex.Store でストアを作成
  • state に、firebase のログインユーザー情報を格納
  • muattions で、stateに設定した user情報を操作するメソッドを公開
  • firebase のユーザーが取得出来たら、store.commit にて、stateにユーザーを格納する
  • new Vue() 内に、storeを設定することで、グローバルにstoreを参照できるように

import Vue from 'vue'
import Vuex from 'vuex'
import '@/plugins/vuetify'
import firebase from '@/plugins/firebase'
import 'firebase/auth'

import { MUTATION_LOGIN_USER } from '@/consts'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    user:null
  },
  mutations: {
    user(state, user) {
      state.user = user;
    }
  }
})

firebase.auth().onAuthStateChanged(user => {
  if (user) {
    store.commit(MUTATION_LOGIN_USER, user);
  } 
})

new Vue({
  render: h => h(App),
  store,
}).$mount('#app')

2.2 const.js

ミューテーションを介して、stateを操作するが、ミューテーションを介した操作をトラックするためにミューテーションの名称を外だし

export const MUTATION_LOGIN_USER = "user";

2.3 App.vue

  • computed の userName で、Vuexのstoreから、firebaseのログインユーザを取得する
  • {{userName}} で上記にバインド。ログインユーザーの表示名をツールバーに表示する
<template>
  <v-app>
    <v-navigation-drawer fixed clipped app v-model="navBar">
      <v-list dense class="pt-0">
        <router-link to="/login">
          <v-list-tile>
            <v-list-tile-action>
              <v-avatar v-if="photoUrl" size="28px">
                <img :src="photoUrl">
              </v-avatar>
              <v-icon v-else>account_box</v-icon>
            </v-list-tile-action>
            <v-list-tile-content>{{userName}}</v-list-tile-content>
          </v-list-tile>
        </router-link>
        <router-link to="/">
          <v-list-tile>
            <v-list-tile-action>
              <v-icon>home</v-icon>
            </v-list-tile-action>
            <v-list-tile-content>HOME</v-list-tile-content>
          </v-list-tile>
        </router-link>
        <router-link to="/entry">
          <v-list-tile>
            <v-list-tile-action>
              <v-icon>edit</v-icon>
            </v-list-tile-action>
            <v-list-tile-content>ENTRY</v-list-tile-content>
          </v-list-tile>
        </router-link>
        <router-link to="/about">
          <v-list-tile>
            <v-list-tile-action>
              <v-icon>settings</v-icon>
            </v-list-tile-action>
            <v-list-tile-content>ABOUT</v-list-tile-content>
          </v-list-tile>
        </router-link>
      </v-list>    
    </v-navigation-drawer>
    <v-toolbar clipped-left fixed app>
      <v-toolbar-side-icon @click.stop="navBar = !navBar"></v-toolbar-side-icon>
      <v-toolbar-title>FavoPhrase</v-toolbar-title>
      <v-spacer></v-spacer>
      <v-toolbar-items class="hidden-sm-and-down">
        <v-btn flat to="/">Home</v-btn>
        <v-btn flat to="/entry">Entry</v-btn>
        <v-btn flat to="/about">About</v-btn>
        <v-btn flat to="/login">
           <v-avatar v-if="photoUrl" size="32px" class="pa-4">
              <img :src="photoUrl">
           </v-avatar>
          {{userName}}
        </v-btn>
      </v-toolbar-items>
    </v-toolbar>
    <v-content>
      <v-container fluid fill-height>
        <v-fade-transition mode="out-in">
          <router-view></router-view>
        </v-fade-transition>
      </v-container>
    </v-content>
  </v-app>
</template>

<script>
  import firebase from '@/plugins/firebase'

  export default {
    name: 'App',
    data() {
      return {
        navBar: null,
      }
    },
    computed: {
      userName() {
        var user = this.$store.state.user;
        if (user != null) {
          if (user.displayName) {
            return user.displayName;
          }
          if (user.email) { 
            return user.email;
          }
        }
        return "LOG IN";
      },
      photoUrl() {
        var user = this.$store.state.user;
        return (user == null)?null:user.photoURL;
      }
    },
    created() {
    },
    mounted() {
    }
  }
</script>
<style>
  a {
    text-decoration: none;
  }
</style>

Reduxより使いやすそう

3.実行

3.1 ログインしていない状態から

login

3.2 Firebase ログインUIから、ログイン

firebaseui_login

3.3 ログインが成功し表示名とアイコンが表示された OK

avater


  1. Google App Engine Java Standard + Spring Boot 環境構築
  2. Spring Bootのテンプレートエンジン Thymeleafを適用

  3. Spring BootにVue.jsを利用する

  4. Spring BootにVuetify導入からクロスドメインAjax通信

  5. Spring Boot+Vuetify GAEへデプロイ、動作確認

  6. Xamarin.FormsアプリをiOS用にビルド

  7. Xamarin.Forms ポップアップの表示と Http通信

  8. Spring Boot+Vuetify ファイルのアップロードとJSONで結果を返す

  9. Google Google Cloud Vision でOCR。VuetifyからSpringBoot経由で呼び出し

  10. Xamarin ファイル選択

  11. Xamarin ファイルのアップロード

  12. Vue Router を導入し画面遷移

1.ナビゲーションメニュー

Vue Routerを導入して画面遷移ができるようになったのだが、Vue CLI で作成したトップページのままだと、スマホ(サイズ)で表示した場合に、右上のメニューが隠れてしまうため、ハンバーガーメニューを、 以下を参考に導入。

https://garicchi.com/?p=20801

<template>
  <v-app>
    <v-navigation-drawer fixed clipped app v-model="navBar">
      <v-list dense class="pt-0">
        <router-link to="/">
          <v-list-tile>
            <v-list-tile-action>
              <v-icon>home</v-icon>
            </v-list-tile-action>
            <v-list-tile-content>HOME</v-list-tile-content>
          </v-list-tile>
        </router-link>
        <router-link to="/entry">
          <v-list-tile>
            <v-list-tile-action>
              <v-icon>edit</v-icon>
            </v-list-tile-action>
            <v-list-tile-content>ENTRY</v-list-tile-content>
          </v-list-tile>
        </router-link>
        <router-link to="/login">
          <v-list-tile>
            <v-list-tile-action>
              <v-icon>account_box</v-icon>
            </v-list-tile-action>
            <v-list-tile-content>LOG IN</v-list-tile-content>
          </v-list-tile>
        </router-link>
        <router-link to="/about">
          <v-list-tile>
            <v-list-tile-action>
              <v-icon>settings</v-icon>
            </v-list-tile-action>
            <v-list-tile-content>ABOUT</v-list-tile-content>
          </v-list-tile>
        </router-link>
      </v-list>    
    </v-navigation-drawer>
    <v-toolbar clipped-left fixed app>
      <v-toolbar-side-icon @click.stop="navBar = !navBar"></v-toolbar-side-icon>
      <v-toolbar-title>FavoPhrase</v-toolbar-title>
      <v-spacer></v-spacer>
      <v-toolbar-items class="hidden-sm-and-down">
        <v-btn flat to="/">Home</v-btn>
        <v-btn flat to="/entry">Entry</v-btn>
        <v-btn flat to="/login">Login</v-btn>
        <v-btn flat to="/about">About</v-btn>
      </v-toolbar-items>
    </v-toolbar>
    <v-content>
      <v-container fluid fill-height>
        <v-fade-transition mode="out-in">
          <router-view></router-view>
        </v-fade-transition>
      </v-container>
    </v-content>
  </v-app>
</template>

<script>
  export default {
    name: 'App',
    data() {
      return {
        navBar: null
      }
    }
  }
</script>
<style>
  a {
    text-decoration: none;
  }
</style>

ブラウザサイズ。

navbar2

スマホサイズ。

navbar3

ハンバーガーメニュー。

navbar

うん。わるくない。

2.Firebase を使って簡単にログイン機能を実現

以下のサイトを参考に実装。

https://firebase.google.com/docs/auth/web/firebaseui?hl=ja

https://qiita.com/okdyy75/items/24e78fdd0f12742b9e82

/main.js

上記サイトを参考に、routes の meta に、認証が必要かどうかをbool で設定し、router.beforeEach で、遷移前ログイン状態を確認し、ログインされていなければ、Loginページに遷移させる。

import Vue from 'vue'
import VueRouter from 'vue-router'
import '@/plugins/vuetify'
import firebase from '@/plugins/firebase'
import 'firebase/auth';

import App from '@/App.vue'

import Home from '@/components/Home'
import Entry from '@/components/Entry'
import Login from '@/components/Login'
import About from '@/components/About'

Vue.config.productionTip = false
Vue.use(VueRouter)

const routes = [
  { name:'Home',  path: '/',      component: Home,  meta: { requiredAuth: false } },
  { name:'Entry', path: '/entry', component: Entry, meta: { requiredAuth: true  } },
  { name:'Login', path: '/login', component: Login, meta: { requiredAuth: false } },
  { name:'About', path: '/about', component: About, meta: { requiredAuth: false } }
]
const router = new VueRouter({
  routes
})

router.beforeEach((to, from, next) =>{
  if (to.matched.some(record => record.meta.requiredAuth)) {
    if (firebase.auth().currentUser) {
      console.log(firebase.auth().currentUser);
      next();
      return;
    }
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        next();
      } else {
        next({name: 'Login'})
      } 
    })
  }
  next();
})

new Vue({
  render: h => h(App),
  router:router
}).$mount('#app')

/plugins/firebase.js

Firebaseを導入する。

https://firebase.google.com/docs/web/setup?hl=ja

import firebase from 'firebase/app'

var config = {
    apiKey: "XXXXXXXXXXXXXxXXXXXXXXXXXXXXXXXX",
    authDomain: "xxxxxxxxxxxx.com",
    databaseURL: "https://xxxxxxxxxxxxxx.com",
    projectId: "favophrase",
    storageBucket: "xxxxxxxxxxxxxxxxxxx.com",
    messagingSenderId: "99999999999999999"
  }
  firebase.initializeApp(config)

  export default firebase

/components/Login.vue コンポーネント

FIrebase UI の最低限の実装。これだけで、ログイン機能が実現される。

<template>
    <v-container>
        <div>
            <v-btn @click="logout">LOGOUT</v-btn>
        </div>
        <div id="firebaseui-auth-container"></div>
    </v-container>
</template>
<script>
import firebase   from 'firebase/app';
import firebaseui from 'firebaseui-ja';

export default {
    mounted() {
        var ui = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(firebase.auth());
        ui.start('#firebaseui-auth-container',{
            signInOptions: [
                firebase.auth.EmailAuthProvider.PROVIDER_ID,
                firebase.auth.FacebookAuthProvider.PROVIDER_ID,
                firebase.auth.TwitterAuthProvider.PROVIDER_ID,
                firebase.auth.GoogleAuthProvider.PROVIDER_ID,
            ],

        });
    },
    methods: {
        logout: function() {
            firebase.auth().signOut().then(
                () => console.log("Sign out.")
            );
        }
    }
}
</Script>

Firebase UI の画面。

うーん、これだけのコード記述だけで、認証機能が実現できるのはかなりうれしい。

本筋の機能実装に専念できるってことだなー。

Baas万歳。

firebaseui

上記で認証を利用するためには、各SNSの開発者ページに設定が必要。

Firebase https://console.firebase.google.com/u/1/

Facebook Developer https://developers.facebook.com/apps

Twitter Developer https://developer.twitter.com/en/apps