手把手教你如何搭建SpringBoot+Vue前后端分離
1 什么是前后端分離
前后端分離是目前互聯(lián)網(wǎng)開發(fā)中比較廣泛使用的開發(fā)模式,主要是將前端和后端的項(xiàng)目業(yè)務(wù)進(jìn)行分離,可以做到更好的解耦合,前后端之間的交互通過xml或json的方式,前端主要做用戶界面的渲染,后端主要負(fù)責(zé)業(yè)務(wù)邏輯和數(shù)據(jù)的處理。

2 Spring Boot后端搭建
2.1 Mapper層
請(qǐng)參閱這篇文章 手把手教你SpringBoot整合Mybatis
此次項(xiàng)目的后端搭建就是在這個(gè)項(xiàng)目的基礎(chǔ)上
2.2 Service層
接口:
/**
* @author 17122
*/
public interface StudentService {
/**
* 添加一個(gè)學(xué)生
*
* @param student
* @return
*/
public int saveStudent(Student student);
/**
* 根據(jù)ID查看一名學(xué)生
*
* @param id
* @return
*/
public Student findStudentById(Integer id);
/**
* 查詢?nèi)繉W(xué)生
*
* @return
*/
public List<Student> findAllStudent();
/**
* 根據(jù)ID刪除一個(gè)
*
* @param id
* @return
*/
public int removeStudentById(Integer id);
/**
* 根據(jù)ID修改
*
* @param student
* @return
*/
public int updateStudentById(Student student);
}
實(shí)現(xiàn)類:
/**
* @author 17122
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private XmlStudentMapper xmlStudentMapper;
@Override
public int saveStudent(Student student) {
return xmlStudentMapper.saveStudent(student);
}
@Override
public Student findStudentById(Integer id) {
return xmlStudentMapper.findStudentById(id);
}
@Override
public List<Student> findAllStudent() {
return xmlStudentMapper.findAllStudent();
}
@Override
public int removeStudentById(Integer id) {
return xmlStudentMapper.removeStudentById(id);
}
@Override
public int updateStudentById(Student student) {
return xmlStudentMapper.updateStudentById(student);
}
}
2.3 Controller層
/**
* @author 17122
*/
@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private StudentService studentService;
/**
* 添加學(xué)生
*
* @param student
* @return
*/
@PostMapping("/save")
public int saveStudent(@RequestBody Student student) {
int result;
try {
result = studentService.saveStudent(student);
} catch (Exception exception) {
return -1;
}
return result;
}
/**
* 查看全部
*
* @return
*/
@GetMapping("/findAll")
public List<Student> findAll() {
return studentService.findAllStudent();
}
/**
* 根據(jù)ID查看
*
* @param id
* @return
*/
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") Integer id) {
return studentService.findStudentById(id);
}
/**
* 刪除一個(gè)
*
* @param id
* @return
*/
@DeleteMapping("/remove/{id}")
public int remove(@PathVariable("id") Integer id) {
return studentService.removeStudentById(id);
}
/**
* 修改學(xué)生信息
*
* @param student
* @return
*/
@PostMapping("/update")
public int update(@RequestBody Student student) {
return studentService.updateStudentById(student);
}
}
2.4 配置類
解決跨域請(qǐng)求
/**
* @author 17122
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
圖解跨域問題:

3 Vue前端搭建
3.1 新建Vue_cli2.x項(xiàng)目
3.2 引入路由
npm install vue-router --save
3.3 新建文件

3.4 配置和測試路由
main.js配置
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router
}).$mount('#app')
index.js
//注冊路由
import Vue from 'vue';
import VueRouter from 'vue-router';
//引入路由
import index from '../view/index'
import update from "../view/update";
import selectAll from "../view/selectAll";
import selectOne from "../view/selectOne";
import insert from "../view/insert";
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{
name: "主頁重定向",
path: "/",
redirect: "/index"
}, {
name: "主頁",
path: "/index",
component: index,
children: [
{
name: "修改操作",
path: "/update",
component: update,
}, {
name: "查看全部",
path: "/selectAll",
component: selectAll,
}, {
name: "查看一個(gè)",
path: "/selectOne",
component: selectOne,
}, {
name: "添加一個(gè)",
path: "/insert",
component: insert,
}
]
}
]
})
export default router
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
index.vue
<template>
<div>
<router-link to="update">update</router-link>
<br>
<router-link to="selectAll"> selectAll</router-link>
<br>
<router-link to="selectOne"> selectOne</router-link>
<br>
<router-link to="insert"> insert</router-link>
<br>
<br>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "index"
}
</script>
<style scoped>
</style>
insert.vue
<template>
<div>
insert
</div>
</template>
<script>
export default {
name: "insert"
}
</script>
<style scoped>
</style>
selectOne.vue
<template>
<div>
selectOne
</div>
</template>
<script>
export default {
name: "selectOne"
}
</script>
<style scoped>
</style>
selectAll.vue
<template>
<div>
selectAll
</div>
</template>
<script>
export default {
name: "selectAll"
}
</script>
<style scoped>
</style>
update.vue
<template>
<div>
update
</div>
</template>
<script>
export default {
name: "update"
}
</script>
<style scoped>
</style>
測試
啟動(dòng)項(xiàng)目
npm run serve
訪問:http://localhost:8080/

點(diǎn)擊相關(guān)標(biāo)簽時(shí)會(huì)顯示響應(yīng)頁面
3.5 引入Element UI
npm i element-ui -S
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.config.productionTip = false
Vue.use(ElementUI)
new Vue({
render: h => h(App),
router
}).$mount('#app')
3.6 使用Element UI美化頁面
index.vue
<template>
<div>
<el-menu class="el-menu-demo" mode="horizontal" :router="true">
<el-menu-item index="/selectAll">全部學(xué)生</el-menu-item>
<el-menu-item index="/insert">添加學(xué)生</el-menu-item>
<el-menu-item index="/selectOne">查看學(xué)生</el-menu-item>
<el-menu-item index="/update">修改學(xué)生</el-menu-item>
</el-menu>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "index"
}
</script>
<style scoped>
</style>
insert.vue
<template>
<div>
<el-form :model="ruleForm" status-icon label-width="100px" class="demo-ruleForm" style="margin-top:30px;width: 30%;">
<el-form-item label="姓名" prop="pass">
<el-input type="text" v-model="ruleForm.name" ></el-input>
</el-form-item>
<el-form-item label="年齡" prop="checkPass">
<el-input type="text" v-model="ruleForm.age" ></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "insert",
data() {
return {
ruleForm: {
name: '',
age: ''
}
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
}
}
</script>
<style scoped>
</style>
selectOne.vue
<template>
<div>
<el-form :model="ruleForm" status-icon label-width="100px" class="demo-ruleForm"
style="margin-top:30px;width: 30%;">
<el-form-item label="ID" prop="pass">
<el-input type="text" v-model="ruleForm.id"></el-input>
</el-form-item>
<el-form-item label="姓名" prop="pass">
<el-input type="text" v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="年齡" prop="checkPass">
<el-input type="text" v-model="ruleForm.age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "selectOne",
data() {
return {
ruleForm: {
id: '',
name: '',
age: ''
}
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
<style scoped>
</style>
selectAll.vue
<template>
<div>
<template>
<el-table
:data="tableData"
style="width: 60%;margin-top:30px;">
<el-table-column
prop="id"
label="ID"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="age"
label="年齡">
</el-table-column>
<el-table-column
label="操作">
<template>
<el-button type="warning" size="small">修改</el-button>
<el-button type="danger" size="small">刪除</el-button>
</template>
</el-table-column>
</el-table>
</template>
</div>
</template>
<script>
export default {
name: "selectAll",
data() {
return {
tableData: []
}
}
}
</script>
<style scoped>
</style>
update.vue
<template>
<div>
<el-form :model="ruleForm" status-icon label-width="100px" class="demo-ruleForm"
style="margin-top:30px;width: 30%;">
<el-form-item label="ID" prop="pass">
<el-input type="text" v-model="ruleForm.id"></el-input>
</el-form-item>
<el-form-item label="姓名" prop="checkPass">
<el-input type="text" v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="年齡" prop="age">
<el-input type="text" v-model="ruleForm.age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="warning" @click="submitForm('ruleForm')">修改</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "update",
data() {
return {
ruleForm: {
id: '',
name: '',
age: ''
}
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
<style scoped>
</style>
效果


3.7 整合axios與Spring Boot后端交互
npm install axios --save
insert.vue
<template>
<div>
<el-form :model="ruleForm" status-icon label-width="100px" class="demo-ruleForm"
style="margin-top:30px;width: 30%;">
<el-form-item label="姓名" prop="pass">
<el-input type="text" v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="年齡" prop="checkPass">
<el-input type="text" v-model="ruleForm.age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm()">提交</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: "insert",
data() {
return {
ruleForm: {
name: '',
age: ''
}
};
},
methods: {
submitForm() {
axios.post("http://localhost:8081/student/save", this.ruleForm).then(function (resp) {
console.log(resp)
})
},
}
}
</script>
<style scoped>
</style>
selectOne.vue
<template>
<div>
<el-form :model="ruleForm" status-icon label-width="100px" class="demo-ruleForm"
style="margin-top:30px;width: 30%;">
<el-form-item label="ID" prop="pass">
<el-input type="text" v-model="ruleForm.id"></el-input>
</el-form-item>
<el-form-item label="姓名" prop="pass">
<el-input type="text" v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="年齡" prop="checkPass">
<el-input type="text" v-model="ruleForm.age"></el-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "selectOne",
data() {
return {
ruleForm: {
id: '',
name: '',
age: ''
}
};
},
methods: {
getStudent() {
const _this = this;
axios.get("http://localhost:8081/student/findById/" + this.$route.query.id).then(function (resp) {
_this.ruleForm = resp.data;
})
}
},
created() {
this.getStudent();
}
}
</script>
<style scoped>
</style>
selectAll.vue
<template>
<div>
<template>
<el-table
:data="tableData"
style="width: 60%;margin-top:30px;">
<el-table-column
prop="id"
label="ID"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="age"
label="年齡">
</el-table-column>
<el-table-column
label="操作">
<template slot-scope="scope">
<el-button type="primary" size="small" @click="select(scope.row)">查看</el-button>
<el-button type="warning" size="small" @click="update(scope.row)">修改</el-button>
<el-button type="danger" size="small" @click="remove(scope.row)">刪除</el-button>
</template>
</el-table-column>
</el-table>
</template>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "selectAll",
data() {
return {
tableData: []
}
},
methods: {
getData() {
const _this = this;
axios.get("http://localhost:8081/student/findAll").then(function (resp) {
_this.tableData = resp.data;
})
},
remove(stu) {
const _this = this;
if (confirm("確定刪除嗎?")) {
axios.delete("http://localhost:8081/student/remove/" + stu.id).then(function (resp) {
if (resp.data == 1) {
_this.getData();
}
})
}
},
select(stu) {
this.$router.push({
path: "/selectOne",
query:{
id: stu.id
}
})
},
update(stu) {
this.$router.push({
path: "/update",
query:{
id: stu.id
}
})
}
},
created() {
this.getData();
}
}
</script>
<style scoped>
</style>
update.vue
<template>
<div>
<el-form :model="ruleForm" status-icon label-width="100px" class="demo-ruleForm"
style="margin-top:30px;width: 30%;">
<el-form-item label="ID">
<el-input type="text" v-model="ruleForm.id" disabled></el-input>
</el-form-item>
<el-form-item label="姓名">
<el-input type="text" v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="年齡">
<el-input type="text" v-model="ruleForm.age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="warning" @click="submitForm()">修改</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "update",
data() {
return {
ruleForm: {
id: '',
name: '',
age: ''
}
};
},
methods: {
submitForm() {
axios.post("http://localhost:8081/student/update", this.ruleForm).then(function (resp) {
console.log(resp)
})
},
getStudent() {
const _this = this;
axios.get("http://localhost:8081/student/findById/" + this.$route.query.id).then(function (resp) {
_this.ruleForm = resp.data;
})
}
},
created() {
this.getStudent();
}
}
</script>
<style scoped>
</style>
4 總結(jié)

到此這篇關(guān)于手把手教你如何搭建SpringBoot+Vue前后端分離的文章就介紹到這了,更多相關(guān)SpringBoot+Vue前后端分離內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot普通類獲取spring容器中bean的操作
這篇文章主要介紹了SpringBoot普通類獲取spring容器中bean的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
springboot如何統(tǒng)一設(shè)置時(shí)區(qū)
這篇文章主要介紹了springboot如何統(tǒng)一設(shè)置時(shí)區(qū)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
Java高性能新一代構(gòu)建工具M(jìn)aven-mvnd(實(shí)踐可行版)
這篇文章主要介紹了Java高性能新一代構(gòu)建工具M(jìn)aven-mvnd(實(shí)踐可行版),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
Java實(shí)現(xiàn)手寫乞丐版線程池的示例代碼
在這篇文章當(dāng)中我們主要介紹實(shí)現(xiàn)一個(gè)非常簡易版的線程池,深入的去理解其中的原理,麻雀雖小,五臟俱全,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)學(xué)習(xí)吧2022-10-10
Java利用LocalDate類實(shí)現(xiàn)日歷設(shè)計(jì)
java中做時(shí)間處理時(shí)一般會(huì)采用java.util.Date,但是相比于Date來說,還有更好的選擇--java.time.LocalDate。本文就來用LocalDate類實(shí)現(xiàn)日歷設(shè)計(jì),感興趣的可以動(dòng)手嘗試一下2022-07-07

