第一版SpringBoot+Vue

  • SpringBoot + Vue
  • 1.1、前后端分离
  • 1.2 、实现技术
  • 2. 实战
  • 2.1、Vue创建项目与讲解
  • 2.2、SpringBoot应用
  • 2.2.1、创建SpringBoot应用
  • 2.2.2、 使用`SpringBootJPA` 访问真实数据库
  • 2.3、 修改前端应用
  • 2.4、后端解决跨域问题
  • 2.5、前端继续完善
  • 2.6、撒花


SpringBoot + Vue

1.1、前后端分离

前后端分离就是将一个应用的前端代码和后端代码分开写,为什么要这么做?如果不适用前后端分离会出现哪些问题:传统的 java web 开发中,前端使用的是jsp开发,JSP不是由后端开发者独立完成。前端->HTML静态布局页面->后端->JSP(需要前端与后端沟通,沟通耗时,严重影响开发效率)。–>耦合度太高。
可以使用前后端分离的方式,完美的解决这个问题。前端只需要独立编写客户端的代码,后端只需要独立编写服务端代码,提供接口API即可。前端使用AJAX请求后端的数据接口,将Model展示到View中即可。
前后端开发者只需要提前约定好接口文档(URL、参数、数据类型…),然后分别独立开发即可。前端可以使用假数据进行测试,完全不需要依赖于后端,后端也不需要依赖前端,可以使用PostMan测试API。最后完成前后端集成即可。真正实现了前后端应用的解耦合,极大的提升了开发效率。

传统单体应用:

springboot和vue模式图解 springboot搭配vue_vue

前后端分离结构:

springboot和vue模式图解 springboot搭配vue_vue_02

之前的单体应用拆分为前端应用于后端应用,前端应用负责数据展示与用户交互。后端应用负责提供数据处理接口。前端–>Ajax–>RESTful接口。

1.2 、实现技术

SpringBoot + Vue
使用 SpringBoot 实现后端应用开发,使用 Vue 进行前端应用开发。

2. 实战

2.1、Vue创建项目与讲解

cmd 创建项目:

vue create vuetest
  1. 选择 Manually select features ,手动选择模板
  2. 选择 BabelRouterVuex
  3. 打开历史记录:选择 Y
  4. Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys) 选择 In dedicated config files
  5. Save this as a preset for future projects? (y/N) 选择 N
  1. 等待创建
  2. 创建完成
  3. 运行一下命令
cd vuetest
npm run serve

运行 http://localhost:8080/

springboot和vue模式图解 springboot搭配vue_spring boot_03

现在可以使用 VsCode 或者 WebStorm 进行开发。

springboot和vue模式图解 springboot搭配vue_springboot和vue模式图解_04

  1. WebStorm 配置项目运行。
  2. 或者通过 Terminal 运行 npm run serve。以上两种哪个都可以。
  3. Vue 单页面讲解:
  1. 结合 Vue.app 源码: 是动态加载的,通过路由映射完成。
  1. 路由映射讲解:
  1. App.vue讲解
<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |  
      <router-link to="/about">About</router-link>
<!--   
1. <router-link>可以理解为Vue的语法标签,暂时我们可以对应HTML中的<a>标签。
2. <router-link to="">中的属性 to 可以理解为 <a href="">中的属性 href。
3. to的属性值需要结合 router 文件夹中的 index.js 文件讲解 -- 路由控制
-->
    </div>
    <router-view/>
  </div>
</template>
<router-view/> <!--给你的 <router-link>标签一个展示的位置吧,所有views文件夹中的视图都会展现在这里 -->
  1. router\index.js讲解
// 先引用 Vue 与 VueRouter,否则路由无法使用
import Vue from 'vue'
import VueRouter from 'vue-router'

// 引用 你的模板
import Home from '../views/Home.vue'
const routes = [
  // 这个地方配置你的路由
  {
    path: '/',  // 给你的文件一个索引,对应你的浏览器url以及App.vue中<router-link>中to的属性值
    name: 'Home', // 给路由一个名字
    component: Home  // 你的模板,对应的是  import Home from '../views/Home.vue'
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')  // vue3.0 语法
  }
]
  1. 自己写一个试试(我的习惯是先写路由,再写视图)
  1. 添加路由MyTest, 在router\index.js中添加一下代码
import MyTest from '../views/MyTest.vue' // 写在文件开头的Home下面

 { // 写在 const routes 中
    path: '/mytest',
    name: 'MyTest',
    component: MyTest
 }
  1. 现在写MyTest.vue,在views文件夹中新建MyTest.vue
<template>
  <h2>This is the page of MyTest.</h2>
</template>

<script>
export default {
	name: "MyTest"
}
</script>

<style scoped>

</style>
  1. App.vue中添加 <router-link>标签
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/mytest">MyTest</router-link> <!-- MyTest -->
  1. 现在你再看你的http://localhost:8080/,是不是发生了一下变化,试着点击一下,你会看到你写的界面(视图)。
  2. 通过上面这个过程,仔细回想一下,刚刚发生了什么,仔细想想,<router-link><router-view>提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

2.2、SpringBoot应用

2.2.1、创建SpringBoot应用

  1. 依赖选择
  2. 修改src\main\resources\application.propertiesapplication.yml,里面配置链接数据库的信息
spring:
    datasource:
        url: jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
        username: root
        password: Cptbtptp123.
        driver-class-name: com.mysql.cj.jdbc.Driver
    jpa:
        show-sql: true # 打印sql信息
        properties:
            hibernate:
                format_sql: true # 格式化sql
server:
    port: 8181  # 配置端口 默认8080,与vue工程冲突

2.2.2、 使用SpringBootJPA 访问真实数据库

  1. 创建实体类在src\main\java\com.southwind.springboottest中 -> New Package -> src\main\java\com.southwind.springboottest\entity -> New Class ->src\main\java\com.southwind.springboottest\entity\Book.class。实体类与表进行绑定。
package com.southwind.springboottest.entity;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;

/**
 * @author 田港
 * @version 1.0
 * @date 2021-03-25 11:06
 */
@Entity // Entity 注解类,绑定book表,根据表名与类名绑定: 类名首字母小写就是我们的表名
@Data  // lombok 注解,自动帮我们生成各种各种的get与set方法
public class Book {
    // 属性对应, 属性名与字段名绑定
    @Id // 主键绑定
    private Integer id;
    private String name;
    private String author;
}
  1. 创建package\interface -> com.southwind.springboottest.repository\BookRepository.interface
package com.southwind.springboottest.repository;

import com.southwind.springboottest.entity.Book;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @author 田港
 * @version 1.0
 * @date 2021-03-25 11:12
 */
public interface BookRepository extends JpaRepository<Book, Integer> {
    // JpaRepository 实现了很多接口,可以Ctrl+左键点进去看看
    // 第一个参数是你的实体类类型
    // 第二个参数是你的主键类型
}
  1. 单元测试
  1. 创建测试类
  2. BookRepositoryTest.java
package com.southwind.springboottest.repository;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author 田港
 * @version 1.0
 * @date 2021-03-25 11:40
 */

@SpringBootTest
        // 添加注解
class BookRepositoryTest {

    // 我们要测试的是BookRepository,所以先注入进来,private代表仅当前类可用
    @Autowired //添加注解,自动注入
    private BookRepository bookRepository;

    @Test // 添加注解
    void findAll() {
        System.out.println(bookRepository.findAll());
    }
}
  1. 运行测试类
  2. 总结:我们每写一个Repository接口,就先测试一下,保证没有问题,再写到controller里面,让外部访问
  1. 创建Package->Class --> com.southwind.springboottest.controller\BookHandler.class
package com.southwind.springboottest.controller;

import com.southwind.springboottest.entity.Book;
import com.southwind.springboottest.repository.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author 田港
 * @version 1.0
 * @date 2021-03-25 12:17
 */

@RestController
@RequestMapping("/book")
public class BookHandler {
    // 注入 BookRepository
    @Autowired
    private BookRepository bookRepository;

    @GetMapping("/findAll")
    public List<Book> findAll() {
        return bookRepository.findAll();
    }

}
  1. 启动Application,就是启动整个项目
  2. 访问 http://localhost:8181/book/findAll, 注意整个url与我们写的BookHandler.java中的@GetMapping对应关系,然后理解一下这个注解的作用。

2.3、 修改前端应用

按照2.1文档创建Book.vue,并在路由以及App.vue中配置好

Bool.vue

<template>
  <div>
    <table>
      <tr>
        <td>编号</td>
        <td>图书名称</td>
        <td>作者</td>
      </tr>
      <!--  v-for 语法 : https://cn.vuejs.org/v2/guide/list.html  -->
      <tr v-for="book in books" :key="book.id">
        <td>{{ book.id }}</td>
        <td>{{ book.name }}</td>
        <td>{{ book.author }}</td>
      </tr>
    </table>
    {{ msg }}
  </div>
</template>

<script>
export default {
  name: "Book",
  data() {
    return { // 定义json数据
      msg: "Hello Vue",
      books: [
        {
          id: 1,
          name: '我们的爱情',
          author: '田港'
        },
        {
          id: 2,
          name: '提问的智慧',
          author: '田港'
        },
        {
          id: 3,
          name: '锻炼的姿势',
          author: '田港'
        },
      ]
    }
  }
}
</script>

<style scoped>

</style>

router\index.js路由中的const routes添加如下代码:

{
    path: '/book',
    name: 'Book',
    component: Book

}

App.vue修改

<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> | <!-- 添加一个竖线 -->
<router-link to="/book">Book</router-link>  <!-- 添加这个代码 -->
  1. 现在我们的想法就是在Book.vue页面中发送Ajax请求,请求8181端口,最终把图书信息替换。那么在Vue中怎么去请求Ajax呢,我们需要安装一个组件axios
  2. 安装axios,打开Terminal, 输入:
vue add axios

springboot和vue模式图解 springboot搭配vue_vue_05


3. 安装完成后,plugins中多了一个axios.js文件。然后,使用一下命令

npm install
  1. main.js中多了一下一行代码,下面就可以使用axios了。
  2. 我们的目的是:当用户刷新Book页面时,就读取图书数据。所以在Book.vue中的script标签中写created函数(初始化函数,当页面被加载时,自动执行created函数代码)。
created() {
    // 使用 axios的get请求,第一个参数为请求的url,即接口
    // 后面是一个回调函数,就是当执行完get请求后,紧接着做哪些操作,then就是然后的意思嘛
    // then里面是一个匿名函数
    axios.get('http://localhost:8181/book/findAll').then(function (resp){
      // 看看resp是啥东西
      console.log(resp); 
    })
  }
  1. 打开http://localhost:8080/book,打开控制台,然后F5刷新页面,会发现控制台报错

    关于跨域问题我们使用后端解决方法,也就是SpringBoot进行配置,当然,前端可以通过一个nginx访问接口。跨域问题是什么呢

2.4、后端解决跨域问题

解决方式很简单,只需要添加一个配置类就ok!创建一个包com.southwind.springboottest.config,里面创建一个类CorsConfig.java

package com.southwind.springboottest.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author 田港
 * @version 1.0
 * @date 2021-03-25 13:27
 * SpringBoot解决跨域问题,先记住就行,用的时候copy到项目中
 */
@Configuration // 添加这个注解
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
				// .allowCredentials(true)
                .allowedHeaders("*")
                .allowedOrigins("*")
                // 运行请求的方法
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .maxAge(3600);
    }
}

配置好之后,再启动。测试一下接口,http://localhost:8181/book/findAll,对于接口没影响,没问题!!!

2.5、前端继续完善

  1. 刷新我们的http://localhost:8080/book,会在控制台看到:
  2. 现在只需要把resp中的data赋值给 <script> 标签databooks就可以了。
created() {
    // 回调函数中的this作用域指的是回调
    // 定义一个vue的this,this指向当前的vue对象
    const _this = this;
    // 使用 axios的get请求,第一个参数为请求的url,即接口
    // 后面是一个回调函数,就是当执行完get请求后,紧接着做哪些操作,then就是然后的意思嘛
    // then里面是一个匿名函数
    axios.get('http://localhost:8181/book/findAll').then(function (resp){
      // 看看resp是啥东西
      // console.log(resp);
      _this.books = resp.data; // 将resp中的data赋值给vue对象中的books
    })
  }
  1. 效果

2.6、撒花

对基本的前后端分离开发有了了解,掌握一些特定功能的代码,比如created函数中使用axios以及_thisthis的区别。记住使用springboot开发接口的过程与特定代码以及注解。

WebStorm

springboot和vue模式图解 springboot搭配vue_ajax_06


IDEA

springboot和vue模式图解 springboot搭配vue_java_07