T.M. SoftStudio

feci quod potui, faciant meliora potentes

Купить полную версию книги "Среда разработки Eclipse 4: Руководство разработчика"

Создание GWT-приложений

Пример. Визуализация карты сайта Sitemap с GWT

Карта сайта представляет собой XML-файл, содержащий элементы <loc> с адресами страниц сайта, подлежащих индексации поисковыми системами.

Однако для тех же поисковых систем, а также для самих пользователей полезно иметь HTML-страницу, содержащую полный список ссылок на индексируемые страницы сайта.

Рассмотрим создание GWT-приложения, которое будет обеспечивать автоматическую генерацию и визуализацию такой HTML-карты сайта на основе файла sitemap.xml.

Откроем среду Eclipse и создадим проект простого GWT-приложения, используя мастер Google | Web Application Project.

Для работы с XML-контентом и HTTP-запросами добавим в файл .gwt.xml проекта наследование модулей:

<inherits name="com.google.gwt.xml.XML"/>

<inherits name="com.google.gwt.http.HTTP"/>

Изменим код главного класса GWT-приложения:

import com.google.gwt.core.client.EntryPoint;

import com.google.gwt.core.client.GWT;

import com.google.gwt.dom.client.Style.Position;

import com.google.gwt.dom.client.Style.Unit;

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.http.client.URL;

import com.google.gwt.user.client.ui.Anchor;

import com.google.gwt.user.client.ui.Button;

import com.google.gwt.user.client.ui.FlexTable;

import com.google.gwt.user.client.ui.HorizontalPanel;

import com.google.gwt.user.client.ui.Label;

import com.google.gwt.user.client.ui.RootPanel;

import com.google.gwt.xml.client.Document;

import com.google.gwt.xml.client.Node;

import com.google.gwt.xml.client.NodeList;

import com.google.gwt.xml.client.XMLParser;

public class GWT_Sitemap implements EntryPoint {

private int start=0;

private int step=10;

private int end;

public static native String ajax(String url) /*-{

AJAX=new XMLHttpRequest();

if (AJAX) {

AJAX.open("GET", url, false);

AJAX.send();

return AJAX.responseText;

} else{

return "";

}

}-*/;

public void onModuleLoad() {

final FlexTable table = new FlexTable();

final FlexTable.FlexCellFormatter cellFormatter = table.getFlexCellFormatter();

table.getElement().addClassName("table");

final RootPanel root=RootPanel.get("container");

root.getElement().getStyle().setPosition(Position.ABSOLUTE);

root.add(table);

final HorizontalPanel btnPanel=new HorizontalPanel();

btnPanel.setSpacing(10);

final Button next=new Button(">");

final Button prev=new Button("<");

final Label count=new Label();

final Button all=new Button("All");

final Button nextnext=new Button(">>");

final Button prevprev=new Button("<<");

btnPanel.add(prevprev);

btnPanel.add(prev);

btnPanel.add(next);

btnPanel.add(nextnext);

btnPanel.add(count);

btnPanel.add(all);

root.add(btnPanel);

RequestBuilder builderContents = new RequestBuilder(RequestBuilder.GET, URL.encode(GWT.getHostPageBaseURL()+"sitemap.xml"));

try {

builderContents.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {

}

public void onResponseReceived(Request request, Response response) {

String xml=response.getText();

Document docxml = XMLParser.parse(xml);

NodeList locList = docxml.getElementsByTagName("loc");

final int length=locList.getLength();

final String link[]=new String[length];

for(int i=0; i<length;i++){

Node loc=locList.item(i);

link[i]=loc.getFirstChild().getNodeValue();

}

end=step;

if(end>=length){

end=length;

}

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

String html=ajax(url);

String title=html.substring(html.indexOf("<title>")+7, html.indexOf("</title>"));

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.setWidget(i, 0, anc);

cellFormatter.addStyleName(i, 0, "cell");

cellFormatter.setWordWrap(i, 0, true);

}

next.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

next.setVisible(false);

table.removeAllRows();

start=end+1;

end=end+step;

if(end>=length){

end=length;

start=end-step;

}

int row=0;

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

String html=ajax(url);

String title=html.substring(html.indexOf("<title>")+7, html.indexOf("</title>"));

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.setWidget(row, 0, anc);

cellFormatter.addStyleName(row, 0, "cell");

cellFormatter.setWordWrap(row, 0, true);

row++;

}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

next.setVisible(true);

}

});

prev.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

prev.setVisible(false);

table.removeAllRows();

end=start-1;

start=end-step;

if(start<=0){

end=step;

start=0;

}

int row=0;

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

String html=ajax(url);

String title=html.substring(html.indexOf("<title>")+7, html.indexOf("</title>"));

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.setWidget(row, 0, anc);

cellFormatter.addStyleName(row, 0, "cell");

cellFormatter.setWordWrap(row, 0, true);

row++;

}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

prev.setVisible(true);

}

});

all.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

all.setVisible(false);

table.removeAllRows();

start=0;

end=length;

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

String html=ajax(url);

String title=html.substring(html.indexOf("<title>")+7, html.indexOf("</title>"));

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.setWidget(i, 0, anc);

cellFormatter.addStyleName(i, 0, "cell");

cellFormatter.setWordWrap(i, 0, true);

}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

all.setVisible(true);

}

});

nextnext.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

nextnext.setVisible(false);

table.removeAllRows();

end=length;

start=end-step;

int row=0;

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

String html=ajax(url);

String title=html.substring(html.indexOf("<title>")+7, html.indexOf("</title>"));

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.setWidget(row, 0, anc);

cellFormatter.addStyleName(row, 0, "cell");

cellFormatter.setWordWrap(row, 0, true);

row++;

}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

nextnext.setVisible(true);

}

});

prevprev.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

prevprev.setVisible(false);

table.removeAllRows();

start=0;

end=step;

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

String html=ajax(url);

String title=html.substring(html.indexOf("<title>")+7, html.indexOf("</title>"));

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.setWidget(i, 0, anc);

cellFormatter.addStyleName(i, 0, "cell");

cellFormatter.setWordWrap(i, 0, true);

}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

prevprev.setVisible(true);

}

});

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

}

});

} catch (RequestException e) {

}

}}

В коде класса GWT_Sitemap создается таблица, содержащая ссылки на страницы сайта, а также панель с кнопками навигации, обеспечивающими показ карты сайта блоками по 10 ссылок.

При загрузке HTML-страницы приложения с помощью класса com.google.gwt.http.client.RequestBuilder производится асинхронный запрос, загружающий файл sitemap.xml, который затем анализируется, используя класс com.google.gwt.xml.client.XMLParser.

Из файла sitemap.xml извлекаются адреса страниц сайта, и затем последовательно производится синхронная загрузка страниц сайта с извлечением из них содержимого тэга <title>.

На основе адреса страницы и ее тэга <title> формируется ссылка на страницу сайта с ее добавлением в таблицу HTML-страницы GWT-приложения.

Код HTML-страницы GWT-приложения:

<!doctype html>

<html>

<head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<link type="text/css" rel="stylesheet" href="GWT_Sitemap.css">

<title>GWT Sitemap</title>

<script type="text/javascript" language="javascript" src="gwt_sitemap/gwt_sitemap.nocache.js"></script>

</head>

<body>

<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>

<noscript>

<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">

Your web browser must have JavaScript enabled

in order for this application to display correctly.

</div>

</noscript>

<div>

<p id="container" ></p>

</div>

</body>

</html>

CSS-файл приложения:

.table{

border: 3px double silver;

padding:10px;

margin:10px;

}

.cell{

border: 2px double silver;

padding:10px;

background:lightgrey;

}

Для полностью асинхронной генерации HTML-версии карты сайта необходимо производить разбор страниц сайта на стороне сервера, для того чтобы связать URL-адрес страницы с ее тэгом <title>.

Поэтому изменим код главного класса GWT-приложения:

import com.google.gwt.core.client.EntryPoint;

import com.google.gwt.core.client.GWT;

import com.google.gwt.dom.client.Style.Position;

import com.google.gwt.dom.client.Style.Unit;

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.http.client.URL;

import com.google.gwt.user.client.ui.Anchor;

import com.google.gwt.user.client.ui.Button;

import com.google.gwt.user.client.ui.HTML;

import com.google.gwt.user.client.ui.HorizontalPanel;

import com.google.gwt.user.client.ui.Label;

import com.google.gwt.user.client.ui.RootPanel;

import com.google.gwt.user.client.ui.VerticalPanel;

import com.google.gwt.xml.client.Document;

import com.google.gwt.xml.client.Node;

import com.google.gwt.xml.client.NodeList;

import com.google.gwt.xml.client.XMLParser;

public class GWT_Sitemap implements EntryPoint {

private int start=0;

private int step=10;

private int end;

private RequestBuilder builder;

public void onModuleLoad() {

final VerticalPanel table = new VerticalPanel();

table.setSpacing(10);

table.getElement().addClassName("cell");

final RootPanel root=RootPanel.get("container");

root.getElement().getStyle().setPosition(Position.ABSOLUTE);

root.add(table);

final HorizontalPanel btnPanel=new HorizontalPanel();

btnPanel.setSpacing(10);

final Button next=new Button(">");

final Button prev=new Button("<");

final Label count=new Label();

final Button all=new Button("All");

final Button nextnext=new Button(">>");

final Button prevprev=new Button("<<");

btnPanel.add(prevprev);

btnPanel.add(prev);

btnPanel.add(next);

btnPanel.add(nextnext);

btnPanel.add(count);

btnPanel.add(all);

root.add(btnPanel);

RequestBuilder builderContents = new RequestBuilder(RequestBuilder.GET, URL.encode(GWT.getHostPageBaseURL()+"sitemap.xml"));

try {

builderContents.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {

}

public void onResponseReceived(Request request, Response response) {

String xml=response.getText();

Document docxml = XMLParser.parse(xml);

NodeList locList = docxml.getElementsByTagName("loc");

final int length=locList.getLength();

final String link[]=new String[length];

for(int i=0; i<length;i++){

Node loc=locList.item(i);

link[i]=loc.getFirstChild().getNodeValue();

}

end=step;

if(end>=length){

end=length;

}

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

//------------------------------------

builder = new RequestBuilder(RequestBuilder.GET, "/get?url="+url);

try {

builder.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {

}

public void onResponseReceived(Request request, Response response) {

if (200 == response.getStatusCode()) {

String respXml= response.getText();

Document docresp = XMLParser.parse(respXml);

String title =docresp.getElementsByTagName("title").item(0).getFirstChild().getNodeValue();

String url =docresp.getElementsByTagName("url").item(0).getFirstChild().getNodeValue();

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.add(anc);

HTML separator=new HTML("<hr/>");

table.add(separator);

} else {

}

}

});

} catch (RequestException e) {

}

//------------------------------------------------------------------

}

next.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

next.setVisible(false);

table.clear();

start=end+1;

end=end+step;

if(end>=length){

end=length;

start=end-step;

}

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

//------------------------------------

builder = new RequestBuilder(RequestBuilder.GET, "/get?url="+url);

try {

builder.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {

}

public void onResponseReceived(Request request, Response response) {

if (200 == response.getStatusCode()) {

String respXml= response.getText();

Document docresp = XMLParser.parse(respXml);

String title =docresp.getElementsByTagName("title").item(0).getFirstChild().getNodeValue();

String url =docresp.getElementsByTagName("url").item(0).getFirstChild().getNodeValue();

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.add(anc);

HTML separator=new HTML("<hr/>");

table.add(separator);

} else {

}

}

});

} catch (RequestException e) {

}

//--------------------------------------------------------------------

}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

next.setVisible(true);

}

});

prev.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

prev.setVisible(false);

table.clear();

end=start-1;

start=end-step;

if(start<=0){

end=step;

start=0;

}

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

//------------------------------------

builder = new RequestBuilder(RequestBuilder.GET, "/get?url="+url);

try {

builder.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {

}

public void onResponseReceived(Request request, Response response) {

if (200 == response.getStatusCode()) {

String respXml= response.getText();

Document docresp = XMLParser.parse(respXml);

String title =docresp.getElementsByTagName("title").item(0).getFirstChild().getNodeValue();

String url =docresp.getElementsByTagName("url").item(0).getFirstChild().getNodeValue();

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.add(anc);

HTML separator=new HTML("<hr/>");

table.add(separator);

} else {

}

}

});

} catch (RequestException e) {

}

//-----------------------------------------------------------------------}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

prev.setVisible(true);

}

});

all.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

all.setVisible(false);

table.clear();

start=0;

end=length;

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

//------------------------------------

builder = new RequestBuilder(RequestBuilder.GET, "/get?url="+url);

try {

builder.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {

}

public void onResponseReceived(Request request, Response response) {

if (200 == response.getStatusCode()) {

String respXml= response.getText();

Document docresp = XMLParser.parse(respXml);

String title =docresp.getElementsByTagName("title").item(0).getFirstChild().getNodeValue();

String url =docresp.getElementsByTagName("url").item(0).getFirstChild().getNodeValue();

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.add(anc);

HTML separator=new HTML("<hr/>");

table.add(separator);

} else {

}

}

});

} catch (RequestException e) {

}

//-------------------------------------------------------------------

}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

all.setVisible(true);

}

});

nextnext.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

nextnext.setVisible(false);

table.clear();

end=length;

start=end-step;

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

//------------------------------------

builder = new RequestBuilder(RequestBuilder.GET, "/get?url="+url);

try {

builder.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {

}

public void onResponseReceived(Request request, Response response) {

if (200 == response.getStatusCode()) {

String respXml= response.getText();

Document docresp = XMLParser.parse(respXml);

String title =docresp.getElementsByTagName("title").item(0).getFirstChild().getNodeValue();

String url =docresp.getElementsByTagName("url").item(0).getFirstChild().getNodeValue();

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.add(anc);

HTML separator=new HTML("<hr/>");

table.add(separator);

} else {

}

}

});

} catch (RequestException e) {

}

//--------------------------------------------------------------------

}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

nextnext.setVisible(true);

}

});

prevprev.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {

prevprev.setVisible(false);

table.clear();

start=0;

end=step;

for(int i=start;i<end;i++){

String url=URL.encode(link[i]);

//------------------------------------

builder = new RequestBuilder(RequestBuilder.GET, "/get?url="+url);

try {

builder.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {

}

public void onResponseReceived(Request request, Response response) {

if (200 == response.getStatusCode()) {

String respXml= response.getText();

Document docresp = XMLParser.parse(respXml);

String title =docresp.getElementsByTagName("title").item(0).getFirstChild().getNodeValue();

String url =docresp.getElementsByTagName("url").item(0).getFirstChild().getNodeValue();

Anchor anc=new Anchor();

anc.setHref(url);

anc.setText(title);

table.add(anc);

HTML separator=new HTML("<hr/>");

table.add(separator);

} else {

}

}

});

} catch (RequestException e) {

}

//------------------------------------------------------------------

}

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

prevprev.setVisible(true);

}

});

count.setText(start+"-"+end+" of "+length);

root.getElement().getParentElement().getStyle().setHeight(root.getElement().getOffsetHeight()+200, Unit.PX);

}

});

} catch (RequestException e) {

}

}}

Создадим сервлет приложения, извлекающий содержимое тэга <title> из страницы сайта:

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.jsoup.Jsoup;

import org.jsoup.nodes.Document;

@SuppressWarnings("serial")

public final class GetServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String url = request.getParameter("url");

Document doc = Jsoup.connect(url).get();

String title=doc.title();

response.setContentType("text/xml;charset=UTF-8");

PrintWriter writer = response.getWriter();

writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><resp><url>"+url+"</url><title>"+title+"</title></resp>");

writer.close();

}

}

В сервлете GetServlet для разбора страницы сайта используется библиотека jsoup (http://jsoup.org/).

Укажем сервлет в дескрипторе развертывания web.xml:

<servlet>

<servlet-name>com.tmsoftstudio.server.GetServlet</servlet-name>

<servlet-class>com.tmsoftstudio.server.GetServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>com.tmsoftstudio.server.GetServlet</servlet-name>

<url-pattern>/get</url-pattern>

</servlet-mapping>

После развертывания HTML-страница GWT-приложения будет отображать карту сайта (рис. 10.12).

Рис. 10.12. Визуализация карты сайта GWT-приложением