Spring Boot 與 Vue.js 整合流程
一直都想嘗試做前后端分離,我之前一直是學(xué) Java 的,所以后端選擇了 Spring Boot;前端選擇了 Vue.js 這個(gè)輕量、易上手的框架。網(wǎng)上其實(shí)已經(jīng)有了不少 Spring Boot 和 Vue.js 整合的資料,Github 上就有好多 repo,但是每當(dāng)我指望按圖索驥的時(shí)候就會(huì)出現(xiàn)各種各樣奇怪的 bug,上 Stack Overflow 問了也沒人搭理。前前后后研究了差不多三個(gè)星期,現(xiàn)在總算是理清楚了。
本文重點(diǎn)介紹我在實(shí)踐過程中的基本流程,以及我遇到的一個(gè)困擾了我好久的問題,就是如何 CORS。
框架版本
- Spring Boot: 2.0.4.RELEASE(JDK 是1.8)
- Vue.js: 2.x
基本流程
前端:編寫 Vue 組件
首先用 vue-cli 搭好腳手架,我這個(gè) Demo 用到的第三方庫有:
- axios:負(fù)責(zé) HTTP 請(qǐng)求
- bootstrap-vue:Bootstrap 和 Vue.js 的整合,方便設(shè)計(jì)頁面
- vue-router:管理路由
- qs:實(shí)現(xiàn) CORS
然后寫一個(gè)登錄組件:
<!-- 下面是我直接從 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>
我現(xiàn)在想實(shí)現(xiàn)的就是用戶登錄成功之后導(dǎo)航到另一個(gè)組件,所以我就又寫了一個(gè)歡迎組件:
<template> <div> <h1>Welcome!</h1> </div> </template>
記得配置路由:
// src/router/index.js
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
因?yàn)橹挥泻蠖颂峁┝私涌?,前端才能調(diào)用,所以現(xiàn)在要進(jìn)行后端開發(fā)。RESTful 是現(xiàn)在很流行的 API 設(shè)計(jì)風(fēng)格,所以我這里也實(shí)踐了一下。下面是 controller 的代碼,完整源碼地址附在文末。
@RestController @RequestMapping("/api") public class LoginController { @RequestMapping(path = "/login", method = RequestMethod.POST) @ResponseBody public String login(@RequestParam String username, @RequestParam String password) { // 簡(jiǎn)單處理一下,實(shí)際開發(fā)中肯定是要用到數(shù)據(jù)庫的 if (username.equals("123") && password.equals("123")) { return "successful"; } else { return "failed"; } } }
后端的 API 現(xiàn)在有了,就差前端調(diào)用了。但是沒這么簡(jiǎn)單,接下來就要解決我前面提到的問題。
實(shí)現(xiàn) CORS
在這個(gè) Demo 中前端占用的端口是8080,后端是 8088。這就存在跨域的問題,如果不解決的話后端就沒法接收前端的請(qǐng)求。
我參考了 這個(gè)例子 ,通過配置 Spring MVC 實(shí)現(xiàn)了 CORS:
@Configuration public class CORSConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins(ALL) .allowedMethods(ALL) .allowedHeaders(ALL) .allowCredentials(true); } }
后端配置好了還不行,前端也要有一些配置,要用 axios 順利地發(fā)送請(qǐng)求并保證后端能接收到,需要對(duì)請(qǐng)求參數(shù)做處理。我參考 這個(gè)回答 用 qs 庫對(duì)請(qǐng)求參數(shù)做了處理:
qs.stringify({ 'username': this.form.username, 'password': this.form.password })
現(xiàn)在只需完善前端調(diào)用后端 API 的代碼:
// Login.vue <script> export default { data () { return { form: { username: '', password: '', checked: [] }, show: true } }, methods: { onSubmit (evt) { evt.preventDefault(); // 關(guān)鍵就在于要對(duì)參數(shù)進(jìn)行處理 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>
至此,終于實(shí)現(xiàn)了前后端的分離,并且保證前后端能夠順利交互。
題外話
讓 controller 能獲取請(qǐng)求參數(shù)
controller 可能無法獲取請(qǐng)求參數(shù), 這篇文章 提供了一種解決方案。我這個(gè) Demo 中并沒有出現(xiàn) controller 收不到請(qǐng)求參數(shù)的問題,但也把這個(gè)問題記錄下來,以后可能遇上也說不準(zhǔn)。
axios 方法中的 this
我這個(gè) Demo 中還試著用 axios 發(fā) GET 請(qǐng)求,然后獲取后端響應(yīng)的 JSON 數(shù)據(jù)。
// 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>
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 就一直報(bào)錯(cuò):
typeError: Cannot set property 'username' of undefined
搞了很久都沒有解決,直到看到 這篇文章 ,才明白原來是 this 作用域的問題(JavaScript 的 this 是真的復(fù)雜?。。。。?。改成下面這樣就沒問題了:
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 上有人說不用箭頭函數(shù)也行,只需提前把指向 Vue 實(shí)例的 this 保存在一個(gè)變量就行了:
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); });
經(jīng)實(shí)踐,這樣也是可以的。
Demo 完整源碼
總結(jié)
以上所述是小編給大家介紹的Spring Boot 與 Vue.js 整合流程,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
hadoop的hdfs文件操作實(shí)現(xiàn)上傳文件到hdfs
這篇文章主要介紹了使用hadoop的API對(duì)HDFS上的文件訪問,其中包括上傳文件到HDFS上、從HDFS上下載文件和刪除HDFS上的文件,需要的朋友可以參考下2014-03-03基于Java代碼實(shí)現(xiàn)數(shù)字在數(shù)組中出現(xiàn)次數(shù)超過一半
這篇文章主要介紹了基于Java代碼實(shí)現(xiàn)數(shù)字在數(shù)組中出現(xiàn)次數(shù)超過一半的相關(guān)資料,需要的朋友可以參考下2016-02-02深入解析Apache Kafka實(shí)時(shí)流處理平臺(tái)
這篇文章主要為大家介紹了Apache Kafka實(shí)時(shí)流處理平臺(tái)深入解析,從基本概念到實(shí)戰(zhàn)操作詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01SpringMvc框架的簡(jiǎn)介與執(zhí)行流程詳解
MVC是一種軟件設(shè)計(jì)典范,用一種業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,將業(yè)務(wù)邏輯聚集到一個(gè)組件里面,在改進(jìn)和個(gè)性化定制界面及用戶交互的同時(shí),不需要重新編寫業(yè)務(wù)邏輯,MVC分層有助于管理和架構(gòu)復(fù)雜的應(yīng)用程序2021-06-06java實(shí)現(xiàn)科學(xué)計(jì)算器的全過程與代碼
最近編寫了一個(gè)功能較全面的科學(xué)計(jì)算器,該計(jì)算器不僅能進(jìn)行加、減、乘、除等混合運(yùn)算,而且能計(jì)算sin、cos、tan、log等函數(shù)的值,還要具有清零、退格、求倒數(shù)、求相反數(shù)等功能,這篇文章主要給大家介紹了關(guān)于java實(shí)現(xiàn)科學(xué)計(jì)算器的相關(guān)資料,需要的朋友可以參考下2022-06-06SpringBoot實(shí)戰(zhàn)項(xiàng)目之谷歌瀏覽器全屏效果實(shí)現(xiàn)
這篇文章主要介紹了通過 Java SpringBoot來實(shí)現(xiàn)谷歌瀏覽器的全屏效果,希望頁面展示時(shí)可以實(shí)現(xiàn)全屏效果以提高用戶體驗(yàn)。感興趣的小伙伴跟著小編往下看吧2021-09-09SpringBoot項(xiàng)目里集成Hibernate的示例
在Spring Boot項(xiàng)目中,集成Hibernate可以幫助我們更輕松地進(jìn)行數(shù)據(jù)庫操作,本文將介紹如何在Spring Boot項(xiàng)目中集成Hibernate,并提供相應(yīng)的示例,感興趣的朋友跟隨小編一起看看吧2023-04-04Java的設(shè)計(jì)模式編程中迪米特法則的應(yīng)用示例
這篇文章主要介紹了Java的設(shè)計(jì)模式編程中迪米特法則的應(yīng)用示例,迪米特法則中主張創(chuàng)建和使用弱耦合的類,需要的朋友可以參考下2016-02-02基于spring?data?jpa?@query返回map的踩坑記錄
這篇文章主要介紹了基于spring?data?jpa?@query返回map的踩坑記錄,具有很好的參考價(jià)值,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11