目录
- 引出
- 一些固定的东西
- 1.固定的响应格式
- 2.name 变成 v-model 进行双向绑定
- 3.下拉框选中--:value="type.id" +v-model="companyDb.typeId"
- 4.vue导包固定写法
- 5.script固定写法
- 6.axios的get请求
- 7.axios的post请求---let params = new URLSearchParams()
- 8.前端美化:
- 数据分页显示
- 1.后端改成resp响应
- 2.前端的修改要点
- (1)显示所有图书信息-----方法queryListByPageNum(pageNum)
- 【bug】一个没有报错信息的bug--应该写在created里
- (2)首页、尾页、上下页
- (3)【有坑】页面的跳转--axios请求异步问题
- 3.前后端完整代码
- (1)后端CompanyListServlet.java代码:
- (2)前端代码:加上了增加和修改,删除的部分,list.jsp页面代码
- 增加一条数据
- 1.jsp到Js+axios+vue的变化
- 2.前端代码修改
- (1)所有输入框的name,改成v-model进行双向绑定
- (2)用一个list对象存查询到所有type的list
- (3)在显示区域进行类型下拉框的显示【bug】---:value
- 【bug】遇到过的bug:value写成vlaue,没加冒号
- 3.后端代码修改
- 4.前后端完整代码
- (1)后端完整代码:AddServlet.java文件:
- (2)前端完整代码:addCompMess.jsp文件
- 修改一条数据
- 1.Jsp到Js+axios+vue的变化
- 【bug】遇到过的bug:value写成vlaue,没加冒号
- 2.前端代码的修改
- (0)要修改数据的id保存的问题 local storage 或者 过一次后端
- (1)时间显示的问题----@JSONField(format = "yyyy-MM-dd")
- (2)类型下拉框回显的问题---v-model="companyDb.typeId" + :value="type.id"
- (3)点击重置的时候,重置哪些东西,除了id之外的其他值
- 3.后端代码的修改
- (1)由于前端有时间框,因此后端实体类加注解
- 4.前后端完整代码--loacal storage版本
- (1)前端list.jsp页面相关代码:
- (2)update.jsp代码
- (3)后端updatePageServlet.java代码
- (4)后端updateServlet.java代码
- 4.前后端完整代码---过一遍servlet版本
- (1)前端list.jsp页面相关代码:
- (2)前端update.jsp页面代码
- (3)该版本的后端updatePageServlet.java代码 和 updateServlet.java代码同local storage版本
- 删除一条数据
- 1.Jsp到Js+axios+vue的变化
- 2.前端代码修改
- 3.后端代码修改
- 4.前后端完整代码--需要权限的例子
- (1)前端删除事件代码:
- (2)后端删除业务代码,权限控制
- 总结
引出
从同步到异步 & 从jsp 到 js + axios + vue 实现 数据分页显示 & 数据增删改查
一些固定的东西
1.固定的响应格式
import com.alibaba.fastjson.JSON;
import com.tianju.entity.ResData;
resp.getWriter().write(JSON.toJSONString(
new ResData(200, "登陆成功", newUser)));
2.name 变成 v-model 进行双向绑定
<%-- 要把原有的书名,和简介,以及类型信息显示出来--%>
书名:<input type="text" v-model="opus.name" ><br>
简介:<input type="text" v-model="opus.intro" ><br>
类型:
<%-- 用forEach把类型信息拼出来--%>
<%-- v-model="opus.typeId" 双向绑定--%>
<select v-model="opus.typeId">
<%-- 如果根据id查询到的书籍信息,和这里拼的某一个类型信息一致,则设置成selected ,实现默认选中--%>
<option v-for="types in bookTypeList" :value="types.id">{{types.name}}</option>
</select><br>
3.下拉框选中–:value=“type.id” +v-model=“companyDb.typeId”
<select v-model="companyDb.typeId">
<option value="">请选择</option>
<option v-for="type in typeList" :value="type.id">{{type.name}}</option>
</select>
4.vue导包固定写法
<head>
<title>修改公司信息</title>
<link rel="stylesheet" href="/day06/bootstrap/css/bootstrap.css">
<script src="/day06/js/axios.min.js"></script>
<script src="/day06/js/jquery-3.5.1.js"></script>
<script src="/day06/bootstrap/js/bootstrap.js"></script>
<script src="/day06/js/vue.min-v2.5.16.js"></script>
</head>
5.script固定写法
let app = new Vue({
// 选择操作的div区域
el:"#app",
// 数据区
data:{},
// 方法区
methods:{},
// 文档加载之后就执行
created(){},
// 整个页面全部加载完成后再执行
mounted(){},
})
6.axios的get请求
axios.get("/day06/types/list/vue?name="+"柯基")
.then(response=>{
let resp = response.data;
console.log(resp);
},error=>{
console.log(error)
})
7.axios的post请求—let params = new URLSearchParams()
let params = new URLSearchParams();
params.append("username",this.username);
params.append("password",this.password);
params.append("rePassword",this.rePassword);
params.append("gender",this.gender);
params.append("birthday",this.birthday);
params.append("imgCode",this.imgCode);
console.log(params);
axios.post("/day06/comUser/register/vue",params)
.then(response=>{
let resp = response.data;
console.log(resp);
if (resp.code==200)
{
// 成功,跳转回到list页面
location.href="/day06/compMess/listVue.jsp"
}
else
{
alert(resp.msg);
}
},error=>{
console.log(error)
})
8.前端美化:
<table class="table-condensed table-hover table-striped table-responsive table-cell table-row-cell table-view table-bordered">
class="btn btn-primary btn-sm"
数据分页显示
1.后端改成resp响应
// 4.new PageInfo对象,共享页数等,以及查询到的数据
List<Company> list = companyService.queryByLikeNameLimit(pageNum, pageSize,name);
PageInfo<Company> pageInfo = new PageInfo<>(pageNum, pageSize, total, pages, list);
resp.getWriter().write(JSON.toJSONString(
new ResData(200, "ok", pageInfo)
));
2.前端的修改要点
(1)显示所有图书信息-----方法queryListByPageNum(pageNum)
因为后端需要知道前端要显示第几页 pageNum,所有在前端定义一个方法queryListByPageNum(pageNum),该方法与后端交互,从拿到pageInfo对象,进而从这个对象中获得pageNum, pageSize, total, pages, list;从而实现整体的功能
methods:{
// 本质每次给后端传一个pageNum,然后后端给前端传要显示的数据
queryListByPageNum(pageNum){
axios.get("/day06/company/messList?pageNum="+pageNum)
.then(response=>{
let resp = response.data;
console.log("~~~~~~~~~queryListByPageNum")
console.log(resp.data)
this.pageInfo = resp.data;
// 应该写到这里
this.gotoPageNum = this.pageInfo.pageNum;
});
// 如果写在这里,在axios发送了请求,等待响应的期间,程序会接着执行,
// 此时,this.pageInfo.pageNum还是响应之前的数据,因此导致这里的
// this.gotoPageNum 被赋值成了上一次到的值
this.gotoPageNum = this.pageInfo.pageNum;
}
},
【bug】一个没有报错信息的bug–应该写在created里
(2)首页、尾页、上下页
基本功能:
首页:调用上面的方法,传入的 pageNum 参数为1,点击时:queryListByPageNum(1);
上页:点击时,queryListByPageNum(pageInfo.pageNum-1);
下页:点击时,queryListByPageNum(pageInfo.pageNum+1);
尾页:点击时,queryListByPageNum(pageInfo.pages)
显示与否:
如果不是第一页,pageInfo.pageNum!=1,首页和上页显示;
如果不是最后一页,pageInfo.pageNum!=pageInfo.pages,下一页和尾页显示;
<button @click="queryListByPageNum(1)" v-show="pageInfo.pageNum!=1">首页</button>
<button @click="queryListByPageNum(pageInfo.pageNum-1)" v-show="pageInfo.pageNum!=1">上一页</button>
<button @click="queryListByPageNum(pageInfo.pageNum+1)" v-show="pageInfo.pageNum!=pageInfo.pages">下一页</button>
<button @click="queryListByPageNum(pageInfo.pages)" v-show="pageInfo.pageNum!=pageInfo.pages">尾页</button>
快速美化:
class="btn btn-primary btn-sm"
(3)【有坑】页面的跳转–axios请求异步问题
输入跳转的目标页码,调用上面的方法,并且把原来输入框中的值改成跳转后页码
显示部分:
跳转到:<input type="text" v-model="gotoPageNum">
<button @click="queryListByPageNum(gotoPageNum)" class="btn btn-primary btn-sm">跳转</button>
有一个坑:
跳转框中的页码什么时候赋值的问题,等到axios请求获得响应后再赋值,写在axios里面
如果写在这里,在axios发送了请求,等待响应的期间,程序会接着执行,此时,this.pageInfo.pageNum还是响应之前的数据,因此导致这里的this.gotoPageNum 被赋值成了上一次到的值
业务逻辑部分:
<script>
let app = new Vue({
el:"#app",
data:{
pageInfo:{},
gotoPageNum:1, // 初始化第一页
},
methods:{
// 本质每次给后端传一个pageNum,然后后端给前端传要显示的数据
queryListByPageNum(pageNum){
axios.get("/day06/company/messList?pageNum="+pageNum)
.then(response=>{
let resp = response.data;
console.log("~~~~~~~~~queryListByPageNum")
console.log(resp.data)
this.pageInfo = resp.data;
this.gotoPageNum = this.pageInfo.pageNum;
});
// 如果写在这里,在axios发送了请求,等待响应的期间,程序会接着执行,
// 此时,this.pageInfo.pageNum还是响应之前的数据,因此导致这里的
// this.gotoPageNum 被赋值成了上一次到的值
// this.gotoPageNum = this.pageInfo.pageNum;
}
},
// 文档加载之后就执行
created(){
// 页面一启动查首页
this.queryListByPageNum(1);
},
// 整个页面全部加载完成后再执行
mounted(){},
})
</script>
3.前后端完整代码
(1)后端CompanyListServlet.java代码:
package com.tianju.servlet.company;
import com.alibaba.fastjson.JSON;
import com.tianju.entity.Company;
import com.tianju.entity.PageInfo;
import com.tianju.entity.ResData;
import com.tianju.service.ICompanyService;
import com.tianju.service.impl.CompanyService;
import com.tianju.util.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* 进行公司信息列表展示的servlet类
*/
@WebServlet("/company/messList")
public class CompanyListServlet extends HttpServlet {
private ICompanyService companyService = new CompanyService();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 2.0版本,支持模糊查询和分页展示信息
// 1.从前端获取数据:要显示第几页,每页显示多少条数据,查询的关键词是啥
String pageNumStr = req.getParameter("pageNum"); // 第几页
String pageSizeStr = req.getParameter("pageSize"); // 每页显示数据条数
String name = req.getParameter("name");
// 2.进行赋值,
// 如果没有输入第几页,默认显示首页,第一页;
Integer pageNum = StringUtils.isBlank(pageNumStr) ? 1:Integer.parseInt(pageNumStr);
// 如果没有输入显示多少条数据,默认每页显示3条;
Integer pageSize = StringUtils.isBlank(pageSizeStr) ? 3:Integer.parseInt(pageSizeStr);
// 如果没有输入查询关键词,数据条数为总数;
Integer total = companyService.countLines(name);
// 3.根据查询数据条数,以及前端获取的每页显示数据条数,计算总页数;
// 思路:如果能整除,则为页数;如果不能整除,则/后再加1;
Integer pages = total % pageSize==0 ? total/pageSize:total/pageSize+1;
// 4.new PageInfo对象,共享页数等,以及查询到的数据
List<Company> list = companyService.queryByLikeNameLimit(pageNum, pageSize,name);
PageInfo<Company> pageInfo = new PageInfo<>(pageNum, pageSize, total, pages, list);
resp.getWriter().write(JSON.toJSONString(
new ResData(200, "ok", pageInfo)
));
}
}
(2)前端代码:加上了增加和修改,删除的部分,list.jsp页面代码
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>公司的信息</title>
<link rel="stylesheet" href="/day06/bootstrap/css/bootstrap.css">
<script src="/day06/js/axios.min.js"></script>
<script src="/day06/js/jquery-3.5.1.js"></script>
<script src="/day06/bootstrap/js/bootstrap.js"></script>
<script src="/day06/js/vue.min-v2.5.16.js"></script>
</head>
<body>
<div id="app">
<table class="table-condensed table-hover table-striped table-responsive table-cell table-row-cell table-view table-bordered">
<tr>
<th>公司id</th>
<th>公司名</th>
<th>公司类型</th>
<th>合伙人</th>
<th>统一信用编码</th>
<th>公司地址</th>
<th>成立时间</th>
<th>用户名</th>
<th>修改时间</th>
<th>执行操作
<button @click="add">添加</button>
<%-- <a href="/day06/compMess/addPage">添加</a>--%>
</th>
</tr>
<tr v-for="comp in pageInfo.compList">
<td>{{comp.id}}</td>
<td>{{comp.name}}</td>
<td>{{comp.typename}}</td>
<td>{{comp.corporation}}</td>
<td>{{comp.creditCode}}</td>
<td>{{comp.address}}</td>
<td>{{comp.createTime}}</td>
<td>{{comp.username}}</td>
<td>{{comp.updateTime}}</td>
<td>
<button @click="update(comp.id)">修改</button>
<button @click="remove(comp.id)">删除</button>
</td>
</tr>
</table><br>
<%-- 分页查询相关--%>
<%-- 如果当前页是第一页,需要控制首页不显示,上一页不显示--%>
<button @click="queryListByPageNum(1)" v-show="pageInfo.pageNum!=1" class="btn btn-primary btn-sm">首页</button>
<button @click="queryListByPageNum(pageInfo.pageNum-1)" v-show="pageInfo.pageNum!=1" class="btn btn-primary btn-sm">上一页</button>
<button @click="queryListByPageNum(pageInfo.pageNum+1)" v-show="pageInfo.pageNum!=pageInfo.pages" class="btn btn-primary btn-sm">下一页</button>
<button @click="queryListByPageNum(pageInfo.pages)" v-show="pageInfo.pageNum!=pageInfo.pages" class="btn btn-primary btn-sm">尾页</button>
<%-- 提示信息,总页数为,当前第几页--%>
总计{{pageInfo.pages}}页/当前{{pageInfo.pageNum}}<br>
跳转到:<input type="text" v-model="gotoPageNum">
<button @click="queryListByPageNum(gotoPageNum)" class="btn btn-primary btn-sm">跳转</button>
</div>
<script>
let app = new Vue({
el:"#app",
data:{
pageInfo:{},
gotoPageNum:1, // 初始化第一页
},
methods:{
// 本质每次给后端传一个pageNum,然后后端给前端传要显示的数据
queryListByPageNum(pageNum){
axios.get("/day06/company/messList?pageNum="+pageNum)
.then(response=>{
let resp = response.data;
console.log("~~~~~~~~~queryListByPageNum")
console.log(resp.data)
this.pageInfo = resp.data;
this.gotoPageNum = this.pageInfo.pageNum;
});
// 如果写在这里,在axios发送了请求,等待响应的期间,程序会接着执行,
// 此时,this.pageInfo.pageNum还是响应之前的数据,因此导致这里的
// this.gotoPageNum 被赋值成了上一次到的值
// this.gotoPageNum = this.pageInfo.pageNum;
},
// 点击添加,直接到添加的页面
add(){
location.href="/day06/compMess/addCompMess.jsp"
},
// 更新信息的事件
update(id){
// // 1.把id存在local storage里
// localStorage.setItem("id",id);
// // 跳转到修改页面
// location.href="/day06/compMess/update.jsp"
// 2.把id交给后端的servlet,然后通过servlet给update.jsp页面
location.href="/day06/update/company/id?id="+id;
},
// 删除数据的事件
remove(id){
axios.get("/day06/company/remove?id="+id)
.then(response=>{
let resp = response.data;
console.log(resp);
if (resp.code==200)
{
// 删除成功,再查第一页数据
alert("成功");
this.queryListByPageNum(1);
}
else
{
alert(resp.msg)
}
})
}
},
// 文档加载之后就执行
created(){
// 页面一启动查首页
this.queryListByPageNum(1);
},
// 整个页面全部加载完成后再执行
mounted(){},
})
</script>
</body>
</html>
增加一条数据
1.jsp到Js+axios+vue的变化
在jsp的模式中,增加一条数据的业务逻辑如下:
(1)点击添加按钮,跳转到servlet,从数据库中查出类型信息,然后共享类型信息的值,转发到添加页面jsp;
(2)在添加页面jsp中,把上一步共享得到的类型信息用foreach的方法拼出一个下拉框,在form表单中用户填完信息后,点击添加按钮;
(3)form表单中的数据发送到处理添加业务的servlet,在该servlet中,把表单中的数据存进数据库,然后再跳转到查询所有数据的servlet中;
(4)在查询所有数据的servlet中,再查一次数据库,然后把显示的数据共享转发给list.jsp,从而最终显示添加之后的数据;
在vue的模式下,增加一条数据的业务逻辑变成如下的形式:
(1)在list页面,点击添加按钮,直接到添加页面;
(2)在添加页面的 created(){} 的启动就执行的方法中,把类型查出来;
(3)在添加页面显示类型下拉框,用户执行添加操作;
(4)点击添加按钮,请求发送给添加的servlet,添加成功后,resp返回状态码200;
(5)前端判断响应resp中的状态码是否为200,如果是,再跳转到显示所有信息的list.jsp页面;
2.前端代码修改
(1)所有输入框的name,改成v-model进行双向绑定
<input type="text" v-model="name"><br>
(2)用一个list对象存查询到所有type的list
<script>
let app = new Vue({
// 选择操作的div区域
el:"#app",
// 数据区
data:{
typeList:[],
},
// 方法区
methods:{
// 查询到所有的类型信息
queryTypes(){
axios.get("/day06/type/list/vue")
.then(response=>{
let resp = response.data;
console.log(resp);
this.typeList = resp.data;
})
}
},
// 文档加载之后就执行
created(){
this.queryTypes();
},
// 整个页面全部加载完成后再执行
mounted(){},
})
</script>
(3)在显示区域进行类型下拉框的显示【bug】—:value
<select v-model="typeId">
<option value="">请选择</option>
<%-- 这部分拼出来--%>
<%-- <option value="1">有限责任公司</option>--%>
<option v-for="type in typeList" :value="type.id">{{type.name}}</option>
</select>
【bug】遇到过的bug:value写成vlaue,没加冒号
同上,不太好找的bug
3.后端代码修改
此时需要补一个查询所有类型信息的servlet
/**
* 直接查询所有类型的list的servlet
*/
@WebServlet("/type/list/vue")
public class TypeListServlet extends HttpServlet {
IComTypeService typeService = new ComTypeServiceImpl();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 查询得到所有的类型
List<ComType> list = typeService.queryAll();
System.out.println(list);
resp.getWriter().write(JSON.toJSONString(
new ResData(200, "ok", list)
));
}
}
AddServlet.java文件改成resp方式
resp.getWriter().write(JSON.toJSONString(new ResData(200, "ok", null)));
4.前后端完整代码
(1)后端完整代码:AddServlet.java文件:
package com.tianju.servlet.company;
import com.alibaba.fastjson.JSON;
import com.tianju.entity.Company;
import com.tianju.entity.ResData;
import com.tianju.service.IComTypeService;
import com.tianju.service.ICompanyService;
import com.tianju.service.impl.ComTypeServiceImpl;
import com.tianju.service.impl.CompanyService;
import com.tianju.util.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* 新增公司信息的业务逻辑
* 目的是:接收从addCompMess.jsp传过来的信息;
* new Company 并存到数据库
*/
@WebServlet("/compMess/add")
public class AddServlet extends HttpServlet {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
private ICompanyService companyService = new CompanyService();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 新增一条数据到数据库
// 1.读取前端的值;
String name = req.getParameter("name");
String corporation = req.getParameter("corporation");
String typeId = req.getParameter("typeId");
String creditCode = req.getParameter("creditCode");
String createTime = req.getParameter("createTime");
String address = req.getParameter("address");
System.out.println(createTime);
// 2.判断是否为空;
if (StringUtils.isBlank(name)
|| StringUtils.isBlank(corporation)
|| StringUtils.isBlank(typeId)
|| StringUtils.isBlank(creditCode)
|| StringUtils.isBlank(createTime)
|| StringUtils.isBlank(address)){
resp.getWriter().write(JSON.toJSONString(
new ResData(1001, "输入为空", null)));
return;
}
// 3.new company实体类;
Company company = new Company();
company.setAddress(address);
company.setName(name);
company.setCorporation(corporation);
System.out.println(typeId);
company.setTypeId(Integer.parseInt(typeId));
company.setCreditCode(creditCode);
try {
company.setCreateTime(sdf.parse(createTime));
} catch (ParseException e) {
throw new RuntimeException(e);
}
// TODO:记录是谁操作的这条信息
company.setUserId(1);
// 4.新增数据到数据库;
Integer addFlag = companyService.add(company);
if (addFlag<1){
// 共享一条msg给前端,提醒一下
resp.getWriter().write(JSON.toJSONString(
new ResData(1002, "系统繁忙,请稍后重试", null)));
return;
}
// 5.重定向到list页面,显示更新后的公司信息
resp.getWriter().write(JSON.toJSONString(new ResData(200, "ok", null)));
}
}
(2)前端完整代码:addCompMess.jsp文件
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>新增公司信息</title>
<link rel="stylesheet" href="/day06/bootstrap/css/bootstrap.css">
<script src="/day06/js/jquery-3.5.1.js"></script>
<script src="/day06/bootstrap/js/bootstrap.js"></script>
<script src="/day06/js/vue.min-v2.5.16.js"></script>
<script src="/day06/js/axios.min.js"></script>
</head>
<body>
<div id="app">
<h1>新增公司信息</h1>
公司名:<input type="text" v-model="name"><br>
合伙人:<input type="text" v-model="corporation"><br>
公司类型:
<select v-model="typeId">
<option value="">请选择</option>
<%-- 这部分拼出来--%>
<%-- <option value="1">有限责任公司</option>--%>
<%-- TODO:忘记加冒号--%>
<option v-for="type in typeList" value="type.id">{{type.name}}</option>
</select>
<br>
统一信用编码:
<input type="text" v-model="creditCode"><br>
公司成立时间:
<input type="date" v-model="createTime"><br>
公司地址:<input type="text" v-model="address"><br>
<span style="color: darkred">{{msg}}</span><br>
<button @click="add">提交</button>
<button @click="reset">重置</button>
<hr>
<a href="/day06/compMess/listVue.jsp">返回</a>
</div>
<script>
let app = new Vue({
el:"#app",
data:{
name:"",
corporation:"",
typeId:"",
creditCode:"",
createTime:"",
address:"",
typeList:[],
msg:"",
},
// 方法区
methods:{
// 查询到所有的类型信息
queryTypes(){
axios.get("/day06/type/list/vue")
.then(response=>{
let resp = response.data;
console.log(resp);
this.typeList = resp.data;
})
},
// 添加数据
add(){
let params = new URLSearchParams();
params.append("name",this.name);
params.append("corporation",this.corporation);
params.append("typeId",this.typeId);
params.append("creditCode",this.creditCode);
params.append("createTime",this.createTime);
params.append("address",this.address);
axios.post("/day06/compMess/add",params)
.then(response=>{
let resp = response.data;
console.log(resp);
if (resp.code==200)
{
alert(resp.msg);
// 再回到list页面
location.href = "/day06/compMess/listVue.jsp";
}
else
{
this.msg=resp.msg;
}
})
},
reset(){
this.name="";
this.corporation="";
this.typeId="";
this.creditCode="";
this.createTime="";
this.address="";
this.msg="";
}
},
// 文档加载之后就执行
created(){
this.queryTypes();
},
// 整个页面全部加载完成后再执行
mounted(){},
})
</script>
</body>
</html>
修改一条数据
1.Jsp到Js+axios+vue的变化
在jsp模式下,修改一条数据的业务流程如下:
(1)在所有数据的页面,用户点击修改,向后端传要修改的id,由updatePage.java中的servlet进行处理;
(2)在该servlet中,把类型信息List查询出来,根据id查询出当前要修改的数据;
(3)把步骤(2)中的类型list和要修改的opus共享值,然后转发到updatePage.jsp前端页面;
(4)在修改的前端updatePage.jsp页面中,把原有的信息进行回显,其中类型的回显用type.id==opus.typeId ? ‘selected’ : ''三元表达式;由于修改的业务需要知道id号,所以在前端设置一个隐藏框,存放opus.id;当用户执行完修改操作后,把数据提交给update.java中的servlet进行处理;
(5)在update.java中,获取要修改的id,更新修改后的opus的相关数据,要进行权限的业务逻辑控制,从session中获取登陆的user对象,获得id,和查询出来的要修改的数据中的userId进行对比,如果不一致,则不允许修改;修改成功,则重定向到查询所有数据的servlet中;
(6)在查询所有数据的servlet中,再查一次数据库,然后把显示的数据共享转发给list.jsp,从而最终显示添加之后的数据;
在vue的异步请求模式下,修改一条数据的业务流程如下:
(1)在所有数据的list页面,用户点击修改按钮,跳转到修改页面,由于需要知道要修改的id,所以要把id想办法保存起来,有3种解决方案:
- [1].把 id 保存到local storage空间,在修改页面中获得保存的 id;
- [2].经过一次servlet,点击修改时,把id传给servlet后端,在该servlet中,共享该id,转发到修改页面jsp中,在修改页面update.jsp中用 id:${id}, 的方式获取id;
- [3].vue-cli路由的方式,后面补上【未完待续】
(2)在修改的update.jsp页面中,定义两个启动就执行的方法,[1].查询所有类型信息的方法;[2].查询要修改的opus数据的方法;
(3)启动页面就执行上面的方法,从而在updat.jsp页面中回显数据,其中类型的回显采用 :value=“types.id”,这里需要注意【注意】冒号不能少;value不要敲错;
(4)用户点击修改按钮,把id,修改后的数据传给后端,等待后端的响应;
(5)如果响应状态码为200,再跳转到显示所有信息的list.jsp页面;
【bug】遇到过的bug:value写成vlaue,没加冒号
同上,不太好找的bug
2.前端代码的修改
(0)要修改数据的id保存的问题 local storage 或者 过一次后端
[1].保存到local storage里面
在list页面,点击修改时,保存id到local storage
update(id){
// 1.把id存在local storage里
localStorage.setItem("id",id);
// 跳转到修改页面
location.href="/day06/compMess/update.jsp"
}
在修改页面拿到id:localStorage.getItem(“id”)
// 文档加载之后就执行
created(){
this.queryTypes();
this.queryMessById(localStorage.getItem("id"));
},
[2]过一次servlet
需要一个专门转发id到update.jsp页面的servlet,UpdateCompIdServlet.java;
package com.tianju.servlet.company;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 保存要修改的id,过一次servlet
* 点击修改,把 id 从list页面传过来
* servlet中共享id,转发到 update.jsp
*/
@WebServlet("/update/company/id")
public class UpdateCompIdServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String id = req.getParameter("id");
// 共享值,转发给update.jsp页面
req.setAttribute("id", id);
req.getRequestDispatcher("/compMess/update.jsp").forward(req,resp);
}
}
更改list页面点击修改按钮的事件:
update(id){
// // 1.把id存在local storage里
// localStorage.setItem("id",id);
// // 跳转到修改页面
// location.href="/day06/compMess/update.jsp"
// 2.把id交给后端的servlet,然后通过servlet给update.jsp页面
location.href="/day06/update/company/id?id="+id;
}
在update.jsp页面的数据区获得后端共享的id,“${id}”
data:{
typeList:[],
// 后端传来的查询到的company对象
companyDb:{},
msg:"",
// 获取经过一次servlet的id
id:"${id}",
},
根据这个id查询要修改的company实体类
// 文档加载之后就执行
created(){
this.queryTypes();
this.queryMessById(this.id);
},
(1)时间显示的问题----@JSONField(format = “yyyy-MM-dd”)
前端时间显示的问题,需要加注解,有一个坑,月份写法要规范,不能用小写mm,要用大写的MM,不然回显到前端的日期框会失效:
import com.alibaba.fastjson.annotation.JSONField;
@JSONField(format = "yyyy-MM-dd")
(2)类型下拉框回显的问题—v-model=“companyDb.typeId” + :value=“type.id”
之前用jsp写的时候,代码如下:
<select name="typeId">
<option value="">请选择</option>
<%-- 这部分拼出来--%>
<%-- <option value="1">有限责任公司</option>--%>
<c:forEach items="${types}" var="type">
<option value="${type.id}">${type.name}</option>
</c:forEach>
</select>
如果想要显示类型下拉框,需要改成vue的v-for的方式,如下:
<select name="typeId">
<option value="">请选择</option>
<option v-for="type in typeList" :value="type.id">{{type.name}}</option>
</select>
如果想要回显,把select框的name也双向绑定,绑定的是从后端查询到要修改的数据中的类型id, v-model=“companyDb.typeId”;
<select v-model="companyDb.typeId">
<option value="">请选择</option>
<option v-for="type in typeList" :value="type.id">{{type.name}}</option>
</select>
(3)点击重置的时候,重置哪些东西,除了id之外的其他值
reset(){
this.companyDb.name="";
this.companyDb.corporation="";
this.companyDb.typeId="";
this.companyDb.creditCode="";
this.companyDb.createTime="";
this.companyDb.address="";
this.msg="";
}
3.后端代码的修改
(1)由于前端有时间框,因此后端实体类加注解
前端时间显示的问题,需要加注解,有一个坑,月份写法要规范,不能用小写mm,要用大写的MM,不然回显到前端的日期框会失效:
import com.alibaba.fastjson.annotation.JSONField;
@JSONField(format = "yyyy-MM-dd")
package com.tianju.entity;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* 公司信息的实体类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Company {
private Integer id;
private String name;
private Integer userId;
private String username;
private Integer typeId;
private String typename;
private String corporation;
private String creditCode; // 工商号
private String address;
@JSONField(format = "yyyy-MM-dd")
private Date createTime; // 公司的创建时间
@JSONField(format = "yyyy-MM-dd")
private Date updateTime; // 这条信息的修改时间
}
4.前后端完整代码–loacal storage版本
(1)前端list.jsp页面相关代码:
update(id){
// 1.把id存在local storage里
localStorage.setItem("id",id);
// 跳转到修改页面
location.href="/day06/compMess/update.jsp"
}
(2)update.jsp代码
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改公司信息</title>
<link rel="stylesheet" href="/day06/bootstrap/css/bootstrap.css">
<script src="/day06/js/axios.min.js"></script>
<script src="/day06/js/jquery-3.5.1.js"></script>
<script src="/day06/bootstrap/js/bootstrap.js"></script>
<script src="/day06/js/vue.min-v2.5.16.js"></script>
</head>
<body>
<div id="app">
<h1>修改公司信息</h1>
公司名:<input type="text" v-model="companyDb.name"><br>
合伙人:<input type="text" v-model="companyDb.corporation"><br>
公司类型:
<select v-model="companyDb.typeId">
<option value="">请选择</option>
<option v-for="type in typeList" :value="type.id">{{type.name}}</option>
</select>
<br>
统一信用编码:
<input type="text" v-model="companyDb.creditCode"><br>
公司成立时间:
<input type="date" v-model="companyDb.createTime"><br>
公司地址:<input type="text" v-model="companyDb.address"><br>
<span style="color: darkred">{{msg}}</span><br>
<button @click="update">修改</button>
<button @click="reset">重置</button>
<hr>
<a href="/day06/company/messList">返回</a>
</div>
<script>
let app = new Vue({
// 选择操作的div区域
el:"#app",
// 数据区
data:{
typeList:[],
// 后端传来的查询到的company对象
companyDb:{},
msg:"",
},
// 方法区
methods:{
// 查询所有类型的方法
queryTypes(){
axios.get("/day06/type/list/vue")
.then(response=>{
let resp = response.data;
console.log(resp);
this.typeList = resp.data;
})
},
// 根据id查询出要修改的公司信息
queryMessById(id){
axios.get("/day06/company/updatePage?id="+id)
.then(response=>{
let resp = response.data;
console.log(resp);
if (resp.code==200)
{
this.companyDb = resp.data;
}
else
{
this.msg = resp.msg;
}
})
},
// 点击修改按钮,传给后端,进行修改
update(){
let params = new URLSearchParams();
params.set("name",this.companyDb.name);
params.set("corporation",this.companyDb.corporation);
params.set("typeId",this.companyDb.typeId);
params.set("creditCode",this.companyDb.creditCode);
params.set("createTime",this.companyDb.createTime);
params.set("address",this.companyDb.address);
params.set("id",this.companyDb.id);
axios.post("/day06/compMess/update",params)
.then(response=>{
let resp = response.data;
console.log(resp);
if (resp.code==200)
{
// 成功,跳转回到list页面
location.href="/day06/compMess/listVue.jsp"
}
else
{
this.msg = resp.msg;
}
})
},
reset(){
this.companyDb.name="";
this.companyDb.corporation="";
this.companyDb.typeId="";
this.companyDb.creditCode="";
this.companyDb.createTime="";
this.companyDb.address="";
this.msg="";
}
},
// 文档加载之后就执行
created(){
this.queryTypes();
this.queryMessById(localStorage.getItem("id"));
},
// 整个页面全部加载完成后再执行
mounted(){
},
})
</script>
</body>
</html>
(3)后端updatePageServlet.java代码
package com.tianju.servlet.company;
import com.alibaba.fastjson.JSON;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.tianju.entity.Company;
import com.tianju.entity.ResData;
import com.tianju.service.IComTypeService;
import com.tianju.service.ICompanyService;
import com.tianju.service.impl.ComTypeServiceImpl;
import com.tianju.service.impl.CompanyService;
import com.tianju.util.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 修改页面的servlet:
* 目的是把已有的信息,查询,返回给修改页面;
* 也要共享一下类型信息
*/
@WebServlet("/company/updatePage")
public class UpdatePagServlet extends HttpServlet {
private ICompanyService companyService = new CompanyService();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.从前端获取修改的id
String id = req.getParameter("id");
System.out.println(id);
// 2.判断不为空;
if (StringUtils.isBlank(id)){
resp.getWriter().write(JSON.toJSONString(new ResData(1001, "未能获取要修改的公司id", null)));
return;
}
// 3.查询出一条信息;
Company companyDb = companyService.queryById(Integer.parseInt(id));
if (companyDb==null){
resp.getWriter().write(JSON.toJSONString(new ResData(1001, "未能根据公司id查询到公司信息", null)));
return;
}
System.out.println(companyDb);
resp.getWriter().write(JSON.toJSONString(new ResData(200, "ok", companyDb)));
}
}
(4)后端updateServlet.java代码
package com.tianju.servlet.company;
import com.alibaba.fastjson.JSON;
import com.tianju.entity.Company;
import com.tianju.entity.ResData;
import com.tianju.service.ICompanyService;
import com.tianju.service.impl.CompanyService;
import com.tianju.util.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* 修改公司信息的servlet
* 目的是:从前端获取要修改的信息;
* 执行修改操作
*/
@WebServlet("/compMess/update")
public class UpdateServlet extends HttpServlet {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
private ICompanyService companyService = new CompanyService();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取要修改的id,和其他信息,更新数据库,再重定向到list页面
// 1.从前端获取信息;
String name = req.getParameter("name");
String corporation = req.getParameter("corporation");
String typeId = req.getParameter("typeId");
String creditCode = req.getParameter("creditCode");
String createTime = req.getParameter("createTime");
String address = req.getParameter("address");
// 要修改的id;
String id = req.getParameter("id");
// 2.判断不为空;
if (StringUtils.isBlank(name) || StringUtils.isBlank(corporation)
|| StringUtils.isBlank(typeId) || StringUtils.isBlank(creditCode)
|| StringUtils.isBlank(createTime) || StringUtils.isBlank(address) || StringUtils.isBlank(id)
){
// 共享一条msg给前端,提醒一下
resp.getWriter().write(JSON.toJSONString(new ResData(1001, "输入为空,请输全公司信息", null)));
return;
}
// 3.new company;
Company company = new Company();
company.setAddress(address);
company.setName(name);
company.setCorporation(corporation);
company.setTypeId(Integer.parseInt(typeId));
company.setCreditCode(creditCode);
try {
company.setCreateTime(sdf.parse(createTime));
} catch (ParseException e) {
throw new RuntimeException(e);
}
// TODO:记录是谁操作的这条信息
company.setUserId(1);
// 公司信息的id
company.setId(Integer.parseInt(id));
// 4.进行修改;
Integer updateFlag = companyService.update(company);
if (updateFlag<1){
// 共享一条msg给前端,提醒一下
resp.getWriter().write(JSON.toJSONString(new ResData(1002, "修改失败,系统繁忙,请稍后重试", null)));
return;
}
resp.getWriter().write(JSON.toJSONString(new ResData(200, "ok", null)));
}
}
4.前后端完整代码—过一遍servlet版本
(1)前端list.jsp页面相关代码:
update(id){
// // 1.把id存在local storage里
// localStorage.setItem("id",id);
// // 跳转到修改页面
// location.href="/day06/compMess/update.jsp"
// 2.把id交给后端的servlet,然后通过servlet给update.jsp页面
location.href="/day06/update/company/id?id="+id;
}
专门给update.jsp转发id的servlet:updateCompIdServlet.java
package com.tianju.servlet.company;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 保存要修改的id,过一次servlet
* 点击修改,把 id 从list页面传过来
* servlet中共享id,转发到 update.jsp
*/
@WebServlet("/update/company/id")
public class UpdateCompIdServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String id = req.getParameter("id");
// 共享值,转发给update.jsp页面
req.setAttribute("id", id);
req.getRequestDispatcher("/compMess/update.jsp").forward(req,resp);
}
}
(2)前端update.jsp页面代码
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改公司信息</title>
<link rel="stylesheet" href="/day06/bootstrap/css/bootstrap.css">
<script src="/day06/js/axios.min.js"></script>
<script src="/day06/js/jquery-3.5.1.js"></script>
<script src="/day06/bootstrap/js/bootstrap.js"></script>
<script src="/day06/js/vue.min-v2.5.16.js"></script>
</head>
<body>
<div id="app">
<h1>修改公司信息</h1>
公司名:<input type="text" v-model="companyDb.name"><br>
合伙人:<input type="text" v-model="companyDb.corporation"><br>
公司类型:
<select v-model="companyDb.typeId">
<option value="">请选择</option>
<option v-for="type in typeList" :value="type.id">{{type.name}}</option>
</select>
<br>
统一信用编码:
<input type="text" v-model="companyDb.creditCode"><br>
公司成立时间:
<input type="date" v-model="companyDb.createTime"><br>
公司地址:<input type="text" v-model="companyDb.address"><br>
<span style="color: darkred">{{msg}}</span><br>
<button @click="update">修改</button>
<button @click="reset">重置</button>
<hr>
<a href="/day06/company/messList">返回</a>
</div>
<script>
let app = new Vue({
// 选择操作的div区域
el:"#app",
// 数据区
data:{
typeList:[],
// 后端传来的查询到的company对象
companyDb:{},
msg:"",
// 获取经过一次servlet的id
id:"${id}",
},
// 方法区
methods:{
// 查询所有类型的方法
queryTypes(){
axios.get("/day06/type/list/vue")
.then(response=>{
let resp = response.data;
console.log(resp);
this.typeList = resp.data;
})
},
// 根据id查询出要修改的公司信息
queryMessById(id){
axios.get("/day06/company/updatePage?id="+id)
.then(response=>{
let resp = response.data;
console.log(resp);
if (resp.code==200)
{
this.companyDb = resp.data;
}
else
{
this.msg = resp.msg;
}
})
},
// 点击修改按钮,传给后端,进行修改
update(){
let params = new URLSearchParams();
params.set("name",this.companyDb.name);
params.set("corporation",this.companyDb.corporation);
params.set("typeId",this.companyDb.typeId);
params.set("creditCode",this.companyDb.creditCode);
params.set("createTime",this.companyDb.createTime);
params.set("address",this.companyDb.address);
params.set("id",this.companyDb.id);
axios.post("/day06/compMess/update",params)
.then(response=>{
let resp = response.data;
console.log(resp);
if (resp.code==200)
{
// 成功,跳转回到list页面
location.href="/day06/compMess/listVue.jsp"
}
else
{
this.msg = resp.msg;
}
})
},
reset(){
this.companyDb.name="";
this.companyDb.corporation="";
this.companyDb.typeId="";
this.companyDb.creditCode="";
this.companyDb.createTime="";
this.companyDb.address="";
this.msg="";
}
},
// 文档加载之后就执行
created(){
this.queryTypes();
this.queryMessById(this.id);
},
// 整个页面全部加载完成后再执行
mounted(){
},
})
</script>
</body>
</html>
(3)该版本的后端updatePageServlet.java代码 和 updateServlet.java代码同local storage版本
删除一条数据
1.Jsp到Js+axios+vue的变化
jsp版本的删除一条数据的业务逻辑
(1)在list页面点击删除,传给后端要删除的id,进行权限确定,
(2)删除成功后,再查数据库,共享,转发到list页面;
vue版本的删除一条数据的流程
(1)在list页面点击删除,触发点击事件;
(2)在后端进行删除业务,前端等待后端的响应;
(3)如果响应状态码是200,更新一下list页面的数据;
2.前端代码修改
在list页面给删除按钮绑定一个事件
// 删除数据的事件
remove(id){
axios.get("/day06/company/remove?id="+id)
.then(response=>{
let resp = response.data;
console.log(resp);
if (resp.code==200)
{
// 删除成功,再查第一页数据
alert("成功");
this.queryListByPageNum(1);
}
else
{
alert(resp.msg)
}
})
}
3.后端代码修改
由于不涉及到权限的问题,所以代码比较简单
@WebServlet("/company/remove")
public class CompanyRemove extends HttpServlet {
private ICompanyService companyService = new CompanyService();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 进行删除
String id = req.getParameter("id");
companyService.deleteById(Integer.parseInt(id));
resp.getWriter().write(JSON.toJSONString(new ResData(200, "ok", null)));
}
}
4.前后端完整代码–需要权限的例子
(1)前端删除事件代码:
remove(id){
axios.get("/day06/opus/remove/vue?id="+id)
.then(response=>{
console.log(response.data)
let resp = response.data;
if (resp.code==200)
{
alert("成功");
// 继续查数据库,渲染列表部分
this.queryList(1);
}
else
{
alert(resp.msg)
}
})
},
(2)后端删除业务代码,权限控制
package com.tianju.servlet.opus;
import com.alibaba.fastjson.JSON;
import com.tianju.entity.Opus;
import com.tianju.entity.ResData;
import com.tianju.entity.User;
import com.tianju.service.IOpusService;
import com.tianju.service.impl.OpusServiceImpl;
import com.tianju.util.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* 删除一本书
*/
@WebServlet("/opus/remove/vue")
public class RemoveServletVue extends HttpServlet {
private IOpusService opusService = new OpusServiceImpl();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取要删除的id
String id = req.getParameter("id");
System.out.println(id);
// 判断输入不为空
if (StringUtils.isBlank(id)){
System.out.println("id为空");
return;
}
// TODO:控制权限
HttpSession session = req.getSession();
User user = (User) session.getAttribute("user");
// 根据id查一条图书信息出来
Opus find = opusService.queryById(Integer.parseInt(id));
if (!find.getAuthorId().equals(user.getId())){
// 如果修改的 人的id 修改的 不是自己 名下的 就不能修改
System.out.println("没有权限");
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(JSON.toJSONString(new ResData(3001, "不能删除别人", null)));
return;
}
// 执行删除操作
opusService.removeById(Integer.parseInt(id));
resp.getWriter().write(JSON.toJSONString(new ResData(200, "删除成功", null)));
}
}
总结
从同步到异步 & 从jsp 到 js + axios + vue 实现 数据分页显示 & 数据增删改查