好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring Boot 与 Vue.js 整合流程

一直都想尝试做前后端分离,我之前一直是学 java 的,所以后端选择了 spring boot;前端选择了 vue.js 这个轻量、易上手的框架。网上其实已经有了不少 spring boot 和 vue.js 整合 的资料,github 上就有好多 repo,但是每当我指望按图索骥的时候就会出现各种各样奇怪的 bug,上 stack overflow 问了也没人搭理。前前后后研究了差不多三个星期,现在总算是理清楚了。

本文重点介绍我在实践过程中的基本流程,以及我遇到的一个困扰了我好久的问题,就是如何 cors。

框架版本

spring boot: 2.0.4.release(jdk 是1.8) vue.js: 2.x

基本流程

前端:编写 vue 组件

首先用 vue-cli 搭好脚手架,我这个 demo 用到的第三方库有:

axios:负责 http 请求 bootstrap-vue:bootstrap 和 vue.js 的整合,方便设计页面 vue-router:管理路由 qs:实现 cors

然后写一个登录组件:

?

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

37

38

<!-- 下面是我直接从 bootstrap-vue 文档抄下来的模板 -->

<template>

  <div>

  <b-form @submit = "onsubmit" @reset = "onreset" v- if = "show" >

   <b-form-group id= "exampleinputgroup1"

      label= "username:"

      label- for = "exampleinput1" >

   <b-form-input id= "exampleinput1"

       type= "text"

       v-model= "form.username"

       required

       placeholder= "enter username" >

   </b-form-input>

   </b-form-group>

   <b-form-group id= "exampleinputgroup2"

      label= "password:"

      label- for = "exampleinput2" >

   <b-form-input id= "exampleinput2"

       type= "text"

       v-model= "form.password"

       required

       placeholder= "enter password" >

   </b-form-input>

   </b-form-group>

   <b-form-group id= "examplegroup4" >

   <b-form-checkbox-group v-model= "form.checked" id= "examplechecks" >

    <b-form-checkbox value= "me" >check me out</b-form-checkbox>

    <b-form-checkbox value= "that" >check that out</b-form-checkbox>

   </b-form-checkbox-group>

   </b-form-group>

   <b-button type= "submit" variant= "primary" >submit</b-button>

   <b-button type= "reset" variant= "danger" >reset</b-button>

  </b-form>

  </div>

</template>

<script>

//...

</script>

我现在想实现的就是用户登录成功之后导航到另一个组件,所以我就又写了一个欢迎组件:

?

1

2

3

4

5

<template>

  <div>

   <h1>welcome!</h1>

  </div>

</template>

记得配置路由:

// src/router/index.js

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import vue from 'vue'

import router from 'vue-router'

import login from '@/components/login.vue'

import information from '@/components/information.vue'

vue.use(router)

export default new router({

  routes: [

  {

   path: '/' ,

   name: 'login' ,

   component: login

  },

  {

   path: '/information' ,

   name: 'information' ,

   component: information

  }

  ]

})

后端:提供 restful api

因为只有后端提供了接口,前端才能调用,所以现在要进行后端开发。restful 是现在很流行的 api 设计风格,所以我这里也实践了一下。下面是 controller 的代码,完整源码地址附在文末。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

@restcontroller

@requestmapping ( "/api" )

public class logincontroller {

  @requestmapping (path = "/login" , method = requestmethod.post)

  @responsebody

  public string login( @requestparam string username,

       @requestparam string password) {

   // 简单处理一下,实际开发中肯定是要用到数据库的

   if (username.equals( "123" ) && password.equals( "123" )) {

    return "successful" ;

   } else {

    return "failed" ;

   }

  }

}

后端的 api 现在有了,就差前端调用了。但是没这么简单,接下来就要解决我前面提到的问题。

实现 cors

在这个 demo 中前端占用的端口是8080,后端是 8088。这就存在跨域的问题,如果不解决的话后端就没法接收前端的请求。

我参考了 这个例子 ,通过配置 spring mvc 实现了 cors:

?

1

2

3

4

5

6

7

8

9

10

11

@configuration

public class corsconfig implements webmvcconfigurer {

  @override

  public void addcorsmappings(corsregistry registry) {

   registry.addmapping( "/**" )

     .allowedorigins(all)

     .allowedmethods(all)

     .allowedheaders(all)

     .allowcredentials( true );

  }

}

后端配置好了还不行,前端也要有一些配置,要用 axios 顺利地发送请求并保证后端能接收到,需要对请求参数做处理。我参考 这个回答 用 qs 库对请求参数做了处理:

?

1

2

3

4

qs.stringify({

   'username' : this .form.username,

   'password' : this .form.password

   })

现在只需完善前端调用后端 api 的代码:

?

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

// login.vue

<script>

export default {

  data () {

  return {

   form: {

   username: '' ,

   password: '' ,

   checked: []

   },

   show: true

  }

  },

  methods: {

  onsubmit (evt) {

   evt.preventdefault();

  

   // 关键就在于要对参数进行处理

   axios.post( 'http://localhost:8088/api/login' ,qs.stringify({

   'username' : this .form.username,

   'password' : this .form.password

   })).then((response) => {

   var status = response.data;

   if (status === 'successful' ) {

    this .$router.push( '/information' );

   } else {

    alert(response.data.message);

   }

   console.log(response);

   }). catch ((error) => {

   console.log(response);

   });

  }

  }

}

</script>

至此,终于实现了前后端的分离,并且保证前后端能够顺利交互。

题外话

让 controller 能获取请求参数

  controller 可能无法获取请求参数, 这篇文章 提供了一种解决方案。我这个 demo 中并没有出现 controller 收不到请求参数的问题,但也把这个问题记录下来,以后可能遇上也说不准。

axios 方法中的 this

我这个 demo 中还试着用 axios 发 get 请求,然后获取后端响应的 json 数据。

?

1

2

3

4

5

6

7

8

9

10

11

12

// information.vue

<template>

  <div>

   <h1>welcome!</h1>

   <div>

    <b-button @click = "getinfo()" >get your information</b-button>

    <h2 v- if = "username !== ''" >your username is: {{ username }}</h2>

    <h2 v- if = "email !== ''" >your email is: {{ email }}</h2>

   </div>

  </div>

</template>

<script>

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

import axios from 'axios'

 

export default {

  data () {

   return {

    username: '' ,

    email: ''

   };

  },

  methods: {

   getinfo () {

    axios.get( 'http://localhost:8088/api/information' )

    .then(function(response) {

     this .username = response.data[ 'username' ];

     this .email = response.data[ 'email' ];

     console.log(response);

    }). catch (function(error) {

     console.log(error);

    });

   }

  }

}

</script>

一开始我是这么写的,乍一看没什么问题,但是 javascript 就一直报错:

typeerror: cannot set property 'username' of undefined

搞了很久都没有解决,直到看到  这篇文章  ,才明白原来是 this 作用域的问题(javascript 的 this 是真的复杂啊!!!)。改成下面这样就没问题了:

?

1

2

3

4

5

6

7

8

axios.get( 'http://localhost:8088/api/information' )

    .then((response) => {

     this .username = response.data[ 'username' ];

     this .email = response.data[ 'email' ];

     console.log(response);

    }). catch ((error) => {

     console.log(error);

    });

后来 stack overflow 上有人说不用箭头函数也行,只需提前把指向 vue 实例的 this 保存在一个变量就行了:

?

1

2

3

4

5

6

7

8

9

var vue = this ;

    axios.get( 'http://localhost:8088/api/information' )

    .then(function (response) {

     vue.username = response.data[ 'username' ];

     vue.email = response.data[ 'email' ];

     console.log(response);

    }). catch ((error) => {

     console.log(error);

    });

经实践,这样也是可以的。

demo 完整源码

总结

以上所述是小编给大家介绍的spring boot 与 vue.js 整合流程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

原文链接:https://HdhCmsTestjianshu测试数据/p/4402545763c8

查看更多关于Spring Boot 与 Vue.js 整合流程的详细内容...

  阅读:26次