24
31

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue.jsをSpringBootアプリに組み込む

Last updated at Posted at 2020-10-26

Vue.jsプロジェクトをjarに内包して実行

フロントエンドはVue.js、バックエンドはJava(SpringBoot)でアプリを作りたいけど、
Vue.jsとJavaでプロジェクトを分けたくない…というシーンに遭遇したので書いておきます

ビルド済みVue.jsリソースをjarファイルに内包してSpringBootの組み込みTomcatで実行します

開発環境

  • Windows10Pro
  • AdoptOpenJDKJ9 1.8.0_265
  • npm 6.14.6
  • vue-cli 4.5.4

Vue.js+SpringBootプロジェクトを作成

IntelliJでSpringBootプロジェクトを作成します

以下のコマンドで作成したSpringBootプロジェクトの中にVue.jsプロジェクトを作成します

cd C:\Users\risab\git\demo
vue create web

これでVue.js+SpringBootプロジェクトができました 画像のwebディレクトリがVue.jsプロジェクトです

image.png

アプリケーションを実装する

今回はVue.jsで作成した簡単な画面にSpringBootで作成したRESTAPIのレスポンスを表示するアプリを作成します

RESTAPI

/blog/entries/latestにアクセスすると最新のブログタイトルと記事内容が返される
RESTAPIコントローラーを作成しました

demo\src\main\java\com\example\demo\controller\BlogController.java
package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/blog")
public class BlogController {

    /**
     * 最新ブログ記事を取得
     * @return タイトルと内容のMap
     */
    @RequestMapping(value = "/entries/latest", method = RequestMethod.GET)
    public Entry getLatestEntry() {
        Entry entryData = new Entry();
        // TODO DBから最新の記事データを取得
        entryData.setTitle("VueRouterを使ってみた");
        entryData.setContent("VueRouterで簡単にページルーティングができました");
        return entryData;
    }

    /**
     * ブログ記事クラス
     */
    private class Entry{
        private String title;
        private String content;

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }
    }
}

IntelliJでSpringBootアプリを作成するとアプリ起動に必要な以下のクラスは自動で生成されています

DemoApplication.java
demo\src\main\java\com\example\demo\DemoApplication.java
package com.example.demo;

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

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}
ServletInitializer.java
demo\src\main\java\com\example\demo\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(DemoApplication.class);
    }

}

アプリ画面

Vue.js+Vuetify+VueRouterで簡単な画面を2つ作成しました

トップページは画面タイトルと「BLOG」ボタンだけのシンプルな画面です

demo\web\src\pages\TopPage.vue
<template>
  <v-app>
    <v-app-bar
        absolute
        color="teal lighten-3"
        dark
    >
      <v-toolbar-title>トップページ</v-toolbar-title>
    </v-app-bar>
    <v-container class="ml-0 mt-16">
      <v-row>
        <v-col cols="4">
          <v-btn
              color="brown lighten-3"
              width="100"
              v-on:click="clickBlogBtn"
          >
            blog
          </v-btn>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  name: "TopPage",
  methods: {
    clickBlogBtn: function () {
      this.$router.push("/blogPage")
    }
  }
}
</script>

<style>
</style>

ブログページは先ほど作成したRESTAPIを呼び出してブログ記事データを表示します

demo\web\src\pages\BlogPage.vue
<template>
  <v-app>
    <v-app-bar
        absolute
        color="teal lighten-3"
        dark
    >
      <v-toolbar-title>tech blog</v-toolbar-title>
    </v-app-bar>
    <v-container class="ml-0 mt-16">
      <v-row>
        <v-col cols="4">
          <v-btn
              color="blue-grey lighten-4"
              width="100"
              v-on:click="clickTopPageBtn"
          >
            top page
          </v-btn>
        </v-col>
      </v-row>
      <v-row>
        <v-card class="ml-3" color="yellow lighten-5">
          <v-card-title>{{ blogPost.title }}</v-card-title>
          <v-card-text>
            {{ blogPost.content }}
          </v-card-text>
        </v-card>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  name: "BlogPage",
  data: () => ({
    // APIから取得した記事データをバインド
    blogPost: {
      title: "",
      content: ""
    }
  }),
  mounted() {
    // RESTAPI呼び出し
    const el = this
    this.axios.get("/blog/entries/latest")
        .then(response => {
          el.blogPost = response.data
        })
  },
  methods: {
    clickTopPageBtn: function () {
      this.$router.push("/")
    }
  }
}
</script>

<style>
</style>

以下のファイルも修正・作成しました main.jsは変更不要です

App.vue
demo\web\src\App.vue
<template>
  <v-app>
    <router-view/>
  </v-app>
</template>

<script>
export default {
  name: 'App'
};
</script>
router.js
demo\web\src\router.js
import Vue from "vue"
import Router from "vue-router"

import TopPage from "@/pages/TopPage";
import BlogPage from "@/pages/BlogPage";

Vue.use(Router)

export default new Router({
    mode: "history",
    routes: [
        {
            path: "/",
            name: "トップページ",
            component: TopPage
        },
        {
            path: "/blogPage",
            name: "ブログ",
            component: BlogPage
        }
    ]
})

これでアプリケーションの作成は完了です

ビルド済みVue.jsの出力先を変更

この時点でwebディレクトリで npm run build するとweb\dist\配下にビルド済みVue.jsリソースが出力されます
web\package.jsonを修正してJavaから見える場所に出力するようにします

scripts.buildを以下のように修正してSpringBootプロジェクトの静的リソースディレクトリに出力するようにします

demo\web\package.json
{
  "name": "demo",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build --dest ../src/main/resources/static/",
    "lint": "vue-cli-service lint"
  },

上記の通りpackage.jsonを修正してビルドすると以下のようになります

cd C:\Users\risab\git\demo\web
npm run build

image.png

jarを生成する

jarファイルはgradleで生成するので、以下の記述をbuild.gradleの末尾に追加します
Main-Classには@SpringBootApplicationを付けているクラスを指定します

demo\build.gradle
jar {
    manifest {
        attributes 'Main-Class': 'DemoApplication'
    }

以下のコマンドを実行するとbuild\libs\配下にjarファイルが生成されます

cd C:\Users\risab\git\demo
gradlew bootJar

image.png

あとは生成されたjarファイルを実行するだけです!

cd C:\Users\risab\git\demo\build\libs
java -jar demo-0.0.1-SNAPSHOT

Started DemoApplication in 2.893 seconds (JVM running for 3.378)のように出力されていればSpringBootアプリケーションが起動できています

SpringBootの組み込みTomcatを利用しているので、ブラウザでhttp://localhost:8080/にアクセスします
image.png

Vue.jsからJavaで作ったRESTAPIも実行できています
image.png

24
31
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
24
31

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?