JSON (JavaScript Object Notation) - это универсальный, легкий и удобный текстовый формат обмена данными, основанный на языке JavaScript. Как и XML, он очень легко воспринимается людьми. JSON является независимым от языка обработки, существуют специальные библиотеки практически во всех языках программирования. В то время, как XML часто используется, например, для хранения настроек программ, то JSON больше используется для работы в сети.
Рассмотрим использование JSON в GWT приложении. В GWT наиболее общий путь взаимодействия с сервером происходит через GWT-RPC, так как он делает все связи на Java особенно простыми и эффективными. JSON используется когда общение с сервером происходит через простые HTTP вызовы.
Создадим веб проект в Eclipse (File - New - Web Application Project) и назовем его “JsonGwtApp”.
Для работы с JSON на клиентской стороне, в файл JsonGwtApp.gwt.xml следует добавить следующую строку:
<inherits name="com.google.gwt.json.JSON" />
Создадим модель объекта, который будет использоваться для хранения данных.
package com.dmitrynikol.json.gwt.server.model;
import java.util.LinkedList;
import java.util.List;
public class Book {
public String id;
public String title;
public String author;
public List<Double> prices = new LinkedList<Double>();
public Book(String id, String title, String author, List<Double> prices) {
this.id = id;
this.title = title;
this.author = author;
this.prices = prices;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public List<Double> getPrices() {
return prices;
}
public void setPrices(List<Double> prices) {
this.prices = prices;
}
}
Теперь пришла очередь к серверной части приложения. Создадим сервлет, который будет использоваться для имитации сервера, от которого мы будет получать данные. Сервлет создает JSON ответ клиенту используя список книг. Также следует добавить в classpath проекта библиотеку json.jar и скопировать ее в “war\WEB-INF\lib”.
package com.dmitrynikol.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 com.dmitrynikol.json.gwt.server.model.Book;
import org.json.JSONObject;
public class BooksServlet extends HttpServlet {
private static final long serialVersionUID = 5984818046261512114L;
private static List<Book> books = new LinkedList<Book>();
static {
books.add(new Book("132529", "The Hound of the Baskervilles",
"Arthur Conan Doyle", Arrays.asList(40.0, 45.2)));
books.add(new Book("745353", "The Man in the Brown Suit",
"Agatha Christie", Arrays.asList(37.0, 40.3)));
books.add(new Book("248941", "Liberty Bar", "Georges Simenon",
Arrays.asList(34.2, 37.7)));
books.add(new Book("478134", "The Case of the Turning Tide",
"Erle Stanley Gardner", Arrays.asList(25.5, 28.3)));
books.add(new Book("328473", "The Dogs of War", "Frederick Forsyth",
Arrays.asList(25.0, 30.3)));
}
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
JSONObject responseObject = new JSONObject();
List<JSONObject> booksObjects = new LinkedList<JSONObject>();
for (Book book : books) {
JSONObject booksObj = new JSONObject();
booksObj.put("id", book.getId());
booksObj.put("title", book.getTitle());
booksObj.put("author", book.getAuthor());
List<JSONObject> pricesObjects = new LinkedList<JSONObject>();
for (Double price : book.getPrices()) {
JSONObject priceObj = new JSONObject();
priceObj.put("price", price);
pricesObjects.add(priceObj);
}
booksObj.put("prices", pricesObjects);
booksObjects.add(booksObj);
}
responseObject.put("books", booksObjects);
PrintWriter writer = response.getWriter();
writer.write(responseObject.toString());
writer.flush();
} catch (Exception ex) {
ex.printStackTrace();
throw new ServletException();
}
}
}
Сервлет нам будет возвращать след. данные:
{
"books": [
{
"id": "132529",
"author": "Arthur Conan Doyle",
"title": "The Hound of the Baskervilles",
"prices": [
{
"price": 40
},
{
"price": 45.2
}
]
} … и т.д.
]
}
Сконфигурируем сервлет так, чтобы он отвечал на определенный url. Нужно поправить файл web.xml (war\WEB-INF\web.xml). Он должен выглядеть так:
<?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>
<servlet>
<servlet-name>BooksServlet</servlet-name>
<servlet-class>com.dmitrynikol.json.gwt.server.BooksServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BooksServlet </servlet-name>
<url-pattern>/jsongwtapp/books</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>JsonGwtApp.html</welcome-file>
</welcome-file-list>
</web-app>
Осталось еще написать клиентскую часть. Создадим стартовую точку GWT приложения. На клиентской стороне последовательность действий выглядит так: выполняется HTTP GET вызов у сервера, приходит ответ в JSON формате и выполняется парсинг ответа.
package com.dmitrynikol.json.gwt.client;
import java.util.LinkedList;
import java.util.List;
import com.dmitrynikol.json.gwt.client.widget.BooksWidget;
import com.dmitrynikol.json.gwt.client.widget.IBook;
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 JsonGwtApp implements EntryPoint {
@Override
public void onModuleLoad() {
final Button tableBooksButton = new Button("Show books");
RootPanel.get("showTableBooksButton").add(tableBooksButton);
tableBooksButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
getDataFromServer();
}
});
}
public void getDataFromServer() {
try {
RequestBuilder requestBuilder = new RequestBuilder(
RequestBuilder.GET, "/jsongwtapp/books");
requestBuilder.setCallback(new RequestCallback() {
@Override
public void onResponseReceived(Request request,
Response response) {
BooksWidget<IBook> booksWidget = new BooksWidget<IBook>();
List<IBook> books = parseJsonData(response.getText());
if (books != null) {
booksWidget.setData(books);
booksWidget.show();
}
}
@Override
public void onError(Request request, Throwable exception) {
Window.alert(exception.getMessage());
}
});
requestBuilder.send();
} catch (RequestException ex) {
Window.alert(ex.getMessage());
}
}
public List<IBook> parseJsonData(String json) {
JSONValue value = JSONParser.parseStrict(json);
JSONObject booksObject = value.isObject();
JSONArray booksArray = booksObject.get("books").isArray();
if (booksArray != null) {
List<IBook> books = new LinkedList<IBook>();
for (int i = 0; i <= booksArray.size() - 1; i++) {
JSONObject bookObj = booksArray.get(i).isObject();
String id = bookObj.get("id").isString().stringValue();
String title = bookObj.get("title").isString().stringValue();
String author = bookObj.get("author").isString().stringValue();
JSONArray pricesArray = bookObj.get("prices").isArray();
List<Double> prices = new LinkedList<Double>();
if (pricesArray != null) {
for (int k = 0; k <= pricesArray.size() - 1; k++) {
JSONObject priceObj = pricesArray.get(k).isObject();
double price = priceObj.get("price").isNumber().doubleValue();
prices.add(price);
}
}
IBook book = new IBook(id, title, author, prices);
books.add(book);
}
return books;
}
return null;
}
}
Для HTTP вызова используется класс RequestBuilder и ассинхронный метод обратного вызова класса RequestCallback. Далее просто вызываем метод send() для отправки HTTP запроса основанного на текущей конфигурации.
Информацию о книгах выведем в таблицу, а саму таблицу поместим в диалоговое окно.
package com.dmitrynikol.json.gwt.client.widget;
import java.util.LinkedList;
import java.util.List;
public class IBook {
public String id;
public String title;
public String author;
public List<Double> prices = new LinkedList<Double>();
public IBook(String id, String title, String author, List<Double> prices) {
this.id = id;
this.title = title;
this.author = author;
this.prices = prices;
}
public String getId() {
return id;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public List<Double> getPrices() {
return prices;
}
public void setPrices(List<Double> prices) {
this.prices = prices;
}
}
package com.dmitrynikol.json.gwt.client.widget;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Widget;
public class BooksWidget<T extends IBook> extends DialogBox {
public static BooksWidgetUiBinder uiBinder = GWT.create(BooksWidgetUiBinder.class);
public interface BooksWidgetUiBinder extends UiBinder<Widget, BooksWidget<?>> {
}
@UiField CellTable<T> bookTable;
@UiField Anchor close;
public BooksWidget() {
setWidget(uiBinder.createAndBindUi(this));
setText("Detective books");
}
public void setData(List<T> books) {
bookTable.addColumn(new TextColumn<T>() {
@Override
public String getValue(T object) {
return object.getId();
}
}, "Id");
bookTable.addColumn(new TextColumn<T>() {
@Override
public String getValue(T object) {
return object.getTitle();
}
}, "Title");
bookTable.addColumn(new TextColumn<T>() {
@Override
public String getValue(T object) {
return object.getAuthor();
}
}, "Author");
bookTable.addColumn(new TextColumn<T>() {
@Override
public String getValue(T object) {
List<Double> prices = object.getPrices();
StringBuffer priceBuf = new StringBuffer();
for (Double price : prices) {
priceBuf.append(price + " ");
}
return priceBuf.toString();
}
}, "Price");
bookTable.setRowCount(books.size(), true);
bookTable.setRowData(0, books);
}
@UiHandler("close")
void onCloseClicked(ClickEvent event) {
hide();
}
}
Также следует изменить файл JsonGwtApp.html, т.к. мы обращаемся к елементу по id.<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
>
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:c='urn:import:com.google.gwt.user.cellview.client'<
g:HTMLPanel
>>
<div<
c:CellTable ui:field="bookTable"/
>>
</div<
div
><
g:Anchor ui:field="close" text="close"/
>>
</div>
</g:HTMLPanel>
</ui:UiBinder
.....
>
<h1 align="center">JSON GWT Application</h1>
<div align="center" id="showTableBooksButton" /
.....
После запуска приложения, на страничке браузера можно увидеть заголовок и кнопку для вывода информации о книгах. После клика на кнопке получаем JSON данные, выполняется парсинг и данные выводятся на экран.
Вот и все. Eclipse проект можно скачать по следующей ссылке.
Комментариев нет:
Отправить комментарий