开篇

当下前后端分离的趋势很明显,的确这也是很有必要的。前后端分离让前端专注于前端,后端专注于后端,而不是哪一方都要学习前后端。学习过JSP的都知道,前后端之前都是套模板,这会让项目很繁琐,而且也提高了项目的耦合性,不利于二次开发,所以现在来通过一个简单的demo来简单的体验一下前后端分离。

涉及技术

  • Vue

  • SprtingBoot

  • Mybatis-plus

准备数据

这里的数据我就使用Mybatis-plus官方提供样例的数据了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CREATE DATABASE IF NOT EXISTS Company;

USE `Company`;

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

前端部分

因为我不是学习的重心不是前端,所以我就不写样式了,主要是展示一下返回的数据

  1. 创建一个Vue的项目

  2. 在项目的views的文件夹下编写test.vue页面用来展示数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <template>
    <div>
    <table>
    <tr>
    <td>主键ID</td>
    <td>姓名</td>
    <td>年龄</td>
    <td>邮箱</td>
    </tr>
    <tr v-for="item in user" :key="item.id">
    <td>{{item.id}}</td>
    <td>{{item.name}}</td>
    <td>{{item.age}}</td>
    <td>{{item.email}}</td>
    </tr>
    </table>
    </div>
    </template>

    <script>
    export default {
    name: "test",
    data(){
    return{
    user: [{
    id : 1,
    name : 'yww',
    age : 10,
    email : '1141@qq.com'
    }]
    }
    },
    }
    </script>
    <style>
    </style>

    前端开始主要注重页面,所以先用假数据。

  3. 编写路由,在router的文件下编写index.js文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import Home from '../views/Home.vue'

    Vue.use(VueRouter)

    const routes = [
    {
    path: '/',
    name: 'Home',
    component: Home
    },
    // 添加test的路由
    {
    path: '/test',
    name: 'Test',
    component: () => import('../views/test.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')
    }
    ]

    const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
    })

    export default router
  4. 在页面上添加路由跳转,编写App.vue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <template>
    <div id="app">
    <div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link to="/test">Test</router-link>
    </div>
    <router-view/>
    </div>
    </template>
  5. 运行vue项目,查看http://localhost:8080/test是否出现假数据,出现则为成功

后端部分

  1. 首先先创建一个SpringBoot的项目,我的版本是2.4.2

  2. 然后在pom.xml导入依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <dependencies>
    <!--web启动器-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--数据库驱动-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    </dependency>
    <!--lombok-->
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    </dependency>
    <!--mybatis-plus-->
    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
    </dependency>
    <!--单元测试-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    </dependencies>
  3. 创建一个实体类,该类在pojo的包下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package com.yww.springboottest.pojo;

    import lombok.Data;

    @Data
    public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
    }
  4. 创建一个Mapper接口,该接口在Mapper的包下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    package com.yww.springboottest.Mapper;

    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.yww.springboottest.pojo.User;
    import org.springframework.stereotype.Repository;

    // 这里只需要基础BaseMapper接口,泛型放入实体类就好了
    @Repository
    public interface UserMapper extends BaseMapper<User> {}
  5. 配置SpringBoot,这里使用的配置文件是application.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 配置MySQL
    spring:
    datasource:
    username: root
    password: password
    url: jdbc:mysql://localhost:3306/Company?userUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 配置日志,以便更好查看结果
    mybatis-plus:
    configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 端口自定义,注意和Vue的端口分开,Vue使用了8080,这里就使用8081好了
    server:
    port: 8081
  6. 扫描注册Mapper接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package com.yww.springboottest;

    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;

    @SpringBootApplication
    @MapperScan("com.yww.springboottest.Mapper")
    public class SpringboottestApplication {
    public static void main(String[] args) {
    SpringApplication.run(SpringboottestApplication.class, args);
    }
  7. 查询测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.yww.springboottest;

    import com.yww.springboottest.Mapper.UserMapper;
    import com.yww.springboottest.pojo.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;

    import java.util.List;

    @SpringBootTest
    class SpringboottestApplicationTests {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void FindAll() {
    List<User> userList = userMapper.selectList(null);
    System.out.println(userList);
    }
    }
  8. 得到结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ==>  Preparing: SELECT id,name,age,email FROM user
    ==> Parameters:
    <== Columns: id, name, age, email
    <== Row: 1, Jone, 18, test1@baomidou.com
    <== Row: 2, Jack, 20, test2@baomidou.com
    <== Row: 3, Tom, 28, test3@baomidou.com
    <== Row: 4, Sandy, 21, test4@baomidou.com
    <== Row: 5, Billie, 24, test5@baomidou.com
    <== Row: 1327829723124920321, lili, 10, sssss
    <== Row: 1327839061415620609, lili, 10, sssss
    <== Row: 1327839257776095234, yww, 20, 1141950370@qq.com
    <== Total: 8

    由此可以看到查询结果没有什么问题,然后就可以写接口返回数据了。

  9. 编写接口,该接口在Controller的包下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.yww.springboottest.Controller;

    import com.yww.springboottest.Mapper.UserMapper;
    import com.yww.springboottest.pojo.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;

    import java.util.List;

    @RestController
    public class UserController {
    @Autowired
    private UserMapper userMapper;

    @GetMapping("/findall")
    public List<User> FindAll() {
    return userMapper.selectList(null);
    }
    }

    访问http://localhost:8081/findall即可查询到查询返回的数据。

前后端交互

  1. 在vue项目里添加axios插件,用来请求接口

    1
    vue add axios
  2. 修改test.vue里的数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <template>
    <div>
    <table>
    <tr>
    <td>主键ID</td>
    <td>姓名</td>
    <td>年龄</td>
    <td>邮箱</td>
    </tr>
    <tr v-for="item in user" :key="item.id">
    <td>{{item.id}}</td>
    <td>{{item.name}}</td>
    <td>{{item.age}}</td>
    <td>{{item.email}}</td>
    </tr>
    </table>
    </div>
    </template>

    <script>
    export default {
    name: "test",
    data(){
    return{
    user: []
    }
    },
    created() {
    // 请求端口数据,并将数据赋值给user数组
    axios.get('http://localhost:8081/findall').then(response => (this.user = response.data))
    }

    }
    </script>
    <style>
    </style>
  3. 在后端部分增加一个工具类,用于解决跨域问题(因为是不同端口的请求),该类在config包下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package com.yww.springboottest.config;

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

    @Configuration
    public class CrosConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
    .allowCredentials(false)
    .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
    .allowedOrigins("*");
    }
    }
  4. 然后访问前端项目的页面http://localhost:8080/test,就能看到后端查询并返回的数据了

结尾

这次是一个简单的demo,实际项目还要复杂很多,这个demo虽然简单,但是也是能让你简单了解一下前后端分离的开发流程。