1. 前言
前后端分离模式,可以让后端和前端开发人员致力于自己擅长的领域,且可以让前端和后端业务逻辑高度解耦合。本文从一个简单的案例入手,讲解使用 spring boot和vue3如何实现前后端的分离。
前后端分离有2 种模式:
- 逻辑分离:在一个项目中的前后分离。项目整体架构还是
MVC模式,适合于小型项目。 - 物理分离:独立的前后端项目分离。因是不同项目,会涉及远程调用等问题,适合于中、大型项目。后端项目仅是
API提供者,可以服务于不同平台的前端项目,如网页版、微信小程序版的前端项目。
本文将使用 Spring Boot、Vue3、Elemnet Plus分别构建这2种分离模式。
无论使用哪一种分离模式,其后端API都是一样的。所以,本文先搭建后端服务项目。
2. Spring Boot API
后端项目也称为服务器端,以提供API为主,数据的应用以及显示由前端负责。本文后端项目的开发工具为IDEA,当然,你也可以选择其它开发工具,关系数据库系统为mysql。
2.1 创建项目
打开 IDEA。新建名为 MyBook 的 Spring Boot项目。

选择spring boot的版本2.7.12,且选择如下的依赖包:
Spring Boot DevTools。LomBok。Spring Web。MyBatis Framework。MySql Driver。
确认后,项目的初始结构如下图所示:

打开项目的application.properties文件,配置项目的jdbc基本信息。
#配置数据库连接信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/bookstore?useUnicode=true&characterEncoding=UTF-8&serverTimezone=PRC
spring.datasource.username=root
spring.datasource.password=abc123

2.2 设计 API
本项目是一个基础MVC架构项目,仅提供一个用于测试的API,功能是用来显示所有的书本信息。
本项目采用由下向上的设计流程,先创建数据库,并设计book表。
Tips:
mysql数据库系统的安装过程这里就不单独讲解,数据库连接客服端使用Navicat Premium。
数据库设计:
-
启动
mysql服务,打开Navicat Premium。创建名为bookstore的数据库,以及在数据库中创建名为book的数据库表,其字段结构如下:字段名 类型 备注 book_id(编号)int主键、自动增长 book_title(书名)varcharbook_author(作者)varcharbook_price(价格)double

- 表命名为
book,并向表中插入2条测试数据。

数据库设计好后,开始项目结构的搭建:因项目使用 mybatis jdbc框架,故先构建mapper层。
mapper层。
新建 mapper层前,先创建book类。使用lombok简化book类的代码。
package com.gk.mybook.bean;
import lombok.*;
@Data
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private Integer bookId;
private String bookTitle;
private String bookAuthor;
private Double bookPrice;
}
新建 BookMapper类:提供查询所有书籍的方法的声明。
package com.gk.mybook.mapper;
import com.gk.mybook.bean.Book;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface BookMapper {
List<Book> getAllBooks();
}
编写 SQL 语句:查询所有书籍。
SELECT book_id,book_title,book_author,book_price from book
sql文件书写在 BookMapper.xml文件中,此文件存储在项目的 resources中。为了让 BookMapper自动找到xml文件,在resources文件中创建com.gk.mybook.mapper结构的目录结构。
Tips:也可能自定义其它位置。
至此,项目结构如下图所示:

BookService层:业务层。
定义业层接口IBookService层,为业务层声明功能。
package com.gk.mybook.service;
import com.gk.mybook.bean.Book;
import java.util.List;
/*
*书籍业务对象
*/
public interface IBookService {
List<Book> getBooks();
}
构建业务对象BookService:实现IBookService接口,依赖BookMapper对象。
package com.gk.mybook.service.impl;
import com.gk.mybook.bean.Book;
import com.gk.mybook.mapper.BookMapper;
import com.gk.mybook.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookService implements IBookService {
@Autowired
private BookMapper bookMapper;
@Override
public List<Book> getBooks() {
return this.bookMapper.getAllBooks();
}
}
此时,项目结构如下图所示:

- 控制器层,并向外映射接口。
package com.gk.mybook.action;
import com.gk.mybook.bean.Book;
import com.gk.mybook.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/book")
public class BookAction {
@Autowired
private IBookService bookService;
@RequestMapping("/books")
List<Book> getBooks(){
return this.bookService.getBooks();
}
}
- 测试接口。为了简化操作,直接在浏览器中测试,启动项目之前,别忘记在启动类前面加
@MappScan注解,其实新版本spring boot可以省略此注解。
package com.gk.mybook;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(value = {"com.gk.mybook.mapper"})
public class MybookApplication {
public static void main(String[] args) {
SpringApplication.run(MybookApplication.class, args);
}
}
运行程序后,打开浏览器,在地址栏中输入http://localhost:8080/book/books。如果能看到下面的结果,说明服务器搭建成功。

3. Vue Project
如上所说,前后分离有 2 种使用方式。
3.1 逻辑分离
直接在服务器项目的view层的html页面中使用vue框架。
在后端项目的resources->static目录中新建index.html文件。在文件中引入Vue、Element plus、axios依赖库。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>书籍</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
<!-- import JavaScript -->
<script src="https://unpkg.com/element-plus"></script>
<script src="https://unpkg.com/vue-router@4"></script>
</head>
<body>
<div id="app">
</div>
</body>
</html>
项目结构如下图:

编写如下JS代码,实现在页面中显示所有书籍信息。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>书籍</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
<!-- import JavaScript -->
<script src="https://unpkg.com/element-plus"></script>
<script src="https://unpkg.com/vue-router@4"></script>
</head>
<body>
<div id="app">
<h1>{{title}}</h1>
<el-table :data="books">
<el-table-column v-for="book in cols" :key="book.en"
:prop="book.en"
:label="book.cn"
show-overflow-tooltip align="center" width="160px">
<template #default="scope">
{{ scope.row[book.en] }}
</template>
</el-table-column>
</el-table>
</div>
<script>
const {createApp} = Vue
var app = createApp({
data() {
return {
title: "我的书籍",
cols: [{"en": "bookId", "cn": "编号"}, {"en": "bookTitle", "cn": "书名"}],
books: []
}
},
mounted() {
axios
.get('http://localhost:8080/book/books')
.then(response => (
this.books = response.data
))
.catch(function (error) { // 请求失败处理
console.log(error);
});
}
}).use(ElementPlus).mount('#app')
</script>
</body>
</html>
测试结果: 运行spring boot项目,打开浏览器,直接输入http://localhost:8080/index.html。可看到如下图所示结果。

3.2 物理分离
物理分离是真正意义上的前后端分离模板,此分离模式除了服务器端项目,还有独立的基于VUE框架的前端项目。项目中能使用VUE单页面,能真正意义上实现组件化编程思想。
创建VUE项目有很多种方式,也有很多优秀的前端开发工具,本文使用HBuild以及其项目创建向导构建VUE项目。
3.2.1 新建 VUE项目
打开HBuild,新建项目,且选择使用vite 构建项目。如下图所示:

新建的项目自动依赖了VUE和vite模块。可以打开项目中的package.json查看相关信息。

为了能使用axios和 Element Plus,需要在项目中安装这两个模块库。
右击项目,在弹出来的快捷菜单中选择使用命名行窗口打开所在目录。在HBuild下面可看到终端窗口。

安装axios模块,在命令模式下输入:
Tips:
axios的使用请查阅官方文档。
npm install axios
安装element-plus模块,在命令模式下输入:
npm install element-plus --save
可以在package.json文件中查看模块的依赖信息。

为了使用element plus的自动导入功能,还需要安装unplugin-vue-components 和 unplugin-auto-import插件。在命令模式下输入如下指令进行安装。
npm install -D unplugin-vue-components unplugin-auto-import
打开vite.config.js文件,添加如下的配置信息:

为了实现axios的跨域访问。还需要后端项目中新建配置类,且添加如下内容。
@Configuration
public class CorsConfig {
@Bean
CorsFilter corsFilter() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(Collections.singletonList("*"));
configuration.setAllowedMethods(Collections.singletonList("*"));
configuration.setAllowedHeaders(Collections.singletonList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return new CorsFilter(source);
}
}
如下图所示:

3.2.2 创建前端页面
在VUE项目中,页面可以是重用的组件。本文直接在已经创建的HelloWorld.vue文件中进行修改,同样实现读取所有书籍。内容如下:
<script setup>
import {
ref,
reactive
} from 'vue'
import axios from 'axios'
defineProps({
msg: String
})
const data = reactive({
books: null
})
/*
* 使用 axios 请求服务器数据
*/
const getData = function() {
axios({
url: 'http://localhost:8080/book/books',
method: 'get',
headers: {
"Access-Control-Allow-Origin": "*",
}
}).then((res) => {
data.books = res.data
console.log(data.books)
});
}
</script>
<template>
<h1>{{ msg }}</h1>
<el-table :data="data.books" style="width: 100%">
<el-table-column prop="bookId" label="编号" width="180" />
<el-table-column prop="bookTitle" label="书名" width="180" />
<el-table-column prop="bookAuthor" label="作者" />
</el-table>
<el-button type="primary" @click="getData">查阅书籍</el-button>
</template>
<style scoped>
a {
color: #42b983;
}
</style>

启动前端、后端项目:
npm run dev
打开浏览器,在地址栏中输入:http://localhost:3000。

点击查阅书籍:

4. 总结
本文通过一个案例,简要介绍了使用spring boot和vue3如何实现项目的前后端分离。



















