Java_23_servlet_interface.ppt
- Количество слайдов: 57
Сетевое программирование и Веб-приложения Продолжение Интерфейсы сервлетов Примеры
Сервлеты - модули обработки HTTP и FTP запросов, ¡ используемые для построения порталов (web gates). ¡ Основой этих порталов является собственно WEB сервер программа, которая держит сокет сервера, принимает и передаёт данные. Чаще всего, для ускорения работы, сервер бывает написан не на Java, а на каком-либо другом языке программирования (например на C++). ¡ В связке с сервером работает базовый сервлет. Именно ему отправляет сервер данные и от него же получает ответ, отправляемый клиенту. Фактически, базовый сервлет является "мозгом" сервера. Основная функция этого сервлета - прочитать запрос клиента, расшифровать его и, в соответствиии с расшифровкой, передать работу сервлету, отвечающему за этот тип запрашиваемой информации. Зачастую, для достижения скорости, роль базового сервлета играет сам сервер. Именно по такой схеме работает, Jacarta Tomcat.
Сервлеты – это технология Java. TM Она предназначенная для увеличения возможностей web-сервера. Сервлеты обеспечивают компонентный, платформонезависимый метод для построения web-приложений без ограничений производительности CGI программ. В отличие от собственных механизмов сервера (таких как Netscape Server API или модулей Apache), сервлеты серверно- и платформо независимы. Сервлеты имеют доступ ко всему семейству прикладных программных интерфейсов Java. TM APIs, включая JDBC TM API для доступа к базам данных.
Сервлеты также могут иметь доступ к библиотеке специальных вызовов HTTP и получать все преимущества полноценного языка Java, включая переносимость, производительность, возможность повторного использования и защиту от аварийных ситуаций. Сервлеты - это распространенный способ написания интерактивных web-приложений. Сторонние контейнеры сервлетов доступны для Apache Web Server, i. Planet Web Server, Microsoft IIS и др. Контейнеры сервлетов могут быть также объединены с серверами приложений, такими как BEA Web. Logic Application Server, IBM Web. Sphere, i. Planet Application Server и др. Сервлет регистрируется в контейнере(deploy)
Интерфейс Servlet Контейнер инициализирует сервлет методом init(). Public void init(Servlet. Config conf); Объект описанный интерфейсом Servlet. Config, coздается веб-приложением и передается контейнеру для инициализации сервлета. Необходимая информация находится в конфигурационном файле(deployment descriptor), который описывает ресурсы веб приложения-web. xml и создается ant
Интерфейс Servlet. Config Каждый объект типа Servlet. Config содержит имя сервлета, извлеченное из web. xml, набор начальных параметров и контекст сервлета в виде объекта Servlet. Context. Получаются эти параметры методами 1. public String get. Servlet. Name(); 2. public Enumeration get. Init. Parametr. Names(); 3. public String get. Init. Parametr(String name); 4. public Servlet. Context get. Servlet. Context();
Пример import java. io. *; import java. util. *; import javax. servlet. *; public class Info. Example extends Generic. Servlet { private Servlet. Config sc; public void init(Servlet. Config conf) throws Servlet. Exception{super. init(conf); sc=conf; } public void service(Servlet. Request req, Servlet. Response resp) throws Servlet. Exception, IOException{ resp. set. Content. Type("text/html; charset=windows-1251"); Print. Writer pw=resp. get. Writer(); pw. println("<html><head>"); pw. println("<title>Параметры сервлета</title>"); pw. println("</head><body>Сведения о сервлете"); pw. println("имя сервлета- "+ sc. get. Servlet. Name() +" "); pw. println("Параметры сервлета: ");
пример Enumeration names = sc. get. Init. Parameter. Names(); while(names. has. More. Elements()){ String name =(String)names. next. Element(); pw. print(name+ ": "); pw. println(sc. get. Init. Parameter(name) + " "); } pw. println("</body></html>"); pw. flush(); pw. close(); } @Override public void destroy(){sc=null; }} Код листинга компилируется, а затем полученный файл устанавливается в контейнер. После процедуры установки сервлет можно вызвать из браузера http: //servlethost: 8080/Info. Appl/servlet/ Info. Example
сервлет Это класс порожденный от класса Http. Servlet с переопреденными методами do. Get и do. Post (управление приходит в один из этих методов в зависимости от того какого типа был запрос. ). Входные-выходные параметры передаются в этих методах через: Http. Servlet. Request req Http. Servlet. Response res
Код сервлета Hello World import import java. io. *; java. text. *; java. util. *; javax. servlet. http. *; /** * The simplest possible servlet. * * @author James Duncan Davidson */ public class Hello. World. Example extends Http. Servlet { public void do. Get(Http. Servlet. Request request, Http. Servlet. Response response) throws IOException, Servlet. Exception { Resource. Bundle rb = Resource. Bundle. get. Bundle("Local. Strings", request. get. Locale()); response. set. Content. Type("text/html"); Print. Writer out = response. get. Writer(); out. println("<html>"); out. println("<head>");
Код сервлета(продолжение) String title = rb. get. String("helloworld. title"); ¡ out. println("<title>" + title + "</title>"); out. println("</head>"); out. println("<body bgcolor="white">"); ¡ ¡ ¡ // // ¡ ¡ // making these absolute till we work out the // addition of a Path. Info issue ¡ ¡ ¡ ¡ note that all links are created to be relative. this ensures that we can move the web application that this servlet belongs to to a different place in the url tree and not have any harmful side effects. } } out. println("<a href=". . /helloworld. html">"); out. println("<img src=". . /images/code. gif" height=24 " + "width=24 align=right border=0 alt="view code"></a>"); out. println("<a href=". . /index. html">"); out. println("<img src=". . /images/return. gif" height=24 " + "width=24 align=right border=0 alt="return"></a>"); out. println("<h 1>" + title + "</h 1>"); out. println("</body>"); out. println("</html>");
Обработка html-формы Это делает код: String res=req. get. Parameter("имя параметра"); А как получить список всех параметров и "пройтись" по этому списку: Enumeration e=req. get. Parameter. Names(); while(e. has. More. Elements()) { String param. Name=(String)e. next. Element(); // имя параметра String param. Val=req. get. Parameter(param. Name); // значение параметра. . . }
Использование кодировки вывода ¡ ¡ ¡ ¡ ¡ ¡ import java. io. *; import javax. servlet. http. *; import java. util. zip. *; // сервлет является наследником Http. Servlet public class Zip. Servlet extends Http. Servlet { // функция обработки метода GET public void do. Get(Http. Servlet. Request request, Http. Servlet. Response response) throws Servlet. Exception, IOException { // устанавливаем, что страничка является HTML документом response. set. Content. Type("text/html"); // берём параметр "Accept-Encoding" из HTTP заголовка String encodings = request. get. Header("Accept-Encoding"); // берём параметр "encoding" - ранее заданная кодировка документа String encode. Flag = request. get. Parameter("encoding"); // Куда будем выводить Print. Writer out; // если поле "Accept-Encoding" в запросе присутствует if(encodings != null) {
Использование кодировки вывода ¡ ¡ ¡ ¡ ¡ // и если это поле содержит значение "gzip", а кодировка ещё не была установлена, if((encodings. index. Of("gzip") != -1)&&!encode. Flag. equals("none")) { // то то, куда будем выводит, будет и сжимать текст с помощью GZIP out = new Print. Writer(new GZIPOutput. Stream(response. get. Output. Stream()), false); // и устанавливаем флаг для браузера, что документ будет сжат response. set. Header("Content-Encoding", "gzip"); } else // в противном случае выводить будем без сжатия out = response. get. Writer(); out. println("This a test!!!"); // пишем тело документа out. close(); // и закрываем вывод. //Всё, по завершению работы этой ф-ии, документ будет отправлен } }
Базовый сервлет
Комментарий к рисунку Клиент подсоединяется к серверу сервер передаёт запрос (request) базовому сервлету ("Basic Servlet") базовый сервлет вычеленяет из запроса URI ресурса если URI указывает на "/sample 1", то запрос целиком (без изменений) передаётся сервлету "Sample 1 Servlet", который, в дальнейшем, и обрабатывает этот запрос если URI указывает на "/sample 2", сервер передаёт запрос сервлету "Sample 2 Servlet" во всех остальных случаях запрос передаётся модулю "JSP Servlet" сервлет, которому было передано управление, обрабатывает данные, создаёт ответ (response), после чего ответ отсылается обратно базовому сервлету. базовый сервлет, не обрабатывая полученные данные, тут же пересылает их обратно серверу сервер выдаёт данные клиенту Таким образом достигается разбиение задачи обработки запроса на логические части, за каждую из которых отвечает свой модуль, свой "программный кирпичик". На самом деле, ступеней в обработке запроса может быть гораздо больше. К примеру за методы "GET" и "POST" могут отвечать разные модули.
Интерфейс Servlet Объединяет все эти модули то, что они сквозным образом связанны между собою с помощью интерфейса javax. servlet. Servlet Посмотрим на этот интерфейс. В нём указано всего 5 методов: public void init(Servlet. Config config) throws Servlet. Exception Этот метод вызывается, чтобы проинформировать сервлет о том, что он включён как модуль для обслуживания запросов клиента. Параметр config разделяет интерфейс javax. servlet. Servlet. Config, несущий информацию об окружении сервера, имени сервлета, начальных параметрах и прочих особенностях. Предполагается, что после вызова этой функции, сервлет аккуратно сохранит этот config у себя в переменной и будет выдавать его с помощью другого метода: public Servlet. Config get. Servlet. Config() Получив системную информацию с помощью "get. Servlet. Config()", сервер может захотеть узнать имя автора, дату создания, прочую информацию о сервлете, что и достигается вызовом public String get. Servlet. Info()
Интерфейс Servlet Чтобы обработать запрос и получить результат его обработки, используется функция public void service(Servlet. Request request, Servlet. Response response) throws Servlet. Exception, java. io. IOException В этой функции коду, который будет обрабатывать данные, передаются два инструмента: один - для получения данных от сервера, другой - для отправки результата работы сервлета. Соответственно это параметры request и response, разделяющие интерфейсы javax. servlet. Servlet. Request и javax. servlet. Servlet. Response Вся работа с данными ведётся именно через эти интерфейсы, так что далее поговорим о них подробнее. После того, как сервер перестал нуждаться в этом модуле вызывается метод public void destroy() который и завершает все операции с объектом сервлета.
Интерфейс Servlet. Config 4 метода, имена которых говорят сами за себя, составляют суть интерфейса javax. servlet. Servlet. Config: public String get. Servlet. Name() public Servlet. Context get. Servlet. Context() public String get. Init. Parameter(String name) public java. util. Enumeration get. Init. Parameter. Names() Думаю, назначение всех функция понятно, кроме public Servlet. Context get. Servlet. Context() Этот метод возвращает ссылку на очень полезный инструмент для работы с сервером: Интерфейс Servlet. Context
Интерфейс Servlet. Context - интерфейс, определяющий доступ к следующим полезным функциям: public Object get. Attribute(String name) public java. util. Enumeration get. Attribute. Names() public void set. Attribute(String name, Object object) public void remove. Attribute(String name) Четыре метода для работы с аттрибутами. Роль аттрибутов выполняет любой объект любого класса. Цель данных функций - пересылать между несвязанными друг с другом сервлетами разные объекты. public String get. Init. Parameter(String name) public java. util. Enumeration get. Init. Parameter. Names() Доступ к параметрам, с которыми был запущен сервер. Тут же могут лежать имя хоста, порт и прочие полезности. public int get. Major. Version() public int get. Minor. Version() Возвращает версии Servlet API. public String get. Mime. Type(String file) Возвращает MIME тип ассоциированный с файлом, путь до которого указан в переменной file.
Интерфейс Servlet. Context public java. util. Set get. Resource. Paths() public java. net. URL get. Resource(String path) throws java. net. Malformed. URLException public Input. Stream get. Resource. As. Stream(String path) Возвращает пути к доступным для сервера ресурсам и сами ресурсы в виде URL и в виде потоков данных. public Request. Dispatcher get. Request. Dispatcher(path) public Request. Dispatcher get. Named. Dispatcher(name) Request. Dispatcher - это инструмент для того, чтобы переслать запрос другому ресурсу. Эти функции нужны, чтобы получить объект этого инструмента для указанных ресурсов. Для того, чтобы перенаправить запрос сервлету "sample 1" из тела сервлета, можно сделать так: get. Servlet. Config(). get. Servlet. Context(). get. Named. Dispatcher("sample 1"). forward(request, response); Собственно класс Request. Dispatcher включает в себя лишь два метода: public void forward(Servlet. Request request, Servlet. Response response) throws Servlet. Exception, java. io. IOException public void include(Servlet. Request request, Servlet. Response response) throws Servlet. Exception, java. io. IOException Причём первый - для перенаправления запроса, а второй - для включения результата работы вызываемого сервлета в результат работы текущего. К примеру, сервлет 1 печатает слово "test 1", потом вызывает include для сервлета два, после чего печатает слово "test 2". Сервлет 2 же просто печатает слово " and ". Результатом работы сервлета 1 будет строка "test 1 and test 2".
Интерфейс Servlet. Context public void log(String msg) Записать что-то в лог сервера. public void log(String message, Throwable throwable) Определить исключение и фразу, которая будет записываться в лог по получении этого исключения. public String get. Real. Path(String path) Переводит путь типа "/index. html" в "http: //host/context. Path/index. html" public String get. Server. Info() Возвращает имя сервера. public Servlet. Context get. Context(String uripath) Этот метод позволяет обмениваться Servlet. Context между разными ресурсами одного и того же сервера. public String get. Servlet. Context. Name() Возвращает имя сервлета, которому принадлежит данный объект интерфейса Servlet. Contect.
Интерфейс Servlet. Request - это инструмент для получения параметров HTTP запроса. Этот интерфейс имеет некоторые методы, идентичные по названию и назначению с Servlet. Context: public Object get. Attribute(String name) public java. util. Enumeration get. Attribute. Names() public void set. Attribute(String name, Object o) public void remove. Attribute(java. lang. String name) public String get. Server. Name() public Request. Dispatcher get. Request. Dispatcher(String path) Оставшися методы позволяют с удобством работать с HTTP заголовком запроса: public String get. Character. Encoding() public void set. Character. Encoding(String env) throws java. io. Unsupported. Encoding. Exception
Работа с кодировкой символов в полях HTTP заголовка. Функции задают метод расшифровки CGI запросов из формы %NN в обычные символы. К примеру, какой стандарт - KOI 8 -R, windows-1251 или UTF-8 нужно применить для расшифровки кириллических символов. public int get. Content. Length() public String get. Content. Type() Читает поля "Content-Length", "Content-Type" из HTTP запроса. public j. String get. Parameter(String name) public java. util. Enumeration get. Parameter. Names() public String[] get. Parameter. Values(String name) public java. util. Map get. Parameter. Map() Функции для получения поля из HTTP заголовка и его значения. public Servlet. Input. Stream get. Input. Stream() throws java. io. IOException public java. io. Buffered. Reader get. Reader() throws java. io. IOException Получить входящий поток данных или его "читатель". Reader применяется для чтения текстовой информации - он автоматически расшифрует строки в соответствии с заданным charset. public String get. Protocol() Получить версию HTTP протокола запроса (к примеру - "HTTP/1. 1").
Интерфейс Servlet. Request public String get. Scheme() Возвращяет имя схемы запроса. Например "http", "https", или "ftp". public int get. Server. Port() public String get. Remote. Addr() public String get. Remote. Host() public boolean is. Secure() Порт сервера, IP адрес клиента, имя хоста клиента и является ли соединение секретным (по протоколу HTTPS) public java. util. Locale get. Locale() public java. util. Enumeration get. Locales() Предпочитаемый клиентом язык документа (результат обработки поля "Accept-Language")
Интерфейс Servlet. Response - это инструмент для отправки данных клиенту. Все методы данного инструмента служат именно этой цели: public java. lang. String get. Character. Encoding() public void set. Locale(java. util. Locale loc) public java. util. Locale get. Locale() Первый метод возвращает MIME тип кодировки (к примеру - UTF 8), в которой будет выдаваться информация. Вторые два метода тоже работают с charset. Они указывают на язык используемый в документе (например - русский). public Servlet. Output. Stream get. Output. Stream() throws java. io. IOException Возвращает поток вывода данных для сервлета. Этот поток используется, к примеру, для вывода бинарных файлов. Текстовые данные можно выводить с помощью java. io. Writer: public java. io. Print. Writer get. Writer() throws java. io. IOException Этот метод автоматически конвертирует строки в тот charset, что указан в методе get. Character. Encoding() и get. Locale(). public void set. Content. Length(int len) Этим методом устанавливается значение поля HTTP заголовка "Content-Length"
Интерфейс Servlet. Response ¡ ¡ ¡ public void set. Content. Type(String type) Метод для отправки MIME типа содержимого документа. Поле HTTP заголовка "Content-Type". public void set. Buffer. Size(int size) public int get. Buffer. Size() public void flush. Buffer() throws java. io. IOException public void reset. Buffer() Дело в том, что поток вывода данных является буфферизованным. Это означает, что следующая порция данных будет выдана клиенту только после заполнения буфера. Указанные методы позволяют, соответственно, установить размер буффера отправки, получить его размер, инициализировать отправку содержимое буффера клиенту, не дожидаясь его заполнения, а так же очистить этот буффер от данных. public boolean is. Committed() Этим методом можно получить флаг, начата ли уже отправка данных клиенту. Флаг будет положительным, если HTTP заголовок ответа был уже отправлен. public void reset() Если HTTP заголовок ещё не отправлен, то этот метод "сбрасывает" HTTP заголовок к значениям "по умолчанию".
Предопределённые типы сервлетов. Java Servlet API, кроме собственно интерфейсов, так же содержит несколько классов сервлетов, которые могут служить основой для ваших программ. Базовым для всех этих классов является абстрактный класс javax. servlet. Generic. Servlet : public abstract class Generic. Servlet implements Servlet, Servlet. Config, java. io. Serializable Как видно из определения этого класса, он имеет все методы интерфейсов Servlet и Servlet. Config. Не реализованным методом остался только public abstract void service(Servlet. Request req, Servlet. Response res) throws Servlet. Exception, java. io. IOException который и был объявлен абстрактным. На базе этого класса был создан другой абстрактный класс javax. servlet. http. Http. Servlet : public abstract class Http. Servlet extends Generic. Servlet implements java. io. Serializable
javax. servlet. http. Http. Servlet Создан этот класс был в соответствии с концепцией "ещё больше удобств для программиста" и имеет много полезных методов: protected void do. Delete(Http. Servlet. Request req, Http. Servlet. Response resp) throws Servlet. Exception, java. io. IOException protected void do. Get(Http. Servlet. Request req, Http. Servlet. Response resp) throws Servlet. Exception, java. io. IOException protected void do. Head(Http. Servlet. Request req, Http. Servlet. Response resp) throws Servlet. Exception, java. io. IOException protected void do. Options(Http. Servlet. Request req, Http. Servlet. Response resp) throws Servlet. Exception, java. io. IOException protected void do. Post(Http. Servlet. Request req, Http. Servlet. Response resp) throws Servlet. Exception, java. io. IOException protected void do. Put(Http. Servlet. Request req, Http. Servlet. Response resp) throws Servlet. Exception, java. io. IOException protected void do. Trace(Http. Servlet. Request req, Http. Servlet. Response resp) throws Servlet. Exception, java. io. IOException protected void service(Servlet. Request req, Servlet. Response res) throws Servlet. Exception, java. io. IOException Различные варианты service(Servlet. Request req, Servlet. Response res) для разных HTTP методов от DELETE и GET до PUT и TRACE. А чтобы с удобством получать данные по CGI интерфейсу не расшифровывывая заголовок были созданы классы Http. Servlet. Request и Http. Servlet. Response, входящие вместе с Http. Servlet в пакет javax. servlet. http
Http. Servlet ¡ ¡ protected long get. Last. Modified(Http. Servlet. Request req) Этот метод возвращает время последней модификации объекта Http. Servlet. Request. Значение времени он берёт из поля "Date" HTTP заголовка запроса. Если же поле не обнаружено, то возвращает -1. ¡ Соответственно разберём и интерфейсы Http. Servlet. Request и Http. Servlet. Response. Они являются наследниками соответственно Servlet. Request и Servlet. Response. ¡ Http. Servlet. Request помимо методов, унаследованных от Servlet. Request, имеет так же следующие полезнейшие методы: ¡ Cookie[] get. Cookies() Возвращает набор Cookies, пересланных клиентом серверу. ¡
Http. Servlet Cookies Класс Cookie, входящий в тот же пакет javax. servlet. http, содержит всю возможную информацию о Cookies. Важнейшими методами этого класса являются int get. Max. Age() String get. Name() String get. Value() выдающие, соответственно, сколько ещё времени Cookies осталось жить, имя Cookies и его значение. Так же Cookie(String name, String value) void set. Value(String new. Value) void set. Max. Age(int expiry) для создания Cookies установки его значения и максимального возраста.
Http. Servlet ¡ ¡ ¡ ¡ long get. Date. Header(String name) Возвращает дату из HTTP заголовка, если таковая есть. int get. Int. Header(java. lang. String name) Возвращает численное значения поля с именем name из HTTP заголовка запроса String get. Method() Возвращает метод HTTP запроса. String get. Query. String() String get. Request. URI() String. Buffer get. Request. URL() Возвращает строку, содержащуюся в URL документа после символа "? ", URI документа и полный URL. Http. Session get. Session() Http. Session get. Session(boolean create) boolean is. Requested. Session. Id. From. Cookie() boolean is. Requested. Session. Id. From. URL() boolean is. Requested. Session. Id. Valid() Функции. позволяющие работать с таким важнейшим механизмом передачи данных, как сессии.
Cессии Сессии необходимы для того, чтобы перемещать за пользователем данные из страницы в страницу. К примеру, пользователь заходит на страницу (1), где ему отправляются некоторые данные для страницы (2), а та сохраняет ещё какие-то вещи для страницы (3). В принципе, на странице (1) можно выслать данные пользователю, потом получить их на странице (2), добавить что-то, выслать пользователю. . . Подобным образом придётся постоянно пересылать весь набор данных от клиента серверу и обратно, причём много раз. Кроме того, что такая пересылка не всегда удобна, она ещё и пожирает траффик.
Передача данных без сессий
Передача данных с сессией Можно так же поступить иначе - использовать механизм сессий. Механизм этот работает следующим образом: данные, присланные пользователем, сервер сохраняет в отдельном файле - файле сессии. С содержимым этого файла и будет производиться вся работа по изменению данных. Клиенту же выдаётся "ключ сессии" (он же Session key, он же Sesseion ID) уникальный указатель на файл, содержащий данные конкретно для этого пользователя. Теперь для того, чтобы получить все данные, касающиеся этого клиента, серверу необходимо знать лишь ключ сессии. Достоинством этого метода является удобство и скорость его использования.
Передача данных с сессией
Интерфейс Http. Servlet. Request. Основное отличие классов, разделяющих данный интерфес, в том, что данные выводятся не сразу. Вначале происходит компановка всех данных в HTTP ответ. Ответ отправляется только после завершения работы Http. Servlet. service(). Методы: void add. Header(String name, String value) void add. Int. Header(String name, int value) void add. Date. Header(String name, long date) Методы добавляют в HTTP заголовок параметры. Последний метод устанавливает параметр "Date". void add. Cookie(Cookie cookie) Метод добавляет cookie в заголовок boolean contains. Header(String name) Позволяет узнать, содержит ли уже заголовок указанный параметр. String encode. URL(String url) String encode. Redirect. URL(String url)
Интерфейс Http. Servlet. Request ¡ ¡ ¡ ¡ ¡ void set. Status(int sc) void send. Error(int sc, String msg) Первый - устанавливает код возврата, вторые два - посылают сообщение об ошибке. В интерфейсе заданы следующие возможные ошибки для параметра sc, соответствующие кодам возврата протокола HTTP: SC_CONTINUE - Status code (100) SC_SWITCHING_PROTOCOLS - Status code (101) SC_OK - Status code (200) SC_CREATED - Status code (201) SC_ACCEPTED - Status code (202) SC_NON_AUTHORITATIVE_INFORMATION - Status code (203) SC_NO_CONTENT - Status code (204) SC_RESET_CONTENT - Status code (205) SC_PARTIAL_CONTENT - Status code (206) SC_MULTIPLE_CHOICES - Status code (300) SC_MOVED_PERMANENTLY - Status code (301) SC_MOVED_TEMPORARILY - Status code (302) SC_SEE_OTHER - Status code (303) SC_NOT_MODIFIED - Status code (304) SC_USE_PROXY - Status code (305)
Коды возврата ¡ ¡ ¡ ¡ ¡ ¡ SC_BAD_REQUEST - Status code (400) SC_UNAUTHORIZED - Status code (401) SC_PAYMENT_REQUIRED - Status code (402) SC_FORBIDDEN - Status code (403) SC_NOT_FOUND - Status code (404) SC_METHOD_NOT_ALLOWED - Status code (405) SC_NOT_ACCEPTABLE - Status code (406) SC_PROXY_AUTHENTICATION_REQUIRED - Status code (407) SC_REQUEST_TIMEOUT - Status code (408) SC_CONFLICT - Status code (409) SC_GONE - Status code (410) SC_LENGTH_REQUIRED - Status code (411) SC_PRECONDITION_FAILED - Status code (412) SC_REQUEST_ENTITY_TOO_LARGE - Status code (413) SC_REQUEST_URI_TOO_LONG - Status code (414) SC_UNSUPPORTED_MEDIA_TYPE - Status code (415) SC_REQUESTED_RANGE_NOT_SATISFIABLE - Status code (416) SC_EXPECTATION_FAILED - Status code (417) SC_INTERNAL_SERVER_ERROR - Status code (500) SC_NOT_IMPLEMENTED - Status code (501) SC_BAD_GATEWAY - Status code (502) SC_SERVICE_UNAVAILABLE - Status code (503) SC_GATEWAY_TIMEOUT - Status code (504) SC_HTTP_VERSION_NOT_SUPPORTED - Status code (505)
Пример показывает, как средствами сервлета можно осуществить непрерывный вывод страницы Такой тип вывода страниц может использоваться, например, в чатах: чтобы прочитать новые сообщения, не нужно будет каждый раз обновлять страницу, новые сообщения будут просто со временем докачиваться. Нужно учесть, что некоторые прокси-серверы не поддерживают такой вид пересылки данных, но с этим - увы - ничего сделать нельзя. Файл Doload. Servlet. java: import java. io. *; import javax. servlet. *; // программа реализует интерфейс Servlet class Doload. Servlet implements Servlet { Servlet. Config config; // объект Servlet. Config public Doload. Servlet() {} // ничего не делает // при инициализации сохраняем config public void init(Servlet. Config config) throws Servlet. Exception {this. config = config; } // выдаёт сохранённый config public Servlet. Config get. Servlet. Config() {return config; } // информация о сервлете public String get. Servlet. Info() {return "Doload. Servlet"; } public void destroy() {} // ничего не делает
непрерывный вывод страницы // обработка запроса public void service(Servlet. Request request, Servlet. Response response) throws Servlet. Exception, java. io. IOException { // разбирать запрос мы не будем, просто сразу // создаём HTTP заголовок: String head = "HTTP/1. 0 200 OKn"+ + "Server: Doload. Servletn" + "Content-Type: text/html; charset=windows-1251n" + "Connection: Keep-Aliven" + "Content-Encoding: multipart/mixedn" + "Transfer-Encoding: chunked" + "Pragma: no-cachenn"; // теперь добавляем первоначальные данные // для этого примера - 20 тэгов " " с переносом строки for(int i = 0; i < 20; i++) head = head + " n"; // берём поток вывода Servlet. Output. Stream os = response. get. Output. Stream(); // пишем туда заголовок и первоначальные данные os. print(head); // отправляем всё записаное в буффер к клиенту response. flush. Buffer();
непрерывный вывод страницы ¡ ¡ ¡ ¡ // начинаем добавлять новые строки: // эти строки будут выглядеть следующим образом: номер строки, потом " n" // каждая новая строка будет появляться раз в 3 секунды int i = 0; while(true) { // инкримент счётчика i++; // пишем строку os. print(""+i+" n"); ¡ ¡ // сброс буффера response. flush. Buffer(); ¡ ¡ ¡ ¡ } } } // примораживаем поток на 3 секунды try {sleep(3000); } catch(Exception e){}
механизм сервлетов Минусом работы сервлетов является низкая скорость первого запуска (сервлет просто компилируется JIT машиной), высокое поребление памяти и недостаток всех программ на Java - низкая скорость работы со строками. Последнее обстоятельство становится заметно при работе сервлетов, принимающих текстовые данные в POST примеры: // дана строка String text // пример 1 // идёт работа со строкой с помощью операции "+" для String test 1 = ""; for(int i = 0; i < text. length(); i++) test 1 += text. char. At(i); // пример 2 // идёт работа со строкой посредством буффера char buf[] = new char[text. length()]; for(int i = 0; i < text. length(); i++) buf[i] = text. char. At(i); String sample 2 = new String(buf); Если взять небольшие строки - до 2 -3 кб, то отличия в работе примеров несущественны, если же взять строку text размером хотя бы в 10 кб, то в первом случае программа будет работать со строкой значительно медленнее. Это является особенностью java и является проблемой реализации функций класса String. Так что если вы хотите написать быстрый сервлет, избегайте работы с длинными строками посредством класса String, используйте, к примеру, класс String. Buffer. Это предупреждение относится прежде всего к получению больших текстов из сети и к обработке локальных файлов (к примеру, в случае текстовой базы данных для гостевой книги при большом количестве сообщений).
Синхронизация Ещё одна проблема касается мультизадачности WEB системы. Сервлет могут одновременно запросить сразу несколько пользователей. Часто возникают проблемы синхронизации данных, обмену сведениями между разными вычислительными потоками одного и того же сервлета, а самая часто встречающаяся проблема - это проблема синхронного доступа к файлам и другим именованым ресурсам системы. К примеру, одна программа открыла файл на чтение, а другая тем временем пытается туда что-то писать. В результате вторая программа либо получает исключение, либо ждёт, пока файл освободится для записи. В связи с этим : не оставляйте за собою незакрытых потоков и закрывайте потоки, как только в них отпала необходимость. Поток, конечно, закроется позже автоматически, но это произойдёт только тогда, когда "мусорщик" до него доберётся, а меж тем вторая программа всё так же не будет иметь доступа к файлу на запись. Дополнительно к мультизадачности можно отметить, что с помощью методов "Object get. Attribute(String name)" и "void set. Attribute(String name, Object object)" интерфейса Servlet. Context вы можете обмениваться между сервлетами данными, в том числе и синхронизирующими.
Запуск и настройка сервлетов Имя файла свойств — servlet. properties. В нем в виде пар «ключ—значение» хранятся свойства, используемые для конфигурации, создания и инициализации сервлетов. Изначально для любого из сервлетов предопределено два свойства. Первое, servlet. <имя сервлета>. code, определяет имя сервлета и ставит его в соответствие двоичному classфайлу сервлета. Например, если вы скомпилировали класс сервлета с именем My. Servlet. Class. Name, то получите в результате компиляции файл с именем My. Servlet. Class. Name. class и можете присвоить ему краткое имя, скажем, myservlet, следующим образом: servlet. myservlet. code=My. Servlet. Class. Name Теперь, когда вы обратитесь к сервлету с именем myservlet, сервер найдет эту строку в файле свойств и, опираясь на найденное значение, загрузит класс My. Servlet. Class. Name, инициализирует его и передаст ему ваш запрос. Следует помнить о том, что имя class-файла должно задаваться полностью, включая имя пакета, в котором определен класс. Второе свойство, servlet. <имя сервлета>. initargs, определяет передаваемые сервлету параметры инициализации. Значения такого рода параметров могут быть получены сервлетом методом get. Init. Parameter. Если параметров несколько, они отделяются друг от друга запятыми. Пример задания параметров: servlet. myservlet. initargs= some. Parameter. Name 1=some. Value, some. Parameter. Name 2=other. Value
Пример сервлета Сервлет, который будет выводить в окне браузера список файлов в определенном каталоге компьютера-сервера, а заодно и показывать количество файлов и их местоположение. Весь вывод данных будет производиться методом println класса Print. Writer, что является наиболее удобным вариантом посылки текстовых данных. Начнем с того, что опишем класс сервлета, наследующий Http. Servlet, и импортируем необходимые классы. После чего займемся методом do. Get — главной частью сервлета: import javax. servlet. *; import javax. servlet. http. *; import java. io. *; public class Sample. Servlet extends Http. Servlet { public void do. Get( Http. Servlet. Request req, Http. Servlet. Response res)throws Servlet. Exception, IOException { /*Методом get. Writer сервлет получает доступ к потоку вывода, через который серверу /* посылается результат: Print. Writer w = res. get. Writer(); res. set. Content. Type(”text/html”); generate. Header(”Directory Viewer Servlet”, w);
Пример сервлета Методом set. Content. Type серверу сообщается, что возвращаемые данные — страница HTML (MIME-тип «text/html» ). Если этого не сделать, то сервер решит, что посылается обычный текст. Метод generate. Header, который идет следом, убирает детали генерации стандартного заголовка Web-страницы, чтобы не загромождать исходный текст. Первый параметр этого метода — заголовок генерируемой страницы, а второй — ссылка на поток вывода, куда этот метод должен пересылать данные. Следующий блок занимается разбором параметров, переданных сервлету: ¡
Пример сервлета if((param = req. get. Parameter(”dir. To. Show”)) == null) if((param = get. Init. Parameter(”dir. To. Show”)) == null) { w. println(”<H 1><FONT COLOR=RED>” + ”The <EM>dir. To. Show</EM> parameter required!</FONT></H 1>”); return; } Сначала сервлет пытается считать значение параметра dir. To. Show из адреса URL (метод get. Parameter). Если такого параметра в запросе нет, то предпринимается попытка получить параметр с этим же именем из файла свойств (метод get. Init. Parameter). Если и там параметр не обнаружен, запрос прерывается, а в ответ клиенту посылается сообщение Если же параметр найден, то его значение запоминается для дальнейшего использования. В следующем блоке исходного текста проверяется, является ли заданный параметр именем каталога и существует ли каталог с таким именем. Если нет, то следует генерация сообщения об ошибке: File root = new File(param); if(!root. is. Directory()) { w. println(”<H 1><FONT COLOR=RED>” + ”The parameter is not a directory or not exist!</FONT></H 1>”); return; }
Пример сервлета ¡ ¡ ¡ ¡ Когда все формальности соблюдены, у каталога запрашивается список всех имеющихся файлов и по нему вычисляется общее количество их в каталоге. Заодно генерируется строка, показывающая полное имя каталога: File[] file. List = root. list. Files(); w. println(”<H 2><FONT COLOR=TEAL>” + ”Total number of files in the choosen directory - ” + file. List. length + ”</FONT></H 2>”); w. println(”<H 3><FONT COLOR=PURPLE>” + ”Directory path - ” + param + ”</FONT></H 3><HR>”); Имена файлов выводятся методом print. Name, который приведен чуть ниже. Для форматирования списка применяется таблица, поэтому нужны две дополнительные строки, формирующие с помощью пары тегов <TABLE> и </TABLE> таблицу с невидимой рамкой: w. println(”<TABLE BORDER=0 CELLSPACING=5>”); for(int i = 0; i < file. List. length; i++) print. Name(file. List[i], w); w. println(”</TABLE><HR>”); generate. Footer(w); Завершается вывод генерацией стандартного окончания HTML-страницы с помощью метода generate. Footer.
Метод print. Name. Он чрезвычайно прост и состоит из строчки, которая проверяет, является ли выводимое имя каталогом или простым файлом. После этого в специально отведенную переменную записывается комментарий о типе. Далее в два столбца в таблицу выводятся тип файла (простой файл или каталог) и его имя: private void print. Name(File name, Print. Writer output) { String type = name. is. Directory() ? ” (Directory)” : ” (File)”; output. println(”<TR><TD>” + type + ”</TD><FONT COLOR=BLUE>” + name. get. Name() + ”</FONT></TD></TR>”); }
Методы generate. Header, generate. Footer get. Servlet. Info. Они просты, что вы без труда разберетесь с ними самостоятельно: private void generate. Header(String title, Print. Writer output) { output. println(”<HTML>n<HEAD>n<TITLE>” + title + ”</TITLE>n</HEAD>n<BODY>”); } private void generate. Footer(Print. Writer output) { output. println(”</BODY>n</HTML>”); output. flush(); output. close(); } public String get. Servlet. Info() { return ”This servlet shows a content of a directory” + ”mentioned in dir. To. Show parameter or property. ”; } } Отлаживать подобного рода сервлеты не просто, а очень просто. Нужно только открыть в браузере режим просмотра исходного текста страницы — и все ваши ошибки сразу же становятся видны.
Session import import java. io. *; java. text. *; java. util. *; javax. servlet. http. *; import util. HTMLFilter; public class Session. Example extends Http. Servlet { Resource. Bundle rb = Resource. Bundle. get. Bundle("Local. Strings"); public void do. Get(Http. Servlet. Request request, Http. Servlet. Response response) throws IOException, Servlet. Exception { response. set. Content. Type("text/html"); Print. Writer out = response. get. Writer(); out. println("<html>"); out. println("<body bgcolor="white">"); out. println("<head>");
Session String title = rb. get. String("sessions. title"); out. println("<title>" + title + "</title>"); out. println("</head>"); out. println("<body>"); out. println("<a href=". . /sessions. html">"); out. println("<img src=". . /images/code. gif" height=24 " + "width=24 align=right border=0 alt="view code"></a>"); out. println("<a href=". . /index. html">"); out. println("<img src=". . /images/return. gif" height=24 " + "width=24 align=right border=0 alt="return"></a>"); out. println("<h 3>" + title + "</h 3>");
Session Http. Session session = request. get. Session(true); out. println(rb. get. String("sessions. id") + " " + session. get. Id()); out. println(" "); out. println(rb. get. String("sessions. created") + " "); out. println(new Date(session. get. Creation. Time()) + " "); out. println(rb. get. String("sessions. lastaccessed") + " "); out. println(new Date(session. get. Last. Accessed. Time())); String data. Name = request. get. Parameter("dataname"); String data. Value = request. get. Parameter("datavalue"); if (data. Name != null && data. Value != null) { session. set. Attribute(data. Name, data. Value); } out. println("<P>"); out. println(rb. get. String("sessions. data") + " "); Enumeration names = session. get. Attribute. Names(); while (names. has. More. Elements()) { String name = (String) names. next. Element(); String value = session. get. Attribute(name). to. String(); out. println(HTMLFilter. filter(name) + " = " + HTMLFilter. filter(value) + " "); }
Session out. println("<P>"); out. print("<form action=""); out. print(response. encode. URL("Session. Example")); out. print("" "); out. println("method=POST>"); out. println(rb. get. String("sessions. dataname")); out. println("<input type=text size=20 name=dataname>"); out. println(" "); out. println(rb. get. String("sessions. datavalue")); out. println("<input type=text size=20 name=datavalue>"); out. println("<input type=submit>"); out. println("</form>"); out. println("<P>GET based form: "); out. print("<form action=""); out. print(response. encode. URL("Session. Example")); out. print("" "); out. println("method=GET>"); out. println(rb. get. String("sessions. dataname")); out. println("<input type=text size=20 name=dataname>"); out. println(" "); out. println(rb. get. String("sessions. datavalue")); out. println("<input type=text size=20 name=datavalue>"); out. println("<input type=submit>"); out. println("</form>");
Session out. print("<p><a href=""); out. print(response. encode. URL("Session. Example? dataname=foo&datavalue=bar")); out. println("" >URL encoded </a>"); out. println("</body>"); out. println("</html>"); } out. println("</body>"); out. println("</html>"); public void do. Post(Http. Servlet. Request request, Http. Servlet. Response response) throws IOException, Servlet. Exception { do. Get(request, response); } }
Session Example import java. io. *; import java. util. *; import javax. servlet. http. *; public class Session. Example extends Http. Servlet { public void do. Get(Http. Servlet. Request request, Http. Servlet. Response response) throws IOException, Servlet. Exception { response. set. Content. Type("text/html"); Print. Writer out = response. get. Writer(); Http. Session session = request. get. Session(true); // print session info Date created = new Date(session. get. Creation. Time()); Date accessed = new Date(session. get. Last. Accessed. Time()); out. println("ID " + session. get. Id()); out. println("Created: " + created); out. println("Last Accessed: " + accessed); // set session info if needed String data. Name = request. get. Parameter("data. Name"); if (data. Name != null && data. Name. length() > 0) { String data. Value = request. get. Parameter("data. Value"); session. set. Attribute(data. Name, data. Value); } // print session contents Enumeration e = session. get. Attribute. Names(); while (e. has. More. Elements()) { String name = (String)e. next. Element(); String value = session. get. Attribute(name). to. String(); out. println(name + " = " + value); } }
Java_23_servlet_interface.ppt