本篇文章将会详细介绍jquery easyui前端框架的使用,通过创建一个crud应用来带大家快速掌握easyui的使用。
easyui是博主最喜欢的前端框架,没有之一,因为它提供了多种主题,而且有圆润的各种组件。
目录
StringToListOfFilterRuleConverter
一、快速开始
easyui的官网地址:
JQuery EasyUI中文网https://www.jeasyui.net/点击上方链接访问easyui中文官网,下载easyui。
在下载页面点击下载对应的版本,本篇文章将使用jquery easyui
选择下载免费版
二、准备工作
下载完成后,得到一个压缩包jquery-easyui-1.7.0.zip。
然后把这个压缩包解压出来,我们需要的是红框内的几个文件及文件夹。
- locale目录下是常用的一些js文件
- themes目录下是easyui的样式文件
通过HBuilderx创建一个基本的html项目
接着,把themes文件夹复制到项目的css目录下,把locale/easyui-lang-zh_CN.js和红框内的两个js文件复制到项目的js目录下。
三、开始使用
完成前面两步之后,就可以开始愉快地使用easyui了。
主题资源
如图,themes下面提供了多种主题样式的资源文件,喜欢哪个主题,引入对应包下的easyui.css即可。
常用组件
datagrid
easyui里用的最多的莫过于数据表格了,datagrid是easyui的表格组件,支持分页功能。只需要在表格渲染的js代码中添加选项pagenation: true即可开启分页功能。
打开easyui的文档页面,找到通过javascript渲染表格的案例代码。
官网提供的渲染easyui datagrid的javascript代码为,url是加载表格数据的地址,columns是表格的列信息。#dg表示的是表格元素的选择器,这是id选择器,表示id为dg的DOM对象。
javascript
$('#dg').datagrid({
url:'datagrid_data.json',
columns:[[
{field:'code',title:'Code',width:100},
{field:'name',title:'Name',width:100},
{field:'price',title:'Price',width:100,align:'right'}
]]
});
textbox
文本框,就是带了easyui样式的input输入框,与之对应的还有passwordbox。
passwordbox
密码框,带了easyui样式的input密码框<input type="password"></input>
dialog
对话框,通常会在对话框内嵌表单,实现数据的添加和修改功能。
四、表格渲染
为了方便快速学会datagird的使用,这里就直接拿之前写的springboot crud案例项目作为后端项目,演示datagird通过ajax异步加载表格数据。
项目git地址如下:
后端代码
添加跨域配置
首先要添加跨域配置,防止使用过程中出现cors问题。
java
package com.example.springboot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* springmvc配置类
* @author heyunlin
* @version 1.0
*/
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
/**
* 解决跨域问题
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(5000);
}
}
添加controller接口
然后在SongController中添加一个接口方法
java
@RequestMapping(value = "/selectList", method = RequestMethod.GET)
public JsonResult<List<Song>> selectList() {
List<Song> list = songService.selectList();
return JsonResult.success("查询成功", list);
}
对应地,在SongService接口添加selectList()方法
java
List<Song> selectList();
SongServiceImpl
java
@Override
public List<Song> selectList() {
return songMapper.selectList(null);
}
前端代码
在前端的easyui项目下创建html目录,在html目录下创建index.html。
修改表格的数据加载地址url为selectList接口的访问地址http://localhost:8083/song/selectList
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>datagrid案例代码</title>
<link rel="stylesheet" href="../css/themes/icon.css" />
<link rel="stylesheet" href="../css/themes/material/easyui.css" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.easyui.min.js"></script>
<script src="../js/easyui-lang-zh_CN.js"></script>
</head>
<body>
<div id="song_list"></div>
<script>
$(document).ready(function() {
$("#song_list").datagrid({
url: "http://localhost:8083/song/selectList",
columns: [[
{field: 'code', title:'Code', width:100},
{field: 'name', title:'Name', width:100},
{field: 'price', title:'Price', width:100, align:'right'}
]]
});
});
</script>
</body>
</html>
然后选择通过firefox运行,打开看到一个空白页面
F12打开浏览器控制台,刷新页面,发现请求接口发生了异常,不支持post请求。
这是因为easyui的datagrid默认是通过ajax post请求加载数据.
打开之前的文档页面,往下滚动,找到数据网格属性。
如图,method属性就是设置请求的类型,而这个属性的默认值是post,我们把它设置成get
method属性
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>datagrid案例代码</title>
<link rel="stylesheet" href="../css/themes/icon.css" />
<link rel="stylesheet" href="../css/themes/material/easyui.css" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.easyui.min.js"></script>
<script src="../js/easyui-lang-zh_CN.js"></script>
</head>
<body>
<div id="song_list"></div>
<script>
$(document).ready(function() {
$("#song_list").datagrid({
url: "http://localhost:8083/song/selectList",
method: "get",
columns: [[
{field: 'code', title:'Code', width:100},
{field: 'name', title:'Name', width:100},
{field: 'price', title:'Price', width:100, align:'right'}
]]
});
});
</script>
</body>
</html>
页面代码修改完成之后,发现只显示了表头,表格数据没有显示出来,而且报了一个错,rows is undefined。
为什么会这样呢,其实问题就在于后端返回的数据不是一个list,而是封装的一个JsonResult对象,list放到这个对象的data里了。所以,这里要对返回的数据进行简单的处理,得到data里的list。
loadFilter属性
就是它了,loadFilter属性是一个方法,用于请求url过滤返回的数据。
注意:我们在后端封装一个JsonResult对象返回是为了能够带上一个请求的状态码code,当这个状态码为200时,表示请求被正确地执行了。
因此,这个过滤方法应该是下面这样:
javascript
loadFilter: function(res) {
if (res.code == 200) {
return res.data;
} else {
return null;
}
},
最后,正确的页面代码如下:
javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>datagrid案例代码</title>
<link rel="stylesheet" href="../css/themes/icon.css" />
<link rel="stylesheet" href="../css/themes/material/easyui.css" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.easyui.min.js"></script>
<script src="../js/easyui-lang-zh_CN.js"></script>
</head>
<body>
<div id="song_list"></div>
<script>
$(document).ready(function() {
$("#song_list").datagrid({
url: "http://localhost:8083/song/selectList",
method: "get",
loadFilter: function(res) {
if (res.code == 200) {
return res.data;
} else {
return null;
}
},
columns: [[
{field: 'id', title: 'id', width: 200},
{field: 'name', title: 'name', width: 200},
{field: 'singer', title: 'singer', width: 200},
{field: 'note', title: 'note', width: 200},
{field: 'lastUpdateTime', title: 'lastUpdateTime', width: 200},
]]
});
});
</script>
</body>
</html>
而此时,页面的数据终于显示出来了,一共800多条数据。
fitColumns属性
上面的页面看起来非常丑,如果表格能占满整个页面会更好看一点,因此,easyui也实现了这种效果,只需要设置fitColumns属性的值为true即可,表格的列宽会自适应当前页面。
于是,在原来的代码基础上添加fitColumns属性,并设置为true
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>datagrid案例代码</title>
<link rel="stylesheet" href="../css/themes/icon.css" />
<link rel="stylesheet" href="../css/themes/material/easyui.css" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.easyui.min.js"></script>
<script src="../js/easyui-lang-zh_CN.js"></script>
</head>
<body>
<div id="song_list"></div>
<script>
$(document).ready(function() {
$("#song_list").datagrid({
url: "http://localhost:8083/song/selectList",
method: "get",
fitColumns: true,
loadFilter: function(res) {
if (res.code == 200) {
return res.data;
} else {
return null;
}
},
columns: [[
{field: 'id', title: 'id', width: 200},
{field: 'name', title: 'name', width: 200},
{field: 'singer', title: 'singer', width: 200},
{field: 'note', title: 'note', width: 200},
{field: 'lastUpdateTime', title: 'lastUpdateTime', width: 200},
]]
});
});
</script>
</body>
</html>
修改页面代码后的效果,比原来看起来舒服的多。
striped属性
页面看起来差不多了,但是总感觉表格也太单调了,全是一种颜色,看起来总感觉怪怪的,能不能再美化一下呢。
答案是:当然可以,上面的页面很单调,是表格全部数据都是一个颜色,如果能给表格的行记录颜色不一样,那就完美了。
于是,striped属性腾空出世,这个属性的作用就是显示条纹,不出所料,这个属性默认值也是false。
把它设置成true看一下效果。
javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>datagrid案例代码</title>
<link rel="stylesheet" href="../css/themes/icon.css" />
<link rel="stylesheet" href="../css/themes/material/easyui.css" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.easyui.min.js"></script>
<script src="../js/easyui-lang-zh_CN.js"></script>
</head>
<body>
<div id="song_list"></div>
<script>
$(document).ready(function() {
$("#song_list").datagrid({
url: "http://localhost:8083/song/selectList",
method: "get",
striped: true,
fitColumns: true,
loadFilter: function(res) {
if (res.code == 200) {
return res.data;
} else {
return null;
}
},
columns: [[
{field: 'id', title: 'id', width: 200},
{field: 'name', title: 'name', width: 200},
{field: 'singer', title: 'singer', width: 200},
{field: 'note', title: 'note', width: 200},
{field: 'lastUpdateTime', title: 'lastUpdateTime', width: 200},
]]
});
});
</script>
</body>
</html>
修改页面之后,视觉效果还不错,有了一点bootstrap的感觉了~
pagination属性
上面的表格外观已经很完美了,作为一个后端开发人员来说,这样的样式已经无可挑剔,但是,之前已经说过了,一共有800多条数据,这还算少的了,假如有几万条数据呢?如果一次性全部查询出来,每次查询的时候,后端服务的压力是很大的。
所以,一般数据量大的时候都会分页查询,每次只查询一部分数据。
easyui的datagrid支持分页功能,只需要设置pagination属性为true,而常用的分页属性还有另外两个pageSize和pageList。
修改前端页面代码,添加pagination属性为true。
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>datagrid案例代码</title>
<link rel="stylesheet" href="../css/themes/icon.css" />
<link rel="stylesheet" href="../css/themes/material/easyui.css" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.easyui.min.js"></script>
<script src="../js/easyui-lang-zh_CN.js"></script>
</head>
<body>
<div id="song_list"></div>
<script>
$(document).ready(function() {
$("#song_list").datagrid({
url: "http://localhost:8083/song/selectList",
method: "get",
striped: true,
fitColumns: true,
pagination: true,
loadFilter: function(res) {
if (res.code == 200) {
return res.data;
} else {
return null;
}
},
columns: [[
{field: 'id', title: 'id', width: 200},
{field: 'name', title: 'name', width: 200},
{field: 'singer', title: 'singer', width: 200},
{field: 'note', title: 'note', width: 200},
{field: 'lastUpdateTime', title: 'lastUpdateTime', width: 200},
]]
});
});
</script>
</body>
</html>
此时,页面好像没有什么区别,好像也没有分页
其实,页面已经变了,只是在当前页面可浏览范围之外,页面滚动到末尾,会发现表格底部多了一个分页栏。
并且,请求携带了额外的参数page和rows
height属性
基于上面的的问题(需要拉到页面底部才能看到分页栏),现在给表格设置一个固定的高度,让它刚好够显示10条数据。通过不断调整,发现高度400比较适合。
javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>datagrid案例代码</title>
<link rel="stylesheet" href="../css/themes/icon.css" />
<link rel="stylesheet" href="../css/themes/material/easyui.css" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.easyui.min.js"></script>
<script src="../js/easyui-lang-zh_CN.js"></script>
</head>
<body>
<div id="song_list"></div>
<script>
$(document).ready(function() {
$("#song_list").datagrid({
url: "http://localhost:8083/song/selectList",
method: "get",
height: 400,
striped: true,
fitColumns: true,
pagination: true,
loadFilter: function(res) {
if (res.code == 200) {
return res.data;
} else {
return null;
}
},
columns: [[
{field: 'id', title: 'id', width: 200},
{field: 'name', title: 'name', width: 200},
{field: 'singer', title: 'singer', width: 200},
{field: 'note', title: 'note', width: 200},
{field: 'lastUpdateTime', title: 'lastUpdateTime', width: 200},
]]
});
});
</script>
</body>
</html>
再次查看页面效果
五、构建应用
完成分页功能
上个章节,已经完成了基本的页面样式的调整,但是能发现,其实并没有分页,这是因为后端没有处理easyui框架传的两个参数page和rows。
这个部分首先需要解决的就是这个问题,要使用mybatis-plus的分页功能,需要添加分页插件。
后端代码
新增mp配置类,添加mybatis-plus分页插件。
java
package com.example.springboot.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* MP配置类
*/
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.example.springboot.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 防全表更新与删除插件
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
前端代码
我们把请求数据的接口改一下,改成selectByPage。
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>datagrid案例代码</title>
<link rel="stylesheet" href="../css/themes/icon.css" />
<link rel="stylesheet" href="../css/themes/material/easyui.css" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.easyui.min.js"></script>
<script src="../js/easyui-lang-zh_CN.js"></script>
</head>
<body>
<div id="song_list"></div>
<script>
$(document).ready(function() {
$("#song_list").datagrid({
url: "http://localhost:8083/song/selectByPage",
method: "get",
height: 400,
striped: true,
fitColumns: true,
pagination: true,
loadFilter: function(res) {
if (res.code == 200) {
return res.data;
} else {
return null;
}
},
columns: [[
{field: 'id', title: 'id', width: 200},
{field: 'name', title: 'name', width: 200},
{field: 'singer', title: 'singer', width: 200},
{field: 'note', title: 'note', width: 200},
{field: 'lastUpdateTime', title: 'lastUpdateTime', width: 200},
]]
});
});
</script>
</body>
</html>
页面效果
至此,分页功能完成~
增删查改功能
接下来完成数据的增删改功能。
给表格添加头部工具栏,新增添加、修改、删除三个按钮。
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>datagrid案例代码</title>
<link rel="stylesheet" href="../css/themes/icon.css" />
<link rel="stylesheet" href="../css/themes/material/easyui.css" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.easyui.min.js"></script>
<script src="../js/easyui-lang-zh_CN.js"></script>
</head>
<body>
<div id="song_list"></div>
<div id="song_dialog" style="display: none;">
<form id="song_form">
<input type="hidden" id="id" name="id" />
<table>
<tr>
<td>name:</td>
<td><input id="name" name="name" /></td>
<td>singer:</td>
<td><input id="singer" name="singer" /></td>
</tr>
<tr>
<td>note:</td>
<td colspan="3"><input id="note" name="note" /></td>
</tr>
</table>
</form>
</div>
<script>
let requestUrl;
let base = "http://localhost:8083";
$(document).ready(function() {
$('#name').textbox({
width: 150,
required: true
});
$('#singer').textbox({
width: 150,
required: true
});
$('#note').textbox({
width: 366,
height: 100,
required: true,
multiline: true
});
$('#song_dialog').dialog({
title: '歌曲信息',
closed: true,
cache: false,
modal: true,
toolbar:[{
text: '保存',
iconCls: 'icon-save',
handler: function() {
let bool = $("#song_form").form("validate");
if (!bool) {
$.messager.alert("系统提示", "请填写正确的表单项", "warning");
} else {
let data = $("#song_form").serialize();
$.post(base + requestUrl, data, function(res) {
$.messager.show({
title: '系统消息',
timeout: 5000,
showType: 'slide',
msg: res.message,
});
$('#song_dialog').dialog('close');
$("#song_list").datagrid("reload");
}, "json");
}
}
}, {
text: '取消',
iconCls: 'icon-cancel',
handler: function() {
$("#song_form").form('clear');
$('#song_dialog').dialog('close');
}
}]
});
$("#song_list").datagrid({
url: base + "/song/selectByPage",
method: "get",
height: 432,
striped: true,
filterBtnIconCls: "icon-filter",
fitColumns: true,
pagination: true,
loadFilter: function(res) {
if (res.code == 200) {
return res.data;
} else {
return null;
}
},
toolbar: [{
iconCls: 'icon-add',
text: '添加',
handler: function() {
requestUrl = "/song/insert";
$('#song_dialog').dialog('open');
}
}, '-', {
iconCls: 'icon-edit',
text: '修改',
handler: function() {
let row = $("#song_list").datagrid('getSelected');
if(row) {
requestUrl = "/song/updateById";
$('#id').val(row.id);
$('#name').textbox('setValue', row.name);
$('#singer').textbox('setValue', row.singer);
$('#note').textbox('setValue', row.note);
$('#song_dialog').dialog('open');
} else {
$.messager.alert("系统提示", "请选择要修改的数据!", "warning");
}
}
}, '-', {
iconCls: 'icon-delete',
text: '删除',
handler: function() {
let rowData = $("#song_list").datagrid("getSelected");
if (rowData) {
$.messager.confirm("提示", "删除后数据无法恢复,是否确认删除?", function(bool) {
if (bool) {
$.get(base + "/song/deleteById/" + rowData.id, {}, function(res) {
$.messager.show({
title: '系统消息',
timeout: 5000,
showType: 'slide',
msg: res.message,
});
$("#song_list").datagrid("reload");
}, "json");
}
});
} else {
$.messager.alert("请选择要删除的数据!", "warning");
}
}
}],
columns: [[
{field: 'id', title: 'id', width: 200},
{field: 'name', title: 'name', width: 200},
{field: 'singer', title: 'singer', width: 200},
{field: 'note', title: 'note', width: 200},
{field: 'lastUpdateTime', title: 'lastUpdateTime', width: 200},
]]
});
});
</script>
</body>
</html>
条件查询功能
最后,要实现表格数据的条件查询功能,在这里通过表格过滤来实现这个功能,需要引入额外的easyui插件。
更多详情可参考以下链接:
EasyUI 数据网格行过滤(DataGrid Filter Row)https://www.jeasyui.net/extension/192.html访问以上地址,页面拉到底部,把这个压缩包下载下来,我们需要它里面的datagrid-filter.js文件。
前端代码
博主下载下来之后,花了点时间看了一下datagrid-filter.js的源代码,发现一个关键的属性remoteFilter,意思是远程过滤,而通过页面的说明,发现这个属性的默认值为false。
根据我使用easyui的经验猜测,如果设置成true,应该会在加载表格数据的时候额外发送请求参数。于是照着葫芦画瓢,给歌曲列表开启行过滤,并设置remoteFilter属性值为true。
javascript
let requestUrl;
let base = "http://localhost:8083";
let pageList = [20, 50, 100, 500, 1000];
$(document).ready(function() {
$('#name').textbox({
width: 150,
required: true
});
$('#singer').textbox({
width: 150,
required: true
});
$('#note').textbox({
width: 366,
height: 100,
required: true,
multiline: true
});
$('#song_dialog').dialog({
title: '歌曲信息',
closed: true,
cache: false,
modal: true,
toolbar:[{
text: '保存',
iconCls: 'icon-save',
handler: function() {
let bool = $("#song_form").form("validate");
if (!bool) {
$.messager.alert("系统提示", "请填写正确的表单项", "warning");
} else {
let data = $("#song_form").serialize();
$.post(base + requestUrl, data, function(res) {
$.messager.show({
title: '系统消息',
timeout: 5000,
showType: 'slide',
msg: res.message,
});
$('#song_dialog').dialog('close');
$("#song_list").datagrid("reload");
}, "json");
}
}
}, {
text: '取消',
iconCls: 'icon-cancel',
handler: function() {
$("#song_form").form('clear');
$('#song_dialog').dialog('close');
}
}]
});
let datagrid = $("#song_list").datagrid({
url: base + "/song/selectByPage",
title: "歌曲列表",
height: 810,
striped: true,
fitColumns: true,
pagination: true,
remoteFilter: true,
clientPaging: false,
pageSize: pageList[0],
pageList: pageList,
loadFilter: function(res) {
if (res.code == 200) {
return res.data;
} else {
return null;
}
},
toolbar: [{
iconCls: 'icon-add',
text: '添加',
handler: function() {
requestUrl = "/song/insert";
$('#song_dialog').dialog('open');
}
}, '-', {
iconCls: 'icon-edit',
text: '修改',
handler: function() {
let row = $("#song_list").datagrid('getSelected');
if(row) {
requestUrl = "/song/updateById";
$('#id').val(row.id);
$('#name').textbox('setValue', row.name);
$('#singer').textbox('setValue', row.singer);
$('#note').textbox('setValue', row.note);
$('#song_dialog').dialog('open');
} else {
$.messager.alert("系统提示", "请选择要修改的数据!", "warning");
}
}
}, '-', {
iconCls: 'icon-delete',
text: '删除',
handler: function() {
let rowData = $("#song_list").datagrid("getSelected");
if (rowData) {
$.messager.confirm("提示", "删除后数据无法恢复,是否确认删除?", function(bool) {
if (bool) {
$.get(base + "/song/deleteById/" + rowData.id, {}, function(res) {
$.messager.show({
title: '系统消息',
timeout: 5000,
showType: 'slide',
msg: res.message,
});
$("#song_list").datagrid("reload");
}, "json");
}
});
} else {
$.messager.alert("请选择要删除的数据!", "warning");
}
}
}],
columns: [[
{field: 'id', title: 'id', width: 200},
{field: 'name', title: 'name', width: 200},
{field: 'singer', title: 'singer', width: 200},
{field: 'note', title: 'note', width: 200},
{field: 'lastUpdateTime', title: 'lastUpdateTime', width: 200},
]]
});
datagrid.datagrid('enableFilter', [{
field: 'name',
type: 'textbox',
op: ['equal', 'contains']
}, {
field: 'singer',
type: 'textbox',
op: ['equal', 'contains'],
}, {
field: 'note',
type: 'textbox',
op: ['equal', 'contains']
}]);
});
果然,刷新页面,发现发送的请求中多了一个filterRules参数。
后端代码
FilterRule
于是在后端创建与之对应的java实体类FilterRule
java
package com.example.springboot.base;
import com.example.springboot.enums.Operator;
import lombok.Data;
/**
* 过滤规则
* @author heyunlin
* @version 1.0
*/
@Data
public class FilterRule {
/**
* 字段名
*/
private String field;
/**
* 比较符
*/
private Operator op;
/**
* 字段值
*/
private String value;
}
并且考虑到这里过滤的比较符有多个,创建一个枚举来保存所有比较符。
java
package com.example.springboot.enums;
/**
* 比较符
* @author heyunlin
* @version 1.0
*/
public enum Operator {
/**
* 包含
*/
contains,
/**
* 等于
*/
equal,
/**
* 不等于
*/
notequal,
/**
* 以...开始
*/
beginwith,
/**
* 以...结尾
*/
endwith,
/**
* 小于
*/
less,
/**
* 小于或等于
*/
lessorequal,
/**
* 大于
*/
greater,
/**
* 大于或等于
*/
greaterorequal
}
Pager
最后在Pager类上额外添加一个filterRules属性,让controller接口接收前端传递的filterRules参数,并将其转换为List<FilterRule>类型。
java
package com.example.springboot.base;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* 基础分页参数对象,包含页数和每页的记录数
* @author heyunlin
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class Pager<T> extends Sorter {
/**
* 页数
*/
private Integer page = 1;
/**
* 每页记录数
*/
private Integer rows = 10;
/**
* 过滤规则
*/
private List<FilterRule> filterRules;
/**
* 根据Pager创建Page对象
* @param pager Pager
* @return Page<T>
*/
public static <T> Page<T> ofPage(Pager<T> pager) {
return new Page<>(pager.getPage(), pager.getRows());
}
}
测试请求一下,发现请求返回400状态码,参数转换异常。
具体的错误提示如下:不能从String类型转换到List<FilterRule>类型,这也是意料之中的事。
java
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'songPagerDTO' on field 'filterRules': rejected value [[{"field":"name","op":"contains","value":"宠坏"}]]; codes [typeMismatch.songPagerDTO.filterRules,typeMismatch.filterRules,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [songPagerDTO.filterRules,filterRules]; arguments []; default message [filterRules]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.List' for property 'filterRules'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.example.springboot.base.FilterRule' for property 'filterRules[0]': no matching editors or conversion strategy found]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:175)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
StringToListOfFilterRuleConverter
于是添加一个类型转换器,完成String到List<FilterRule>的转换。这里使用alibaba的fastjson来实现
java
package com.example.springboot.base;
import com.alibaba.fastjson.JSON;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author heyunlin
* @version 1.0
*/
@Component
public class StringToListOfFilterRuleConverter implements Converter<String, List<FilterRule>> {
@Override
public List<FilterRule> convert(String source) {
return JSON.parseArray(source, FilterRule.class);
}
}
完成以上修改之后,请求总算是通了,正常返回了数据。
Pager
最后,在后端实现数据过滤功能,根据filterRules参数动态添加查询条件。在Pager类值统一处理过滤
java
package com.example.springboot.base;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* 基础分页参数对象,包含页数和每页的记录数
* @author heyunlin
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class Pager<T> extends Sorter {
/**
* 页数
*/
private Integer page = 1;
/**
* 每页记录数
*/
private Integer rows = 10;
/**
* 过滤规则
*/
private List<FilterRule> filterRules;
/**
* 根据Pager创建Page对象
* @param pager Pager
* @return Page<T>
*/
public static <T> Page<T> ofPage(Pager<T> pager) {
return new Page<>(pager.getPage(), pager.getRows());
}
/**
* 根据Pager创建QueryWrapper对象
* @param pager Pager
* @return QueryWrapper<T>
*/
public static <T> QueryWrapper<T> getQueryWrapper(Pager<T> pager) {
List<FilterRule> filterRules = pager.getFilterRules();
if (filterRules != null && !filterRules.isEmpty()) {
QueryWrapper<T> wrapper = new QueryWrapper<>();
for (FilterRule filterRule : filterRules) {
String field = filterRule.getField();
String value = filterRule.getValue();
switch (filterRule.getOp()) {
case less:
wrapper.lt(field, value);
break;
case equal:
wrapper.eq(field, value);
break;
case greater:
wrapper.gt(field, value);
break;
case notequal:
wrapper.ne(field, value);
break;
case lessorequal:
wrapper.le(field, value);
break;
case greaterorequal:
wrapper.ge(field, value);
break;
case beginwith:
wrapper.likeLeft(field, value);
break;
case endwith:
wrapper.likeRight(field, value);
break;
case contains:
wrapper.like(field, value);
break;
default:
break;
}
}
return wrapper;
}
return null;
}
}
SongServiceImpl
最后修改一下selectByPage()方法的具体实现,从Pager类获取QueryWrapper对象,而不是自己构建。
java
package com.example.springboot.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.springboot.base.Pager;
import com.example.springboot.dto.SongInsertDTO;
import com.example.springboot.dto.SongPagerDTO;
import com.example.springboot.dto.SongUpdateDTO;
import com.example.springboot.entity.Song;
import com.example.springboot.exception.GlobalException;
import com.example.springboot.mapper.SongMapper;
import com.example.springboot.restful.ResponseCode;
import com.example.springboot.service.SongService;
import com.example.springboot.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author heyunlin
* @version 1.0
*/
@Service
public class SongServiceImpl implements SongService {
private final SongMapper songMapper;
@Autowired
public SongServiceImpl(SongMapper songMapper) {
this.songMapper = songMapper;
}
// ...其它代码
@Override
public Page<Song> selectByPage(SongPagerDTO pagerDTO) {
QueryWrapper<Song> wrapper = Pager.getQueryWrapper(pagerDTO);
Page<Song> page = Pager.ofPage(pagerDTO);
return songMapper.selectPage(page, wrapper);
}
}
至此,所有功能都已经完成。
好了,文章就分享到这里了,看完不要忘了点赞+收藏哦~
前端项目地址如下,可按需获取
https://gitcode.net/heyl163_/easyui.githttps://gitcode.net/heyl163_/easyui.git