# 使用 jsGrid 组件
> 原文: [http://zetcode.com/articles/jsgridservlet/](http://zetcode.com/articles/jsgridservlet/)
在本教程中,我们从 Derby 数据库检索数据并将其显示在 jsGrid 组件中。 数据以 JSON 格式从 Derby 发送到 jsGrid。 作者的 Github [信息库](https://github.com/janbodnar/jsGrid-Servlet)中提供了本教程的源代码。
jsGrid 是基于 jQuery 的轻量级客户端数据网格控件。 它支持基本的网格操作,如插入,编辑,过滤,删除,排序和分页。 jsGrid 组件允许自定义其外观和子组件。
jQuery 是一个快速,小型且功能丰富的 JavaScript 库。 通过易于使用的 API(可在多种浏览器中使用),它使 HTML 文档的遍历和操作,事件处理,动画和 Ajax 变得更加简单。
Apache Derby 是完全用 Java 实现的开源关系数据库。 Derby 占用空间小,易于部署和安装。 它有两种模式:嵌入式和客户端/服务器。 也称为 Java DB。
JSON(JavaScript 对象表示法)是一种轻量级的数据交换格式。 人类很容易读写,机器也很容易解析和生成。 JSON 的官方互联网媒体类型为`application/json`。 JSON 文件扩展名是`.json`。
在我们的应用中,我们将使用以下四种 HTTP 方法:
* GET - 读取资源
* POST - 创建新资源
* PUT — 修改资源
* DELETE — 删除资源
这些 HTTP 动词将调用相应的 Java servlet 方法。
`cars.sql`
```java
CREATE TABLE CARS(ID INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY
(START WITH 1, INCREMENT BY 1), NAME VARCHAR(30), PRICE INT);
INSERT INTO CARS(NAME, PRICE) VALUES('Audi', 52642);
INSERT INTO CARS(NAME, PRICE) VALUES('Mercedes', 57127);
INSERT INTO CARS(NAME, PRICE) VALUES('Skoda', 9000);
INSERT INTO CARS(NAME, PRICE) VALUES('Volvo', 29000);
INSERT INTO CARS(NAME, PRICE) VALUES('Bentley', 350000);
INSERT INTO CARS(NAME, PRICE) VALUES('Citroen', 21000);
INSERT INTO CARS(NAME, PRICE) VALUES('Hummer', 41400);
INSERT INTO CARS(NAME, PRICE) VALUES('Volkswagen', 21600);
```
在示例中,我们使用`CARS`数据库表,该表位于 Derby `testdb`数据库中。
```java
javax
javaee-web-api
7.0
provided
org.apache.derby
derbyclient
10.12.1.1
com.googlecode.json-simple
json-simple
1.1.1
com.google.guava
guava
19.0
org.apache.derby
derbyoptionaltools
10.12.1.1
```
这些是我们项目中使用的依赖项。 `javaee-web-api`是一组用于创建 Java Web 应用的 JAR。 `derbyclient`是 Derby 的数据库驱动程序。 `json-simple`库用于处理 JSON 数据。 本项目使用`guava`的辅助方法。 `derbyoptionaltools`包含一个帮助程序方法,该方法将数据库结果集转换为 JSON 格式。
`index.html`
```java
jsGrid example
```
在`index.html`文件中,我们包含 jQuery 和 jsGrid 库。
```java
```
jsGrid 作为`div`标签包含在内。
`style.css`
```java
html {
height: 100%;
}
body {
height: 100%;
font-family: Verdana, Georgia;
}
```
为了显示 jsGrid 组件的完整大小,我们需要设置``和``标签的高度。
`sample.js`
```java
$(function () {
$.ajax({
type: "GET",
url: "/JsGridEx/ManageCars"
}).done(function () {
$("#jsGrid").jsGrid({
height: "60%",
width: "50%",
inserting: true,
editing: true,
sorting: true,
paging: true,
autoload: true,
pageSize: 10,
controller: {
loadData: function (filter) {
return $.ajax({
type: "GET",
url: "/JsGridEx/ManageCars",
data: filter
});
},
insertItem: function (item) {
return $.ajax({
type: "POST",
url: "/JsGridEx/ManageCars",
data: item
});
},
updateItem: function (item) {
return $.ajax({
type: "PUT",
url: "/JsGridEx/ManageCars",
data: item
});
},
deleteItem: function (item) {
return $.ajax({
type: "DELETE",
url: "/JsGridEx/ManageCars",
data: item
});
}
},
fields: [
{name: "NAME", title: "Name", type: "text", width: 60},
{name: "PRICE", title: "Price", type: "text", width: 50},
{type: "control"}
]
});
});
});
```
在`sample.js`文件中,我们创建并配置 jsGrid 组件。
```java
inserting: true,
editing: true,
sorting: true,
paging: true,
```
我们的 jsGrid 组件可以插入,编辑和排序数据,还支持分页。
```java
loadData: function (filter) {
return $.ajax({
type: "GET",
url: "/JsGridEx/ManageCars",
data: filter
});
}
```
`loadData()`函数在`ManageCars` Servlet 上发出 HTTP GET 方法。
```java
insertItem: function (item) {
return $.ajax({
type: "POST",
url: "/JsGridEx/ManageCars",
data: item
});
}
```
当我们插入新项目时,将在`ManageCars` Servlet 上发出 HTTP POST 方法。
```java
updateItem: function (item) {
return $.ajax({
type: "PUT",
url: "/JsGridEx/ManageCars",
data: item
});
}
```
更新项目会在`ManageCars` Servlet 上生成 HTTP PUT 方法。
```java
deleteItem: function (item) {
return $.ajax({
type: "DELETE",
url: "/JsGridEx/ManageCars",
data: item
});
}
```
删除项目会在`ManageCars` Servlet 上生成 HTTP DELETE 方法。
```java
fields: [
{name: "NAME", title: "Name", type: "text", width: 60},
{name: "PRICE", title: "Price", type: "text", width: 50},
{type: "control"}
]
```
jsGrid 组件具有三个两列:`NAME`和`PRICE`。 它们必须与 JSON 中返回的键完全匹配。
`ManageCars.java`
```java
package com.zetcode.web;
import com.zetcode.service.CarService;
import com.zetcode.util.Utils;
import java.io.IOException;
import java.util.Map;
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 org.json.simple.JSONArray;
@WebServlet(name = "ManageCars", urlPatterns = {"/ManageCars"})
public class ManageCars extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
JSONArray ar = CarService.getCarsJSON();
response.getWriter().write(ar.toJSONString());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException {
String name = request.getParameter("NAME");
int price = Integer.valueOf(request.getParameter("PRICE"));
CarService.insertCar(name, price);
getServletContext().log("Car " + name + " inserted");
}
@Override
protected void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException {
Map dataMap = Utils.getParameterMap(request);
String carName = dataMap.get("NAME");
int carPrice = Integer.valueOf(dataMap.get("PRICE"));
CarService.updateCar(carName, carPrice);
getServletContext().log("Car " + carName + " updated" + carPrice);
}
@Override
protected void doDelete(HttpServletRequest request, HttpServletResponse response)
throws ServletException {
Map dataMap = Utils.getParameterMap(request);
String carName = dataMap.get("NAME");
CarService.deleteCar(carName);
getServletContext().log("Car:" + carName + " deleted");
}
}
```
`ManageCars`是 Java Servlet,其中包含 HTTP GET,POST,PUT 和 DELETE 方法的相应方法。
```java
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
JSONArray ar = CarService.getCarsJSON();
response.getWriter().write(ar.toJSONString());
}
```
响应于 HTTP GET 方法,调用`doGet()`方法。 它调用`CarService`的`getCarsJSON()`方法,该方法从 CARS 表中返回所有汽车。 数据以 JSON 格式发送回客户端。
```java
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException {
String name = request.getParameter("NAME");
int price = Integer.valueOf(request.getParameter("PRICE"));
CarService.insertCar(name, price);
getServletContext().log("Car " + name + " inserted");
}
```
在`doPost()`方法中,我们从请求中检索`NAME`和`PRICE`参数,然后使用`CarService.insertCar()`方法将它们插入数据库中。 当我们收到一个 HTTP POST 方法时,`doPost()`方法被调用,期望添加新的资源。
```java
@Override
protected void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException {
Map dataMap = Utils.getParameterMap(request);
String carName = dataMap.get("NAME");
int carPrice = Integer.valueOf(dataMap.get("PRICE"));
CarService.updateCar(carName, carPrice);
getServletContext().log("Car " + carName + " updated" + carPrice);
}
```
在`doPut()`方法中,我们从请求中检索`NAME`和`PRICE`参数,然后使用`CarService.updateCar()`方法将它们插入数据库中。 当我们接收到 HTTP PUT 方法时,会期望`doPut()`方法被调用,期望对资源进行修改。
```java
@Override
protected void doDelete(HttpServletRequest request, HttpServletResponse response)
throws ServletException {
Map dataMap = Utils.getParameterMap(request);
String carName = dataMap.get("NAME");
CarService.deleteCar(carName);
getServletContext().log("Car:" + carName + " deleted");
}
```
在`doDelete()`方法中,我们从请求中检索`NAME`参数,并使用`CarService.deleteCar()`方法删除汽车。 当我们收到一个 HTTP DELETE 方法,期望删除资源时,将调用`doDelete()`方法。
`CarService.java`
```java
package com.zetcode.service;
import com.zetcode.util.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.apache.derby.optional.api.SimpleJsonUtils;
import org.json.simple.JSONArray;
public class CarService {
private static final Logger LOG = Logger.getLogger(CarService.class.getName());
private static JSONArray jarray;
public static void updateCar(String name, int price) {
Connection con = null;
PreparedStatement pst = null;
try {
DataSource ds = Utils.getDataSource();
con = ds.getConnection();
pst = con.prepareStatement("UPDATE CARS SET NAME=?, PRICE=? WHERE NAME=?");
pst.setString(1, name);
pst.setInt(2, price);
pst.setString(3, name);
pst.executeUpdate();
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(CarService.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
} finally {
try {
if (pst != null) {
pst.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
LOG.log(Level.WARNING, ex.getMessage(), ex);
}
}
}
public static void deleteCar(String name) {
Connection con = null;
PreparedStatement pst = null;
try {
DataSource ds = Utils.getDataSource();
con = ds.getConnection();
pst = con.prepareStatement("DELETE FROM CARS WHERE Name=?");
pst.setString(1, name);
pst.executeUpdate();
} catch (SQLException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
} finally {
try {
if (pst != null) {
pst.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
LOG.log(Level.WARNING, ex.getMessage(), ex);
}
}
}
public static void insertCar(String name, int price) {
Connection con = null;
PreparedStatement pst = null;
try {
DataSource ds = Utils.getDataSource();
con = ds.getConnection();
pst = con.prepareStatement("INSERT INTO CARS(NAME, PRICE) "
+ "VALUES(?, ?)");
pst.setString(1, name);
pst.setInt(2, price);
pst.executeUpdate();
} catch (SQLException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
} finally {
try {
if (pst != null) {
pst.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
LOG.log(Level.WARNING, ex.getMessage(), ex);
}
}
}
public static JSONArray getCarsJSON() {
Connection con = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
DataSource ds = Utils.getDataSource();
con = ds.getConnection();
pst = con.prepareStatement("SELECT NAME, PRICE FROM Cars");
rs = pst.executeQuery();
jarray = SimpleJsonUtils.toJSON(rs);
} catch (SQLException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
} finally {
try {
if (rs != null) {
rs.close();
}
if (pst != null) {
pst.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
LOG.log(Level.WARNING, ex.getMessage(), ex);
}
}
return jarray;
}
}
```
`CarService`包含用于数据检索和修改的方法。 我们使用标准的 JDBC 代码。 Java 数据库连接(JDBC)是 Java 编程语言的应用编程接口(API),它定义了客户端如何访问数据库。
```java
DataSource ds = Utils.getDataSource();
con = ds.getConnection();
pst = con.prepareStatement("DELETE FROM CARS WHERE Name=?");
pst.setString(1, name);
pst.executeUpdate();
```
在这里,我们创建数据源并建立与 Derby 数据库的新连接。 我们执行`DELETE` SQL 语句。
```java
DataSource ds = Utils.getDataSource();
con = ds.getConnection();
pst = con.prepareStatement("INSERT INTO CARS(NAME, PRICE) "
+ "VALUES(?, ?)");
pst.setString(1, name);
pst.setInt(2, price);
pst.executeUpdate();
```
这是用于插入新车的 JDBC 代码。
```java
DataSource ds = Utils.getDataSource();
con = ds.getConnection();
pst = con.prepareStatement("SELECT NAME, PRICE FROM Cars");
rs = pst.executeQuery();
jarray = SimpleJsonUtils.toJSON(rs);
```
在`getCarsJSON()`方法中,我们得到一个结果集,并使用`SimpleJsonUtils.toJSON()`将其转换为`JSONArray`。 该方法是`derbyoptionaltools`的一部分。
`Utils.java`
```java
package com.zetcode.util;
import com.google.common.base.Splitter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import org.apache.derby.jdbc.ClientDataSource;
public class Utils {
public static DataSource getDataSource() {
ClientDataSource ds = new ClientDataSource();
ds.setDatabaseName("testdb");
ds.setUser("app");
ds.setPassword("app");
ds.setServerName("localhost");
ds.setPortNumber(1527);
return ds;
}
public static Map getParameterMap(HttpServletRequest request) {
BufferedReader br = null;
Map dataMap = null;
try {
InputStreamReader reader = new InputStreamReader(
request.getInputStream());
br = new BufferedReader(reader);
String data = br.readLine();
dataMap = Splitter.on('&')
.trimResults()
.withKeyValueSeparator(
Splitter.on('=')
.limit(2)
.trimResults())
.split(data);
return dataMap;
} catch (IOException ex) {
Logger.getLogger(Utils.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ex) {
Logger.getLogger(Utils.class.getName()).log(Level.WARNING, null, ex);
}
}
}
return dataMap;
}
}
```
`Utils`是一个帮助程序类,它包含两个方法:`getDataSource()`和`getParameterMap()`。
```java
public static DataSource getDataSource() {
ClientDataSource ds = new ClientDataSource();
ds.setDatabaseName("testdb");
ds.setUser("app");
ds.setPassword("app");
ds.setServerName("localhost");
ds.setPortNumber(1527);
return ds;
}
```
`getDataSource()`创建并返回一个 Derby 数据源。
```java
InputStreamReader reader = new InputStreamReader(
request.getInputStream());
br = new BufferedReader(reader);
String data = br.readLine();
dataMap = Splitter.on('&')
.trimResults()
.withKeyValueSeparator(
Splitter.on('=')
.limit(2)
.trimResults())
.split(data);
return dataMap;
```
与`doGet()`和`doPost()`方法不同,`doPut()`和`doDelete()`无法使用`getParameter()`方法检索请求参数。 我们必须从流中获取它们。 为此,我们使用番石榴的`Splitter`类。 解析参数并在映射中返回。
![jsGrid component](img/7cfc528dc29ee4ecf7293504e8ec2a5c.jpg)
图:jsGrid 组件
在本教程中,我们使用了 jsGrid 组件。 我们已使用从 Derby 数据库检索的数据填充了该组件。 数据以 JSON 格式从数据库发送。
您可能也对以下相关教程感兴趣: [Java 教程](/lang/java/), [jQuery DatePicker 教程](/articles/jquerydatepicker/), [Datatables JSON 服务器教程](/articles/datatablesjsonserver/), [Apache Derby 教程](/db/apachederbytutorial/) 。