第一版SpringBoot+Vue
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