InfoCity
InfoCity - виртуальный город компьютерной документации
Реклама на сайте







Размещение сквозной ссылки

 

Гномы серверов
Часть 2


Дмитрий Рамодин


В первой части этой статьи (см. «Мир ПК», № 3/99, с. 140) мы познакомились с возможностями сервлетов. Теперь рассмотрим, как настроить и запустить сервлет, после чего разберем конкретный пример сервлета.

Запуск и настройка сервлетов


Настало время остановиться на деталях настройки и запуска сервлетов. Для этого следует поговорить о файле свойств. Имя этого файла — servlet.properties. В нем в виде пар «ключ—значение» хранятся свойства, используемые для конфигурации, создания и инициализации сервлетов. Изначально для любого из сервлетов предопределено два свойства. Первое, servlet.<имя сервлета>.code, определяет имя сервлета и ставит его в соответствие двоичному class-файлу сервлета. Например, если вы скомпилировали класс сервлета с именем MyServletClassName, то получите в результате компиляции файл с именем MyServletClassName. class и можете присвоить ему краткое имя, скажем, myservlet, следующим образом:

servlet.myservlet.code=MyServletClassName

Теперь, когда вы обратитесь к сервлету с именем myservlet, сервер найдет эту строку в файле свойств и, опираясь на найденное значение, загрузит класс MyServletClassName, инициализирует его и передаст ему ваш запрос. Следует помнить о том, что имя class-файла должно задаваться полностью, включая имя пакета, в котором определен класс. Второе свойство, servlet.<имя сервлета>.initargs, определяет передаваемые сервлету параметры инициализации. Значения такого рода параметров могут быть получены сервлетом методом getInitParameter. Если параметров несколько, они отделяются друг от друга запятыми. Пример задания параметров:

servlet.myservlet.initargs= \
someParameterName1=someValue, someParameterName2=otherValue

Файл servlet.properties помещают в определенный каталог на сервере, где хранятся class-файлы. Заметим, однако, что разные серверы допускают альтернативное местоположение файла свойств (по настройке администратора).

Теперь поговорим об утилите servletrunner, которая по сути является простейшим Web-сервером, специально предназначенным для работы с сервлетами. После запуска он «слушает» порт 8080, и если произошел запрос, то, обратившись к сервлету, servletrunner получает от него ответ и пересылает последний программе-клиенту. Командная строка servletrunner имеет различные опции, но полезными могут оказаться лишь следующие:

  • p port — «прослушиваемый» в ожидании запроса порт;
  • t timeout — время тайм-аута в мс;
  • d dir — каталог, где лежат сервлеты;
  • r root — корневой каталог, в котором хранятся документы;
  • s filename — альтернативное имя файла свойств servlet property file name
  • v — отображать выводимые в стандартные потоки данные.

Никаких дополнительных настроек вам не потребуется. Просто запустите утилиту servletrunner и обращайтесь к ней с помощью браузера или другой клиентской программы. Главное, чтобы servletrunner могла найти ваши сервлеты.

Теперь вкратце о том, как обратиться к сервлету из Web-браузера. По умолчанию адрес URL для отправки запроса состоит из нескольких частей: имени компьютера, номера порта, каталога servlet, имени сервлета и списка параметров. К примеру, обратиться к сервлету myservlet, находящемуся на локальном компьютере, можно так:

http://localhost:8080/servlet/myservlet?param=somevalue

Напомним, что, тоже по умолчанию, утилита servletrunner (и некоторые серверы Web) «слушает» запросы к порту с номером 8080. Приведенный выше запрос обращается к сервлету myservlet, передавая ему параметр param со значением somevalue. Это весьма полезно, когда нужно задавать параметры запроса «на лету» (в отличие от параметров инициализации).

Пример сервлета


Чтобы все рассказанное о сервлетах не осталось для вас пустыми словами, создадим собственный сервлет, который будет выводить в окне браузера список файлов в определенном каталоге компьютера-сервера, а заодно и показывать количество файлов и их местоположение. Готовый исходный текст показан в листинге. Мы не станем детально описывать теги HTML, которые сервлет вставляет в генерируемую страницу, — обратитесь самостоятельно к документации по этому языку. Весь вывод данных будет производиться методом println класса PrintWriter, что является наиболее удобным вариантом посылки текстовых данных.

Начнем с того, что опишем класс сервлета, наследующий HttpServlet, и импортируем необходимые классы. После чего займемся методом doGet — главной частью сервлета:

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class SampleServlet extends HttpServlet
{
  public void doGet( HttpServletRequest req,  HttpServletResponse  res)throws 
ServletException, IOException
  {

Методом getWriter сервлет получает доступ к потоку вывода, через который серверу посылается результат:

PrintWriter w = res.getWriter(); res.setContentType(”text/html”); generateHeader(”Directory Viewer Servlet”, w);

После чего методом setContentType серверу сообщается, что возвращаемые данные — страница HTML (MIME-тип «text/html»). Если этого не сделать, то сервер решит, что вы посылаете обычный текст. Метод generateHeader, который идет следом, убирает детали генерации стандартного заголовка Web-страницы, чтобы не загромождать исходный текст. Первый параметр этого метода — заголовок генерируемой страницы, а второй — ссылка на поток вывода, куда этот метод должен пересылать данные.

Следующий блок занимается разбором параметров, переданных сервлету:

if((param = req.getParameter(”dirToShow”)) == null)
      if((param = getInitParameter(”dirToShow”)) == null)
      {
        w.println(”<H1><FONT COLOR=RED>” +
          ”The <EM>dirToShow</EM> parameter 
required!</FONT></H1>”);
        return;
      }
Рис.1

Сначала сервлет пытается считать значение параметра dirToShow из адреса URL (метод getParameter). Если такого параметра в запросе нет, то предпринимается попытка получить параметр с этим же именем из файла свойств (метод getInitParameter). Если и там параметр не обнаружен, запрос прерывается, а в ответ клиенту посылается сообщение (рис. 1).

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

File root = new File(param);
    if(!root.isDirectory())
    {
      w.println(”<H1><FONT COLOR=RED>” +
        ”The parameter is not a directory or not exist!</FONT></H1>”);
      return;
    }

Когда все формальности соблюдены, у каталога запрашивается список всех имеющихся файлов и по нему вычисляется общее количество их в каталоге. Заодно генерируется строка, показывающая полное имя каталога:

    File[] fileList = root.listFiles();
    w.println(”<H2><FONT COLOR=TEAL>” +
        ”Total number of files in the choosen directory - ” +
        fileList.length + ”</FONT></H2>”);
    w.println(”<H3><FONT COLOR=PURPLE>” +
        ”Directory path - ” + param + ”</FONT></H3><HR>”);

Имена файлов выводятся методом printName, который приведен чуть ниже. Для форматирования списка применяется таблица, поэтому нужны две дополнительные строки, формирующие с помощью пары тегов <TABLE> и </TABLE> таблицу с невидимой рамкой:

w.println(”<TABLE BORDER=0 CELLSPACING=5>”);
    for(int i = 0; i < fileList.length; i++)
        printName(fileList[i], w);
    w.println(”</TABLE><HR>”);
    generateFooter(w);

Завершается вывод генерацией стандартного окончания HTML-страницы с помощью метода generateFooter.

Теперь о методе printName. Он чрезвычайно прост и состоит из строчки, которая проверяет, является ли выводимое имя каталогом или простым файлом. После этого в специально отведенную переменную записывается комментарий о типе. Далее в два столбца в таблицу выводятся тип файла (простой файл или каталог) и его имя:

  private void printName(File name, PrintWriter output)
  {
    String type = name.isDirectory()
        ? ” (Directory)” : ” (File)”;
    output.println(”<TR><TD>” + type + ”</TD><TD><FONT COLOR=BLUE>”
        + name.getName() + ”</FONT></TD></TR>”);
  }

Остается лишь рассмотреть вспомогательные методы generateHeader, generateFooter getServletInfo. Они настолько просты, что вы без труда разберетесь с ними самостоятельно:

  private void generateHeader(String title, PrintWriter output)

  {
    output.println(”<HTML>\n<HEAD>\n<TITLE>” +
        title + ”</TITLE>\n</HEAD>\n<BODY>”);
  }
  private void generateFooter(PrintWriter output)
  {
    output.println(”</BODY>\n</HTML>”);
    output.flush();
    output.close();
  }
  public String getServletInfo()
  {
    return ”This servlet shows a content of a directory” +
           ”mentioned in dirToShow parameter or property.”;
  }
}

Отлаживать подобного рода сервлеты не просто, а очень просто. Нужно только открыть в браузере режим просмотра исходного текста страницы — и все ваши ошибки сразу же становятся видны. Ниже приведен исходный текст файла свойств servlet.properties

:
# dirlist servlet
servlet.dirviewer.code=SampleServlet
servlet.dirviewer.initArgs=\
                  dirToShow=D:\\SUN\\SDK\\examples
Рис.2

Обратите внимание, что символ «обратная косая» в пути к каталогу задается по правилам языка Java, т. е. двойными «обратными косыми». Можно, однако, использовать и одинарную «прямую косую», как это принято в ОС UNIX.

На рис. 2 показано, как примерно будет выглядеть результат работы сервлета. В качестве запроса была введена строка:

http://mitrich/servlet/dirviewer?dirToShow=D:/Sun/SDK/examples

Запускается сервлет следующей строкой:

servletrunner -p 80 -d E:\PROJECTS\Java\Servlet -r E:\PROJECTS\Java\Servlet

Не забудьте, что все каталоги актуальны лишь для компьютера, на котором работает автор. Вы же подставите собственные пути.

Изготовление сервлетов в Borland JBuilder 2


Довольно хорошими возможностями по созданию сервлетов обладает пакет Borland JBuilder 2. Если заглянуть в список имеющихся у него мастеров, то можно обнаружить соответствующую пиктограмму, щелкнув на которой вы запускаете программу генерации исходного текста сервлета (рис. 3).

Рис.3

Сначала потребуется ввести исходные данные для создания нового проекта: название проекта, имя автора и т.д. (рис. 4).

Рис.4

Сам мастер генерации сервлета запускается чуть позже, когда создан проект. Диалоговая панель мастера (рис. 5) предложит создать те элементы сервлета, с которыми вы уже познакомились в предыдущей части статьи. Опция Implement SingleThreadModel добавляет в список наследования класса сервлета интерфейс SingleThreadModel, не разрешающий множественное обращение к сервлету. Generate HTML Page создает Web-страницу для сервлета. И наконец, вы можете включать генерацию нескольких основных методов-обработчиков для сервлета: service, doGet, doPost, doPut, doDelete.

Рис.5

Рис.6

На следующем этапе задаются параметры инициализации. Кроме имени параметра и его типа также задаются: описание параметра; переменная внутри сервлета, которой будет передано значение параметра после его считывания; значение параметра по умолчанию; имя метода сервлета, в котором должно происходить считывание параметра (рис. 6).

Если ввести параметры так, как это показано на предыдущих рисунках, то вы получите проект с двумя Java-классами. Первый представляет собой простейший сервер. Он настроен на порт 8080 и умеет распознавать две опции командной строки -p и -d, которыми можно задать порт сервера и каталог с сервлетами соответственно. Вот исходный текст такого сервера, сгенерированный JBuilder:

package Samples;
import sun.servlet.http.*;
public class ServletServer {
  public static void main(String[] args) {
    boolean portSet = false;
    boolean servletDirSet = false;
    for (int i = 0; i < args.length; i++) {
      if (args[i].equals(”-p”)) {
        portSet = true;
      }
      if (args[i].equals(”-d”)) {
        servletDirSet = true;
      }
    }
    int i = 0;
    String[] arguments = new String[args.length + (servletDirSet ? 0 : 2) + 
     (portSet ? 0 : 2)];
    for (; i < args.length; i++) {
      arguments[i] = args[i];
    }
    if (!portSet) {
      arguments[i++] = ”-p”;
      arguments[i++] = ”8080”;
    }
    if (!servletDirSet) {
      arguments[i++] = ”-d”;
      String servletDir = System.getProperty(”java.class.path”);
      servletDir = servletDir.substring(0,servletDir.indexOf(java.io.File.pathSeparator));
      arguments[i++] = servletDir;
    }
    HttpServer.main(arguments);
  }
}

Сам класс сервлета не делает ничего выдающегося, а просто обрабатывает значение параметра инициализации и элементарным образом реагирует на запросы, выводя некое сообщение:

package Samples;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class TestServlet extends HttpServlet {
  public void init(ServletConfig config) throws ServletException {
    super.init(config);
    //Каталог, содержимое которого нужно показать
    try { pathToDir = getInitParameter(”dirToShow”); } catch (Exception e) 
     { e.printStackTrace(); }
  }
  String pathToDir = ”E:/Projectes/”;
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
   ServletException, IOException {
    response.setContentType(”text/html”);
    PrintWriter out = new PrintWriter (response.getOutputStream());
    out.println(”<html>”);
    out.println(”<head><title>TestServlet</title></head>”);
    out.println(”<body>”);
    out.println(”</body></html>”);
    out.close();
  }
  public void doPost(HttpServletRequest request, HttpServletResponse response) 
   throws 
   ServletException, IOException {
    response.setContentType(”text/html”);
    PrintWriter out = new PrintWriter (response.getOutputStream());
    out.println(”<html>”);
    out.println(”<head><title>TestServlet</title></head>”);
    out.println(”<body>”);
    out.println(”</body></html>”);
    out.close();
  }
  public String getServletInfo() {
    return ”Samples.TestServlet Information”;
  }
}

Итак, вы получили представление о том, как пишутся сервлеты. К сожалению, без Java Web Server компании Sun трудно отладить сколь-нибудь сложные сервлетные классы, а утилита servletrunner обладает лишь простейшими возможностями по их запуску. Однако компания JavaSoft обещает исправить этот недостаток, включив в следующую версию Java Servlet Development Kit усовершенствованный маленький Web-сервер, с которым процесс отладки и проверки станет намного проще.

Листинг: Пример сервлета


import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class SampleServlet extends HttpServlet
{ 
  public void doGet( HttpServletRequest req, HttpServletResponse res)
                                     throws ServletException, IOException
  {
    String param;
    PrintWriter w = res.getWriter();
    res.setContentType(”text/html”);
    generateHeader(”Directory Viewer Servlet”, w);
    if((param = req.getParameter(”dirToShow”)) == null)
      if((param = getInitParameter(”dirToShow”)) == null)
      {
        w.println(”<H1><FONT COLOR=RED>” +
          ”The <EM>dirToShow</EM> parameter 
            required!</FONT></H1>”);
        return;
      }
    File root = new File(param);
    if(!root.isDirectory())
    {
      w.println(”<H1><FONT COLOR=RED>” +
        ”The parameter is not a directory or not exist!</FONT></H1>”);
      return;
    }
    File[] fileList = root.listFiles();
    w.println(”<H2><FONT COLOR=TEAL>” +
        ”Total number of files in the choosen directory - ” +
        fileList.length + ”</FONT></H2>”);
    w.println(”<H3><FONT COLOR=PURPLE>” +
        ”Directory path - ” + param + ”</FONT></H3><HR>”);
    w.println(”<TABLE BORDER=0 CELLSPACING=5>”);
    for(int i = 0; i < fileList.length; i++)
        printName(fileList[i], w);
    w.println(”</TABLE><HR>”);
    generateFooter(w);
  }

  private void printName(File name, PrintWriter output)
  {
    String type = name.isDirectory()
        ? ” (Directory)” : ” (File)”;
    output.println(”<TR><TD>” + type + ”</TD><
       TD><FONT COLOR=BLUE>”
        + name.getName() + ”</FONT></TD></TR>”);
  }

  private void generateHeader(String title, PrintWriter output)
  {
    output.println(”<HTML>\n<HEAD>\n<TITLE>” +
        title + ”</TITLE>\n</HEAD>\n<BODY>”);
  }

  private void generateFooter(PrintWriter output)
  {
    output.println(”</BODY>\n</HTML>”);
    output.flush();
    output.close();
  }

  public String getServletInfo()
  {
    return ”This servlet shows a content of a directory” +
           ”mentioned in dirToShow parameter or property.”;
  }
}

[Назад]


Реклама на InfoCity

Яндекс цитирования



Финансы: форекс для тебя








1999-2009 © InfoCity.kiev.ua