一、工具版本
编写java代码:IdeaIU-2021.1.3
管理项目依赖:Maven-3.8.3
管理项目文件:Git-2.34.1
关系型数据库:Mysql-8.0.27
二、项目搭建
1.创建MySQL数据库
USE game_web;
CREATE TABLE game_introduce(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10) NOT NULL UNIQUE,
type VARCHAR(9),
creation_time DATE,
insert_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
description VARCHAR(70),
address VARCHAR(50)
);
INSERT INTO game_introduce (
name,
type,
creation_time,
description,
address
) VALUES(
"植物大战僵尸",
"策略小游戏",
"2012-03-23",
"一个看似简单实则极富策略性的小游戏,可怕的僵尸即将
入侵你的家园,您唯一的防御方式就是您栽种的植物。",
"http://www.4399.com/flash/18012.htm"
);
SELECT * FROM game_introduce;
2.设计Maven目录结构
3.编写复制Element页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Display</title>
<style lang="scss">
</style>
</head>
<body>
<div id="display">
<!--对表单的操作-->
<el-form :inline="true" :model="introduce" class="demo-form-inline" >
<el-form-item>
<el-button id="allDelete" type="danger" plain @click="handleBulkDelete">批量删除</el-button>
<el-button id="insert" type="primary" plain @click="dialogVisible = true">新增</el-button>
</el-form-item>
<el-form-item label="游戏名" id="gameQuery" class="text">
<el-input v-model="introduce.name" placeholder="游戏名"></el-input>
</el-form-item>
<el-form-item label="游戏描述" id="descQuery" class="text">
<el-input v-model="introduce.description" placeholder="游戏描述"></el-input>
</el-form-item>
<el-form-item>
<el-button class="button" type="info" @click="handleRetrieval" round>查询</el-button>
</el-form-item>
</el-form>
<!--列表展示-->
<template>
<el-table
ref="singleTable"
:data="tableList"
highlight-current-row
:header-cell-style="{background:'#11ffee00',color:'#adff2f'}"
style="width: 100%"
@selection-change="handleSelectChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
type="index"
width="50">
</el-table-column>
<el-table-column
prop="name"
label="游戏名"
width="120"
align="center">
</el-table-column>
<el-table-column
id="filter"
prop="type"
label="类型"
width="100"
align="center"
:filters="[ ]"
:filter-method="filterTag"
filter-placement="bottom-end">
<template slot-scope="scope">
<el-tag
:type=" "
disable-transitions>{{scope.row.type}}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="creationTime"
label="创作时间"
sortable
width="180"
align="center">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.creationTime }}</span>
</template>
</el-date-picker>
</el-table-column>
<el-table-column
label="描述"
prop="description"
width="200"
align="center">
</el-table-column>
<el-table-column
label="操作"
width="200"
align="center">
<template slot-scope="scope">
<el-button
class="button"
size="mini"
@click="handleUpdate(scope.row)">编辑</el-button>
<el-button
class="button"
size="mini"
type="danger"
@click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--分页工具条-->
<el-pagination v-if="paginationShow"
class="page"
align="center"
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.currentPage"
:page-size=""
:page-sizes="[ ]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total">
</el-pagination>
</template>
<!--新增表单-->
<el-dialog
title="新增游戏"
:visible.sync="dialogVisible"
width="30%">
<el-form ref="form" :model="introduce" label-width="80px">
<el-form-item label="游戏名">
<el-input v-model="introduce.name"></el-input>
</el-form-item>
<el-form-item label="游戏类型">
<el-select v-model="introduce.type" placeholder="请选择游戏类型">
<el-option label=" " value=" "></el-option>
</el-select>
</el-form-item>
<el-form-item label="创作时间">
<el-col :span="11">
<el-date-picker type="date" placeholder="选择时间" v-model="introduce.creationTime" style="width: 100%;"></el-date-picker>
</el-col>
</el-form-item>
<el-form-item label="游戏网址">
<el-input placeholder="请输入网址" v-model="introduce.address">
<template slot="prepend">https://</template>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
</el-form-item>
<el-form-item label="游戏描述">
<el-input type="textarea" v-model="introduce.description"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleAdd">立即创建</el-button>
<el-button :plain="true" @click="cancelAdd">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
<!--编辑表单-->
<el-dialog
title="编辑游戏"
:visible.sync="updateVisible"
width="30%">
<el-form ref="form" :model="formData" label-width="80px">
<el-form-item label="游戏名" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="游戏类型" prop="type">
<el-select v-model="formData.type" placeholder="请选择游戏类型">
<el-option label=" " value=""></el-option>
</el-select>
</el-form-item>
<el-form-item label="创作时间" prop="creationTime">
<el-col :span="11">
<el-date-picker type="date" placeholder="选择时间" v-model="formData.creationTime" style="width: 100%;"></el-date-picker>
</el-col>
</el-form-item>
<el-form-item label="游戏网址" prop="address">
<el-input placeholder="请输入网址" v-model="formData.address">
<template slot="prepend">https://</template>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
</el-form-item>
<el-form-item label="游戏描述" prop="description">
<el-input type="textarea" v-model="formData.description"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleEdit">确认修改</el-button>
<el-button :plain="true" @click="cancelUpdate">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
<!--AJAX 异步JavaScript和XML-->
<script src="../js/axios-0.18.0.js"></script>
<!--Vue 前端框架 免除了HTML中DOM的操作-->
<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>
new Vue({
el:"#display",
created(){
this.query();
},
data() {
return {
introduce: {
id: '',
name: '',
type: '',
creationTime: '',
description: '',
address: ''
},
multipleSelection: [],
introduceIds: [],
tableList: [],
formData: {},
paginationShow: true,
pagination: { //分页模型数据
currentPage: 1,
pageSize: 4,
total: 0
},
dialogVisible: false,
updateVisible: false
}
},
methods: {
query() {
},
handleAdd() {
},
cancelAdd(){
},
handleRetrieval(){
},
handleSelectChange(val){
this.multipleSelection = val;
},
handleBulkDelete() {
},
handleUpdate(row) {
},
handleEdit(){
},
cancelUpdate(){
},
handleDelete(row) {
},
handleSizeChange(val) {
},
handleCurrentChange(val) {
},
filterTag(value, row) {
return row.tag === value;
},
filterHandler(value, row, column) {
const property = column['property'];
return row[property] === value;
}
}
})
</script>
</body>
</html>
4.创建实体类使用注解将类属性对应数据列
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("game_introduce")
public class Introduce {
//@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private String type;
@TableField(value = "creation_time")
private Date creationTime;
@TableField(value = "insert_time")
private Date insertTime;
private String description;
private String address;
}
三、三层架构及测试
1.mapper层通过继承Mybatis-plus提供的BaseMapper直接简化开发
@Mapper
public interface IntroduceMapper extends BaseMapper<Introduce> {
}
2.在测试类中,通过Spring提供的依赖注入实现对继承后的接口的测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class IntroduceDaoTest {
@Autowired
private IntroduceMapper mapper;
@Test
public void testInsert(){
Introduce introduce = new Introduce();
introduce.setName("二战前线");
introduce.setType("射击小游戏");
introduce.setCreationTime(null);
introduce.setDescription("这次的二战前线版本的游戏是最无敌的!可以随意调关卡、武器全开、血无限。还有什么比这爽的?!速速来体验吧!");
introduce.setAddress("http://www.4399.com/flash/21674_3.htm");
System.out.println(mapper.insert(introduce));
System.out.println(introduce.getId());
}
@Test
public void testUpdateById(){
Introduce introduce = new Introduce();
introduce.setId(29);
introduce.setDescription("这次的二战前线版本的游戏是最无敌的!可以随意调关卡、武器全开、血无限。还有什么比这爽的?!速速来体验吧!");
mapper.updateById(introduce);
}
@Test
public void testUpdate1(){
Introduce introduce = new Introduce();
introduce.setName("无敌二战前线");
QueryWrapper<Introduce> wrapper = new QueryWrapper<>();
wrapper.eq("id",29);
//UPDATE game_introduce SET name = "无敌二战前线" WHERE id = 29;
System.out.println(mapper.update(introduce, wrapper));
}
@Test
public void testUpdate2(){
UpdateWrapper<Introduce> wrapper = new UpdateWrapper<>();
wrapper.eq("id",29).set("name","无敌");
System.out.println(mapper.update(null, wrapper));
}
@Test
public void testDeleteById(){
System.out.println(mapper.deleteById(29));
}
@Test
public void testDeleteByMap(){
HashMap<String,Object> columnMap = new HashMap<>();
columnMap.put("name","无敌二战前线");
columnMap.put("creation_time","2009-12-29");
//DELETE FROM game_introduce WHERE name = ? AND creation_time = ?
/*
QueryWrapper<Introduce> wrapper = new QueryWrapper<>(introduce);
mapper.delete(wrapper);
*/
System.out.println(mapper.deleteByMap(columnMap));
}
@Test
public void testDeleteBatchIds() {
//DELETE FROM game_introduce WHERE id IN ( ? , ? , ? )
int[] data = {34,35};
List<Integer> list = Arrays.stream(data).boxed().collect(Collectors.toList());
int result = mapper.deleteBatchIds(list);
System.out.println("result = " + result);
}
@Test
public void testSelectById(){
System.out.println(mapper.selectById(1));
}
@Test
public void testSelectList(){
List<Introduce> users = mapper.selectList(null);
for (Introduce introduce : users) {
System.out.println(introduce);
}
}
@Test
public void testSelectOne(){
//根据条件查询一条数据,如果结果超过一条会报错
QueryWrapper<Introduce> wrapper = new QueryWrapper<>();
wrapper.eq("name","植物大战僵尸");
System.out.println(mapper.selectOne(wrapper));
}
@Test
public void testSelectCount(){
QueryWrapper wrapper = new QueryWrapper();
wrapper.gt("id",25);
//SELECT COUNT( 1 ) FROM game_introduce WHERE id > ?
System.out.println(mapper.selectCount(wrapper));
}
@Test
public void testSelectPage(){
QueryWrapper<Introduce> wrapper = new QueryWrapper<>();
wrapper.gt("id",25);
IPage<Introduce> page = new Page<>(2,2);
IPage<Introduce> iPage = mapper.selectPage(page, wrapper);
System.out.println("数据总条数:" + iPage.getTotal());
System.out.println("总页数:" + iPage.getPages());
List<Introduce> introduces = iPage.getRecords();
//SELECT * FROM game_introduce WHERE id > ? LIMIT ?,?
for (Introduce introduce : introduces) {
System.out.println("introduce = " + introduce);
}
}
@Test
public void testLimitByCondition(){
QueryWrapper<Introduce> wrapper = new QueryWrapper<>();
wrapper.like("name","切").or().
like("description","大鱼吃小鱼");
IPage<Introduce> page = new Page<>(1,5);
List<Introduce> Introduces = mapper.selectPage(page, wrapper).getRecords();
for (Introduce introduce : Introduces) {
System.out.println(introduce);
}
}
@Test
public void testLike(){
QueryWrapper<Introduce> wrapper = new QueryWrapper<>();
wrapper.like("name","切");
List<Introduce> introduces = mapper.selectList(wrapper);
//SELECT * FROM game_introduce WHERE name LIKE ?
//parameter %切%
for (Introduce introduce : introduces) {
System.out.println("introduce = " + introduce);
}
}
@Test
public void testOrder(){
QueryWrapper<Introduce> wrapper = new QueryWrapper<>();
//SELECT * FROM game_introduce ORDER BY creation_time DESC
wrapper.orderByDesc("creation_time");
List<Introduce> introduces = mapper.selectList(wrapper);
for (Introduce introduce : introduces) {
System.out.println(introduce);
}
}
@Test
public void testAnd(){
QueryWrapper<Introduce> wrapper = new QueryWrapper<>();
//SELECT * FROM game_introduce WHERE name = ? AND creation_time = ?
wrapper.eq("name","保卫萝卜").eq("creation_time","2013-07-12");
List<Introduce> introduces = mapper.selectList(wrapper);
for (Introduce introduce : introduces) {
System.out.println(introduce);
}
}
@Test
public void testOr(){
QueryWrapper<Introduce> wrapper = new QueryWrapper<>();
//SELECT id,type FROM game_introduce WHERE name = "保卫萝卜" or creation_time = "2009-05-10"
wrapper.eq("name","保卫萝卜")
.or()
.eq("creation_time","2009-05-10")
.select("id","type");
List<Introduce> introduces = mapper.selectList(wrapper);
for (Introduce introduce : introduces) {
System.out.println(introduce);
}
}
@Test
public void testGetPage(){
IPage page = new Page(1,5);
List list = mapper.selectPage(page, null).getRecords();
for (Object l : list) {
System.out.println(l);
}
}
}
3.service层先定义接口后实现,为数据层,服务层,业务层解耦合
@Service
public class IntroduceServiceImpl implements IntroduceService {
@Autowired
private IntroduceMapper mapper;
@Override
public Boolean add(Introduce introduce) {
return mapper.insert(introduce) > 0;
}
@Override
public Boolean remove(Integer id) {
return mapper.deleteById(id) > 0;
}
@Override
public Boolean remove(Integer[] ids) {
List<Integer> idList = Arrays.asList(ids);
return mapper.deleteBatchIds(idList) > 0;
}
@Override
public Boolean modify(Introduce introduce) {
return mapper.updateById(introduce) > 0;
}
@Override
public List<Introduce> list() {
return mapper.selectList(null);
}
@Override
public Introduce query(Integer id) {
return mapper.selectById(id);
}
@Override
public List<Introduce> query(Introduce introduce) {
return mapper.selectList(new QueryWrapper(introduce));
}
@Override
public IPage<Introduce> getPage(Integer currentPage, Integer pageSize){
IPage<Introduce> page = new Page<>(currentPage,pageSize);
return mapper.selectPage(page,null);
}
@Override
public IPage<Introduce> LimitByCondition(Integer currentPage, Integer PageSize, Introduce introduce) {
String name = introduce.getName();
String description = introduce.getDescription();
QueryWrapper<Introduce> wrapper = new QueryWrapper<>();
if (name.length() != 0 && description.length() != 0) {
wrapper.like("name",name).or().
like("description",description);
} else if (name.length() == 0 && description.length() != 0) {
wrapper.like("description",description);
} else if (name.length() != 0) {
wrapper.like("name", name);
} else {
wrapper = null;
}
IPage<Introduce> page = new Page<>(currentPage,PageSize);
return mapper.selectPage(page,wrapper);
}
}
4.也可使用MyBatisPlus提供有业务层通用接口(ISerivce)与业务层通用实现类(ServiceImpl)快速开发
public interface IntroduceService extends IService<Introduce> {
//追加的操作与原始操作通过名称区分,功能类似
Boolean delete(Integer id);
Boolean insert(Introduce introduce);
Boolean modify(Introduce introduce);
Introduce get(Integer id);
}
@Service
public class IntroduceServiceImpl extends ServiceImpl<IntroduceMapper,Introduce> implements IntroduceService {
}
5.当对页面进行分页操作时,创建MybatisPlus配置类,添加分页插件或Mp拦截器
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件
*/
/*@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
*/
@Bean
public MybatisPlusInterceptor mpInterceptor() {
//1.定义Mp拦截器
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2.添加具体的拦截器
mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mpInterceptor;
}
}
5.对编写好的service层通过依赖注入进行测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class IntroduceServiceTest {
@Autowired
private IntroduceService service;
@Test
public void testAdd(){
Introduce introduce = new Introduce();
introduce.setName("35y6s");
introduce.setType("hufa小游戏");
introduce.setDescription("好好玩呀快来玩呀");
System.out.println(service.add(introduce));
}
@Test
public void testRemove1(){
System.out.println(service.remove(38));
}
@Test
public void testRemove2(){
Integer[] ref = {39,40};
System.out.println(service.remove(ref));
}
@Test
public void testModify(){
Introduce introduce = new Introduce();
introduce.setId(58);
introduce.setName("huang");
introduce.setCreationTime(new Date(2022-03-22));
introduce.setDescription("wefqwfsac");
introduce.setAddress("好玩");
System.out.println(service.modify(introduce));
}
@Test
public void query1(){
List<Introduce> introduces = service.list();
for (Introduce introduce : introduces) {
System.out.println(introduce);
}
}
@Test
public void query2(){
System.out.println(service.query(1));
}
@Test
public void testGetPage(){
List<Introduce> introduces = service.getPage(0, 5).getRecords();
for (Introduce introduce : introduces) {
System.out.println(introduce);
}
}
@Test
public void testLimitByCondition(){
Introduce introduce = new Introduce();
introduce.setName("切");
introduce.setDescription(null);
List<Introduce> introduces = service.LimitByCondition(1, 5, introduce).getRecords();
for (Introduce introduce1 : introduces) {
System.out.println(introduce1);
}
}
}
6.设计统一的返回值结果类型便于前端开发读取数据
@Data
@NoArgsConstructor
@AllArgsConstructor
public class R {
private Boolean flag;
private Object data;
public R(Boolean flag) {
this.flag = flag;
}
}
7.controller层使用Restful风格编写,注解增Post删Delete改Put查Get
@RestController
@RequestMapping("/introduces")
public class IntroduceController {
@Autowired
private IntroduceService service;
@PostMapping
public R save(@RequestBody Introduce introduce) {
return new R(service.add(introduce));
}
@DeleteMapping("/{id}")
public R delete(@PathVariable Integer id) {
return new R(service.remove(id));
}
@DeleteMapping("ordinal/{ids}")
public R delete(@PathVariable Integer[] ids) {
return new R(service.remove(ids));
}
@PutMapping
public R update(@RequestBody Introduce introduce) {
return new R(service.modify(introduce));
}
@GetMapping
public R list() {
return new R(true, service.list());
}
@GetMapping("/{id}")
public R query(@PathVariable Integer id) {
return new R(true, service.query(id));
}
/*
@PostMapping
public R query(@RequestBody Introduce introduce){
List<Introduce> introduces = service.query(introduce);
Boolean flag = introduces != null;
return new R(flag,introduces);
}
*/
@GetMapping("/{currentPage}/{pageSize}")
public R limit(@PathVariable Integer currentPage, @PathVariable Integer pageSize) {
IPage<Introduce> page = service.getPage(currentPage, pageSize);
return new R(null != page, page);
}
@PostMapping("/{currentPage}/{pageSize}")
public R conditionLimit(@PathVariable Integer currentPage, @PathVariable Integer pageSize, @RequestBody Introduce introduce) {
IPage<Introduce> page = service.LimitByCondition(currentPage, pageSize, introduce);
return new R(null != page,page);
}
}
四、前后端协议联调
1.前后端分离结构设计,页面归属前端服务器,通过ElementUI提供的触发事件与异步通信框架axios实现页面展示及功能作用,单体工程中页面放置在resources目录下的static目录中
2.页面数据补充
<el-table-column
id="filter"
prop="type"
label="类型"
width="100"
align="center"
:filters="[ { text: '策略', value: '策略小游戏' },
{ text: '休闲', value: '休闲小游戏' },
{ text: '体育', value: '体育小游戏' },
{ text: '冒险', value: '冒险小游戏' },
{ text: '动作', value: '动作小游戏' },
{ text: '射击', value: '射击小游戏' },
{ text: '敏捷', value: '敏捷小游戏' },
{ text: '棋牌', value: '棋牌小游戏' },
{ text: '益智', value: '益智小游戏' }]"
:filter-method="filterTag"
filter-placement="bottom-end">
<template slot-scope="scope">
<el-tag
:type="scope.row.type === '敏捷小游戏' ? '' :
scope.row.type === '益智小游戏' ? 'danger' :
scope.row.type === '射击小游戏' ? 'success' :
scope.row.type === '动作小游戏' ? 'success' :
scope.row.type === '休闲小游戏' ? 'info' :
scope.row.type === '体育小游戏' ? 'info' : 'warning'"
disable-transitions>{{scope.row.type}}
</el-tag>
</template>
</el-table-column>
<el-pagination v-if="paginationShow"
class="page"
align="center"
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.currentPage"
:page-size="4"
:page-sizes="[4, 8, 12, 16]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total">
</el-pagination>
<el-select v-model="introduce.type" placeholder="请选择游戏类型">
<el-option label="休闲" value="休闲小游戏"></el-option>
<el-option label="体育" value="体育小游戏"></el-option>
<el-option label="冒险" value="冒险小游戏"></el-option>
<el-option label="动作" value="动作小游戏"></el-option>
<el-option label="射击" value="射击小游戏"></el-option>
<el-option label="敏捷" value="敏捷小游戏"></el-option>
<el-option label="棋牌" value="棋牌小游戏"></el-option>
<el-option label="益智" value="益智小游戏"></el-option>
<el-option label="策略" value="策略小游戏"></el-option>
</el-select>
3.触发事件
methods: {
query() {
axios.get("/introduces/" + this.pagination.currentPage + "/" + this.pagination.pageSize).then((res)=>{
this.pagination.total = res.data.data.total;
this.tableList = res.data.data.records;
})
},
handleAdd() {
axios.post("/introduces",this.introduce).then((res)=>{
if(res.data.flag){
this.dialogVisible = false;
this.$message.success("添加成功");
}else{
this.$message.error("添加失败");
}
}).finally(()=>{
this.query();
});
},
cancelAdd(){
this.dialogVisible = false;
this.$message({
message: '已取消创建',
center: true
});
},
handleRetrieval(){
axios.post("/introduces/" + this.pagination.currentPage + "/" + this.pagination.pageSize, this.introduce).then((res)=>{
this.pagination.total = res.data.data.total;
this.tableList = res.data.data.records;
})
},
handleSelectChange(val){
this.multipleSelection = val;
},
handleBulkDelete() {
this.$confirm('此操作将删除所选所有数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//创建id数组
for (let i = 0; i < this.multipleSelection.length; i++) {
let selectionElement = this.multipleSelection[i];
this.introduceIds[i] = selectionElement.id;
}
axios.delete("/introduces/ordinal/" + this.introduceIds).then((res) =>{
if(res.data.flag){
this.query();
this.$message({
message: '已全部删除',
type: 'success'
});
}
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
handleUpdate(row) {
axios.get("/introduces/" + row.id).then((res)=>{
//确保数据同步
if(res.data.flag && res.data.data != null){
this.updateVisible = true;
this.formData = res.data.data;
}else{
this.$message.error("数据同步失败,自动刷新");
}
}).finally(()=>{
this.query();
});
},
handleEdit(){
axios.put("/introduces",this.formData).then((res)=>{
console.log(res.data.flag);
if(res.data.flag){
this.updateVisible = false;
this.$message.success("修改成功");
}else{
this.$message.error("修改失败");
}
}).finally(()=>{
this.query();
});
},
cancelUpdate(){
this.updateVisible = false;
this.$message({
message: '已取消修改',
center: true
});
},
handleDelete(row) {
this.$confirm("此操作将会永久删除当前数据,是否继续","提示",{
type: 'info'
}).then(()=>{
axios.delete("/introduces/" + row.id).then((res)=>{
if(res.data.flag){
this.$message("删除成功");
}else{
this.$message.error("数据同步失败,自动刷新");
}
}).finally(()=>{
this.query();
});
}).catch(()=>{
this.$message.info("取消删除");
});
},
handleSizeChange(val) {
this.pagination.pageSize = val;
this.query();
},
handleCurrentChange(val) {
this.pagination.currentPage = val;
this.query();
},
filterTag(value, row) {
return row.tag === value;
},
filterHandler(value, row, column) {
const property = column['property'];
return row[property] === value;
}
}
五、错误总结
1.当后端测试用例成功,前端发送异步请求未出现异常,但列表任然展示不出,解决方法:column中prop的属性值要与pojo实体类属性值一致
2.展示列表依旧尚未成功,并出现 No converter found for return value of type: class xxx 日志,解决方法:为传参实体类private属性设置setter、getter方法
3.当页面可以展示所有数据时,但当发送分页请求并传递参数时,出现 Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer' 日志,解决方法:路径错误参数传递失败,将所需传递的Integer类型数据直接添加到""上
4.使用分页工具条,但只能显示第一面的数据,分页无效,解决方法:在script标签中data区添加paginationShow=true,并使用v-if="paginationShow"每次都重新显示分页,页面刷新;但是依旧没有效果,最后通过另外编写一个分页工具条进行对比发现,html标签的属性写错了
5.在做更新操作时,测试数据没有问题,但更新操作一直失败,通过console.log()方法,将信息打印到浏览器开发者工具的控制台上和输出台,返回的flag全显示为false,最终确定返回的R对象构造方法写错了,因为没设置flag,所以返回默认值false,解决方法:将R类构造方法的形参由data转为flag,或添加以flag为形参的构造方法
6.int数组,Integer数组,String数组,List集合转换
int[] data = {4, 5, 3, 6, 2, 5, 1};
// int[] 转 List<Integer>
List<Integer> list1 = Arrays.stream(data).boxed().collect(Collectors.toList());
// Arrays.stream(arr) 可以替换成IntStream.of(arr)。
// 1.使用Arrays.stream将int[]转换成IntStream。
// 2.使用IntStream中的boxed()装箱。将IntStream转换成Stream<Integer>。
// 3.使用Stream的collect(),将Stream<T>转换成List<T>,因此正是List<Integer>。
// int[] 转 Integer[]
Integer[] integers1 = Arrays.stream(data).boxed().toArray(Integer[]::new);
// 前两步同上,此时是Stream<Integer>。
// 然后使用Stream的toArray,传入IntFunction<A[]> generator。
// 这样就可以返回Integer数组。
// 不然默认是Object[]。
// List<Integer> 转 Integer[]
Integer[] integers2 = list1.toArray(new Integer[0]);
// 调用toArray。传入参数T[] a。这种用法是目前推荐的。
// List<String>转String[]也同理。
// List<Integer> 转 int[]
int[] arr1 = list1.stream().mapToInt(Integer::valueOf).toArray();
// 想要转换成int[]类型,就得先转成IntStream。
// 这里就通过mapToInt()把Stream<Integer>调用Integer::valueOf来转成IntStream
// 而IntStream中默认toArray()转成int[]。
// Integer[] 转 int[]
int[] arr2 = Arrays.stream(integers1).mapToInt(Integer::valueOf).toArray();
// 思路同上。先将Integer[]转成Stream<Integer>,再转成IntStream。
// Integer[] 转 List<Integer>
List<Integer> list2 = Arrays.asList(integers1);
// 最简单的方式。String[]转List<String>也同理。
// 同理
String[] strings1 = {"a", "b", "c"};
// String[] 转 List<String>
List<String> list3 = Arrays.asList(strings1);
// List<String> 转 String[]
String[] strings2 = list3.toArray(new String[0]);
————————————————
原文链接:https://blog.csdn.net/PitBXu/article/details/97672145