最终环境配置:
maven3.8:依赖包管理
IDEA2021+JDK8+mysql connector java5+Mysql5+mybatis3.5:从数据库取出数据。
tomcat7插件:web服务器
servlet、fastjson、axios:处理前后端数据交互
fastjson:阿里提供的依赖包。新增时后端收到前端发过来的JSON字符串后,简化将JSON字符串解析成对象。展示商品列表时后端通过mybatis从数据库中查出数据封装成实体类对象的list之后,简化将对象list序列化成JSON字符串。
axios框架:封装了原生JavaScript的ajax操作,简化了HTTP请求的发起和响应参数的获取。
vue.js+ElementUI+html5+css3+chorme:vue.js封装了JavaScript。ElementUI组件库,封装了vue.js,通过提供了搭配的CSS。所以作为后端搭建个简易前端界面,只需要新建个html页面,new一个Vue,绑定一个DIV,然后在这个DIV里填ElementUI提供的组件,并且在head标签中的style中填ElementUI提供的CSS样式就行了。
重点:记住一切操作的背后都是对象,比如前端是在操作vue data中return的对象,后端就是new 的Brand对象。感觉唯一的难点就是逻辑和深浅拷贝涉及到了JS的内存知识
【JS】深拷贝与浅拷贝的区别,实现深拷贝的几种方法 - 听风是风 - 博客园壹 ❀ 引 如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。 此篇文章中也会简单https://www.cnblogs.com/echolun/p/7889848.html
==========================================================
前端页面访问地址:http://localhost:8080/brand-crud/brand.html
实际执行操作的接口如下:
查询所有http://localhost:8080/brand-crud/selectAllServlet
模糊查询http://localhost:8080/brand-crud/selectLikeServlet POST一条JSON格式的brand
新增:http://localhost:8080/brand-crud/addServlet POST一条JSON格式的brand
删除一条:http://localhost:8080/brand-crud/deleteOneServlet?id= GET传入ID
批量删除:http://localhost:8080/brand-crud/deleteSelectedListServlet POST一条JSON格式的brand集合
修改更新一条:http://localhost:8080/brand-crud/updateOneBrandServlet POST一条JSON格式的brand
项目结构:
项目效果:
=========================================================================
建表数据SQL
/*
Navicat MySQL Data Transfer
Source Host : localhost:3306
Source Database : db1
Target Server Type : MYSQL
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tb_brand
-- ----------------------------
DROP TABLE IF EXISTS `tb_brand`;
CREATE TABLE `tb_brand` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`brand_name` varchar(20) DEFAULT NULL,
`company_name` varchar(20) DEFAULT NULL,
`ordered` int(11) DEFAULT NULL,
`description` varchar(100) DEFAULT NULL,
`status` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=63 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tb_brand
-- ----------------------------
INSERT INTO `tb_brand` VALUES ('46', '凡人修仙传3华为666', '公司3华为QQQWWW', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('47', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('48', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('50', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('51', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('52', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('53', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('54', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('55', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('57', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
INSERT INTO `tb_brand` VALUES ('58', '凡人修仙传3华为666', '公司3华为', '222', '描述3', '1');
前端页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.el-table .warning-row {
background: oldlace;
}
.el-table .success-row {
background: #f0f9eb;
}
</style>
</head>
<body>
<div id="app">
<!--模糊查询表单-->
<el-form :inline="true" :model="brandLike" class="demo-form-inline">
<el-form-item label="当前状态">
<el-select v-model="brandLike.status" placeholder="当前状态">
<el-option label="启用" value="1"></el-option>
<el-option label="禁用" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item label="企业名称">
<el-input v-model="brandLike.companyName" placeholder="企业名称"></el-input>
</el-form-item>
<el-form-item label="品牌名称">
<el-input v-model="brandLike.brandName" placeholder="品牌名称"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="selectBySelect">查询</el-button>
</el-form-item>
</el-form>
<!--删除、新增按钮-->
<el-row>
<el-button type="danger" plain @click="deleteList">批量删除</el-button>
<el-button type="primary" plain @click="dialogVisible = true">新增</el-button>
</el-row>
<!--添加数据对话框表单-->
<el-dialog
title="编辑品牌"
:visible.sync="dialogVisible"
width="30%"
>
<el-form ref="form" :model="brandAdd" label-width="80px">
<el-form-item label="品牌名称">
<el-input v-model="brandAdd.brandName"></el-input>
</el-form-item>
<el-form-item label="企业名称">
<el-input v-model="brandAdd.companyName"></el-input>
</el-form-item>
<el-form-item label="排序">
<el-input v-model="brandAdd.ordered"></el-input>
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" v-model="brandAdd.description"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-switch v-model="brandAdd.status"
active-value="1"
inactive-value="0"
></el-switch>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="addBrand">提交</el-button>
<el-button @click="cancelDo">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
<!--修改的弹对话框表单-->
<el-dialog
title="修改更新品牌"
:visible.sync="dialogVisibleUpdate"
width="30%"
>
<el-form ref="form" :model="brand" label-width="80px">
<el-form-item label="品牌名称">
<el-input v-model="brand.brandName"></el-input>
</el-form-item>
<el-form-item label="企业名称">
<el-input v-model="brand.companyName"></el-input>
</el-form-item>
<el-form-item label="排序">
<el-input v-model="brand.ordered"></el-input>
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" v-model="brand.description"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-switch v-model="brand.status"
:active-value="1"
:inactive-value="0"
></el-switch>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="updateBrandDo">提交修改</el-button>
<el-button @click="dialogVisibleUpdate = false">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
<!--显示数据的主表格-->
<template>
<el-table
:data="tableData.slice((currentPage-1)*pageSize,currentPage*pageSize)"
style="width: 100%"
:row-class-name="tableRowClassName"
@selection-change="handleSelectionChange"
>
<!-- 每条记录最前方的小选择框-->
<el-table-column
type="selection"
width="55">
</el-table-column>
<!-- 每条记录的编号-->
<el-table-column
label="序号"
type="index"
width="50">
</el-table-column>
<!-- <el-table-column-->
<!-- prop="id"-->
<!-- label="ID"-->
<!-- align="center"-->
<!-- //row自动对应整个对象,取出ID备用 >-->
</el-table-column>
<el-table-column
prop="brandName"
label="品牌名称"
align="center"
>
</el-table-column>
<el-table-column
prop="companyName"
label="企业名称"
align="center"
>
</el-table-column>
<el-table-column
prop="ordered"
align="center"
label="排序">
</el-table-column>
<el-table-column
prop="description"
align="center"
label="描述">
</el-table-column>
<el-table-column
prop="status"
align="center"
label="当前状态"
:formatter="stateFormat"
>
</el-table-column>
<el-table-column
align="center"
label="操作"
>
<template slot-scope="updateData">
<el-row>
<el-button type="primary" @click="updateOneBrand(updateData.row)">修改</el-button>
<el-button type="danger" @click="deleteOneBrand(updateData.row)">删除
</el-button>
</el-row>
</template>
</el-table-column>
</el-table>
</template>
<!--分页工具条-->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="pageSizes"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="totalNum">
</el-pagination>
</div>
<!--引入依赖-->
<script src="js/vue.js"></script>
<script src="element-ui/lib/index.js"></script>
<link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
<script src="js/axios-0.18.0.js"></script>
<script>
new Vue({
el: "#app",
methods: {
//点击取消新增或者取消修改按钮时执行此方法重置提示框
cancelDo() {
this.dialogVisible = false;
this.brand = {
status: '',
brandName: '',
companyName: '',
id: "",
ordered: "",
description: ""
};
this.brandAdd = {
status: '',
brandName: '',
companyName: '',
id: "",
ordered: "",
description: ""
}
},
//显示每行颜色间隔变化
tableRowClassName({row, rowIndex}) {
if (rowIndex === 1) {
return 'warning-row';
} else if (rowIndex === 3) {
return 'success-row';
}
return '';
},
// 复选框选中后执行的方法
handleSelectionChange(val) {
this.multipleSelection = val;//选中的
let listSelect = this.multipleSelection;
//发起删除请求
//TODO
console.log(listSelect[0])
console.log(listSelect)
},
//点击批量删除后执行此方法
deleteList() {
let _this = this;
console.log("想要批量删除:" + _this.multipleSelection);
axios({
method: "post",
url: "http://localhost:8080/brand-crud/deleteSelectedListServlet",
data: JSON.stringify(this.multipleSelection)//会自动转换,可以不写转换语句
//JS对象转通过方法JSON.stringify(js对象) 转换为 JSON串,servlet中以req.getReader()流的形式读取
}).then(function (resp) {
// 判断响应数据是否为 success
if (resp.data === "success") {
_this.selectAll();
// alert("查询成功!"
_this.$message({message: '批量删除成功', type: 'success'});
} else {
alert("删除失败");
_this.selectAll();
}
})
},
// 点击查询后执行此方法:按条件模糊查询
selectBySelect() {
console.log("模糊查询的条件为" + this.brandLike.status + this.brandLike.companyName + this.brandLike.brandName);
let _this = this;
console.log("想要添加:" + _this.brand.brandName);
axios({
method: "post",
url: "http://localhost:8080/brand-crud/selectLikeServlet",
data: JSON.stringify(this.brandLike)//会自动转换,可以不写转换语句
//JS对象转通过方法JSON.stringify(js对象) 转换为 JSON串,servlet中以req.getReader()流的形式读取
}).then(function (resp) {
// 判断响应数据是否为 success
if (resp.data != "") {
// alert("查询成功!")
_this.tableData = resp.data;
_this.$message({message: '查询成功', type: 'success'});
} else {
alert("查询失败");
}
})
},
// 点击新增按钮后会将新增提示框显现,数据填写完毕后,点击提交会执行此方法:添加数据
addBrand() {
let _this = this;
console.log("想要添加:" + _this.brandAdd.brandName);
axios({
method: "post",
url: "http://localhost:8080/brand-crud/addServlet",
data: JSON.stringify(this.brandAdd)//会自动转换,可以不写转换语句
//JS对象转通过方法JSON.stringify(js对象) 转换为 JSON串,servlet中以req.getReader()流的形式读取
}).then(function (resp) {
// 判断响应数据是否为 success
if (resp.data == "success") {
// alert("添加成功!")
_this.dialogVisible = false;
_this.selectAll();
_this.brandAdd = {};//重置brandAdd对象
// location.href = "http://localhost:8080/brand-crud/brand.html";
// 弹出消息提示
_this.$message({message: '恭喜你,添加成功', type: 'success'});
} else {
alert("添加失败");
_this.selectAll();
// location.href = "http://localhost:8080/brand-crud/brand.html";
}
})
},
//数据较少进行前端分页,不进行后端分页==========================================
//每页显示条数改变后执行:选择 ?条/页后执行此方法
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
this.pageSize = val;
},
//当前也改变后执行:
//选择 123456.。。之后执行此方法。
//选择 前往?页后执行此方法
handleCurrentChange(val) {
this.currentPage = val;
console.log(`当前页: ${val}`);
console.log(`当前全表: ` + this.tableData);
console.log(`当前范围起始编号: ` + (this.currentPage - 1) * this.pageSize);
console.log(`当前每页多少: ` + this.pageSize);
},
//查询所有,页面初始加载完毕后通过mounted方法调用。
//添加、删除、修改成功后也会被调用。
selectAll() {
let _this = this;
axios({
method: "get",
url: "http://localhost:8080/brand-crud/selectAllServlet"
})
.then(function (resp) {
_this.tableData = resp.data;
console.log(_this.tableData);
_this.totalNum = _this.tableData.length;
})
},
//点击删除按钮后执行此方法
deleteOneBrand(data) {
console.log("想要删除的数据的ID" + data.id)
let _this = this;
//页面加载完成后发送异步请求获取列表数据,获取到的为JSON字符串
//往前端传JS对象会自动转成JSON字符串
axios({
method: "get",
url: "http://localhost:8080/brand-crud/deleteOneServlet?id=" + data.id
}).then(function (resp) {
//axios会将后端传过来JSON字符串自动转成JS对象
//将JSON字符串转成JS对象的原生JS方法是===parse(str) :
// 将 JSON串转换为 js 对象。使用方式是: var jsObject = JSON.parse(jsonStr);
// 判断响应数据是否为 success
if (resp.data == "success") {
_this.selectAll();
// 弹出消息提示
_this.$message({message: '删除成功', type: 'success'});
} else {
alert("删除失败");
_this.selectAll();
}
});
},
//点击修改按钮后获取当前行数据,修改提示框显现
updateOneBrand(data) {
console.log("想要修改的数据的ID" + data.id)
this.dialogVisibleUpdate = true;
// this.brand = data;//浅拷贝,我改你也改
this.brand = JSON.parse(JSON.stringify(data));//深拷贝,我改你不改
},
//修改提示框显现后,显示停用启用
stateFormat(row, column) {
if (row.status === 1) {
return '启用'
} else {
return '停用'
}
},
//填写修改后的信息后,点击提交修改按钮后,执行此方法
updateBrandDo() {
let _this = this;
console.log("想要添加:" + _this.brand.brandName);
axios({
method: "post",
url: "http://localhost:8080/brand-crud/updateOneBrandServlet",
data: JSON.stringify(this.brand)//会自动转换,可以不写转换语句
//JS对象转通过方法JSON.stringify(js对象) 转换为 JSON串,servlet中以req.getReader()流的形式读取
}).then(function (resp) {
// 判断响应数据是否为 success
if (resp.data == "success") {
// alert("添加成功!")
_this.dialogVisibleUpdate = false;//关闭弹窗
_this.selectAll();//重现所有
_this.brand = {};//重置brand对象
// location.href = "http://localhost:8080/brand-crud/brand.html";
// 弹出消息提示
_this.$message({message: '修改成功', type: 'success'});
} else {
alert("修改失败");
_this.selectAll();
// location.href = "http://localhost:8080/brand-crud/brand.html";
}
})
},
},
//钩子函数,页面初次加载DIV被EL后自动调用此方法
mounted() {
this.selectAll();
},
//页面中用到的相关VM对象
data() {
return {
// 默认当前页码
currentPage: 1,
//每页显示多少条选择框
pageSizes: [3, 10, 15, 20],
//当前每页默认显示多少条
pageSize: 3,
//默认总数据的条数
totalNum: 0,
// 添加数据对话框是否展示的标记
dialogVisible: false,
//修改更新数据对话框是否展示的标记
dialogVisibleUpdate: false,
// 品牌模型数据:用于修改
brand: {
status: '',
brandName: '',
companyName: '',
id: "",
ordered: "",
description: ""
},
//品牌模型数据:用于模糊查询
brandLike: {
status: '',
brandName: '',
companyName: '',
id: "",
ordered: "",
description: ""
},
//品牌模型数据:用于新增
brandAdd: {
status: '',
brandName: '',
companyName: '',
id: "",
ordered: "",
description: ""
},
// 复选框选中数据集合
multipleSelection: [],
// 表格数据,从后端接收到的JSON字符串经过AXIOS自动转成JS对象并赋值到这里
tableData: [
// {
// brandName: '华为',
// companyName: '华为科技有限公司',
// ordered: '100',
// status: "1"
// }, {
// brandName: '华为',
// companyName: '华为科技有限公司',
// ordered: '100',
// status: "1"
// }, {
// brandName: '华为',
// companyName: '华为科技有限公司',
// ordered: '100',
// status: "1"
// }, {
// brandName: '华为',
// companyName: '华为科技有限公司',
// ordered: '100',
// status: "1"
// }
]
}
}
})
</script>
</body>
</html>