新手福利,通過一個簡單示例快速上手Spring Boot+Vue前後端分離

  • 2019 年 10 月 29 日
  • 筆記

Spring Boot + Vue 前後端分離的開發方式現在真的是火的不得了,之前楠哥寫過一篇前後端分離的教程以及一篇用 Vue + Element UI 搭建後台管理系統介面的教程:

1、還搞不明白前後端分離?看完這篇文章,小白也能馬上學會

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 前後端分離的開發,很簡單吧,你學會了嗎