目的:让页面调用controller,将数据加载到页面中(只不过这个前端页面我们直接就是放到了static里面了)。
第一步:导入文件
所需要的文件见本文最后“文件获取”:
(1)文件如下:
(2)全选并复制:
(3)粘贴到项目目录中去
第二步:使用clean进行刷新
(1)点击右侧clean
(2)clean成功
如果没有clean成功,提示Error running 'demo4 [clean]' No valid Maven installation found. Either set the home directory in the configuration dialog or set the M2_HOME environment variable on your system,出现这种错误看我的博客:http://t.csdnimg.cn/Dd9ex
(3)第三步:开始运行
(1)输入以下链接并回车
注意:我用的是8080,如果你用的是别的,需要自行改一下。
http://localhost:8080/pages/fuels.html
第四步:代码知识详解
(1)<head>标签
定义了所有的头部信息,以及样式表的导入,以及页面的链接标题。
代码位置如下:
代码为:
<head> <!-- 页面meta --> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>springboot实现fuel静态页面的展示</title> <meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport"> <!-- 引入样式 --> <link rel="stylesheet" href="../plugins/elementui/index.css"> <link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css"> <link rel="stylesheet" href="../css/style.css"> </head>
(2)最左侧的头标签content-header
对应位置为:
代码为:
<div class="content-header"> <h1>fuels管理系统</h1> </div>
(3)标签和按钮
①输入标签
在代码中的位置:
代码为:
<el-input placeholder="id" style="width: 200px;" class="filter-item"></el-input> <el-input placeholder="fossialEnergyType" style="width: 200px;" class="filter-item"></el-input> <el-input placeholder="CAD:" style="width: 200px;" class="filter-item"></el-input> <el-input placeholder="CD" style="width: 200px;" class="filter-item"></el-input> <el-input placeholder="NaVar" style="width: 200px;" class="filter-item"></el-input> <el-input placeholder="FC:" style="width: 200px;" class="filter-item"></el-input> <el-input placeholder="FCbj" style="width: 200px;" class="filter-item"></el-input> <el-input placeholder="NCVbj:" style="width: 200px;" class="filter-item"></el-input>
②按钮
<el-button @click="getAll()" class="dalfBut">查询</el-button> <el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>
(4)分页组件
<!--分页组件--> <div class="pagination-container"> <el-pagination class="pagiantion" @current-change="handleCurrentChange" :current-page="pagination.currentPage" :page-size="pagination.pageSize" layout="total, prev, pager, next, jumper" :total="pagination.total"> </el-pagination> </div>
(5)导入js组件,包括vue组件和elementui组件
代码为:
<!-- 引入组件库 --> <script src="../js/vue.js"></script> <script src="../plugins/elementui/index.js"></script> <script type="text/javascript" src="../js/jquery.min.js"></script> <script src="../js/axios-0.18.0.js"></script> <script>
(6)vue的控制结构
①展示的列表数据list格式
dataList: [],
放到网页的页面上进行展示
②控制弹层(增删改需要用的弹出界面)
默认不可见,不然我们一打开网页就是乱七八糟的表单弹窗,而是等我们在增删改需要的时候再将这个置为true
第一个用于控制新增的,第二个用于控制修改的
dialogFormVisible: false,//添加表单是否可见 dialogFormVisible4Edit:false,//编辑表单是否可见
③表单数据(新增修改用的每一条数据的详细信息)
formData: {},//表单数据
④分页控制参数
pagination: {//分页相关模型数据 currentPage: 1,//当前页码 pageSize:10,//每页显示的记录数 total:0//总记录数 }
⑤钩子函数(vue初始化完成之后先调用它)
//钩子函数,VUE对象初始化完成后自动执行 created() { },
⑥方法操作
methods: { //列表 getAll() { }, //弹出添加窗口 handleCreate() { }, //重置表单 resetForm() { }, //添加 handleAdd () { }, //取消 cancel(){ }, // 删除 handleDelete(row) { }, //弹出编辑窗口 handleUpdate(row) { }, //修改 handleEdit() { }, //分页查询 //切换页码 handleCurrentChange(currentPage) { }, //条件查询 }
第五步:功能实现
(1)展示全部数据
①配置钩子函数调用“展示全部数据”的方法
在created()里面书写this.getAll()方法:
②添加getAll方法内操作
先用postman确定访问的URL路径名(fuels)以及请求方法(get)。
③然后我们在getAll方法内使用axios结合上面的请求路径:
getAll() { //使用axios发送异步请求 //①路径为fuels //②方法为get //④使用then和res将数据提取 //⑤提取的数据部分为R对象中的data //⑥使用console实现网页中控制台对数据的接受打印。 axios.get("/fuels").then((res)=>{ console.log(res.data); }); },
程序运行:
④将数据在页面上展示出来
根据上面的③我们知道,我们传过去的data,对应网页控制端object(内部还包含一个打他),因此,要想将获取的数据给传给list集合,我们就需要使用data.data。
因此我们就需要在前面③的里面加上:
this.dataList=res.data.data;
效果如下:
(2)增添数据功能
①找到按钮位置
点击之后会跳转到handleCreate位置。
②新建该方法并设置弹层可视化
对应代码为:
this.dialogFormVisible=true;
这样的话,点击之后这个增加数据的表单就会自动弹出来。
③设置对应的弹层内容
<!-- 新增标签弹层 --> <div class="add-form"> <el-dialog title="新增燃料信息" :visible.sync="dialogFormVisible"> <el-form ref="dataAddForm" :model="formData" :rules="rules" label-position="right" label-width="100px"> <el-row> <el-col :span="12"> <el-form-item label="燃料种类" prop="fossilEnergyType"> <el-input v-model="formData.fossilEnergyType"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="CAD值" prop="CAD"> <el-input v-model.number="formData.CAD"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="CD值" prop="CD"> <el-input v-model.number="formData.CD"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="NaVar值" prop="NaVar"> <el-input v-model.number="formData.NaVar"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="FC值" prop="FC"> <el-input v-model.number="formData.FC"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="FCbj值" prop="FCbj"> <el-input v-model.number="formData.FCbj"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="NCVbj值" prop="NCVbj"> <el-input v-model.number="formData.NCVbj"/> </el-form-item> </el-col> </el-row> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="cancel()">取消</el-button> <el-button type="primary" @click="handleAdd()">确定</el-button> </div> </el-dialog> </div>
效果:
上述的所有内容被放到了formData里面:
④点击“确认”将上述表单中的数据接受并传给后端
首先找到确认按钮的位置:
然后对应找到handleAdd()函数的位置,编写内容如下:
//添加 handleAdd () { //①使用的是post请求 //②传递的路径是fuels //③传到后端的数据是formData axios.post("/fuels",this.formData).then((res)=>{ if(res.data.flag==true) { //④关闭弹层表单 this.dialogFormVisible=false; } //⑤重新加载更新后的数据并展示 this.getAll(); }) },
⑤测试数据传送效果
输入数据并点击确定:
可以发现数据成功被添加并展示:
⑥优化
每一次我们添加完成之后,再次打开网页点击添加,还是会出现上次留下来的数据,因此我们需要在每次添加完成之后把表单中的数据清除一下:
因此我们需要定义一个“重置表单”的操作:
//重置表单 resetForm() { this.formData={};//直接将数据置空 },
然后我们设置每一次打开表单的时候进行一次重置表单,也就是需要在handleCreate()里面调用resetForm()功能:
⑦设置取消按钮的功能
找到“取消”按钮所在的位置:
找到“cancel()”函数的位置,并书写内部关闭表单弹窗的代码语句:
//取消 cancel(){ this.dialogFormVisible=false; this.$message.info("当前操作取消");//灰色 },
之后我们点击“取消”这个添加的弹窗就可以被关闭了。
(3)删除数据功能
①首先要先找到删除的按钮位置
可以看到,我们需要去找handleDelete()操作
解析参数scope.row;它将整个行对象封装成为scope,而这个row指的是这一行的数据。
②找到handleDelete()函数位置:
先使用console.log进行测试:
可以发现当我们在网页上点击删除按钮的时候,网页能够正常获取这一行的数据:
③handleDelete()函数代码
// 删除 handleDelete(row) { //打印出这一行的数据 console.log(row); //①路径是/fuels/id,我们这里用字符串拼接的方式来做的 //②设置删除失败与成功的判断操作 axios.delete("/fuels/"+row.id).then((res)=>{ if(res.data.flag==true) { //⑥删除成功提示绿色 this.$message.success("删除成功!"); } else { //⑦删除失败为红色 this.$message.error("删除失败!"); } //删除完成之后重新刷新页面 this.getAll(); }) },
点击删除进行测试效果:
④拓展
使用提示“此操作永久删除当前信息,是否继续”功能:
代码:
this.$confirm("此操作永久删除当前信息,是否继续?","警告",{type:"info"}).then(()=> { console.log("success");//点击确认之后跳转到这里 }).catch(()=>{ console.log("cancel"); })
同时点击确认之后,也可以在网页控制台上看到success:
我们将③和④整合到一块:
代码为:
// 删除 handleDelete(row) { this.$confirm("此操作永久删除当前信息,是否继续?","警告",{type:"info"}).then(()=> { console.log("success");//点击确认之后跳转到这里 //打印出这一行的数据 console.log(row); //①路径是/fuels/id,我们这里用字符串拼接的方式来做的 //②设置删除失败与成功的判断操作 axios.delete("/fuels/"+row.id).then((res)=>{ if(res.data.flag==true) { //⑥删除成功提示绿色 this.$message.success("删除成功!"); } else { //⑦删除失败为红色 this.$message.error("删除失败!"); } //删除完成之后重新刷新页面 this.getAll(); }) }).catch(()=>{ console.log("concel"); this.$message.info("当前操作取消"); }) },
(4)修改数据功能
①先找到修改功能对应的操作位置
②找到对应的handleUpdate位置
1.我们首先要先获取全部的数据,并将数据展示到表单上
//弹出编辑窗口 handleUpdate(row) { //①先获取全部数据 axios.get("/fuels").then((res)=>{ console.log(res.data); this.dataList=res.data.data; }); //②获取我们点的这行的数据,并展示到表单 axios.get("/fuels/"+row.id).then((res)=>{ this.dialogFormVisible4Edit=true; this.formData=res.data.data; }); },
这样我们每一次点击“编辑”按钮后,就会出现这行的全部信息,如下:
2.增加数据没有展示不出来的情况(核心是因为开了多个界面,导致没刷新上)
使用if-else判断代码:
//弹出编辑窗口 handleUpdate(row) { //①先获取全部数据 axios.get("/fuels").then((res)=>{ console.log(res.data); this.dataList=res.data.data; }); //②获取我们点的这行的数据,并展示到表单 axios.get("/fuels/"+row.id).then((res)=>{ if(res.data.flag==true) { this.dialogFormVisible4Edit=true; this.formData=res.data.data; } else { this.$message.error("数据同步失败,自动刷新!"); this.getAll(); } }); },
效果:
③点击“确定”的时候将数据同步到后端
先找到对应的“确认”按钮:
接着找到handleEdit位置部分:
内容如下(类似于上面的添加操作):
//修改 handleEdit() { //①使用的是put请求 //②传递的路径是fuels //③传到后端的数据是formData axios.put("/fuels",this.formData).then((res)=>{ if(res.data.flag==true) { //④关闭弹层表单 this.dialogFormVisible4Edit=false; //⑥添加成功提示绿色 this.$message.success("修改成功!"); } else { //⑦添加失败为红色 this.$message.error("修改失败!"); } //⑤重新加载更新后的数据并展示 this.getAll(); }) },
④设置“取消”按钮操作
找到cancel()位置:
效果:
(5)异常消息处理
异常举例:
可以发现,这个于我们常规定义的前后端联调时候用的统一数据格式R不一样,所以这就给我们的开发造成了困扰。
因此:我们就需要对所有的异常格式进行一个统一的处理,并且要处理成跟原来一样的格式。
①我们创建新的类,类名为:projectExceptionAdvice
其中:我们将这个异常处理放到了controller层,而没有放到业务层和dao层,原因是就算放了最终异常也会传到controller这里,所以干脆直接就在这做了。
②给我们的统一数据格式R类加上一个新的属性量msg,代表错误信息
③在projectExceptionAdvice类里面书写异常处理操作
使用@RestControllerAdvice或者@ControllerAdvice定义这是一个异常类,其中@RestControllerAdvice包含了@ControllerAdvice
类中代码为:
//作为springmvc的异常处理器 //@ControllerAdvice @RestControllerAdvice public class projectExceptionAdvice { @ExceptionHandler public R exception(Exception e) { e.printStackTrace();//将异常打印到控制台里面进行显示 R r = new R(); r.setFlag(false); r.setData(null); r.setMsg("服务器故障,请稍后再试!"); return r; } }
实现效果:(统一的数据返回格式)
③将这个返回的信息能够返回到页面上
例如:原先我们在(2)添加数据功能“添加失败”部分:
我们可以将这个改成:
效果:
(6)分页查询
我们只需要在原先getAll()方法的基础上增加分页操作即可。
①分页组件
总代码:
<!--分页组件--> <div class="pagination-container"> <el-pagination class="pagiantion" @current-change="handleCurrentChange" :current-page="pagination.currentPage" :page-size="pagination.pageSize" layout="total, prev, pager, next, jumper" :total="pagination.total"> </el-pagination> </div>
分别介绍:
1.class="pagiantion"代表样式表
2.@current-change="handleCurrentChange"实现页码跳转操作的时候用这个
3.加载数据部分
:current-page="pagination.currentPage"当前页码
:page-size="pagination.pageSize"每页展示的条目数
:total="pagination.total">总共有多少条数据
4:layout="total, prev, pager, next, jumper"布局模式部分
分别代表的含义如下:
②样式表pagiantion的信息设置
代码为:
pagination: {//分页相关模型数据 currentPage: 1,//当前页码 pageSize:10,//每页显示的记录数 total:0//总记录数 }
③然后我们修改getAll()方法
getAll() { //使用axios发送异步请求 //①路径为fuels //②方法为get //④使用then和res将数据提取 //⑤提取的数据部分为R对象中的data //⑥使用console实现网页中控制台对数据的接受打印。 // axios.get("/fuels").then((res)=>{ // console.log(res.data); // this.dataList=res.data.data; // }); axios.get("/fuels/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res)=>{ console.log(res.data); this.dataList=res.data.data; }); },
在页面的运行效果为:
我们可以看到分页查询的请求已经正确发送给后端了:
并且我们点击“相应”部分也可以看到,分页的数据前端也的确获取到了:
并且我们可以看到数据是在record里面的,也就是接受的数据格式有一些需要变动,因此我们需要将this.dataList=res.data.data;改成对应的records的相关操作为。
修改后的代码为:
getAll() { //使用axios发送异步请求 //①路径为fuels //②方法为get //④使用then和res将数据提取 //⑤提取的数据部分为R对象中的data //⑥使用console实现网页中控制台对数据的接受打印。 // axios.get("/fuels").then((res)=>{ // console.log(res.data); // this.dataList=res.data.data; // }); axios.get("/fuels/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res)=>{ console.log(res.data); //this.dataList=res.data.data; this.dataList=res.data.data.records; }); },
这样我们的页面就能把数据加载进去了:
③更新右下角的数据显示
也就是我们要更新pagination中的currentPage、pageSize和total的值
总代码为:
getAll() { //使用axios发送异步请求 //①路径为fuels //②方法为get //④使用then和res将数据提取 //⑤提取的数据部分为R对象中的data //⑥使用console实现网页中控制台对数据的接受打印。 // axios.get("/fuels").then((res)=>{ // console.log(res.data); // this.dataList=res.data.data; // }); axios.get("/fuels/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res)=>{ console.log(res.data); //this.dataList=res.data.data; this.pagination.pageSize=res.data.data.size; this.pagination.currentPage=res.data.data.current; this.pagination.total=res.data.data.total; this.dataList=res.data.data.records; }); },
效果:
可以看到我们的右下角的页面信息被正确加载进来了。
④切换页码操作,点击页码实现跳转
对应的按钮位置就是:
因此我们需要向下寻找到对应的handleCurrentChange()方法的位置并书写代码:
//切换页码 handleCurrentChange(currentPage) { //①修改页码值为当前选中的页码值 this.pagination.currentPage=currentPage; //②执行查询 this.getAll(); },
效果:
可以发现,当我们点击2的时候能够实现跳转:
(7)条件查询
①将条件查询与分页查询进行绑定
因为条件查询的结果一般输出可以是多条数据,而多条数据必然和分页紧密相连,所以我们更改原先的条件查询属性内容:
②将条件查询输入框和分页查询相关联
对应就是将条件查询的输入框中的数据用分页查询这个模型中我们新定义的属性参数来接收:
③测试数据输入的数据能否被接收到
用id来做测试:(在getAll()里面的)
效果:
因此发现可以接收到我们输入在输入框中的内容!
④书写条件查询表达式
表达式为:
效果为:
⑤将上述条件表达式和条件查询连一起
在原有的get函数后面连接上我们上面写的condition就行。
测试效果:
可以发现条件查询拼凑成功了。
⑤测试后端能不能拿到数据
输入框输入:
在原有条件查询的基础上加上fuel对象,并观察得到能够接收来自前端的输入框输入:
⑥下面我们自己写一个独立的分页和条件查询的函数(重载形式)
1.fuel.html的getAll()部分(增加对主键id非空的判断)
getAll() { //使用axios发送异步请求 //①路径为fuels //②方法为get //④使用then和res将数据提取 //⑤提取的数据部分为R对象中的data //⑥使用console实现网页中控制台对数据的接受打印。 // axios.get("/fuels").then((res)=>{ // console.log(res.data); // this.dataList=res.data.data; // }); //console.log(this.pagination.id);//测试能否接收到条件查询数据 //拼接条件查询/fuels/2/5?id=&fossilEnergyType&…… condition="?q";//一个无效前缀,主要是为了后面的格式能够统一 if (this.pagination.id==null) { condition+="&id="+1234567890; } else { condition+="&id="+this.pagination.id; } condition+="&fossilEnergyType="+this.pagination.fossilEnergyType; condition+="&CAD="+this.pagination.CAD; condition+="&CD="+this.pagination.CD; condition+="&NAVar="+this.pagination.NAVar; condition+="&FC="+this.pagination.FC; condition+="&FCbj="+this.pagination.FCbj; condition+="&NCVbj="+this.pagination.NCVbj; //测试条件查询 console.log(condition); axios.get("/fuels/"+this.pagination.currentPage+"/"+this.pagination.pageSize+condition).then((res)=>{ console.log(res.data); //this.dataList=res.data.data; this.pagination.pageSize=res.data.data.size; this.pagination.currentPage=res.data.data.current; this.pagination.total=res.data.data.total; this.dataList=res.data.data.records; }); },
2.FuelController部分
//分页+条件 @GetMapping("{currentPage}/{pageSize}") public R getPage(@PathVariable int currentPage, @PathVariable int pageSize,Fuel fuel) { System.out.println(fuel); R r=new R(); boolean flag=true;//走到了这一步,都是查询成功 IPage iPage=fuelService.getPage(currentPage, pageSize,fuel); if(currentPage>iPage.getPages()) { iPage=fuelService.getPage((int)iPage.getPages(), pageSize,fuel); } r.setFlag(flag); r.setData(iPage); return r; }
3.FuelService接口部分
//分页+条件 IPage<Fuel> getPage(int currentPage, int pageSize,Fuel fuel);
4.FuelServiceImpl部分
//分页+条件 @Override public IPage<Fuel> getPage(int currentPage, int pageSize, Fuel fuel) { LambdaQueryWrapper<Fuel> wrapper=new LambdaQueryWrapper<>(); if(fuel.getId()!=null) {//避免查询的字段为null名字的字段 if(fuel.getId()!=1234567890) { wrapper.like(Fuel::getId, fuel.getId());//第一个是属性名字,第二个是我们输入要like的内容 } //如果等于1234567890代表我们没有进行任何查询,因为id不可以为null,所以我们设置一个非null来表示 } if(fuel.getFossilEnergyType()!=null) {//避免查询的字段为null名字的字段 wrapper.like(Fuel::getFossilEnergyType, fuel.getFossilEnergyType());//第一个是属性名字,第二个是我们输入要like的内容 } if(fuel.getCAD()!=null) {//避免查询的字段为null名字的字段 wrapper.like(Fuel::getCAD, fuel.getCAD());//第一个是属性名字,第二个是我们输入要like的内容 } if(fuel.getCD()!=null) {//避免查询的字段为null名字的字段 wrapper.like(Fuel::getCD, fuel.getCD());//第一个是属性名字,第二个是我们输入要like的内容 } if(fuel.getNAVar()!=null) {//避免查询的字段为null名字的字段 wrapper.like(Fuel::getNAVar, fuel.getNAVar());//第一个是属性名字,第二个是我们输入要like的内容 } if(fuel.getFC()!=null) {//避免查询的字段为null名字的字段 wrapper.like(Fuel::getFC, fuel.getFC());//第一个是属性名字,第二个是我们输入要like的内容 } if(fuel.getFCbj()!=null) {//避免查询的字段为null名字的字段 wrapper.like(Fuel::getFCbj, fuel.getFCbj());//第一个是属性名字,第二个是我们输入要like的内容 } if(fuel.getNCVbj()!=null) {//避免查询的字段为null名字的字段 wrapper.like(Fuel::getNCVbj, fuel.getNCVbj());//第一个是属性名字,第二个是我们输入要like的内容 } IPage page=new Page<>(currentPage,pageSize); return fuelDao.selectPage(page,wrapper); }
效果展示:
文件获取:
(1)网页测试URL
http://localhost:8080/pages/fuels.html
(需要按照你的端口替换一下这个8080)
(2)数据库
通过百度网盘分享的文件:燃煤热电数据库2.2.zip
链接:https://pan.baidu.com/s/1CobrQkEb7i0bAdUOcmxIIg?pwd=vebf
提取码:vebf
--来自百度网盘超级会员V5的分享
(3)后端代码
通过百度网盘分享的文件:springboot实现前后端调用axios异步请求(后端单体服务器s...
链接:https://pan.baidu.com/s/1o9RFrwjWa3ipvjVY8W2hlQ?pwd=gi6b
提取码:gi6b
--来自百度网盘超级会员V5的分享
(3)静态页面文件(参考使用的是黑马程序员的文件并进行修改调整)
通过百度网盘分享的文件:static.zip
链接:https://pan.baidu.com/s/148WsM22v96-5sIh2QQ_IDg?pwd=2l68
提取码:2l68
--来自百度网盘超级会员V5的分享
如果运行我打包的项目,为了能够正常运行(需要兼容maven以及java版本),具体的调整方法看我博客:http://t.csdnimg.cn/Uovig
好啦,希望能够帮助到大家!