Оглавление

Сетевые приложения
Адрес IP
Адрес URL
Класс URL
Сокеты
Потоковые сокеты
Класс Socket
Датаграммные сокеты
Связь с Web
Аплет ShowChart
Приложения SocketServ и SocketClient
Аплет Form

    Аплет Form

    На примере аплета Form мы покажем, как приложения Java могут взаимодействовать с расширениями сервера Web, такими как программы CGI или приложения ISAPI.

    В окне нашего аплета находится форма, содержащая два однострочных поля редактирования, кнопку и многострочное поле редактирования (рис. 5).

    pic05.gif (4332 bytes)

    Рис. 5. Окно аплета Form

    Эта форма предназначена для добавления записей в базу данных, содержащую электронные почтовые адреса. Заполнив поля имени и адреса E-Mail, пользователь должен нажать кнопку Send. При этом введенная информация будет передана расширению сервера CGI, который запишет ее в базу данных, а затем отправит обратно аплету. Сохраненные записи, полученные от программы CGI, аплет FORM отобразит в многострочном поле редактирования, как это показано на рис. 5.

    Исходные тексты аплета Form

    Исходные тексты аплета Form представлены в листинге 5.

    Листинг 5. Файл Form.java

    import java.applet.*;
    
    import java.awt.*;
    
    import java.net.*;
    
    import java.io.*;
    
    import java.util.*;
    public class Form extends Applet
    
      implements Runnable
    
    {
    
      private Thread m_store = null;
      TextField txtName;
    
      TextField txtEMail;
    
      TextArea  txta;
    
      Button btnGetText;
      public void init()
    
      {
    
        Label lbName;
    
        Label lbEMail;
    
        Label lbPress;    
        lbName = new Label("Enter your name:");
    
        lbEMail = new Label(
    
          "Enter your E-Mail address:");    
        add(lbName);
        txtName = new TextField("Your name", 40);
    
        add(txtName);
        add(lbEMail);
        txtEMail = 
    
          new TextField("your@email", 40);
    
        add(txtEMail);
        btnGetText = new Button("Send!");
    
        add(btnGetText);
        txta = new TextArea(8, 65);
    
        add(txta);
        setBackground(Color.yellow);
    
      }
      public void paint(Graphics g)
    
      {
    
        setBackground(Color.yellow);	
        Dimension dimAppWndDimension = getSize();
    
        g.setColor(Color.black);
    
        g.drawRect(0, 0, 
    
          dimAppWndDimension.width  - 1, 
    
          dimAppWndDimension.height - 1);
    
      }
      public boolean action(Event evt, Object obj)
    
      {
    
        Button btn;
        if(evt.target instanceof Button)
    
        {
    
          btn = (Button)evt.target;
          if(evt.target.equals(btnGetText))
    
          {
    
            startTransaction();
    
          }
    
          else
    
            return false;
    
          return true;
    
        }
    
        return false;
    
      }
      void startTransaction()
    
      {
    
        m_store = new Thread(this);
    
        m_store.start();
    
      }  
      public void stop()
    
      {
    
        if (m_store != null)
    
        {
    
          m_store.stop();
    
          m_store = null;
    
        }
    
      }
      public void run()
    
      {
    
        URL u;
    
        URLConnection c;
    
        PrintStream ps;
    
        DataInputStream is;  
        try
    
        {
    
          String szSourceStr = 
    
            txtName.getText() + 
    
    	", " + txtEMail.getText();	
          String szReceived;
    
          String szURL = 
    
          "http://frolov/scripts/store.exe";
          u = new URL(szURL);
    
          c = u.openConnection();
          ps = new PrintStream(
    
            c.getOutputStream());
    
          ps.println(szSourceStr);
    
          ps.close();
          is = new DataInputStream(
    
            c.getInputStream());
          szReceived = is.readLine();
    
          is.close();
          txta.appendText(szReceived + "\r\n");
    
          repaint();
    
        }
    
        catch (Exception ioe)
    
        {
    
          showStatus(ioe.toString());
    
          stop();
    
        }
    
      }
    
    }

    Исходный текст документа HTML, который был подготовлен для нас системой Java Workshop, мы немного отредактировали, изменив параметр CODEBASE (листинг 6).

    Листинг 6. Файл Form.tmp.html

    <applet name="Form" 
    
      code="Form.class" 
    
      codebase="http://frolov/"
    
      width="500"
    
      height="200"
    
      align="Top"
    
      alt="If you had a java-enabled browser,
    
     you would see an applet here.">
    
       <hr>If your browser 
    
    recognized the applet tag, 
    
    you would see an applet here.<hr>
    
    </applet>

    В этом параметре следует указать путь к каталогу, в котором располагается байт-код аплета.

    Описание исходныех текстов аплета Form

    При инициализации метод init создает все необходимые органы управления и добавляет их в окно аплета.

    Когда пользователь заполняет форму и нажимает кнопку Send, обработчик соответствующего события вызывает метод startTransaction, запускающий процесс обмена данными с расширением сервера Web:

    if(evt.target.equals(btnGetText))
    
    {
    
      startTransaction();
    
    }

    Метод startTransaction, определенный в нашем приложении, создает и запускает на выполнение поток, который и будет взаимодействовать с программой CGI:

    void startTransaction()
    
    {
    
      m_store = new Thread(this);
    
      m_store.start();
    
    }  

    При этом в качестве отдельного потока, работающего одновременно с кодом аплета, выступает метод run. Именно в нем сосредоточена вся логика обмена данными с сервером Web.

    Так как в процессе взаимодействия могут возникать различные исключения, мы предусмотрели их обработку при помощи блока try-catch:

    URL u;
    
    URLConnection c;
    
    PrintStream ps;
    
    DataInputStream is;  
    try
    
    {
    
      . . .
    
    }
    
    catch (Exception ioe)
    
    {
    
      showStatus(ioe.toString());
    
      stop();
    
    }

    Название возникшего исключения будет отображено в строке состояния браузера.

    Теперь о том, что делает метод run после получения управления.

    Первым делом он извлекает из однострочных текстовых полей имя и электронный адрес, объединяя их и записывая полученную текстовую строку в поле szSourceStr:

    String szSourceStr = 
    
       txtName.getText() + ", " +
    
       txtEMail.getText();

    В строке szURL находится адрес URL программы CGI:

    String szURL = 
    
      "http://frolov/scripts/store.exe";

    В реальном приложении этот адрес необходимо передавать аплету через параметр. Мы использовали непосредственное кодирование только для упрощения исходного текста.

    На следующем этапе метод run создает для программы CGI объект класса URL и открывает с ним соединение:

    u = new URL(szURL);
    
    c = u.openConnection();

    Пользуясь этим соединением, метод run создает форматированный поток вывода, записывает в него строку имени и электронного адреса, а затем закрывает поток:

    ps = new PrintStream(c.getOutputStream());
    
    ps.println(szSourceStr);
    
    ps.close();

    Переданные таким образом данные попадут в стандартный поток ввода программы CGI, откуда она их и прочитает.

    Сделав это, программа CGI запишет в стандартный выходной поток строку ответа, которую необходимо прочитать в методе run нашего аплета. Для этого мы открываем входной поток, создаем на его основе форматированный входной поток данных, читаем одну строку текста и закрываем входной поток:

    is = new DataInputStream(c.getInputStream());
    
    String szReceived;
    
    szReceived = is.readLine();
    
    is.close();

    Сразу после этого программа CGI завершит свою работу и будет готова к обработке новых запросов на добавление записей. Что же касается метода run, то он добавит полученную от расширения сервера текстовую строку в многострочное окно редактирования, как это показано ниже, а затем инициирует перерисовку окна аплета:

    txta.appendText(szReceived + "\r\n");
    
    repaint();

    Заметим, что использованный нами способ передачи данных подходит только для латинских символов. Если вам нужно передавать символы кириллицы, следует преобразовывать их из кодировки UNICODE, например, в гексадецимальную кодировку, а в программе CGI выполнять обратное преобразование. Аналогичную методику можно применять и для передачи произвольных двоичных данных.

    Исходный текст программы CGI store.exe

    Исходный текст программы CGI store.exe очень прост и показан в листинге 7.

    Листинг 7. Файл store.c

    #include <windows.h>
    
    #include <tchar.h>
    
    #include <wchar.h>
    
    #include <stdio.h>
    
    #include <stdlib.h>
    
    #include <string.h>
    void main(int argc, char *argv[])
    
    {
    
      int   nInDatasize;
    
      char  * szMethod;
    
      char  szBuf[2000];
      FILE *fDatabase;
    
      CRITICAL_SECTION csAddRecord;
      szMethod = getenv("REQUEST_METHOD");
    
      if(!strcmp(szMethod, "POST"));
    
      {
    
        nInDatasize = atoi(
    
          getenv("CONTENT_LENGTH"));
        fread(szBuf, nInDatasize, 1, stdin);
    
        szBuf[nInDatasize] = '\0';
        InitializeCriticalSection(&csAddRecord);
    
        EnterCriticalSection(&csAddRecord);
        fDatabase = 
    
          fopen("c:\\EMAIL.DAT", "a+");
    
        if(fDatabase != NULL)
    
        {
    
          fputs(szBuf, fDatabase);
    
          fclose(fDatabase);
    
        }
        LeaveCriticalSection(&csAddRecord);
    
        DeleteCriticalSection(&csAddRecord);
        printf(
    
          "Content-type: text/plain\r\n\r\n");
    
        printf("Stored information: %s", szBuf);
    
      }
    
    }

    Этот текст подготовлен для работы в среде  Windows 95 или Windows NT, так как для синхронизации доступа к файлу мы использовали специфические для этих операционных систем функции работы с критическими секциями.

    Свою работу программа CGI начинает с анализа переменной среды REQUEST_METHOD. Убедившись, что при запуске программы ей передали данные методом POST, программа определяет размер этих данных исходя из содержимого переменной среды CONTENT_LENGTH.

    Далее программа считывает соответствующее количество байт данных из стандартного потока ввода, записывает их в файл. Затем, после добавления заголовка "Stored information:", программа CGI записывает полученную строку в стандартный выходной поток, передавая ее таким образом аплету Form.

    Так как при реальной работе в сети Internet вашу программу CGI могут одновременно запустить несколько пользователей, для синхронизации обновления файла базы данных мы применили критическую секцию. В результате с файлом может работать в любой момент времени только одна копия программы CGI.

    Еще одно замечание касается пути к файлу, который в нашем случае создается в корневом каталоге диска C:. При установке программы CGI на сервер вам необходимо обеспечить доступ на запись к каталогу, в котором располагается файл, для удаленных пользователей. О том, как это сделать, вы можете узнать из документации на ваш сервер Web.



Java | Продукты и решения | Технологии | Сервис и обучение
О компании | Партнеры | Новости | Поиск
Sun Microsystems Inc. Corporate Information Our partners News and Events Search on site Java Computing Products and Solutions Technologies and Researches Education and Service Content
Используются технологии uCoz