从零开始搭建Vue2.0项目(三)之集成SpringBoot

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 前面一篇主要是介绍了怎么完成`axios`请求测试以及`mock.js`模拟真实数据请求,前后端分离的实际应用还是得与后端进行交互,下面是关于怎么样与`java`后台进行交互的介绍。

前言📋

前面一篇主要是介绍了怎么完成axios请求测试以及mock.js模拟真实数据请求,前后端分离的实际应用还是得与后端进行交互,下面是关于怎么样与java后台进行交互的介绍。

快速开始⚡

我么将要完成Mybatis框架的集成,并编写查询语句查询出MySQL数据库的数据,通过controller层的API暴露给前端,从而实现数据的交互。

首先,完成SpringBoot项目的创建,添加mybatis、spring-web、spring-configuration、mysql、lombok依赖。

项目目录

创建完成后,项目目录如下:

img

一、添加依赖

pom.xml

    <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>2.1.4</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

二、编写yaml配置文件

将根目录下的application.properties重命名为application.yml,然后进行配置:

server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
# 数据库驱动
# 此處驱动有两个
# com.mysql.jdbc.Driver
# com.mysql.cj.jdbc.Driver
# MySQL5用的驱动url是com.spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver.mysql.jdbc.Driver,
#  MySQL6以后用的是com.mysql.cj.jdbc.Driver。
# 使用何种驱动,根据安装MySQL的版本而定
# 下面是Mybatis下划线转驼峰
mybatis:
  configuration:
    map-underscore-to-camel-case: true

注意:这里如果添加了Mybatis而不进行数据库连接池的配置,将会报出异常!

三、编写主类文件

User.java

package com.deepinsea.cors.entity;

import lombok.Data;

/**
 * @author 南街北巷
 * @data 2021/1/6 15:51
 */
@Data
public class User {

    private int id;
    private String name;
    private int age;
}

注意:我们应该事先创建好MySQL数据库,设置库、表编码为utf8mb64(为什么MySQL不用utf-8?),然后根据数据库设置的字段编写实体类!

UserMapper.java

package com.deepinsea.cors.mapper;

import com.deepinsea.cors.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @author 南街北巷
 * @data 2021/1/6 15:52
 */
@Mapper
@Repository
public interface UserMapper {

    /**
     * 根据id查询User
     * @param id
     * @return
     */
    @Select("select * from user where id = #{id}")
    User findById(int id);

    /**
     * 查询所有用户
     * @return
     */
    @Select("select * from user")
    List<User> findAll();
}

HelloController.java

package com.deepinsea.cors.controller;

import com.deepinsea.cors.entity.User;
import com.deepinsea.cors.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author 南街北巷
 * @data 2021/1/6 14:44
 * @RestController 等同于 @Controller+@ResponseBody
 */
@RestController
@RequestMapping("/user")
public class HelloController {

    @Autowired
    private UserMapper userMapper;

    @PostMapping("/getBy/{id}")
    public User findById(@PathVariable int id){
        User user = userMapper.findById(id);
        return user;
    }

    @PostMapping("/getAll")
    public List<User> getAll(){
        List<User> users = userMapper.findAll();
        return users;
    }
}

四、测试使用

下面以请求APIhttp://localhost:8080/user/getBy/2为例进行测试:

img

测试以后,发现返回JSON字符串成功(需要自定义序列化配置、异常、枚举可以自行配置,这里仅快速集成)!

好了,到了这里,数据库 => 后端的数据传递也完成了!可以正式进行后端 => 前端的数据交互了:

前后端交互

现在是正式集成进行后端与前端的跨域请求,因此我们需要把注释的portproxyTable打开:

端口

port: 8081 # 后端端口为8080

代理配置

  proxyTable: {
        // 跨域配置
        // 修改配置后如果项目启动404,记得重启项目(类似于redis,webpack是依赖配置文件启动的)
        // 错误日志:xhr.js?ec6c:177 POST http://localhost:8081/user/getAll 404 (Not Found)
        '/api': {
          target: 'http://localhost:8080/',
          changeOrigin: true,
          secure: false,  // 如果是https接口,需要配置这个参数
          pathRewrite: {
            '^/api': ''
          }
        }
    },

上面的配置相当于将前端的请求代理为:

http://localhost:8081/api => http://localhost:8080

上面将原后端增加一个/api路径参数,是为了隐藏真实的后端API地址,但是对于前端请求真实的API地址没有用。因此 ,我们需要在main.js中(或者vue.config.js)设置前端跨域代理的基本路径,这样就不用编写地址时每次都加一个/api了:

axios.defaults.baseURL = '/api' // 设置跨域代理基本路径

因为使用axios进行过测试(后面可以集成vuex状态管理器对axios进行二次封装),只需要将Home.vue中的测试API访问地址更改为后端的API地址即可:

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
import MockTest from '@/components/MockTest.vue' // 这里不能使用./AxiosTest.vue的方式引入
  name: 'Home',
  components: { // 局部注册(引入并注册)
    HelloWorld,
    MockTest
  },
  methods: {
    mockTest () {
      this.$axios.post('/user/getAll') // 'https://v1.alapi.cn/api/music/search?   keyword=我爱你'
        .then(res => {
          console.log(res) // 在控制台打印响应数据(包括响应头与响应体)
        })
        .catch(err => {
          console.log(err)
        })
    }
  }
</script>

注意:也可以在created()mounted()生命周期函数里面添加该方法,将会自动执行。

测试使用

跨域配置完成了,启动项目:

img

可以看到,成功返回了后端的数据!

到这里基本可以结束了,下面是关于数组遍历出对象显示到前端的部分(主要为原理深究)

读取对象数组数据

1. 使用foreach遍历读取

首先,一般遍历Javascript遍历实现数据的传递都是通过document.getElementById()方法进行单向数据传递,但是对于已经默认进行了双向绑定的vue对象来说——即:在data()中声明的对象,进行数据的传递往往要考虑一个数据的状态变化性(动态变化性)。

因为获取到axios响应体的数据一般是通过this指针传递给vue对象的,因此this指向的对象发生变化时全局的对象的值也会随之发生改变(this相当于指针),这将会导致数组使用for循环以及其他各种遍历方式非钩子函数,遍历时新数组对象都会将原来的数组对象覆盖:

下面是使用for循环遍历等各种数组测试

Home.vue

<template>
  <div class="home">
    <Hello-World />
    <Mock-Test />
    <button @click="userTest">试试</button>
  <!-- 下面两种方式进行遍历都可以,index是数组下标0,1,2...,item是id序号1,2,3... -->
  <!-- 当两种标签遍历方式都存在时,只用item的遍历会报key重复错误(应该是DOM结构冲突),
       因此最好使用item和index同时定位对象的遍历方式 -->
  <p>{{userList}}</p>
  <!-- <p v-for="item in userList" :key="item.id">{{item}}</p>
  <p v-for="(item,index) in userList" :key="index">{{item.id}}</p> -->

  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
import MockTest from '@/components/MockTest.vue' // 这里不能使用./AxiosTest.vue的方式引入

export default {
  name: 'Home',
  components: {
    HelloWorld,
    MockTest
  },
  data () {
    return {
      userList: '' // 注意: 这里为对象数组时参数时定义为userList:[](适用于单个对象)的话会默认产生一个[]符号,
    }
  },
  // created () { // 或created: function(),为生命周期函数created,也可以是mounted—已挂载,可在页面加载时自动执行方法
  //   this.userTest()
  // },
  methods: {
    userTest () {
      this.$axios.post('/user/getAll') // 'https://v1.alapi.cn/api/music/search?keyword=我爱你'
        .then(res => {
          // 响应体获取测试
          // console.log(res)
          // console.log(res.data) // 这里采用逐步分层取值的方式测试
          // console.log(res.data[0])
          // console.log(res.data[0].name)
          // console.log(res.data[res.data[0].id].name) // 嵌套取值
          // console.log(res.data.length)

          // var _this = this// 这句话的位置需要注意
          // console.log(this)// 依然是这个方法的对象
          // console.log(_this) // 这个变成了原来的对象

          // 循环取值测试(因为this的指针变化问题,不可行,因为this无论是否处于严格模式下都引用全局对象。)
          for (var i = 0; i < res.data.length; i++) { // 遍历出所有对象
            // 将对象合并(for循环遍历赋值、Object.assign()、序列化、浅拷贝、深拷贝(不会覆盖对象)、foreach遍历(测试成功))
            // 1.遍历赋值
            // this.userList = res.data[i] // 测试发现只有id为2(即:第二个对象)对象的值,说明userList的this指向被修改了
            // console.log(this.userList)
            // 2.Object.assign()
            // var objList = Object.assign({}, res.data[i]) // 参数表示,测试时也可以直接用常数表示
            // console.log(objList)
            // this.userList >= objList
            // 3.序列化
            // const obj = JSON.parse(JSON.stringify(res.data[i]))
            // this.userList = obj
            // console.log(obj)
            // 浅拷贝与深拷贝需要下载JQuery,暂时没有尝试
          }

          // 4.foreach遍历测试
          // var list = ['750', '1080', '1125', '1242', '1242']
          // var data = []
          // Object.keys(list).forEach(key => {
          //   let item = {
          //     val: list[key]
          //   }
          //   data.push(item)
          // })
          // console.log(list)
          // 正式使用
          var list = res.data
          var data = []
          Object.keys(list).forEach(key => { // 因为这里使用了ES6语法中的 => 钩子函数,因此将不会
            data.push(list[key])
          })
          this.userList = data
          console.log(data)

          // this.userList = res.data
          // console.log(res.data)
          // axios的response采用默认参数data存放数据,这里只需要传data的值就行了,
          // 否则要从一个加了其他参数的多重JSON对象中取值,无异于自己设计一个JSON序列化工具
          // 注意:这里res.data前不需要加this指针,因为箭头函数没有自己的this(因此本身是局部变量),
          // 箭头函数里面的this是对象的指针(定义时的全局变量),如果加了this那么将获取不到res.data的值
        })
        .catch(err => {
          console.log(err)
        })
    }
  }
}
</script>

使用for循环里面的遍历赋值与浅拷贝都会导致最终数组元素的值发生改变,导致对象数组遍历出对象再合并出现对象覆盖的现象:

img

但是使用foreach遍历搭配钩子函数就能避免这个问题:

 // 4.foreach遍历测试
      // var list = ['750', '1080', '1125', '1242', '1242']
      // var data = []
      // Object.keys(list).forEach(key => {
      //   let item = {
      //     val: list[key]
      //   }
      //   data.push(item)
      // })
      // console.log(list)
      // 正式使用
      var list = res.data
      var data = []
      Object.keys(list).forEach(key => { // 因为这里使用了ES6语法中的 => 钩子函数,因此将不会
        data.push(list[key])
      })
      this.userList = data
      console.log(data)

2. 使用v-for读取

对此,vue2.0提供了默认的数组遍历方法(当然,数组还存在下标属性更新不了以及数组长度不可响应式改变的问题,具体参考issues;这些在vue3.0中使用proxy代替Object.defineProperty()时得到了解决),下面是关于vue的数组遍历方法v-for的使用:

Home.vue

<template>
  <div class="home">
    <Hello-World />
    <Mock-Test />
    <button @click="userTest">试试</button>
  <!-- 下面两种方式进行遍历都可以,index是数组下标0,1,2...,item是id序号1,2,3... -->
  <!-- 当两种标签遍历方式都存在时,只用item的遍历会报key重复错误(应该是DOM结构冲突),
       因此最好使用item和index同时定位对象的遍历方式 -->
  <p>{{userList}}</p>
  <p v-for="item in userList" :key="item.id">{{item}}</p>
  <!-- 使用单item作为参数的方式最好不要获取详细到具体key的值,否则会提示错误,因此这种适合整个对象的获取 -->
  <!-- <p v-for="(item,index) in userList" :key="index">{{item.id}}</p> -->

  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
import MockTest from '@/components/MockTest.vue' // 这里不能使用./AxiosTest.vue的方式引入

export default {
  name: 'Home',
  components: {
    HelloWorld,
    MockTest
  },
  data () {
    return {
      userList: '' // 注意: 这里为对象数组时参数时定义为userList:[](适用于单个对象)的话会默认产生一个[]符号,
    }
  },
  // created () { // 或created: function(),为生命周期函数created,也可以是mounted—已挂载,可在页面加载时自动执行方法
  //   this.userTest()
  // },
  methods: {
    userTest () {
      this.$axios.post('/user/getAll') // 'https://v1.alapi.cn/api/music/search?keyword=我爱你'
        .then(res => {
          // 响应体获取测试
          // console.log(res)
          // console.log(res.data) // 这里采用逐步分层取值的方式测试
          // console.log(res.data[0])
          // console.log(res.data[0].name)
          // console.log(res.data[res.data[0].id].name) // 嵌套取值
          // console.log(res.data.length)

          // var _this = this// 这句话的位置需要注意
          // console.log(this)// 依然是这个方法的对象
          // console.log(_this) // 这个变成了原来的对象

          // 循环取值测试(因为this的指针变化问题,不可行,因为this无论是否处于严格模式下都引用全局对象。)
          for (var i = 0; i < res.data.length; i++) { // 遍历出所有对象
            // 将对象合并(for循环遍历赋值、Object.assign()、序列化、浅拷贝、深拷贝(不会覆盖对象)、foreach遍历(测试成功))
            // 1.遍历赋值
            // this.userList = res.data[i] // 测试发现只有id为2(即:第二个对象)对象的值,说明userList的this指向被修改了
            // console.log(this.userList)
            // 2.Object.assign()
            // var objList = Object.assign({}, res.data[i]) // 参数表示,测试时也可以直接用常数表示
            // console.log(objList)
            // this.userList >= objList
            // 3.序列化
            // const obj = JSON.parse(JSON.stringify(res.data[i]))
            // this.userList = obj
            // console.log(obj)
            // 浅拷贝与深拷贝需要下载JQuery,暂时没有尝试
          }

          // 4.foreach遍历测试
          // var list = ['750', '1080', '1125', '1242', '1242']
          // var data = []
          // Object.keys(list).forEach(key => {
          //   let item = {
          //     val: list[key]
          //   }
          //   data.push(item)
          // })
          // console.log(list)
          // 正式使用
          // var list = res.data
          // var data = []
          // Object.keys(list).forEach(key => { // 因为这里使用了ES6语法中的 => 钩子函数,因此将不会
          //   data.push(list[key])
          // })
          // this.userList = data
          // console.log(data)

          this.userList = res.data
          console.log(res.data)
          // axios的response采用默认参数data存放数据,这里只需要传data的值就行了,
          // 否则要从一个加了其他参数的多重JSON对象中取值,无异于自己设计一个JSON序列化工具
          // 注意:这里res.data前不需要加this指针,因为箭头函数没有自己的this(因此本身是局部变量),
          // 箭头函数里面的this是对象的指针(定义时的全局变量),如果加了this那么将获取不到res.data的值
        })
        .catch(err => {
          console.log(err)
        })
    }
  }
}
</script>

启动项目,成功获取到数据:

img

前后端数据请求成功!

小结

前后端打通了,下面就是项目UI框架的集成了,冲冲冲💪💪

【学无止境❤️谦卑而行】欢迎关注白羊🐏,感谢观看ヾ(◍°∇°◍)ノ゙

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
28天前
|
XML Java 应用服务中间件
SpringBoot项目打war包流程
本文介绍了将Spring Boot项目改造为WAR包并部署到外部Tomcat服务器的步骤。主要内容包括:1) 修改pom.xml中的打包方式为WAR;2) 排除Spring Boot内置的Tomcat依赖;3) 添加Servlet API依赖;4) 改造启动类以支持WAR部署;5) 打包和部署。通过这些步骤,可以轻松地将Spring Boot应用转换为适合外部Tomcat服务器的WAR包。
132 64
SpringBoot项目打war包流程
|
14天前
|
Java 关系型数据库 MySQL
SpringBoot 通过集成 Flink CDC 来实时追踪 MySql 数据变动
通过详细的步骤和示例代码,您可以在 SpringBoot 项目中成功集成 Flink CDC,并实时追踪 MySQL 数据库的变动。
119 43
|
10天前
|
前端开发 JavaScript Java
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
57 13
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
|
11天前
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
57 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
9天前
|
SQL JavaScript 安全
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
47 11
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
|
13天前
|
人工智能 JavaScript 安全
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
57 13
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
|
16天前
|
监控 前端开发 Java
SpringBoot集成Tomcat、DispatcherServlet
通过这些配置,您可以充分利用 Spring Boot 内置的功能,快速构建和优化您的 Web 应用。
48 21
|
12天前
|
监控 JavaScript 前端开发
ry-vue-flowable-xg:震撼来袭!这款基于 Vue 和 Flowable 的企业级工程项目管理项目,你绝不能错过
基于 Vue 和 Flowable 的企业级工程项目管理平台,免费开源且高度定制化。它覆盖投标管理、进度控制、财务核算等全流程需求,提供流程设计、部署、监控和任务管理等功能,适用于企业办公、生产制造、金融服务等多个场景,助力企业提升效率与竞争力。
66 12
|
1月前
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
136 36
|
1月前
|
监控 Java Nacos
使用Spring Boot集成Nacos
通过上述步骤,Spring Boot应用可以成功集成Nacos,利用Nacos的服务发现和配置管理功能来提升微服务架构的灵活性和可维护性。通过这种集成,开发者可以更高效地管理和部署微服务。
208 17

热门文章

最新文章