Опубликован: 24.03.2009 | Доступ: свободный | Студентов: 2283 / 115 | Оценка: 4.24 / 3.93 | Длительность: 17:47:00
Лекция 10:

Создание взаимодействующих с сервером приложений в Silverlight

Silverlight и Java

Язык программирования Java компилируется в байт-код, который либо интерпретируется, либо компилируется методом Just-In-Time (JIT) и вызывается во время выполнения на виртуальной машине. Это делает его идеально подходящим для серверных сред, особенно когда в центре обработки данных представлены различные операционные системы. Java поддерживается практически всеми основными операционными системами.

Существует много способов создания серверных приложений на Java и ее версии для предприятий, называемой обычно J2EE или просто JEE. Один из методов - Серверные страницы Java (Java Server Pages, JSP), концепция которых аналогична PHP, в которых для разметки необходимого вывода используется код, выполняющийся во время выполнения. Итак, для создания таких страниц используется стандартная разметка HTML, но в нее помещаются теги JSP, которые будут выполняться при отображении страницы. Другой способ - использование Сервлета (Servlet) Java, который является приложением, выполняющимся на сервере и принимающим параметры через HTTP.

Открытость Silverlight позволяет создавать приложения, объединяющие в себе Silverlight и Java. Для построения страниц, включающих содержимое Silverlight, может использоваться технология JSP и серверные технологии, такие как сервлеты, идеально подходят для формирования XAML, отображаемого браузером.

Чтобы продемонстрировать создание приложений Silverlight в среде Java, поработаем с обеими технологиями. Сначала рассмотрим, как построить JSP-страницу для размещения элемента управления Silverlight. Затем создадим сервлет для генерирования XAML, визуальное представление которого будет формировать элемент управления Silverlight.

Создание сервлета для генерирования XAML

Сервлет - это приложение, расширяющее класс HttpServlet из пространства имен javax.servlet. Он предоставляет две функции, doGet и doPost, используемые для перехвата команд HTTP-GET v\ HTTP-POST, соответственно. Каждая из этих функций принимает объекты HTTPRequest (HTTP-запрос) и HTTPResponse (HTTP-ответ). Первый используется для получения сведений запроса, второй управляет ответом. Как правило, параметры считываются из объекта HTTPRequest, выходные данные записываются в объект HTTPResponse. Далее представлен пример этих функций:

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
 throws ServletException, IOException {
  // Обрабатываем GET 
 }
protected void doPost(HttpServletRequest request, HttpServletResponse response) 
  throws ServletException, IOException {
  // Обрабатываем POST 
}

В типовом шаблоне проектирования создается вспомогательная функция, принимающая объекты запроса и ответа, и затем методы doGet и doPost вызывают эту функцию. С этой точки зрения, код будет выполняться один и тот же, независимо от метода вызова сервлета.

В данном примере сервлет принимает XAML-документ как шаблон и использует прикладные программные интерфейсы (API) XML в Java для обработки документа, заполняя его результатами запроса к базе данных.

Далее представлен простой XAML-документ, используемый в этом учебном примере:

<Canvas xmlns=" http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="200" Height="80" Background="#FF000000">
  <TextBlock x:Name="txtName" Width = "200" Height="24" Canvas.Left="24" 
       Canvas.Top="8" Foreground="#FFEFB9B9" Text="Name" TextWrapping="Wrap"/>
  <TextBlock x:Name="txtCity" Width = "200" Height="24" Canvas.Left="24" 
       Canvas.Top="40" Foreground="#FFEFB9B9" Text="City" TextWrapping="Wrap"/>
  <TextBlock x:Name="txtCountry" Width="200" Height="24" Canvas.Left="24" 
       Canvas.Top="72" Foreground="#FFEFB9B9" Text="Country" TextWrapping="Wrap"/>
</Canvas>

Данный XAML включает три элемента TextBlock. Сервлет выполняет запрос к таблице Customers (Покупатели) базы данных Northwind и заполняет элементы TextBlock результатами запроса. Запрос принимает в качестве параметра ID покупателя и использует его для извлечения соответствующей записи покупателя, в которой нас интересуют имя покупателя, город проживания и страна.

Если у вас еще нет используемой в этом примере базы данных Northwind, ее можно скачать на сайте Microsoft Developer Network (MSDN). База данных Northwind Traders является примером базы данных, которая предоставляется Microsoft свободно для SQL Server. Она содержит базу сведений о фиктивном Интернет-магазине и является полезным источником тестовых данных для таких примеров, какой рассматривается здесь.

Чтобы заполнить элементы TextBlock, необходимо найти их в XAML-документе. При использовании в Java XML API для поиска узлов по XPath понадобится задать префикс стандартного пространства имен для элементов. Так позже вы заметите, что ссылки на элементы стандартного пространства имен ( <TextBlock>, например) формируются с использованием добавляемого во время выполнения префикса стандартного пространства имен (т.е. <d:TextBlock> ).

Итак, в Java мы будем использовать API XML для поиска узла, который необходимо редактировать, по имени. Например, TextBlock, содержащий сведения о стране, называется txtCountry. Таким образом, для формирования XAML нашего приложения вспомогательная функция должна выполнять следующие шаги:

Принять входной параметр. Если он null, присвоить ему значение по умолчанию.

Задать text/xml в качестве выходного типа MIME.

Создать объект для XML-документа и загрузить в него XAML-файл шаблона. В этом примере XAML хранится в документе Template.xml.

Открыть базу данных SQL Server и выполнить запрос к таблице Northwind Customers для поиска покупателя, соответствующего входному параметру.

Необходимо будет прочитать максимум одну строку, читаем ее.

Используем XPath для узла ContactName (Имя контакта), чтобы найти его, и замещаем его содержимое значением поля ContactName, полученным из базы данных.

Используем XPath для узла City (Город), чтобы найти его, и замещаем его содержимое значением поля City, полученным из базы данных.

Используем XPath для узла Country (Страна), чтобы найти его, и замещаем его содержимое значением поля Country, полученным из базы данных.

Записываем XML в поток HTTP-ответа.

Имейте в виду этот алгоритм, рассматривая код листинга 10.3, в котором показана вспомогательная функция, используемая сервлетом для генерирования XAML

protected void processRequest(HttpServletRequest request,
    HttpServletResponse response)
  throws ServletException, IOException {
  try
  {
    String strID = request.getParameter("ID");
    if(strID==null)
      strID="ALFKI";
    DocumentBuilderFactory factory =
    DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    response.setContentType("text/xml");
    PrintWriter out = response.getWriter();
    DocumentBuilder builder = factory.newDocumentBuilder();
    String uri = getServletContext().getRealPath("template.xml");
    Document doc = builder.parse(uri);
    DOMSource domSource = new DOMSource(doc);
    StreamResult streamResult = new StreamResult(out);
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer serializer = tf.newTransformer();
    XPathFactory xpFactory = XPathFactory.newInstance();
    XPath xpath = xpFactory.newXPath();
    xpath.setNamespaceContext(new DefaultNameSpaceContext());
    String strContactName="";
    String strCity="";
    String strCountry="";
    java.lang.Class.forName
      ("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    Connection c = java.sql.DriverManager.getConnection
      ("jdbc:sqlserver://localhost\\SQLEXPRESS;databasename=Northwind;
    user=javauser;password=javauser;");
    String SQL =
      "Select ContactName, City, Country
    from Customers where CustomerID = ?";
    PreparedStatement pstmt = c.prepareStatement(SQL);
    pstmt.setString(1, strID);
    ResultSet rs = pstmt.executeQuery();
    while (rs.next()) 
    {
      strContactName = rs.getString("ContactName");
      strCity=rs.getString("City");
      strCountry=rs.getString("Country");
      String strXPath = "//d:TextBlock[@x:Name='txtName']";
      XPathExpression expr = xpath.compile(strXPath);
      Object result = expr.evaluate(doc,XPathConstants.NODESET);
      NodeList nodes = (NodeList) result;
      Node ndeT1 =
        nodes.item(0).getAttributes().getNamedItem("Text");
      ndeT1.setNodeValue(strContactName);
      strXPath = "//d:TextBlock[@x:Name='txtCity']";
      expr = xpath.compile(strXPath);
      result = expr.evaluate(doc,XPathConstants.NODESET);
      nodes = (NodeList) result;
      ndeT1 =
      nodes.item(0).getAttributes().getNamedItem("Text");
      ndeT1.setNodeValue(strCity);
      strXPath = "//d:TextBlock[@x:Name='txtCountry']";
      expr = xpath.compile(strXPath);
      result = expr.evaluate(doc,XPathConstants.NODESET);
      nodes = (NodeList) result;
      ndeT1 =
        nodes.item(0).getAttributes().getNamedItem("Text");
      ndeT1.setNodeValue(strCountry);
    }
    rs.close();
    pstmt.close();
    serializer.transform(domSource, streamResult);
    out.close();
  }
  catch(Exception ex)
  {
    ex.printStackTrace();
  }
}
Листинг 10.3. Java код для генерирования XAML

Результаты выполнения этого сервлета (на сервере приложений Tomcat) представлены на рис. 10.8.

 Генерирование XAML с помощью сервлета

Рис. 10.8. Генерирование XAML с помощью сервлета
Отображение Silverlight из JSP

Чтобы получить JSP-страницу, создается HTML-страница и затем те ее части, в которых должна выполняться логика страницы, дополняются с помощью разметки JSP. В данном случае мы хотим отображать Silverlight-приложение. Обычно это делается путем импорта библиотек сценариев Silverlight.js и createSilverlight.js с последующим вызовом createSilverlight в именованном элементе DIV.

Однако наша JSP-страница будет немного более функциональной: она сможет принимать параметр и использовать его для построения элемента исходного XAML, созданного ранее. Для этого пишем код на Java и встраиваем его с помощью тегов JSP <% и %>. Полный код JSP-страницы представлен в листинге 10.4.

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
     "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <script type="text/javascript" src="js/silverlight.js"></script>
      <script type="text/javascript"
      src="js/createSilverlight.js"></script>
      <script type="text/javascript">
        function handleLoad(control, userContext, rootElement)
        {
        <%
        String strValue="";
        if (request.getParameter("ID") == null) {
         strValue = "ALFKI";
        } else {
         strValue = request.getParameter("ID");
        }
        %>
        control.source = "http://localhost:8084/ScreenCast2/XamlSource?ID=<% out.print(strValue); %>
          ";
          }
        </script>
      <title>JSP Page</title>
    </head>
  <body>
    <h1>Silverlight JSP Page</h1>
    <div id="slContent">
      <script type="text/javascript">
        createSilverlight();
      </script>
    </div>
  </body>
</html>
Листинг 10.4. JSP код для отображения содержимого Silverlight

На рис. 10.9 и 10-10 показано, как эта страница выглядит. Заметьте, что параметр AROUT передается в JSP-страницу в строке запроса первой страницы, тогда как ALFKI передается во вторую страницу.

 Выполнение JSP с параметром ID AROUT

Рис. 10.9. Выполнение JSP с параметром ID AROUT
 Выполнение JSP с параметром ID ALFKI

Рис. 10.10. Выполнение JSP с параметром ID ALFKI