第一版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。最后完成前后端集成即可。真正实现了前后端应用的解耦合,极大的提升了开发效率。
传统单体应用:
前后端分离结构:
之前的单体应用拆分为前端应用于后端应用,前端应用负责数据展示与用户交互。后端应用负责提供数据处理接口。前端–>Ajax–>RESTful接口。
1.2 、实现技术
SpringBoot + Vue
使用 SpringBoot 实现后端应用开发,使用 Vue 进行前端应用开发。
2. 实战
2.1、Vue创建项目与讲解
cmd
创建项目:
vue create vuetest
- 选择
Manually select features
,手动选择模板 - 选择
Babel
、Router
、Vuex
- 打开历史记录:选择
Y
- Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys) 选择
In dedicated config files
- Save this as a preset for future projects? (y/N) 选择
N
- 等待创建
- 创建完成
- 运行一下命令
cd vuetest
npm run serve
运行 http://localhost:8080/
现在可以使用 VsCode
或者 WebStorm
进行开发。
WebStorm
配置项目运行。- 或者通过
Terminal
运行npm run serve
。以上两种哪个都可以。 Vue
单页面讲解:
- 结合
Vue.app
源码: 是动态加载的,通过路由映射完成。
- 路由映射讲解:
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文件夹中的视图都会展现在这里 -->
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 语法
}
]
- 自己写一个试试(我的习惯是先写路由,再写视图)
- 添加路由
MyTest
, 在router\index.js
中添加一下代码
import MyTest from '../views/MyTest.vue' // 写在文件开头的Home下面
{ // 写在 const routes 中
path: '/mytest',
name: 'MyTest',
component: MyTest
}
- 现在写
MyTest.vue
,在views
文件夹中新建MyTest.vue
<template>
<h2>This is the page of MyTest.</h2>
</template>
<script>
export default {
name: "MyTest"
}
</script>
<style scoped>
</style>
- 在
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 -->
- 现在你再看你的
http://localhost:8080/
,是不是发生了一下变化,试着点击一下,你会看到你写的界面(视图)。 - 通过上面这个过程,仔细回想一下,刚刚发生了什么,仔细想想,
<router-link>
、<router-view>
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
2.2、SpringBoot应用
2.2.1、创建SpringBoot应用
- 依赖选择
- 修改
src\main\resources\application.properties
为application.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
访问真实数据库
- 创建实体类在
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;
}
- 创建
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+左键点进去看看
// 第一个参数是你的实体类类型
// 第二个参数是你的主键类型
}
- 单元测试
- 创建测试类
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());
}
}
- 运行测试类
- 总结:我们每写一个Repository接口,就先测试一下,保证没有问题,再写到controller里面,让外部访问
- 创建
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();
}
}
- 启动
Application
,就是启动整个项目 - 访问
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> <!-- 添加这个代码 -->
- 现在我们的想法就是在
Book.vue
页面中发送Ajax
请求,请求8181
端口,最终把图书信息替换。那么在Vue中怎么去请求Ajax
呢,我们需要安装一个组件axios
。 - 安装
axios
,打开Terminal
, 输入:
vue add axios
3. 安装完成后,plugins
中多了一个axios.js
文件。然后,使用一下命令
npm install
main.js
中多了一下一行代码,下面就可以使用axios
了。- 我们的目的是:当用户刷新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);
})
}
- 打开
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、前端继续完善
- 刷新我们的
http://localhost:8080/book
,会在控制台看到: - 现在只需要把
resp
中的data
赋值给<script>
标签data
的books
就可以了。
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
})
}
- 效果
2.6、撒花
对基本的前后端分离开发有了了解,掌握一些特定功能的代码,比如created
函数中使用axios
以及_this
与this
的区别。记住使用springboot
开发接口的过程与特定代码以及注解。
WebStorm
IDEA