Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

JAVA. Серверные приложения

.pdf
Скачиваний:
0
Добавлен:
06.09.2026
Размер:
2 Мб
Скачать
Часть 3 Серверные Java-компоненты Servlet 171
Глава 26. Работа servlet с HTTP-протоколом передачи
данных
Доступ к методам передачи осуществляется через указание специа­льных элементов в конструкциях HTML.
Использование широко распространенного протокола HyperText Transfer Protocol (HTTP) является еще одним преимуществом servlet. Простой текстовой протокол, предназначенный для взаимодействия браузера клиента и сервера, HTTP имеет несколько важных методов, определяющих передачу данных. GET, POST и HEAD, остальные мето­ды редко используются в силу малой распространенности. HTTP-запрос посылается на сервер в приблизительно следующем формате — указы­вается метод передачи GET /somewhere.com/servlet/servletName?pa­ram1=value1¶m2=value2%20.
Данный запрос пересылает два параметра — param1 и param2, раз­деленных знаком амперсанда (&), — в servlet по адресу somewhe­re.com/servlet/servletName. Знак вопроса (?) извещает о начале пара­метров, комбинация %20 определяет окончание параметров.
Метод GET пересылает данные как часть параметров URL. Данные
могут быть любого значения. Одно важное ограничение связано с использованием метода GET. Некоторые Web-серверы не поддер­живают длинных строк при передаче URL (обычно несколько сотен байтов). Метод GET используется при указании способа передачи GET в HTML-форме. Если необходимо переслать очень длинный запрос, то лучше воспользоваться методом POST.
Метод POST пересылает клиентские данные на сервер, может ис­пользоваться для различных целей, например для пересылки дан­ных в группы новостей или для добавления каких-либо значений и т. д. Метод POST пересылает данные в отдельном потоке и вызы­вается, когда используется HTTP POST запрос использующийся в HTML-форме.
Метод HEAD подобен GET в работе с одним дополнением — HEAD возвращает служебную информацию о документе, такую, как дата последнего изменения документа, размер документа перед переда­чей, тип сервера, на котором обрабатывается запрос, тип возвра­щаемого документа (MIME). Для обработки HTTP-запросов необхо­димо использовать объекты класса HttpServlets, такие, êàê HttpServletRequest è HttpServletResponse.
В объект HttpServletRequest включена информация о клиентском за­просе, в том числе информация о системном окружении клиента и дан­ные, которые клиент посылает на обработку в servlet. Объект HttpServ­letRequest имеет методы для выделения нужной servlet информации и формировании ответа.
Объект HttpServletResponse — динамически генерируемый объект для формирования ответа, ответ чаще всего оформляется в виде HTML­страницы, которая посылается обратно клиенту. Каждый раз, когда кли­ент посылает запрос, новый поток обращается к методам service(), doGet() или doPost(), которые и обрабатывают данный запрос. Наконец, сущест-
172 Часть 3 Серверные Java-компоненты Servlet
вуют методы по получению информации о самом запросе. Метод getMet­hod() указывает, какой способ, GET или POST-передачи осуществлялся самим запросом. Для более новой HTTP версии 1.1 могут применяться до­полнительные методы — HEAD, OPTIONS, PUT, и DELETE. Еще один метод, getRequestURI(), указывает адрес, с которого поступил запрос, и getRequestProtocol() указывает номер версии "HTTP/1.0"или "HTTP/1.1".
Servlet являются многопоточными приложениями, это значит, что при обращении к методу service() создается новый поток обработки клиент­ского запроса. Для предотвращения изменений совместно используемых разными потоками глобальных переменных необходимо указать ключе­вое слово synchronized перед совместно используемыми переменными.
Последние версии servlet реализуют интерфейс SingleThreadModel, который обрабатывает потоки запросов к методу service() или его ана­логу последовательно.
Методы getParameterNames(), getParameterValues() помогают полу­чить доступ к HTTP-параметрам пересылаемых методами GET или POST. Метод getParameterValues() возвращает массив строк, передан­ных параметров по HTTP-протоколу.
После рассмотрения методов передачи, используемых HTTP-прото­колом, и основных методов servlet можно подвести маленький итог.
Итак, метод servlet doGet()
при использовании HTTP-протоколом способа передачи GET;
для установки свойств заголовков;
для формирования ответа;
для чтения данных, поступивших в виде дискретных значений.
А метод servlet doPost()
при передаче параметров способом POST;
при обработке HTML-форм;
при очень большом количестве данных, поступивших от клиента.
должен описываться в теле в случае:
используется при:
Остальные способы передачи, используемые HTTP-протоколом, ис­пользуют либо методы doGet(), либо doPost().
HEADERS
Когда HTTP-клиент (Web-браузер) посылает запрос, в первых сто­ках обычно определяется некая системная информация, передаваемая клиентом серверу. Эти системные строки называются заголовками (hea­ders), для каждого метода отправления они разные. Чаще всего пользу­ются при передаче методами GET, POST и HEAD. Информация, необ­ходимая для доставки данных и осуществления контроля над их пере­дачей, также осуществляется при помощи этих маленьких текстовых сообщений, присоединяемых к передаваемым данными.
Наиболее популярные типы заголовков:
Accept — описывает MIME тип приложения, используемый брау­зером.
Accept-Charset — указывает тип раскладки, используемый брау­зером.
Accept-Encoding — указывает тип кодировки, которую браузер может декодировать.
Часть 3 Серверные Java-компоненты Servlet 173
Accept-Language — язык, используемый в HTML-странице, если
используется больше чем один язык для отображения информации в Web-браузере. Authorization — информация об авторизации пользователя.
Connection — указывает, является ли соединение постоянным. Ес-
ли servlet получает значение Keep-Alive или используется прото­кол HTTP версии 1.1, в этом случае соединение определяется как постоянное. Content-Length — указывает длину присоединенных данных.
Cookie.
From — указывает e-mail — адрес запроса, не используется в бра-
узерах. URL хоста.
Pragma — значение no-cache указывает,что сервер должен обно-
вить локальную копию документа. User-Agent, тип браузера, полезен при создании браузерозависи-
мых приложений.
Чтение служебной информации облегчает работу. Вызывая метод getHeader() объекта, порожденного от HttpServletRequest, можно полу­чить набор строк, передаваемых запросом, null возвращается, если та­ковых не имеется. Однако некоторые заголовки (headers) нельзя полу­чить вышеуказанным методом. Метод, используемый для получения за­головков HTTP-запроса getHeaderNames() возвращает массив всех переданных заголовков.
Другие полезные методы getAuthType () и getRemoteUser() дают возможность получить данные о клиенте. Методы getDateHeader() и ge­tIntHeader() предназначены для конвертации специальных заголовков в типы Date и int соответственно.
ИСПОЛЬЗОВАНИЕ CGI ПЕРЕМЕННЫХ
Использование CGI переменных является распространенной практи­кой работы Web-приложений, и servlets не являются исключением.
Существует несколько типов CGI переменных, а значит, и несколько их эквивалентов в servlets: CGI переменные доступны для методов do­Get() или doPost().
AUTH_TYPE CGI переменная — указывает на поддержку заголовка авторизации, эквивалентный способ, используемый в servlet, осуществ­ляется через вызов метода request.getAuthType().
CONTENT_LENGTH — только для POST-запросов, определяет ко­личество пересылаемых клиентом данных. Можно воспользоваться эк­вивалентом String.valueOf(request.getContentLength()), который возвра­щает строковое значение или request.getContentLength(), указывающий непосредственно длину как тип int.
CONTENT_TYPE MIME — определяет тип присоединенных данных request.getContentType().
DOCUMENT_ROOT — определяет путь, где находится документ, за­меняет более раннюю версию getRealPath("/") íà getServletCon­text().getRealPath("/").
174 Часть 3 Серверные Java-компоненты Servlet
HTTP_XXX_YYY — определяет доступ к HTTP-заголовкам requ­est.getHeader("Xxx-Yyy"), где Xxx-Yyy является каким-то заголовком.
PATH_INFO — указывает путь в формате URL. Эквивалентом явля­ется метод request.getPathInfo().
PATH_TRANSLATED — относительный путь преобразует в реаль­ный на сервере. Метод request.getPathTranslated().
Последние два метода практически идентичны.
QUERY_STRING для GET-запроса — используется при пересылке строк больших объемов для доступа к индивидуальным параметрам re­quest.getQueryString().
REMOTE_ADDR — адрес IP-клиента, сделавшего запрос, возвраща­ет строковое значение числовых параметров "192.9.68.12". request.getRe­moteAddr().
REMOTE_HOST — полное доменное имя удаленного хоста (напри­мер, "java.sun.com"), с которого клиент послал запрос. В случае невоз­можности определения определяется IP, адрес. Используется метод re­quest.getRemoteHost().
REMOTE_USER — часть авторизации request.getRemoteUser().
REQUEST_METHOD — определяет тип запроса, обычно GET или POST, но также возможно HEAD, PUT, DELETE, OPTIONS или TRACE. request.getMethod().
SCRIPT_NAME — путь, по которому находится выполняющийся ser­vlet request.getServletPath().
SERVER_NAME — возвращает имя сервера request.getServerName().
SERVER_PORT — определяет прослушивающийся порт. Для этого предназначена конструкция String.valueOf(request.getServerPort()), воз­вращающая строку. Обычно можно просто обратиться к методу requ­est.getServerPort(), возвращающий число типа int.
SERVER_PROTOCOL — имя и версия протокола, используемого в запросе (например, HTTP/1.0 или HTTP/1.1). request.getProtocol().
SERVER_SOFTWARE — определяет программные данные о Web­сервере getServletContext().getServerInfo().
PrintWriter out = response.getWriter();
String[][] variables =
{ { "AUTH_TYPE", request.getAuthType() },
{ "CONTENT_LENGTH", String.valueOf(request.getContentLength()) },
{ "CONTENT_TYPE", request.getContentType() },
{ "DOCUMENT_ROOT", getServletContext().getRealPath("/") },
{ "PATH_INFO", request.getPathInfo() },
{ "PATH_TRANSLATED", request.getPathTranslated() },
{ "QUERY_STRING", request.getQueryString() },
{ "REMOTE_ADDR", request.getRemoteAddr() },
{ "REMOTE_HOST", request.getRemoteHost() },
{ "REMOTE_USER", request.getRemoteUser() },
{ "REQUEST_METHOD", request.getMethod() },
{ "SCRIPT_NAME", request.getServletPath() },
{ "SERVER_NAME", request.getServerName() },
{ "SERVER_PORT", String.valueOf(request.getServerPort()) },
{ "SERVER_PROTOCOL", request.getProtocol() },
{ "SERVER_SOFTWARE", getServletContext().getServerInfo() };
Часть 3 Серверные Java-компоненты Servlet 175
String title = "Servlet Example: Showing CGI Variables";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
"<TH>CGI Variable Name<TH>Value");
for(int i=0; i<variables.length; i++) {
String varName = variables[i][0];
String varValue = variables[i][1];
if (varValue == null)
varValue = "Not specified</I>";
out.println("<TR><TD>" + varName + "<TD>" + varValue); }
out.println("</TABLE></BODY></HTML>");
Работа с HTTP-заголовками предусмотрена в объектах класса Serv­letResponse и HttpServletResponse. Основой метод — setHeader(), кото­рый устанавливает имя и значение заголовка. Имеются два специаль­ных метода по работе с датами: setDateHeader() и setIntHeader(). Пер­вый возвращает значение в миллисекундах, прошедшее с 1 января 1970 года, начала эпохи. Второй конвертирует данное строковое числовое значение в строку.
if (request.getProtocol(). compareTo ("http/1.0")==0){
response.setHader("pragma","no-cashe");}
else if (request.getProtocol().compareTo("HTTP/1.1")==0)
response.setHeader("cashe-control,"no-cashe"); }
setHeader("Pragma","no cashe")
Данный пример иллюстрирует способ перезагружать страницу каж­дый раз при обращении к ней и не помещает страницу в кэш.
Более полную информацию о передаваемых заголовках получают с помощью метода getHeaderNames(). Для облегчения работы с множест­вом заголовков можно воспользоваться конструкцией while совместно с коллекциями и использованием интерфейса Enumeration, как это было указано выше.
STATUS CODE
Когда Web-сервер отвечает на запрос Web-браузера, то кроме отве­та собирается другая информация. Об успешном выполнении, т. е. пока­зе запрашиваемой HTML-страницы, сервер сообщает клиенту при по­мощи специальных строк, отсылаемых клиенту:
HTTP/1.1 200 OK
Content-Type: text/plain
Hello World
Это так называемые статусные строки. В них сообщается имя версия HTTP-протокола, числовое значение выполнения операции, очень ко­роткое сообщение. В общем, это уже известный заголовок с описанием типа передаваемого ресурса. Строка Content-Type указывает непосред­ственно MIME тип запрошенного документа. Не все методы используют
176 Часть 3 Серверные Java-компоненты Servlet
указание типа документа, например, метод HEAD отправляет только цифровое значение status code.
Servlets могут выполнять различные задачи по управлению линией статуса и формированию заголовков. Например, servlet может отправ­лять пользователя на другие сетевые ресурсы, в том числе HTML-стра­ницы, или могут сообщать пользователю, что доступ к документу воз­можен при использовании пароля. Иногда в силу различных причин за­прашиваемый клиентом ресурс недоступен. В HTTP-протоколе в этой ситуации также используются коды состояний (status code).
Servlet использует различные методы для работы с кодами состояний.
Обычно код состояний включает номер кода как числовое значение и ассоциированное с ним сообщение. Для установки кода можно восполь­зоваться методом setStatus(int) объекта HttpServletResponse. Номер, пе­редаваемый этим методом, соответствует константе с системным пре­фиксом SC. Например, сообщение 404 file not found соответствует кон­станте SC_NOT_FOUND объекта HttpServletResponse
protected void doGet ( HttpServletRequest req, HttpServletResponse res)
throws ServletException{
// тело основного метода;
// отсутствие запрашиваемого ресурса
res.sendError(404); }
Еще один пример, иллюстрирующий возможные ситуации при пере­мещении ресурса, можно воспользоваться константой SC_MOVED_TEMPORARILY. После ее обработки можно сообщить бра­узеру новый адрес, используя два оператора response.setStatus(respon­se.SC_MOVED_TEMPORARILY) и response.setHeader("Location", url) или response.sendRedirect(url) и решение проблемы перемещения ре­сурса найдено.
Так же как и вызовы, обработанные servlet ответы могут быть пере­направлены в любое другое приложение, JSP или HTML-страницы, ser­vlet. Использование метода response.sendRedirect("myHtml.html") пере­сылает данные на указанную страницу. При возникновении исключите­льной ситуации данные могут переслать код ошибки, вызвав метод response.sendError(response.SC_NO_CONTENT).
Для работы со статусной строкой используется метод setStatus() объ­екта HttpServletResponse. Использование данного метода должно пред­варять отправление ответа, т. е. выполнение оператора response.setSta­tus() должно быть указано до выполнения оператора, описывающего выходной поток. Основным методом для установки кода состояния яв­ляется response.setStatus(int), правда, имеются два дополнительных ме­тода в объекте HttpServletResponse. Первый метод — sendError() — ис­пользуется для посылки сообщения клиенту в виде HTML-страницы. Другой метод — sendRedirect() — генерирует сообщение 302, если ука­занный в заголовке Location содержит ссылку на новый документ.
COOKIES
Для работы с данными во HTTP-сессии существуют маленькие тек­стовые сообщения. В отличие от заголовков, пересылаемых в голове за­проса, cookies несут дополнительную информацию, предназначенную
Часть 3 Серверные Java-компоненты Servlet 177
для идентификации клиента и клиентской сессии. Cookies обычно ассо­циированы с сервером, на котором они созданы, но специальные методы позволяют по необходимости установить имя другого сервера.
Java servlet API версии 2.1 имеет специальный класс по работе с cooki­es. Класс cookies содержит методы по установке и получению параметров cookies. Cookies, используемые HTTP-протоколом, состоят из двух пара­метров, имени и значения. Для создания cookies используется конструк­тор основного класса с двумя параметрами, первый определяет имя cooki­es, другой параметр — идентификационное значение. И тот и другой па­раметры указываются создателем cookies и могут иметь любые значения.
Например, для работы с Cookies необходимо использовать другой ме­тод getCookie(), который возвращает содержимое Cookie и помещает в массив Cookie объекты. Cookies — маленькие текстовые сообщения, по­сылаемые сервером клиенту и возвращаемые браузером, когда клиент снова оказывается на данной странице. Служат для идентификации по­льзователя. Могут содержать какие-либо данные о пользователе в тек­стовом виде. Записываются во время сессии на локальный диск.
Прежде чем послать cookies клиенту, servlet должен создать один или более cookies с названием параметров их значениями. Для этой операции используется конструктор new Cookie (nameCookie, valueCookie). При этом установить добавочные атрибуты по необходимости можно, воспо­льзовавшись методом cookie.setXxx(), и добавить cookies объект response, используя response.addCookie (cookie). Для прочитывания входящих coo­kies вызывается request.getCookies(), возвращающий массив Cookie объ­ектов. В большинстве случаев в дальнейшем используется операция по­иска необходимого значения. Ниже приведен пример по работе с Cookie.
import java.io.*; import javax.servlet.*; import javax.servlet.http.*;
public class CookieServlet extends HttpServlet {protected void servi­ce(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int calledCount = 0;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML><TITLE>CookiesServlet</TITLE><BODY>");
out.println("<H2>Servlet Cookie Example:</H2><HR>");
if (getReqCookie(req, out, "calledCount") == null)
calledCount = 0;
else
calledCount = new Integer(getReqCookie(request, out,"calledCo­unt")).intValue();
out.print("The value of the cookie calledCount sent in on the request: ");
if (calledCount == 0) out.println ("null — value not sent in on requ­est<HR>");
else out.println(calledCount + "<HR>");
calledCount++;
Cookie cookie = new Cookie("calledCount", new Integer(calledCo­unt).toString());
178 Часть 3 Серверные Java-компоненты Servlet
response.addCookie(cookie);
out.println("The value of the cookie calledCount set on the response:
" +calledCount); out.println("</BODY><HTML>");
out.close();}
private String getReqCookie(HttpServletRequest req, PrintWriter
out, String name) { Cookie[] cookie = request.getCookie ();
if (cookies != null && cookies.length > 0) {
for(int i=0; i<cookies.length; i++) {
if (cookies[i].getName().equals(name))
return (cookies[i].getValue());}}
return null;}
Как обычно, первая строка указывает импортированные пакеты, во второй строке создается класс, порожденный от HttpServlert со всеми обычными параметрами. Наборы строк с третьей по четвертую уже до­статочно обсуждались, представляют собой стандартные операции вы­вода информации в виде HTML-страницы для клиента. В восьмой стро­ке проверяется значение имени cookie, возвращенное методом getReq­Cookie (HttpServletRequest req, PrintWriter out, String name), строка двадцать первая, и если имя не совпадает, т. е. данный cookie отсутст­вует в полученной коллекции, то производятся следующие действия: создается новый cookie со значением количества вызовов и отправляет­ся обратно клиенту.
ЧТЕНИЕ СПЕЦИАЛЬНЫХ АТРИБУТОВ COOKIE
Прежде чем добавить cookie в заголовок, посылаемый клиенту, необ­ходимо установить определенные параметры cookie. Для получения и присваивания определенных атрибутов существует несколько пар мето­дов getXXX()/setXXX(). Сам cookies является в большей степени ком­ментарием к клиентской сессии. Но и он может содержать какие-либо данные, также являющиеся комментариями. Данная пара предназначе­на для установки и чтения комментариев
getComment()/setComment()
Другие методы определяют имена клиентских доменов:
getDomain()/setDomain()
Согласно имени данных методов, они определяют имя домена. Обыч­но cookies выделяют только имя хоста и возвращают это же имя. Метод setSomaun позволяет указать другой домен. Данные методы позволяют указывать браузеру возвращаемое значение части имени домена. Ука­зание имени домена должно начинаться с точки и должно содержать две точки для не географических доменов и три точки для доменов, в имени которых содержится краткое именование страны.
Для сохранения информации о клиентской сессии cookies должен со­хранять свое значение в течение определенного количества времени.
Часть 3 Серверные Java-компоненты Servlet 179
МЕТОДЫ GETMAXAGE()/SETMAXAGE ()
Эта пара методов указывает, как много времени (в секундах) прой­дет, прежде чем cookie будет уничтожен. Если значение не установить, cookie будут жить только в момент клиентской сессии и значение не бу­дет сохранено на локальном диске клиента. При необходимости можно создать очень долгоживущий cookies. Существует LongLivedCookie класс, являющийся порождением от класса Cookie класса, с максималь­ным количеством времени жизни, приблизительно в один год.
Кроме временных характеристик, каждый cookies может иметь соб­ственное имя, облегчающее впоследствии поиск данных, передаваемых данным cookies.
getName()/setName()
Имя cookie. Имя является одним из основных частей cookie. Метод getCookies() класса HttpServletRequest возвращает массив Cookie как именных объектов. Стандартной операцией проверки массива можно найти соответствующее имя и проверить значение объекта с данным именем, используя метод getValue().
Имя и возраст иметь хорошо. Найти и отправить дополнительную co­okie, можно используя методы
getPath()/setPath()
Определяют путь расположения созданного во время клиентской сессии cookie. Если не указать значение пути, cookie вернет все значе­ния пути, в которых находятся вызывающая страница.
Секретность передаваемой информации можно обеспечить, восполь­зовавшись методами
getSecure()/setSecure()
Указывают, должны ли быть закодированы посылаемые cookie. Дан­ными методами секретность обеспечивается только при использовании SSL-протокола.
Основными методами можно считать методы получения значений, передаваемых cookie.
getValue()/setValue().
Указывают значение ассоциированные с данным cookie.
Еще один внутренний параметр, номер версии используемого cookie:
getVersion()/setVersion()
Можно получить номера версии используемого cookie. Существуют только два номера версии: 0, принятый по умолчанию, и 1. Последняя версия хоть и достаточна нова, но пока не очень широко распростра­нена.
Установив и получив все необходимые значения, сконструированный cookie можно отправлять клиенту. Размещением cookie отправляемом в заголовке занимается метод addCookie() объекта класса HttpServletRes­ponse. Как во всех других примерах, все банально просто.
Cookie userCookie = new Cookie("user", "uid1234");
response.addCookie(userCookie);
Для чтения значений cookie, посланных клиентом, существует метод getCookies() класса HttpServletRequest. Данный метод вернет массив
180 Часть 3 Серверные Java-компоненты Servlet
Cookie, значение которых совпадает с переданным в заголовке значени­ем. Расширенные возможности предоставляет метод getCookieValue(), возвращающий массив cookies и их значения.
Необходимо также учесть, что разные браузеры по-разному отобра­жают внешние данные. Создание простого поискового механизма прак­тически ограничивается получением исходной строки при условии, что данные, которые необходимо найти, не являются видео-, аудио- или графическим приложением.
Здесь операторы импорта можно опустить, они такие же, какивлю­бом примере, указанном выше, но для сокращения записи некоторые из уже упоминавшихся выше операторов перенесены в одну строку.
1. import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import
java.net.*;
2. public class SearchEngines extends HttpServlet {public void doGet(HttpSer­vletRequest request, HttpServletResponse response) throws ServletException, IOException {
3. String searchString = URLEncoder.encode(request.getParameter("search­String"));
4. String searchString = URLEncoder.encode(request.getParameter("search­String"));
5. String numResults = request.getParameter("numResults");
6. String searchEngine = request.getParameter("searchEngine");
7. SearchSpec[] commonSpecs = SearchSpec.getCommonSpecs();
8. for(int i=0; i<commonSpecs.length; i++) {
9. SearchSpec searchSpec = commonSpecs[i];
10. if (searchSpec.getName().equals(searchEngine)) {
11. String url = response.encodeURL(searchSpec.makeURL(searchString,num­Results));
12. response.sendRedirect(url);
13. return;} }
14. response.sendError(response.SC_NOT_FOUND,"No search engine specified."); }
15. public void doPost(HttpServletRequest request, HttpServletResponse res­ponse)
16. throws ServletException, IOException {
17. doGet(request, response); }}
18. class SearchSpec {
19. private String name, baseURL, numResultsSuffix;
20. private static SearchSpec[] commonSpecs = {
21. new SearchSpec("altavista", "http://www.altavista.com/search?q=", "&num="),
22. new SearchSpec("infoseek",http://infoseek.go.com/Titles?qt=", "&nh="),
23. new SearchSpec("lycos","http://lycospro.lycos.com/cgi-bin/pursuit?que­ry=", "&maxhits="),
24. new SearchSpec("hotbot","http://www.hotbot.com/?MT=", "&DC=") };
25. public SearchSpec(String name, String baseURL, String numResultsSuffix) {
26. this.name = name;
27. this.baseURL = baseURL;
28. this.numResultsSuffix = numResultsSuffix; }
29. public String makeURL(String searchString, String numResults) {
30. return(baseURL + searchString + numResultsSuffix + numResults); }