新手福利,通過一個簡單示例快速上手Spring Boot+Vue前後端分離
- 2019 年 10 月 29 日
- 筆記
2、動態載入router,用Vue+Element UI搭建後台管理系統介面
Vue + Element UI 並不是真正的前後端分離,它只有前端服務,並沒有後端服務提供數據介面,很多小夥伴在後台留言希望楠哥能寫一篇完整的 Spring Boot + Vue 前後端分離教程。大家有需求,楠哥就會盡量滿足,所以今天用一個簡單易懂的例子,快速教會大家如何實現 Spring Boot + Vue 的前後端分離開發。
既然是前後端分離,那麼我們就分開來寫兩個獨立的服務,首先完成後端服務,提供數據介面。然後完成前端服務通過 Ajax 調用後端介面並動態綁定數據。後端服務我們使用 Spring Boot + MyBatis,前端服務使用 Vue + Element UI。
後端服務
1、我們以查詢圖書為例,完成基於 RESTful 的介面開發,資料庫建表語句如下所示。
DROP TABLE IF EXISTS `bookcase`; CREATE TABLE `bookcase` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; LOCK TABLES `bookcase` WRITE; INSERT INTO `bookcase` VALUES (1,'社會'), (2,'情感'), (3,'國學'), (4,'推理'), (5,'繪畫'), (6,'心理學'), (7,'傳記'), (8,'科技'), (9,'電腦'), (10,'小說'); UNLOCK TABLES; DROP TABLE IF EXISTS `book`; CREATE TABLE `book` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, `author` varchar(20) DEFAULT NULL, `publish` varchar(20) DEFAULT NULL, `pages` int(10) DEFAULT NULL, `price` float(10,2) DEFAULT NULL, `bookcaseid` int(10) DEFAULT NULL, `abled` int(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `FK_ieh6qsxp6q7oydadktc9oc8t2` (`bookcaseid`), CONSTRAINT `FK_ieh6qsxp6q7oydadktc9oc8t2` FOREIGN KEY (`bookcaseid`) REFERENCES `bookcase` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=74 DEFAULT CHARSET=utf8; LOCK TABLES `book` WRITE; INSERT INTO `book` VALUES (1,'解憂雜貨店','東野圭吾','電子工業出版社',102,27.30,9,0), (2,'追風箏的人','卡勒德·胡賽尼','上海人民出版社',230,33.50,3,0), (3,'人間失格','太宰治','作家出版社',150,17.30,1,1), (4,'這就是二十四節氣','高春香','電子工業出版社',220,59.00,3,1), (5,'白夜行','東野圭吾','南海出版公司',300,27.30,4,1), (6,'擺渡人','克萊兒·麥克福爾','百花洲文藝出版社',225,22.80,1,1), (7,'暖暖心繪本','米攔弗特畢','湖南少兒出版社',168,131.60,5,1), (8,'天才在左瘋子在右','高銘','北京聯合出版公司',330,27.50,6,1), (9,'我們仨','楊絳','生活.讀書.新知三聯書店',89,17.20,7,1), (10,'活著','余華','作家出版社',100,100.00,6,1), (11,'水滸傳','施耐庵','三聯出版社',300,50.00,1,1), (12,'三國演義','羅貫中','三聯出版社',300,50.00,2,1), (13,'紅樓夢','曹雪芹','三聯出版社',300,50.00,5,1), (14,'西遊記','吳承恩','三聯出版社',300,60.00,3,1); UNLOCK TABLES;
2、新建 Maven 工程,pom.xml 引入相關依賴。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
3、創建實體類。
@Data public class BookCase { private int id; private String name; } @Data public class Book { private int id; private String name; private String author; private String publish; private int pages; private double price; private BookCase bookCase; } @Data public class BookVO { private Integer total; private List<Book> data; private Integer pageSize; }
4、創建 Repository 介面。
public interface BookRepository { public List<Book> find(Integer index,Integer limit); public Integer count(); } public interface BookCaseRepository { public BookCase findById(Integer id); }
5、在 resources/mapping 路徑下創建 Repository 對應的 Mapper.xml。
<mapper namespace="com.southwind.repository.BookRepository"> <resultMap id="bookMap" type="Book"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="author" column="author"/> <result property="publish" column="publish"/> <result property="pages" column="pages"/> <result property="price" column="price"/> <association property="bookCase" javaType="BookCase" select="com.southwind.repository.BookCaseRepository.findById" column="bookcaseid"></association> </resultMap> <select id="find" resultMap="bookMap"> select * from book limit #{param1},#{param2} </select> <select id="count" resultType="Integer"> select count(*) from book </select> </mapper> <mapper namespace="com.southwind.repository.BookCaseRepository"> <select id="findById" parameterType="java.lang.Integer" resultType="BookCase"> select * from bookcase where id = #{id} </select> </mapper>
6、創建 Service 介面及實現類。
public interface BookService { public BookVO findByPage(Integer page); } @Service public class BookServiceImpl implements BookService { @Autowired private BookRepository bookRepository; private Integer limit = 10; @Override public BookVO findByPage(Integer page) { Integer index = (page-1)*limit; BookVO bookVO = new BookVO(); bookVO.setData(bookRepository.find(index,limit)); bookVO.setTotal(bookRepository.count()); bookVO.setPageSize(limit); return bookVO; } }
7、創建 Handler。
@RestController @RequestMapping("/book") public class BookHandler { @Autowired private BookService bookService; @GetMapping("/findByPage/{page}") public BookVO findByPage(@PathVariable("page") Integer page){ return bookService.findByPage(page); } }
8、前端服務調用後端介面時存在跨域問題,在 Spring Boot 中可以通過實現 WebMvcConfigurer 介面來解決跨域問題。
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") .allowCredentials(true) .maxAge(3600) .allowedHeaders("*"); } }
9、在 resources 路徑下創建配置文件 application.yml。
server: port: 8181 spring: datasource: url: jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=UTF-8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:/mapping/*.xml type-aliases-package: com.southwind.entity logging: level: com.southwind.repository.*: debug
10、創建啟動類 Application 並運行。
@SpringBootApplication @MapperScan("com.southwind.repository") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); } }
11、啟動成功後使用 Postman 測試 Handler 介面,如下圖所示。

埠為 8181 的後端服務創建成功,接下來完成前端服務,並調用後端服務介面 。
前端服務
1、創建 Vue 工程,並安裝 Element UI 和 axios。
2、我們使用 Element UI 來搭建前端介面,Element UI 提供了數據表格的組件,非常簡單,直接查看 Element UI 官方文檔即可,官方示例程式碼如下所示。
<template> <el-table :data="tableData" border style="width: 100%"> <el-table-column fixed prop="date" label="日期" width="150"> </el-table-column> <el-table-column prop="name" label="姓名" width="120"> </el-table-column> <el-table-column prop="province" label="省份" width="120"> </el-table-column> <el-table-column prop="city" label="市區" width="120"> </el-table-column> <el-table-column prop="address" label="地址" width="300"> </el-table-column> <el-table-column prop="zip" label="郵編" width="120"> </el-table-column> <el-table-column fixed="right" label="操作" width="100"> <template slot-scope="scope"> <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button> <el-button type="text" size="small">編輯</el-button> </template> </el-table-column> </el-table></template><script> export default { methods: { handleClick(row) { console.log(row); } }, data() { return { tableData: [ {date: '2016-05-03',name: '王小虎',province: '上海',city: '普陀區',address: '上海市普陀區金沙江路 1518 弄',zip: 200333}, {date: '2016-05-03',name: '王小虎',province: '上海',city: '普陀區',address: '上海市普陀區金沙江路 1518 弄',zip: 200333}, {date: '2016-05-03',name: '王小虎',province: '上海',city: '普陀區',address: '上海市普陀區金沙江路 1518 弄',zip: 200333}, {date: '2016-05-03',name: '王小虎',province: '上海',city: '普陀區',address: '上海市普陀區金沙江路 1518 弄',zip: 200333} ] } } } </script>
3、運行結果如下圖所示。

4、在 Vue 工程 components 路徑下創建 Table.Vue,在初始化方法中通過 axios 調用後端服務的數據介面並完成動態綁定,程式碼如下所示。
<template> <div> <div> <el-table :data="tableData" border style="width: 80%;margin-left: 100px;margin-top: 30px;"> <el-table-column fixed prop="id" label="編號" width="100"> </el-table-column> <el-table-column prop="name" label="圖書" width="150"> </el-table-column> <el-table-column prop="author" label="作者" width="150"> </el-table-column> <el-table-column prop="publish" label="出版社" width="180"> </el-table-column> <el-table-column prop="pages" label="總頁數" width="100"> </el-table-column> <el-table-column prop="price" label="價格" width="100"> </el-table-column> <el-table-column prop="bookCase.name" label="分類" width="120"> </el-table-column> <el-table-column fixed="right" label="操作" width="100"> <template slot-scope="scope"> <el-button type="text" size="small">修改</el-button> <el-button type="text" size="small">刪除</el-button> </template> </el-table-column> </el-table> <el-pagination background layout="prev, pager, next" :total="total" :page-size="pageSize" @current-change="change" > </el-pagination> </div> </div> </template> <script> export default { methods: { change(currentPage) { this.currentPage = currentPage const _this = this axios.get('http://localhost:8181/book/findByPage/'+currentPage).then(function (resp) { _this.tableData = resp.data.data }) } }, data() { return { total:0, pageSize:5, tableData: [], currentPage:0 } }, created() { const _this = this axios.get('http://localhost:8181/book/findByPage/1').then(function (resp) { console.log(resp.data) _this.pageSize = resp.data.pageSize _this.total = resp.data.total _this.tableData = resp.data.data }) } } </script>
5、在 router.js 中設置 Table.Vue 路由,程式碼如下所示。
import Table from '../components/Table' routes:[ { path: '/table', component: Table, name: '查詢圖書' } ]
6、在終端執行命令 npm run serve 啟動 Vue 服務,打開瀏覽器訪問 http://localhost:8080/table,結果如下圖所示。

這樣我們就完成了 Spring Boot + Vue 前後端分離的開發,很簡單吧,你學會了嗎