我在一个单页面应用程序上工作,我想在使用Spring MVC的应用程序的一部分中使用网格功能。 自从我上次使用JQGrid以来已经有一段时间了,找到让我起床所需的信息有点困难。 在这篇文章中,我想整理所有信息并将其放入教程中以供遵循,以便任何可能使用相同功能的人都可以发现设置JQGrid很有帮助 。
首先,我们将在Eclipse上设置一个示例Web项目,并如下定义web.xml;
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>JQGridExample</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>JQGridExample</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JQGridExample</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
为了连接Spring MVC,我已经注册了DispatcherServlet以便在启动时加载。 基本上,这就是注册任何Spring MVC应用程序的方式。 接下来,我们需要创建spring配置以注册我们spring MVC应用程序所需的组件/元素。
在这种情况下,我将spring上下文文件名保留为web.xml上给出的“ servlet-name”,因为默认情况下,当spring容器加载时,它将查找格式为<servletname> -servlet的文件。 XML文件
如果要为spring上下文配置文件使用任何其他名称,则可以这样做。 您只需要在web.xml上注册上下文加载器 。
因此,让我们看看我们的spring上下文配置文件是什么样子;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.example.jqgrid.controller" />
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<mvc:annotation-driven/>
</beans>
我们首先注册包含所有控制器类的包。 在这种情况下,它将只是一个控制器。 使用component-scan元素,它将扫描“ controller”包下的所有类。
接下来,我们告诉Spring容器如何解析我们的JSP文件。 在这种情况下,将使用内部视图解析器,并且我们提供JSP文件在应用程序上的驻留位置。
此配置的下一个有趣的部分是<mvc:resources>元素。 定义它的原因是让Spring容器知道我们的静态资源,例如javascript文件,图像,样式表。 如果我们不将它们定义为资源,那么每当您在应用程序中例如引用javascript文件时,spring mvc都将通过查看定义的URL模式来尝试匹配现有的控制器。 在这种情况下,我所有的css,javascript,图像文件都位于resources文件夹下。
然后,我定义index.jsp ,这是我们应用程序的入口点。 现在,我不想在此页面上执行任何操作,而只是将其重定向到通过spring-mvc解决的另一页面。 我们的index.jsp文件如下:
<script type="text/javascript">
window.location.replace("jqGridExample");
</script>
我只是将URL 重定向到jqGridExample 。 现在,要了解如何通过spring-mvc解决此问题,我们将需要查看控制器类。 我们的控制器类如下:
package com.example.jqgrid.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.example.jqgrid.common.util.JsonUtil;
import com.example.jqgrid.dto.JQGridDTO;
import com.example.jqgrid.dto.SuperHeroDTO;
import com.example.jqgrid.handler.JQGridHandler;
/**
* This class acts as the controller for JQGrid related functionality.
*
* @author Dinuka Arseculeratne
*
*/
@Controller
public class JQGridController {
/**
* This method will display the page used to display the grid.
*
* @param req
* @param res
* @return
*/
@RequestMapping(method = { RequestMethod.POST, RequestMethod.GET }, path = "/jqGridExample")
public String jqGrid(HttpServletRequest req, HttpServletResponse res) {
String forward = "jqgrid/jqGridData";
return forward;
}
/**
* This method will handle fetching data required for the JQGrid.
*
* @param req
* @param res
* @return
*/
@RequestMapping(method = { RequestMethod.POST, RequestMethod.GET }, path = "/loadData")
public String loadData(HttpServletRequest req, HttpServletResponse res) {
String forward = "common/formData";
JQGridDTO<SuperHeroDTO> gridData = new JQGridHandler().loadSuperHeroes(req);
req.setAttribute("formData", JsonUtil.toJsonObj(gridData));
return forward;
}
}
因此,如果我们看第一种方法,可以看到我们只是返回了一个名为“ jqgrid / jqGridData”的文本。 现在要了解它的作用,我们需要返回并查看我们的spring上下文配置文件。 这样,我们指定所有JSP文件都位于“ WEB-INF / jsp ”文件夹中,后缀为“ .jsp ”。 因此,在这种情况下,我们从此方法返回的路径告诉spring容器,实际上要返回的JSP在“ WEB-INF / jsp / jqgrid / jqGridData.jsp ”中。 请注意,我们不需要将后缀指定为“ .jsp”,因为我们已经在spring上下文配置中对其进行了配置。
在查看定义了JQGrid的页面之后,我们将回到第二种方法。 jqGridData.jsp如下所示;
<!DOCTYPE html>
<html>
<head>
<title>JQGrid Example</title>
<link href="resources/css/jquery-ui.css" rel="stylesheet">
<link href="resources/css/jquery-ui.theme.css" rel="stylesheet">
<link href="resources/css/jquery-ui.structure.min.css" rel="stylesheet">
<link rel="stylesheet" href="resources/css/ui.jqgrid.css">
</head>
<body>
<div>
<table id="list">
<tr>
<td />
</tr>
</table>
<div id="pager"></div>
<div style="margin-top:10px;">
<input type="button" id="showSelected" value="Show Selected"/>
</div>
</div>
<script src="resources/js/jquery-1.11.1.min.js"></script>
<script src="resources/js/jquery-ui.min.js"></script>
<script src="resources/js/i18n/grid.locale-en.js"></script>
<script src="resources/js/jquery.jqGrid.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#list").jqGrid({
url : "loadData",
datatype : "json",
mtype : 'POST',
colNames : [ 'Name','Alias','Super Power'],
colModel : [ {
name : 'name',
index : 'name',
width : 150
}, {
name : 'alias',
index : 'alias',
width : 150,
editable : false
}, {
name : 'power',
index : 'power',
width : 550,
editable : false
}],
pager : '#pager',
rowNum : 10,
height: 'auto',
rowList : [ 10 ],
sortname : 'invid',
sortorder : 'desc',
viewrecords : true,
gridview : true,
multiselect: true,
multiboxonly: false,
caption : 'Super Heroes',
jsonReader : {
repeatitems : false,
}
});
jQuery("#list").jqGrid('navGrid', '#pager', {
edit : false,
add : false,
del : false,
search : false
});
$('#showSelected').on('click',function(){
var selRowArr = jQuery("#list").getGridParam('selarrrow');
var selectedAppIds = [];
for(var i=0;i<selRowArr.length;i++){
var celValue = $('#list').jqGrid('getCell', selRowArr[i], 'alias');
selectedAppIds.push(celValue);
}
alert(selectedAppIds);
$('#list').trigger( 'reloadGrid' );
});
});
</script>
</body>
</html>
首先,我们需要定义将在其上加载JQGrid的元素。 在这种情况下,这是ID为“ list ”HTML表格元素。 并且由于我们需要分页功能,因此可以在网格下方定义分页部分。 在这种情况下,分页部分由div定义,其ID为“ pager ”。
然后,我们将Java脚本代码作为底部。 在这里,我们通过调用传入所需属性的方法jqGrid()来加载JQGrid。 我将不解释此处定义的所有属性,因为在此实例中还有许多未使用的属性。 将解释与本教程最相关的属性。 首先, URL 。 这被定义为“ loadData ”。 我们需要返回控制器类以了解其映射方式。
在控制器上,我们将第二种方法定义为“ loadData ”,该方法获取网格所需的数据。 现在有趣的是,JQGrid期望以特定格式发送数据。 为了遵守这种格式,我定义了一个类来保存此结构,该类定义为JQGridDTO 。 让我们看看该类的样子。
package com.example.jqgrid.dto;
import java.io.Serializable;
import java.util.List;
/**
* This class acts as common template for all pages that use the JQGrid.
*
* @author Dinuka Arseculeratne
*
* @param <T>
*/
public class JQGridDTO < T extends Serializable > {
private int page;
private String total;
private String records;
private List<T> rows;
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public String getTotal() {
return total;
}
public void setTotal(String total) {
this.total = total;
}
public String getRecords() {
return records;
}
public void setRecords(String records) {
this.records = records;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
}
这是JQGrid所需的数据结构。 为了使此类能够根据需要将不同类型的数据传递到网格,我将行数据结构保持通用。 只要实现Serializable接口,它就可以是任何类型的对象。
所以我是超级英雄的忠实粉丝,因此在这种情况下,我将显示一些超级英雄的信息。 我加入了DC和Marvel宇宙中的超级英雄,以使所有人开心。
因此,让我们看一下数据对象和将加载数据的处理程序类;
package com.example.jqgrid.dto;
import java.io.Serializable;
/**
*
* @author Dinuka Arseculeratne
*
*/
public class SuperHeroDTO implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1420635747715993129L;
private String name;
private String alias;
private String power;
public SuperHeroDTO(String name, String alias, String power) {
this.name = name;
this.alias = alias;
this.power = power;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getPower() {
return power;
}
public void setPower(String power) {
this.power = power;
}
}
package com.example.jqgrid.handler;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.example.jqgrid.dto.JQGridDTO;
import com.example.jqgrid.dto.SuperHeroDTO;
/**
* The handler class used to fetch the data required.
*
* @author Dinuka Arseculeratne
*
*/
public class JQGridHandler {
/**
* This method will fetch the super hero list. Of course i have mixed and
* matched DC and Marvel in order to keep peace on the universe.
*
* @return
*/
public JQGridDTO<SuperHeroDTO> loadSuperHeroes(final HttpServletRequest req) {
/**
* The page and rows are sent from the JQGrid component with the Ajax
* query.
*
*/
int page = Integer.valueOf(req.getParameter("page")).intValue();
int pageSize = Integer.valueOf(req.getParameter("rows")).intValue();
/**
* I am not using the star index and end index in this case, but in an
* ideal situation, you will be passing the start and end index to your
* pagination SQL query.
*
*/
int startIndex = page == 1 ? 0 : (pageSize * (page - 1));
int endIndex = page == 1 ? pageSize : pageSize * page;
int total = -1;
JQGridDTO<SuperHeroDTO> jqGridData = new JQGridDTO<SuperHeroDTO>();
List<SuperHeroDTO> superHeroList = new LinkedList<SuperHeroDTO>();
SuperHeroDTO flash = new SuperHeroDTO("Barry Allen", "Flash", "Super speed, Taping into the speed force");
superHeroList.add(flash);
SuperHeroDTO superMan = new SuperHeroDTO("Clark Kent", "Superman", "Flying, super speed");
superHeroList.add(superMan);
SuperHeroDTO batman = new SuperHeroDTO("Bruce Wayne", "Batman", "Cool toys, Intelligence");
superHeroList.add(batman);
SuperHeroDTO professorX = new SuperHeroDTO("Professor Xavier", "Professor X", "Mind control");
superHeroList.add(professorX);
/**
* The total in the ideal situation would be the count of the records of
* your SQL query from the table you want to fetch data from.
*
*/
total = superHeroList.size();
jqGridData.setPage(page);
jqGridData.setTotal(String.valueOf(Math.ceil((double) total / pageSize)));
jqGridData.setRecords(String.valueOf(total));
jqGridData.setRows(superHeroList);
return jqGridData;
}
}
通常,您将使用数据库来获取数据。 为了保持本教程的简洁,我刚刚加载了静态数据。 在代码注释中,我提到了使用实际数据库时如何传递数据。
在这种情况下,将JQGrid设置为接收JSON格式的数据。 因此,要将我们的超级英雄对象转换为其等效的JSON,我使用了Google的GSON库。 我编写了一个帮助程序类,将JSON对象转换为Java对象,并将Java对象转换为JSON对象,这是我在以前的一篇文章中共享的,您可以在这里找到。
我尚未使用spring-mvc默认功能发送JSON响应。 在这个示例中,我要做的是在请求属性中设置JSON输出,然后将页面转发到一个普通页面,在该页面中,它只是打印出该属性,并且响应将由JQGrid组件发出的Ajax请求发送回去。 该公共页面定义如下:
<%=request.getAttribute("formData")%>
回到定义JQGrid的JSP文件,我要关注的下一个重要属性是“ colModel ” 。 这会将在JSON输出上发送的数据映射到显示的网格列。 在这种情况下,您可以看到此处提到的名称是在我们的超级英雄数据对象上定义的实例变量名称。 其余属性是不言自明的,因此我不会深入研究这些属性的细节。
我需要的另一个重要用例是能够将选定的行发送到后端。 为此,您可以使用内置的JQGrid函数。 以下代码显示了在所有选定行上检索超级英雄名称的代码(在这种情况下,因为网格上启用了多选功能),并将其放入Java脚本数组中。
$('#showSelected').on('click',function(){
var selRowArr = jQuery("#list").getGridParam('selarrrow');
var selectedAppIds = [];
for(var i=0;i<selRowArr.length;i++){
var celValue = $('#list').jqGrid('getCell', selRowArr[i], 'alias');
selectedAppIds.push(celValue);
}
alert(selectedAppIds);
$('#list').trigger( 'reloadGrid' );
});
- 最后以关于如何使用Spring MVC和Gson设置JQGrid的教程结束。 工作代码已签入我的GIT存储库,可以在这里找到。
您可以根据需要克隆存储库并运行该应用程序。
翻译自: https://www.javacodegeeks.com/2016/01/integrating-jqgrid-spring-mvc-gson.html