Аплет Form

Оглавление

Сетевые приложения
Адрес IP
Адрес URL
Класс URL
Сокеты
Потоковые сокеты
Класс Socket
Датаграммные сокеты
Связь с Web
Аплет ShowChart
Приложения SocketServ и SocketClient
Аплет 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.

Назад Вперед
Используются технологии uCoz