SpringBoot与VUE前后端分离最佳实践

前后端分离的开发模式大家都很清楚了,甚是麻烦:

  • 前端启动webpack-dev-server
  • 后端启动接口服务
  • 开启代理服务器,前端通过代理服务器请求后端接口(解决跨域问题)

但是这些东西对于后端来说,太麻烦了,直接把前端打包好的dist文件丢到后端静态服务器里面就好了。
至于前端的webpack-dev-server热部署特性,改完前端代码立即在浏览器生效,对于后端来说有什么用呢?

  • 配置前端项目打包Task
  • 配置后端项目启动Task(执行前端编译、拷贝编译后的静态文件、启动后端)
  • 一键启动

本地环境

  • IntelliJ IDEA:2019.1 (Ultimate Edition)
  • Gradle:5.4.1

创建项目

使用Gradle来构建项目,他的Task构建任务非常灵活,远胜Maven。

创建项目

image.png

注意,这里不要勾选任何库和框架(只勾选了Kotlin DSL,因为Gradle默认使用Groovy来描述配置文件,不太熟悉这个脚本语言,还是使用Kotlin吧)

image.png

项目创建成功,这时是一个空的项目,在里面加入后端和前端模块

创建前端模块

image.png

同样的,不要勾选任何框架,只选择使用Kotlin DSL就行了。
image.png

image.png

修改settings.gradle.kts,将新建的前端项目作为模块引入进来:

1
2
rootProject.name = "springboot-vue-gradle"
include("webui")

打开终端,使用vue-cli初始化前端项目:
image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  ~ cd Development/other-projects/springboot-vue-gradle 
➜ springboot-vue-gradle vue init webpack webui

? Target directory exists. Continue? Yes
? Project name webui
? Project description A Vue.js project
? Author 吴汶泽 <wuwz@live.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Set up unit tests No
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (recom
mended) yarn

注意,这里初始化前端项目时,文件夹名称要覆盖掉之前创建的前端模块(webui)构建好的文件目录结构如下:
image.png

前端项目暂告一段落,现在开始创建后端项目

创建后端模块

image.png

这里使用Spring Initializer,免去一些配置SpringBoot的麻烦事儿
image.png

配置项目,选用Gradle构建,并使用Kotlin语言
image.png

选择项目依赖,由于是演示,这里就只选了WEB,数据库这些都不弄了
image.png

修改settings.gradle.kts,将新建的后端项目作为模块引入进来:

1
2
rootProject.name = "springboot-vue-gradle"
include("webui", "server")

构建的后端项目现在还没有生成文件夹和启动类,需要我们自己手动创建一下:
image.png

创建后的效果图如下:
image.png

先编写一个简单的后端接口:

1
2
server:
port: 10054

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
@SpringBootApplication
class Application {
companion object {
@JvmStatic fun main(args: Array<String>) {
runApplication<Application>(*args)
}
}

@GetMapping("/sayHello")
fun sayHello(): Map<String, Any?> {
return mapOf("message" to "Hello, Springboot & Vue")
}
}

image.png

编写前端构建任务

  • springboot-vue-gradle/webui/build.gradle.kts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.moowork.gradle.node.yarn.YarnTask

group = "com.wuwenze"
version = "1.0-SNAPSHOT"

plugins {
id("com.moowork.node") version "1.3.1"
}

tasks {
// start the webui app (以webpack-dev-server方式)
register<YarnTask>("startWebUI") {
group = "application"
setYarnCommand("run", "start")
}

// build the webui app
register<YarnTask>("buildWebUI") {
group = "application"
setYarnCommand("run", "build")
}
}

使用Gradle编写两个构建命令,一个是启动前端,一个是编译前端,其本质是调用yarn命令
image.png

编写项目构建任务

  • springboot-vue-gradle/build.gradle.kts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
group = "com.wuwenze"
version = "1.0-SNAPSHOT"

tasks {
register<Copy>("copyWebDist") {
group = "application"

dependsOn("webui:buildWebUI")
from("webui/dist")
into("server/src/main/resources/static")
}

// 启动开发服务,先编译前端项目,再启动SpringBoot
register("startDevServer") {
group = "application"

dependsOn(":copyWebDist", "server:bootRun")
}
}

image.png

前后端算是无缝打通了

对于后端人员来说,直接启动startDevServer就行了
不需要单独启动前端,再启动后端,最后在来个代理服务器(太麻烦了)

执行测试

之前在后端提供了一个/sayHello接口,在前端调用这个接口试试。

1
2
cd webui/
yarn add axios --save

改造一下前端的webui/src/components/HelloWorld.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
import axios from "axios";
export default {
name: 'HelloWorld',
data() {
return {
msg: 'Welcome to Your Vue.js App'
}
},
created() {
axios.get("/sayHello").then((res) => this.msg = res.data.message)
}
}
</script>

启动项目:
image.png

浏览器访问:localhost:10054
image.png

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×