将JSON功能添加到您的GWT应用程序中

JSON简介
在Web应用程序上工作时,总是会出现客户端-服务器数据交换的问题。 在此问题上有多种方法,其中许多使用XML进行交换。 执行此任务的一种不太知名的格式是JSON。 JSON(JavaScript对象表示法)是一种轻量级的数据交换格式。 这对人类来说很容易读写,对机器来说也很容易解析和生成。 尽管JSON在传输的数据上可能有所不同,但与XML相比,JSON被认为不那么冗长,过时。 在线上有多种资源可帮助您开始使用JSON

JSON库
JSON是一种完全独立于语言的文本格式,并且提供了可用于大量编程语言的库。 对于Java中的JSON ,实现的源代码可用。 请注意,该站点未在存档文件中提供二进制文件,但是我们已经编译了这些类并将它们捆绑在一个JAR文件中,您可以在此处直接下载。

GWT和JSON集成
在本教程中,我将向您展示如何在GWT中操作JSON,以便您可以与启用JSON的Web应用程序进行通信。 请注意,在GWT应用程序中,实现客户端与服务器通信的最常见方法是通过RPC调用 因此,使用JSON通常适用于通过普通的旧HTTP调用访问外部服务器的情况。

创建应用程序
让我们开始创建一个新的Eclipse项目(“ File?New?Web Application Project”)并将其命名为“ JsonGwtProject”。 选择仅支持Google的Web工具包,而不支持App Engine。 服务器的角色将由GWT SDK提供的嵌入式Jetty容器扮演。

将JSON功能添加到您的GWT应用程序中

创建项目框架后,编辑模块声明文件(在本例中为“ JsonGwtProject.gwt.xml”)。 在读取“其他模块继承”的行之后添加以下行,以使您的GWT应用程序启用JSON。

<inherits name="com.google.gwt.json.JSON" />

领域模型对象
现在,让我们创建将用于保存数据的模型对象。 我们的模型是具有各个领域的“产品”类:

  • 名称
  • 公司
  • ***
  • 价格

为了说明如何使用嵌套的JSON表达式,将使用多种价格。

相应的Java类(普通的Java旧对象)如下:

package com.javacodegeeks.json.gwt.server.model;

import java.util.LinkedList;
import java.util.List;

public class Product {
 
 private String name;
 private String company;
 private String serialNumber;
 private List<Double> prices = new LinkedList<Double>();
 
 public Product(String name, String company, String serialNumber, List<Double> prices) {
  super();
  this.name = name;
  this.company = company;
  this.serialNumber = serialNumber;
  this.prices = prices;
 }
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getCompany() {
  return company;
 }
 public void setCompany(String company) {
  this.company = company;
 }
 public String getSerialNumber() {
  return serialNumber;
 }
 public void setSerialNumber(String serialNumber) {
  this.serialNumber = serialNumber;
 }
 public List<Double> getPrices() {
  return prices;
 }
 public void setPrices(List<Double> prices) {
  this.prices = prices;
 }

}

应用程序的服务器端
现在,让我们创建应用程序的服务器端代码。 我们将创建一个servlet,该servlet将用于模拟从中检索数据的外部服务器。 Servlet使用产品的静态列表创建对客户端的JSON响应(在实际应用程序中,将从DAO或更好地从其他服务中获取产品)。 确保将下载的json.jar包含在项目的类路径中,并且还将其复制到“ war \ WEB-INF \ lib”文件夹中。 servlet代码如下:

package com.javacodegeeks.json.gwt.server;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONObject;

import com.javacodegeeks.json.gwt.server.model.Product;

public class ProductsServlet extends HttpServlet {
 
 private static final long serialVersionUID = 8032611514671727168L;
 
 private static List<Product> products = new LinkedList<Product>();
 
 static {
  Product product1 = new Product("Prod1", "Company1", "12345", Arrays.asList(123.2, 123.6));
  Product product2 = new Product("Prod2", "Company2", "67890", Arrays.asList(234.2, 234.6));
  products.add(product1);
  products.add(product2);
 }

 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  
  try {
   
   JSONObject responseObj = new JSONObject();
   
   List<JSONObject> productObjects = new LinkedList<JSONObject>();
   
   for (Product product : products) {
    
    JSONObject productObj = new JSONObject();
    
    productObj.put("name", product.getName());
    productObj.put("company", product.getCompany());
    productObj.put("serialNumber", product.getSerialNumber());
    
    List<JSONObject> pricesObjects = new LinkedList<JSONObject>();
    for (Double price : product.getPrices()) {
     JSONObject priceObj = new JSONObject();
     priceObj.put("price", price);
     pricesObjects.add(priceObj);
    }
    
    productObj.put("prices", pricesObjects);
    
    productObjects.add(productObj);
   }
   
   responseObj.put("products", productObjects);
   
   PrintWriter writer = resp.getWriter();
   writer.write(responseObj.toString());
   writer.flush();
   
  } 
  catch (Exception e) {   
   e.printStackTrace();
   throw new ServletException(e);
  }
  
 }
 
}

Java JSON响应生成
让我解释一下如何生成JSON响应。 确保您是从org.json包而不是com.google.gwt.json导入JSON类。 第一步是创建一个JSONObject,它将保存响应。 由于我们很可能拥有许多产品,因此我们还创建了一个JSONObjects列表。 我们遍历现有产品,并为每个产品创建一个单独的对象。 在该对象中,我们添加键值对,就像使用Map一样。 对于价格,我们还创建了一个JSONObjects列表,然后将整个列表添加到产品的JSONObject中。 最后,我们将产品对象列表添加到响应的JSONObject中。 JSONObject的toString()方法用于创建字符串表示形式。 对于该示例,结果为:

{“产品”:
[
{“公司”:“公司1”,“名称”:“产品1”,“价格”:[{“价格”:123.2},{“价格”:123.6}],“***”:“ 12345”}
{“公司”:“公司2”,“名称”:“产品2”,“价格”:[{“价格”:234.2},{“价格”:234.6}],“***”:“ 67890”}
]}

web.xml中的Servlet配置
现在让我们配置应用程序,以便Servlet响应特定的URL。 编辑web.xml文件(位于“ war / WEB-INF”中)并粘贴以下内容(所有带有greetingService声明的原始内容都将被删除):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  
  <!-- Servlets -->
  <servlet>
    <servlet-name>ProductsServlet</servlet-name>
     <servlet-class>
     com.javacodegeeks.json.gwt.server.ProductsServlet
    </servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>ProductsServlet</servlet-name>
    <url-pattern>/jsongwtproject/products.json</url-pattern>
  </servlet-mapping>
  
  <!-- Default page to serve -->
  <welcome-file-list>
    <welcome-file>JsonGwtProject.html</welcome-file>
  </welcome-file-list>

</web-app>

GWT的客户端
最后,让我们创建GWT应用程序的入口点“ JsonGwtProject”(原始内容已完全删除)。 客户端将调用对服务器的HTTP GET调用,将接收JSON格式的响应,然后解析响应。 代码是:

package com.javacodegeeks.json.gwt.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;

public class JsonGwtProject implements EntryPoint {
    
    public void onModuleLoad() {
        
        final Button fetchDataButton = new Button("Fetch data");
        fetchDataButton.addStyleName("sendButton");
        
        RootPanel.get("fetchDataButtonContainer").add(fetchDataButton);
        
        fetchDataButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                fetchDataFromServer();
            }
        });
        
    }

    private void fetchDataFromServer() {
        
        try {
            
            RequestBuilder rb = new RequestBuilder(
                 RequestBuilder.GET, "/jsongwtproject/products.json");
            
            rb.setCallback(new RequestCallback() {
                @Override
                public void onResponseReceived(Request request, Response response) {
                    parseJsonData(response.getText());
                }
                @Override
                public void onError(Request request, Throwable exception) {
                    Window.alert("Error occurred" + exception.getMessage());
                }
            });
            rb.send();
            
        } 
        catch (RequestException e) {
            Window.alert("Error occurred" + e.getMessage());
        }
    }

    private void parseJsonData(String json) {

        JSONValue value = JSONParser.parse(json);

        JSONObject productsObj = value.isObject();
        
        JSONArray productsArray = productsObj.get("products").isArray();
        
        if (productsArray != null) {
            
            for (int i=0; i<=productsArray.size()-1; i++) {
                
                JSONObject productObj = productsArray.get(i).isObject();
                
                String name = productObj.get("name").isString().stringValue();
                String company = productObj.get("company").isString().stringValue();
                String serialNumber = productObj.get("serialNumber").isString().stringValue();
                
                StringBuffer priceSb = new StringBuffer();
                
                JSONArray pricesArray = productObj.get("prices").isArray();
                if (pricesArray != null) {
                    for (int j=0; j<=pricesArray.size()-1; j++) {
                        JSONObject priceObj = pricesArray.get(j).isObject();
                        double price = priceObj.get("price").isNumber().doubleValue();
                        if (j!=pricesArray.size()-1) {
                            priceSb.append("-");
                        }
                    }
                }
                String message = "Product -- " +
                    "\nName: " + name + 
                    "\nCompany: " + company +
                    "\nSerial: " + serialNumber + 
                    "\nPrices: " +  priceSb.toString();
                Window.alert(message);
                
            }
            
        }
    }

}

对于HTTP调用,使用RequestBuilder类。 定义了HTTP方法(GET)以及端点URL(已将servlet配置为响应)。 然后,使用RequestCallback类提供异步回调方法。 最后,请求被发送。 当响应从服务器到达时(如果未发生错误),将调用我们的parseJsonData方法。 使用GWT解析JSON数据现在让我们看看如何使用GWT内置方法解析接收到的数据。 确保您是从com.google.gwt.json包而不是org.json导入JSON类。 首先,我们使用JSONParser从字符串响应中创建一个JSONValue对象。 然后,我们使用isObject()方法检索一个JSONObject实例。 因为我们知道响应实际上是产品列表,所以我们通过调用JSONValue的isArray()方法来创建JSONArray类。 然后使用一个循环,并使用发生的JSONString对象的stringValue()方法提取模型的字段。 请注意,为了提取多个价格值,我们使用相同的过程遍历JSONArray对象。 准备HTML文件还必须更改“ JsonGwtProject.html”,以便为界面的按钮提供占位符。 编辑它,并在“ noscript”声明之后添加以下几行:

...
    <h1>Web Application Starter Project</h1>

    <table align="center">
      <tr>
        <td id="fetchDataButtonContainer"></td>
      </tr>
      <tr>
        <td colspan="2" style="color:red;" id="errorLabelContainer"></td>
      </tr>
    </table>
...

运行示例如果我们运行项目,则会出现该界面,实际上只有一个按钮。 点击按钮。 检索JSON数据,执行解析并将结果打印在屏幕上: 将JSON功能添加到您的GWT应用程序中 仅此而已。 与往常一样,您可以从此处下载Eclipse项目。

请享用!

相关文章 :

翻译自: https://www.javacodegeeks.com/2010/07/add-json-gwt-application.html