Spring?Boot和Vue前后端分離項(xiàng)目架構(gòu)的全過(guò)程
Spring Boot+Vue 前后端分離項(xiàng)目架構(gòu)
項(xiàng)目流程:

1. SpringBoot 后端項(xiàng)目
1、新建一個(gè) SpringBoot 工程,并添加項(xiàng)目開(kāi)發(fā)過(guò)程中需要的相關(guān)依賴;


2、數(shù)據(jù)庫(kù)新建 book 數(shù)據(jù)表;

-- ---------------------------- -- Table structure for book -- ---------------------------- DROP TABLE IF EXISTS `book`; CREATE TABLE `book` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `title` varchar(55) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `publish` varchar(55) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `authors` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `createTime` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0), `updateTime` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0), PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of book -- ---------------------------- INSERT INTO `book` VALUES (2, '數(shù)據(jù)結(jié)構(gòu)', '浙江出版社', '嚴(yán)威', '2022-03-18 14:38:22', '2022-03-18 14:38:25'); INSERT INTO `book` VALUES (5, '計(jì)算機(jī)組成原理', '機(jī)械工業(yè)出版社', '唐朔飛', '2022-03-14 14:38:28', '2022-03-15 14:38:36'); INSERT INTO `book` VALUES (6, '機(jī)器學(xué)習(xí)', '人民郵電出版社', '周志華', '2022-03-16 14:38:41', '2022-03-16 14:38:45'); INSERT INTO `book` VALUES (7, '圖論及其應(yīng)用', '科學(xué)技術(shù)出版社', '徐俊明', '2022-03-03 14:38:49', '2022-03-18 18:33:57'); INSERT INTO `book` VALUES (8, '推薦系統(tǒng)開(kāi)發(fā)實(shí)戰(zhàn)', '電子工業(yè)出版社', '高團(tuán)陽(yáng)', '2022-03-14 14:38:57', '2022-03-16 14:39:02'); INSERT INTO `book` VALUES (9, '大數(shù)據(jù)導(dǎo)論', '機(jī)械工業(yè)出版社', '曾誠(chéng)', '2022-03-10 14:39:06', '2022-03-12 14:39:09'); INSERT INTO `book` VALUES (13, 'Java從零基礎(chǔ)到實(shí)戰(zhàn)', '中國(guó)工信出版集團(tuán)', '寧楠', '2022-03-18 17:05:18', '2022-03-18 17:05:18');
3、application.yml 配置數(shù)據(jù)源和項(xiàng)目啟動(dòng)的端口號(hào);
# 修改服務(wù)啟動(dòng)的端口
server:
port: 8181
spring:
datasource:
url: jdbc:mysql://localhost:3306/book?useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
# 配置日志,打印執(zhí)行的sql語(yǔ)句
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
項(xiàng)目整體的目錄結(jié)構(gòu)如下:

4、創(chuàng)建實(shí)體類(lèi) Book.java;
@AllArgsConstructor
@NoArgsConstructor
@Data
@TableName(value = "book")
public class Book {
@TableId(type = IdType.AUTO)
private Long id;
private String title;
private String publish;
private String authors;
@TableField(value = "createTime", fill = FieldFill.INSERT)
private Date createTime;
@TableField(value = "updateTime", fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
5、添加 MyBatis Plus 自動(dòng)填充的處理器 config/DataHandler.java;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class DataHandler implements MetaObjectHandler{
//插入時(shí)的填充策略
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
}
//更新時(shí)的填充策略
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
6、持久化層 mapper/BookMapper.java;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.trainingl.entity.Book;
import org.springframework.stereotype.Repository;
@Repository //持久層注解
public interface BookMapper extends BaseMapper<Book> {
//所有的CRUD操作都已經(jīng)編寫(xiě)好了
}
7、服務(wù)層 service;
service/BookService.java
import com.trainingl.entity.Book;
import java.util.List;
//數(shù)據(jù)的增刪改查接口
public interface BookService {
public List<Book> findAll();
public Book findById(Long id);
public int insert(Book book);
public int deleteById(Long id);
public int updateById(Book book);
}
service/Impl/BookServiceImpl.java
import com.trainingl.entity.Book;
import com.trainingl.mapper.BookMapper;
import com.trainingl.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookMapper bookMapper;
@Override
public List<Book> findAll() {
//查詢搜索記錄
return bookMapper.selectList(null);
}
@Override
public Book findById(Long id) {
return bookMapper.selectById(id);
}
@Override
public int insert(Book book) {
return bookMapper.insert(book);
}
@Override
public int deleteById(Long id) {
return bookMapper.deleteById(id);
}
@Override
public int updateById(Book book) {
return bookMapper.updateById(book);
}
}
8、控制層 Controller;
controller/BookController.java
import com.trainingl.entity.Book;
import com.trainingl.service.BookService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@CrossOrigin //跨域注解
public class BookController {
@Autowired
private BookService bookService;
@RequestMapping("/booklist")
public List<Book> booklist(){
return bookService.findAll();
}
@RequestMapping("/addbook")
public int addbook(@RequestBody Book book){
return bookService.insert(book);
}
@DeleteMapping("/deleteById/{id}")
public int deleteById(@PathVariable("id") Long id){
Integer result = 0;
result = bookService.deleteById(id);
//刪除成功則返回受影響的行數(shù)
return result;
}
@GetMapping("/findById/{id}")
public Book findById(@PathVariable("id") Long id){
return bookService.findById(id);
}
@PutMapping("/updateById")
public int updateById(@RequestBody Book book){
//返回修改的條數(shù)
return bookService.updateById(book);
}
}
2. Vue 前端項(xiàng)目
1、主頁(yè)面 App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
data(){
return{
}
},
}
</script>
2、數(shù)據(jù)列表視圖 views/table.vue

<template>
<div>
<el-table
:data="tableData"
border
style="width: 70%">
<el-table-column
fixed
prop="id"
label="編號(hào)"
width="80">
</el-table-column>
<el-table-column
prop="title"
label="書(shū)籍名稱"
width="160">
</el-table-column>
<el-table-column
prop="publish"
label="出版社"
width="150">
</el-table-column>
<el-table-column
prop="authors"
label="作者"
width="120">
</el-table-column>
<el-table-column
prop="createTime"
label="創(chuàng)建時(shí)間"
width="150">
</el-table-column>
<el-table-column
prop="updateTime"
label="修改時(shí)間"
width="150">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="150">
<template slot-scope="scope">
<el-button @click="del(scope.row)" type="danger" size="small">刪除</el-button>
<el-button @click="edit(scope.row)" type="success" size="small">編輯</el-button>
</template>
</el-table-column>
</el-table>
<el-button type="primary" @click="addBook" icon="el-icon-edit" size="small">添加記錄</el-button>
</div>
</template>
<script>
export default {
name: "table",
methods: {
addBook(){
this.$router.push("/addbook")
},
del(row) {
let _this = this;
this.$confirm('此操作將永久刪除該記錄, 是否繼續(xù)?', '提示', {
confirmButtonText: '確定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.delete("http://localhost:8181/deleteById/" + row.id).then(function (response) {
if (response.data == 1) {
//刷新頁(yè)面
location.reload();
} else {
_this.$message({
showClose: true,
message: '刪除信息失敗!',
type: 'danger'
});
}
})
})
},
edit(row) {
this.$router.push("/edit?id=" + row.id);
}
},
data() {
return {
tableData: []
}
},
created(){
let _this = this;
this.$axios.get("http://localhost:8181/booklist").then(function (response) {
_this.tableData = response.data;
})
}
}
</script>
<style scoped>
</style>
3、新增視圖文件 views/addBook.vue

<template>
<div>
<h2 style="padding-left: 200px">新增圖書(shū)信息</h2>
<el-form :model="ruleForm" style="width: 500px;" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="書(shū)籍名稱" prop="title">
<el-input type="text" v-model="ruleForm.title" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="出版社" prop="publish">
<el-input type="text" v-model="ruleForm.publish" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="作者信息" prop="authors">
<el-input v-model.number="ruleForm.authors"></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: "addBook",
data() {
var checkAuthor = (rule, value, callback) => {
if (value === '') {
callback(new Error('請(qǐng)輸入作者信息'));
} else {
callback();
}
};
var validateTitle = (rule, value, callback) => {
if (value === '') {
callback(new Error('請(qǐng)輸入書(shū)籍名稱'));
} else {
callback();
}
};
var validatePublish = (rule, value, callback) => {
if (value === '') {
callback(new Error('請(qǐng)輸入出版社'));
} else {
callback();
}
};
return {
ruleForm: {
title: '',
publish: '',
authors: ''
},
rules: {
title: [
{ validator: validateTitle, trigger: 'blur' }
],
publish: [
{ validator: validatePublish, trigger: 'blur' }
],
authors: [
{ validator: checkAuthor, trigger: 'blur' }
]
}
};
},
methods: {
submitForm(formName) {
let _this = this;
this.$refs[formName].validate((valid) => {
if (valid) {
this.$axios.post("http://localhost:8181/addbook", _this.ruleForm).then(function (response) {
if(response.data == 1){
//跳轉(zhuǎn)到表格頁(yè)面
_this.$router.push('/table')
}
})
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
<style scoped>
</style>
4、編輯或修改視圖文件 views/edit.vue

<template>
<div>
<h2 style="padding-left: 200px">修改圖書(shū)信息</h2>
<el-form :model="ruleForm" style="width: 500px;" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="圖書(shū)編號(hào)">
<el-input type="text" readonly v-model="ruleForm.id" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="書(shū)籍名稱" prop="title">
<el-input type="text" v-model="ruleForm.title" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="出版社" prop="publish">
<el-input type="text" v-model="ruleForm.publish" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="作者信息" prop="authors">
<el-input v-model.number="ruleForm.authors"></el-input>
</el-form-item>
<el-form-item label="創(chuàng)建時(shí)間">
<el-input readonly v-model.number="ruleForm.createTime"></el-input>
</el-form-item>
<el-form-item label="修改時(shí)間">
<el-input readonly v-model.number="ruleForm.updateTime"></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: "edit",
data() {
var checkAuthor = (rule, value, callback) => {
if (value === '') {
callback(new Error('請(qǐng)輸入作者信息'));
} else {
callback();
}
};
var validateTitle = (rule, value, callback) => {
if (value === '') {
callback(new Error('請(qǐng)輸入書(shū)籍名稱'));
} else {
callback();
}
};
var validatePublish = (rule, value, callback) => {
if (value === '') {
callback(new Error('請(qǐng)輸入出版社'));
} else {
callback();
}
};
return {
ruleForm: {
id: '',
title: '',
publish: '',
authors: '',
createTime: '',
updateTime: ''
},
rules: {
title: [
{ validator: validateTitle, trigger: 'blur' }
],
publish: [
{ validator: validatePublish, trigger: 'blur' }
],
authors: [
{ validator: checkAuthor, trigger: 'blur' }
]
}
};
},
methods: {
submitForm(formName) {
let _this = this;
this.$refs[formName].validate((valid) => {
if (valid) {
this.$axios.put("http://localhost:8181/updateById", _this.ruleForm).then(function (response) {
if(response.data === 1){
//跳轉(zhuǎn)到表格頁(yè)面
_this.$router.push('/table')
}
})
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
},
mounted(){
let _this = this;
this.$axios.get("http://localhost:8181/findById/" + this.$route.query.id).then(function (response) {
_this.ruleForm = response.data;
});
}
}
</script>
<style scoped>
</style>
5、路由文件 router.js
import Vue from 'vue'
//1.導(dǎo)入路由依賴,安裝 vue-router組件后系統(tǒng)帶有的依賴
import VueRouter from 'vue-router'
//2.導(dǎo)入兩個(gè)頁(yè)面
import Login from "@/views/login";
import Second from "@/views/Second";
import Table from "@/views/table";
import AddBook from "@/views/addBook";
import Edit from "@/views/edit";
// 3.使用路由
Vue.use(VueRouter);
//4.創(chuàng)建路由對(duì)象,new VueRouter為上面import設(shè)置的名稱
const router = new VueRouter({
//沒(méi)有history,訪問(wèn)URL會(huì)有#
mode: "history",
routes: [
{
path:"/login",
component: Login
},
{
path:"/second",
component: Second
},
{
path:"/table",
component: Table
},
{
path:"/addbook",
component: AddBook
},
{
path:"/edit",
component: Edit
},
]
});
export default router;6、組件的全局配置 main.js
import Vue from 'vue'
import App from './App.vue'
import router from "./router/index"
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from "axios"
import qstring from "querystring"
// Vue 全局Vue對(duì)象,prototype原型設(shè)置全局屬性
Vue.prototype.$axios = axios
Vue.prototype.$qstring=qstring
Vue.config.productionTip = false;
Vue.use(ElementUI);
new Vue({
router,
render: h => h(App),
}).$mount('#app')
總結(jié)
到此這篇關(guān)于Spring Boot和Vue前后端分離項(xiàng)目架構(gòu)的文章就介紹到這了,更多相關(guān)Spring Boot Vue前后端分離內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring boot過(guò)濾器FilterRegistrationBean實(shí)現(xiàn)方式
這篇文章主要介紹了spring boot過(guò)濾器FilterRegistrationBean實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
javaweb圖書(shū)商城設(shè)計(jì)之用戶模塊(1)
這篇文章主要介紹了javaweb圖書(shū)商城設(shè)計(jì)之用戶模塊的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
Spring MVC攔截器_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
Spring MVC的攔截器,是屬于HandlerMapping級(jí)別的,可以有多個(gè)HandlerMapping ,每個(gè)HandlerMapping可以有自己的攔截器,具體內(nèi)容詳情大家通過(guò)本文學(xué)習(xí)吧2017-08-08
Java方法參數(shù)是引用調(diào)用還是值調(diào)用?
Java方法參數(shù)是引用調(diào)用還是值調(diào)用?這是一個(gè)值得思考的問(wèn)題。閱讀本文,找出答案2016-02-02
Java concurrency之AtomicLong原子類(lèi)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
AtomicLong是作用是對(duì)長(zhǎng)整形進(jìn)行原子操作。下面通過(guò)本文給大家介紹Java concurrency之AtomicLong原子類(lèi)的相關(guān)知識(shí),感興趣的朋友一起看看吧2017-06-06

