Spring中带有服务器端处理的JQuery数据表(使用Java和Thymeleaf)
我有一个使用Java和Thymeleaf的Spring启动应用程序。在其中,我有一个带有JQuery数据表的页面。这个表中有数千行,所以虽然我目前只是将其全部放在页面上,让JQuery完全处理它,但我想切换到使用服务器端处理来进行分页、排序等 我被设置为在后端执行此操作,在后端,我可以将开始和结束行号以及排序信息动态地传递给我的SQL查询。然而,我的问题是,当用户单击“下一页”按钮或排序按钮时,我无法准确地理解DataTables是如何试图通过控制器通知我的我的控制器在哪里/如何获取这些信息,以便我可以将其插入SQL查询并返回所需信息? 所以,假设我有一个对象,比如“人” 我的新数据表控制器:Spring中带有服务器端处理的JQuery数据表(使用Java和Thymeleaf),java,jquery,spring-boot,datatables,thymeleaf,Java,Jquery,Spring Boot,Datatables,Thymeleaf,我有一个使用Java和Thymeleaf的Spring启动应用程序。在其中,我有一个带有JQuery数据表的页面。这个表中有数千行,所以虽然我目前只是将其全部放在页面上,让JQuery完全处理它,但我想切换到使用服务器端处理来进行分页、排序等 我被设置为在后端执行此操作,在后端,我可以将开始和结束行号以及排序信息动态地传递给我的SQL查询。然而,我的问题是,当用户单击“下一页”按钮或排序按钮时,我无法准确地理解DataTables是如何试图通过控制器通知我的我的控制器在哪里/如何获取这些信息,以
@RequestMapping(path = "/ApplicationName/Data/Person", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public List<Person> getPersonData() {
System.out.println("I was called!");
SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.setOrderByString("name");
searchCriteria.setUsePaging(false);
searchCriteria.setFIRST_NUMBER(null);
searchCriteria.setLAST_NUMBER(null);
return myMapperService.getPeople(searchCriteria); //returns an ArrayList<Person>
}
@RequestMapping(path=“/ApplicationName/Data/Person”,method=RequestMethod.GET,products=“application/json”)
@应答器
公共列表getPersonData(){
System.out.println(“我被叫到了!”);
SearchCriteria SearchCriteria=新的SearchCriteria();
searchCriteria.setOrderByString(“名称”);
searchCriteria.setUsePaging(false);
searchCriteria.setFIRST_编号(空);
searchCriteria.setLAST_编号(空);
return myMapperService.getPeople(searchCriteria);//返回ArrayList
}
我的更改(更复杂)Javascript:(第2版)
$(文档).ready(函数(){
$('#myDataTable')。DataTable({
"摧毁":对,,
“服务器端”:正确,
“sAjaxSource”:“/ApplicationName/Data/Person”,
“sAjaxDataProp”:“,
“订单”:[0,'asc']],
“列”:
[
{“数据”:“名称”,
“呈现”:函数(数据、类型、行、元){
如果(类型=='display'){
数据=“”
}
返回数据;
}
} ,
{“数据”:“社会安全”},
{“数据”:“出生日期”},
{“数据”:“性别”}
],
“滚动”:300,
“滚动崩溃”:对,
“分页”:对,
“自动宽度”:true,
“排序”:正确,
“搜索”:错误,
“页面长度”:20,
“长度变化”:错误,
“pagingType”:“完整编号”,
“dom”:“rt”
});
});
=============================================================
这也行得通。特别是如果我删除了“'serverSide':true”配置,DataTable的工作方式与我进行上述更改之前完全相同,但现在它调用了我的新数据JSON控制器,而不是使用模型属性
问题:
但是,在DataTable中添加了“'serverSide':true”配置后,每次我转到表的新“页面”时,它都会调用我的“/Clinic/Detail/Data/Patient”控制器
但是,我需要DataTables来传递控制器有关用户选择的页面或用户尝试排序的列的信息。我还需要(动态地)传递表中的总行数(count),以便DataTables可以为用户正确设置页码
DataTables是否向我的控制器发送一些我可以获取的附加参数?类似于@PathVariable(“随便什么”)的东西
我觉得我很快就能让它工作了,但我被困在这一点上了
我真的很感激任何帮助 我已经设法解决了我的问题 表的MyHTML保持不变,如下所示:
<table id="myDataTable" class="dataTable display compact">
<thead>
<tr>
<th>Name</th>
<th>Social Security</th>
<th>Birthdate</th>
<th>Gender</th>
</tr>
</thead>
</table>
@GetMapping("/ApplicationName/MyDataTablePage")
public String myDataTablePage(Model model) {
return "/pages/MyDataTablePage";
}
用于检索需要更改的数据的表的My控制器。首先,它需要获取datatables发送的@RequestParam
,其中包括我需要显示的记录数量、需要排序的记录以及排序的单元格等所有参数。其次,它不只是返回一个列表
,而是需要返回一个格式良好的JSON对象,其中包含Datatable用来决定在屏幕上显示多少页面的某些参数,以及数据列表
本身
@RequestMapping(path = "/ApplicationName/Data/Person", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public TableBean getPersonData(@RequestParam Map<String, String> allRequestParams) {
TableParameters tableParameters = myMapperService
.getTableParameters(allRequestParams);
return myMapperService.mapTableBean(tableParameters); //returns an TableBean which contains the ArrayList<Person>
}
然后我需要制作一个方法,该方法将从请求参数中提取这些变量,并将它们映射到新bean。这告诉我在SQL中使用什么,如何排序,以及从哪些数字开始和返回
private static String iDisplayLength = "iDisplayLength";
private static String iDisplayStart = "iDisplayStart";
private static String iColumns = "iColumns";
private static String sSearch = "sSearch";
private static String bRegex = "bRegex";
private static String iSortingCols = "iSortingCols";
private static String sEcho = "sEcho";
private static String iSortCol_0 = "iSortCol_0";
private static String sSortDir_0 = "sSortDir_0";
public TableParameters getTableParameters(Map<String, String> allRequestParams) {
TableParameters finalBean = new TableParameters();
if (null != allRequestParams.get(bRegex)) {
finalBean.setbRegex(new Boolean(allRequestParams.get(bRegex)));
}
if (null != allRequestParams.get(iColumns)) {
finalBean.setiColumns(new Integer(allRequestParams.get(iColumns)));
}
if (null != allRequestParams.get(iDisplayLength)) {
finalBean.setiDisplayLength(new Integer(allRequestParams.get(iDisplayLength)));
}
if (null != allRequestParams.get(iDisplayStart)) {
finalBean.setiDisplayStart(new Integer(allRequestParams.get(iDisplayStart)));
}
if (null != allRequestParams.get(iSortingCols)) {
finalBean.setiSortingCols(new Integer(allRequestParams.get(iSortingCols)));
}
if (null != allRequestParams.get(sEcho)) {
try {
finalBean.setsEcho(new Integer(allRequestParams.get(sEcho)));
} catch (Exception e) {
// ignore
}
}
if (null != allRequestParams.get(sSearch)) {
finalBean.setsSearch(allRequestParams.get(sSearch));
}
int numberOfColumnsSortedOn = 0;
if (allRequestParams.containsKey(iSortingCols) && null != allRequestParams.get(iSortingCols)) {
numberOfColumnsSortedOn = new Integer(allRequestParams.get("iSortingCols")).intValue();
}
if (numberOfColumnsSortedOn > 0) {
if (null != allRequestParams.get(iSortCol_0)) {
finalBean.setSortedColumnNumber(new Integer(allRequestParams.get(iSortCol_0)));
}
if (null != allRequestParams.get(sSortDir_0)) {
finalBean.setSortedColumnDirection(allRequestParams.get(sSortDir_0));
}
String keyForName = "mDataProp_" + finalBean.getSortedColumnNumber();
if (null != allRequestParams.get(keyForName)) {
finalBean.setSortedColumnName(allRequestParams.get(keyForName).toUpperCase());
}
}
return finalBean;
}
还有mapTableBean方法,该方法通过实际调用数据库来获取记录,从而将所有内容整合在一起
public TableBean mapTableBean(TableParameters tableParameters) {
int iTotalRecords = database.getCount();
int iTotalDisplayRecords = iTotalRecords;
if (null != tableParameters.getsEcho()){
String sEcho = tableParameters.getsEcho().toString();
}
List data = database.search(tableParameters.getiDisplayStart(), tableParameters.getiDisplayLength(),
tableParameters.getSortedColumnName(),
tableParameters.getSortedColumnDirection().equalsIgnoreCase("asc"));
return new TableBean(iTotalRecords, iTotalDisplayRecords, sEcho, data);
}
最后,必须修改Javascript,以便DataTables知道通过添加'sAjaxDataProp':'data',
配置,查看名为'data'的变量,查找表中显示的bean列表
$(document).ready(function () {
$('#myDataTable').DataTable({
'destroy' : true,
'serverSide' : true,
'sAjaxSource': '/ApplicationName/Data/Person',
'sAjaxDataProp': 'data',
'order': [ [ 0, 'asc' ] ],
'columns':
[
{ 'data': 'name',
'render': function(data, type, row, meta){
if(type === 'display'){
data = '<a href="javascript:openPersonDetail(''+ row.socialSecurity +'');">' + data + '</a>'
}
return data;
}
} ,
{ 'data': 'socialSecurity'} ,
{ 'data': 'birthdate'} ,
{ 'data': 'gender'}
],
'scrollY' : 300,
'scrollCollapse' : true,
'paging' : true,
'autoWidth' : true,
'ordering' : true,
'searching' : false,
'pageLength' : 20,
'lengthChange' : false,
'pagingType' : 'full_numbers',
'dom' : '<"top"ip>rt<"bottom"fl><"clear">'
});
});
$(文档).ready(函数(){
$('#myDataTable')。DataTable({
"摧毁":对,,
“服务器端”:正确,
“sAjaxSource”:“/ApplicationName/Data/Person”,
“sAjaxDataProp”:“数据”,
“订单”:[0,'asc']],
“列”:
[
{“数据”:“名称”,
“呈现”:函数(数据、类型、行、元){
如果(类型=='display'){
数据=“”
}
返回数据;
}
} ,
{“数据”:“社会安全”},
{“数据”:“出生日期”},
{“数据”:“性别”}
],
“滚动”:300,
“滚动崩溃”:对,
“分页”:对,
“自动宽度”:true,
“排序”:正确,
“搜索”:错误,
“页面长度”:20,
“长度变化”:错误,
“pagingType”:“完整编号”,
“dom”:”
$(document).ready(function () {
$('#myDataTable').DataTable({
'destroy' : true,
'serverSide' : true,
'sAjaxSource': '/ApplicationName/Data/Person',
'sAjaxDataProp': '',
'order': [ [ 0, 'asc' ] ],
'columns':
[
{ 'data': 'name',
'render': function(data, type, row, meta){
if(type === 'display'){
data = '<a href="javascript:openPersonDetail(''+ row.socialSecurity +'');">' + data + '</a>'
}
return data;
}
} ,
{ 'data': 'socialSecurity'} ,
{ 'data': 'birthdate'} ,
{ 'data': 'gender'}
],
'scrollY' : 300,
'scrollCollapse' : true,
'paging' : true,
'autoWidth' : true,
'ordering' : true,
'searching' : false,
'pageLength' : 20,
'lengthChange' : false,
'pagingType' : 'full_numbers',
'dom' : '<"top"ip>rt<"bottom"fl><"clear">'
});
});
<table id="myDataTable" class="dataTable display compact">
<thead>
<tr>
<th>Name</th>
<th>Social Security</th>
<th>Birthdate</th>
<th>Gender</th>
</tr>
</thead>
</table>
@GetMapping("/ApplicationName/MyDataTablePage")
public String myDataTablePage(Model model) {
return "/pages/MyDataTablePage";
}
@RequestMapping(path = "/ApplicationName/Data/Person", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public TableBean getPersonData(@RequestParam Map<String, String> allRequestParams) {
TableParameters tableParameters = myMapperService
.getTableParameters(allRequestParams);
return myMapperService.mapTableBean(tableParameters); //returns an TableBean which contains the ArrayList<Person>
}
public class TableParameters implements Serializable {
private static final long serialVersionUID = 1L;
private Integer iDisplayStart;
private Integer iDisplayLength;
private Integer iColumns;
private String sSearch;
private Boolean bRegex;
private Integer iSortingCols;
private Integer sEcho;
private Integer sortedColumnNumber;
private String sortedColumnName;
private String sortedColumnDirection;
// ... getters and setters
}
private static String iDisplayLength = "iDisplayLength";
private static String iDisplayStart = "iDisplayStart";
private static String iColumns = "iColumns";
private static String sSearch = "sSearch";
private static String bRegex = "bRegex";
private static String iSortingCols = "iSortingCols";
private static String sEcho = "sEcho";
private static String iSortCol_0 = "iSortCol_0";
private static String sSortDir_0 = "sSortDir_0";
public TableParameters getTableParameters(Map<String, String> allRequestParams) {
TableParameters finalBean = new TableParameters();
if (null != allRequestParams.get(bRegex)) {
finalBean.setbRegex(new Boolean(allRequestParams.get(bRegex)));
}
if (null != allRequestParams.get(iColumns)) {
finalBean.setiColumns(new Integer(allRequestParams.get(iColumns)));
}
if (null != allRequestParams.get(iDisplayLength)) {
finalBean.setiDisplayLength(new Integer(allRequestParams.get(iDisplayLength)));
}
if (null != allRequestParams.get(iDisplayStart)) {
finalBean.setiDisplayStart(new Integer(allRequestParams.get(iDisplayStart)));
}
if (null != allRequestParams.get(iSortingCols)) {
finalBean.setiSortingCols(new Integer(allRequestParams.get(iSortingCols)));
}
if (null != allRequestParams.get(sEcho)) {
try {
finalBean.setsEcho(new Integer(allRequestParams.get(sEcho)));
} catch (Exception e) {
// ignore
}
}
if (null != allRequestParams.get(sSearch)) {
finalBean.setsSearch(allRequestParams.get(sSearch));
}
int numberOfColumnsSortedOn = 0;
if (allRequestParams.containsKey(iSortingCols) && null != allRequestParams.get(iSortingCols)) {
numberOfColumnsSortedOn = new Integer(allRequestParams.get("iSortingCols")).intValue();
}
if (numberOfColumnsSortedOn > 0) {
if (null != allRequestParams.get(iSortCol_0)) {
finalBean.setSortedColumnNumber(new Integer(allRequestParams.get(iSortCol_0)));
}
if (null != allRequestParams.get(sSortDir_0)) {
finalBean.setSortedColumnDirection(allRequestParams.get(sSortDir_0));
}
String keyForName = "mDataProp_" + finalBean.getSortedColumnNumber();
if (null != allRequestParams.get(keyForName)) {
finalBean.setSortedColumnName(allRequestParams.get(keyForName).toUpperCase());
}
}
return finalBean;
}
public class TableBean implements Serializable {
private static final long serialVersionUID = 1L;
private int iTotalRecords;
private int iTotalDisplayRecords;
private String sEcho;
private List data;
public TableBean(int iTotalRecords, int iTotalDisplayRecords, String sEcho, List data) {
super();
this.iTotalRecords = iTotalRecords;
this.iTotalDisplayRecords = iTotalDisplayRecords;
this.sEcho = sEcho;
this.data = data;
}
// ... getters and setters
}
public TableBean mapTableBean(TableParameters tableParameters) {
int iTotalRecords = database.getCount();
int iTotalDisplayRecords = iTotalRecords;
if (null != tableParameters.getsEcho()){
String sEcho = tableParameters.getsEcho().toString();
}
List data = database.search(tableParameters.getiDisplayStart(), tableParameters.getiDisplayLength(),
tableParameters.getSortedColumnName(),
tableParameters.getSortedColumnDirection().equalsIgnoreCase("asc"));
return new TableBean(iTotalRecords, iTotalDisplayRecords, sEcho, data);
}
$(document).ready(function () {
$('#myDataTable').DataTable({
'destroy' : true,
'serverSide' : true,
'sAjaxSource': '/ApplicationName/Data/Person',
'sAjaxDataProp': 'data',
'order': [ [ 0, 'asc' ] ],
'columns':
[
{ 'data': 'name',
'render': function(data, type, row, meta){
if(type === 'display'){
data = '<a href="javascript:openPersonDetail(''+ row.socialSecurity +'');">' + data + '</a>'
}
return data;
}
} ,
{ 'data': 'socialSecurity'} ,
{ 'data': 'birthdate'} ,
{ 'data': 'gender'}
],
'scrollY' : 300,
'scrollCollapse' : true,
'paging' : true,
'autoWidth' : true,
'ordering' : true,
'searching' : false,
'pageLength' : 20,
'lengthChange' : false,
'pagingType' : 'full_numbers',
'dom' : '<"top"ip>rt<"bottom"fl><"clear">'
});
});
<script>
$('#example').DataTable({
"processing": true,
"serverSide": true,
"ajax": {
"url": "/employees",
"type": "POST",
"dataType": "json",
"contentType": "application/json",
"data": function (d) {
return JSON.stringify(d);
}
},
"columns": [
{"data": "name", "width": "20%"},
{"data": "position","width": "20%"},
{"data": "office", "width": "20%"},
{"data": "start_date", "width": "20%"},
{"data": "salary", "width": "20%"}
]
});
</script>