Передача бинарного файла клиенту из jsp


Как установить двоичный режим передачи файлов в FileZilla, Total Commander и CuteFTP

Из этого туториала вы узнаете, как установить двоичный режим передачи файлов в FileZilla , Total Commander и CuteFTP.

С помощью FTP можно загружать файлы на сервер в двух режимах: ASCII и двоичном (binary). В режиме ASCII файлы передаются в формате ‘текст’. В Двоичном (Binary) файлы передаются в исходном формате данных.

Если у вас возникли проблемы с поврежденными при передаче файлами, для решения этого вопроса можно использовать двоичный режим. Для большинства популярных FTP -клиентов способ выбора двоичного режима передачи отличается:

Total Commander : в панели инструментов вверху найдите вкладку «Режим передачи» (‘Transfer mode’). Затем в выпадающем списке выберите «двоичный» (‘Binary’) (архивы, документы т. д.)’:

FileZilla : в верхнем меню выберите Передача (Transfer)> Тип передачи (Transfer type)> Двоичный (Binary):

CuteFTP: перейдите в раздел Файл (File)> Тип передачи (Transfer Type)> Двоичный (Binary):

Вы также можете воспользоваться детальным видео — туториалом:

Передача двоичного файла (данных) в Java

Я имел обыкновение быть программистом переменного тока. В C, если я хочу передать двоичные данные (не только текстовые файлы) из станд гипергликемии, я просто не могу это сделать, не вызывая getchar() и putchar() снова и снова, пока не достигнет EOF . Мой вопрос заключается в том , что это возможно сделать так же , как в Java? Могу ли я просто позвонить readline() и writeline() снова и снова? Если нет, то что я могу сделать?
Спасибо!

Нет, вы должны абсолютно не ничего с использовать readLine() и writeLine() звонки. Это для текстовых данных. Если вы переносите двоичные данные, вы должны использовать InputStream и OutputStream — ничего с Reader или Writer от имени. Если преобразовать двоичные данные в текст, вы почти гарантированно потерять данные.

Но тогда вы можете просто скопировать блоки данных в то время:

Jsp -> servlet -> jsp, как передать данные?

Здравствуйте, возник вопрос как передать данные из jsp в servlet для обработки и вернуть в ту же jsp. У меня servlet возвращает пустую страницу, подскажите, пожалуйста, где я ошибся.

Суть проекта, в том, что через форму calc.jsp мы вводим цифры и выбираем операцию, обработка запроса происходит на сервлете и он возвращает строи операций (ArrayList) обратно в сервлет где он отображается.

  • Вопрос задан более трёх лет назад
  • 9995 просмотров

Метод doGet должен просто форвордить на jsp, на которой ваша форма, которая отправляет POST запрос, который обрабатывает метод doPost. Результат обработки, вы добавляете в реквест с помощью методов setAttribute.

setAttribute — метод HttpServletRequest-а специально предназначен для передачи данных между сервлетами/jsp

передача файла в 1С через http сервис 1с

Собственно проблема в следующем.
есть в конфигурации http-сервис. который генерит следующий текст html:

Этот код позволяет выбрать, загрузить и передать в 1с файл в теле запроса.
В полученной html форме народ выбирает файл и нажимает кнопку отправить.
Но проблема в следующем. Передача файлов и др. бинарной информации возможна только с применением кодирования «multipart/form-data» а это кодирование предполагает хранение заголовков запроса и файла единым текстом с использованием разделителя. Http сервисы типа Php разбирают такой текст без проблем — стандартными языковыми структурами. Мой вопрос — как это сделать в 1С?

АйТиБложик

Маленький IT блог с характером 1С.

Страницы

Поиск по блогу

четверг, 29 октября 2015 г.

Передача двоичных данных с помощью веб-сервиса

Объект метаданных «Веб-сервис» предназначен для обмена данными посредством веб-технологий, а если быть точнее — по протоколу HTTP. Как же осуществляется передача двоичных данных в мире веб-разработки? Для этого используется кодирование двоичных данных под названием base64 (64 — это число символов в алфавите кодирования, из которого формируется конечный буквенно-цифровой текст на основе латинского алфавита).

Закодированные двоичные данные выглядят примерно так:
TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0

Платформа 1С в своем арсенале имеет имеет парочку функций, которые умеют кодировать двоичные данные в base64:

  • Base64Строка — имеет один входящий параметр типа ДвоичныеДанные, возвращает строку, закодированную по алгоритму base64.
  • XMLСтрока — так же имеет один входящий параметр, который может принимать значение типа ДвоичныеДанные и возвращать строку в формате base64, следует использовать для создания XML.

Допустим, имеется веб-сервис, который содержит метод GetFacsimile. Этот метод принимает номер заказа и возвращает счет факсимиле в виде PDF-файла.

Рисунок 1. Метод веб-сервиса GetFacsimile

Если метод возвращает значение (в нашем случае это файл), то нужно указать тип возвращаемого значения, выберем тип String пространства имен http://www.w3.org/2001/XMLSchema, ведь base64 это строка.

Рисунок 2. Тип возвращаемого значения метода

Напишем программный код для метода:


Функция GetFacsimile(Number)

ФайлКакBase64 = «»;

НомерЗаказаКлиента = СокрЛП(Number);

ЗаказКлиента = Документы.ЗаказКлиента.НайтиПоНомеру(НомерЗаказаКлиента);
Если Не ЗаказКлиента.Пустая() Тогда

МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(ЗаказКлиента);
СтруктураТипов = ОбщегоНазначенияУТ.СоответствиеМассивовПоТипамОбъектов(МассивОбъектов);

ПараметрыПечати = Новый Структура;
ПараметрыПечати.Вставить(«ДополнитьКомплектВнешнимиПечатнымиФормами», Ложь);
ПараметрыПечати.Вставить(«ОтображатьФаксимиле», Истина);

ИмяВременногоФайла = ПолучитьИмяВременногоФайла(«pdf»);

ТабличныйДокумент = Обработки.ПечатьСчетовНаОплату.СформироватьПечатнуюФормуСчетНаОплату(
СтруктураТипов,
Новый СписокЗначений,
ПараметрыПечати);
ТабличныйДокумент.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.PDF);

ДвоичныеДанныефайла = Новый ДвоичныеДанные(ИмяВременногоФайла);

Попытка
УдалитьФайлы(ИмяВременногоФайла);
Исключение
КонецПопытки;

ФайлКакBase64 = Base64Строка(ДвоичныеДанныефайла);

Иначе
ЗаписьЖурналаРегистрации(
«Документы.ЗаказКлиента.НайтиПоНомеру»,
УровеньЖурналаРегистрации.Предупреждение,
Метаданные.Документы.ЗаказКлиента,
,
«Не найден счет факсимиле по номеру заказа клиента: » + НомерЗаказаКлиента + «.»);
КонецЕсли;

Возврат ФайлКакBase64;

КонецФункции

Но можно и по другому, для этого находим информацию в синтакс-помощнике о типе ДвоичныеДанные и смотрим, может ли данный тип сериализоваться в объект XDTO, если да, то какому типу соответствует.

Рисунок 3. Дополнительно описание типа ДвоичныеДанные

Из рисунка 3 видно, что тип ДвоичныеДанные сопоставим с типами base64Binary и hexBinary, которые относятся к пространству имен http://www.w3.org/2001/XMLSchema. Далее указываем для метода тип возвращаемого значения (см. рисунок 2) из списка сопоставимых. Теперь в методе можно возвращать двоичные данные без явного кодирования в base64, система это сделает за вас.

Функция GetFacsimile(Number)

// Создание файла . . .

ДвоичныеДанныефайла = Новый ДвоичныеДанные(ИмяВременногоФайла);

Возврат ДвоичныеДанныефайла ;

КонецФункции

Принимающей стороне остается декодировать строку формата base64 в двоичные данные.

Получение файла с сервера с обработкой возможных ошибок

Для одной из наших интранет-систем мы делали простой поиск по содержимым файлов, присоединённых к официальным документам. Результатом поиска был список имён файлов и ссылок на сервлет, эти файлы выгружающий. Сервлет читает файл по его идентификатору из хранилища и выдаёт его с «Content-Type: application/octet-stream» или MIME-типу, соответствующему файлу. Но как поступить, если на сервере произошла ошибка, как сказать об этом оператору? Можно было бы устроить переадресацию на страницу с сообщением, но это неудобно — надо возвращаться назад, где введённые в формы данные потеряны.
С другой стороны, можно вызвать сервлет через AJAX XmlHttpRequest и вывести сообщение об ошибке, но как же тогда вернуть файл? Функции обратных вызовов объекта XHR не работают с пришедшими с сервера двоичными данными и не смогут показать стандартный браузерный диалог «Сохранить/загрузить файл».

Вышли из положения таким образом. Клиент вызывает сервлет два раза. На шаге 1 он просит его загрузить файл из серверного хранилища (по технологии AJAX передавая все необходимые для этого параметры), сервлет вычитывает файл и кладёт его содержимое, имя, MIME-тип и прочие атрибуты в сессию, а клиенту отвечает (формат ответа JSON) либо неким session_id (документ успешно получен и ждёт клиента), либо строкой ошибки, которую Javascript на клиенте легко покажет через window.alert() . Получив на шаге 1 session_id, клиент делает второй ход: с помощью обычной переадресации вида example.com/servletname?session_ > тут же делает следующий запрос к тому же сервлету с этим параметром и получает в ответ Content-Type: application/octet-stream сотоварищи, что в конечном итоге приводит к появлению стандартного диалога в браузере. После этого документ удаляется из сессии, освобождая место.

Несколько коротких замечаний:

  • Для всей AJAX-кухни мы используем MochiKit старой версии 1.3.1.
  • При выдаче документа с не-ASCII символами в имени файла это имя не отображается правильно во всех браузерах.
  • Для формирования JSON-ответов можно было бы воспользоваться готовыми библиотеками, например распространённой json-lib, но для такой малой задачи не хотелось добавлять к проекту новых зависимостей.

Дополнительное описание работы можно получить в представленном коде.

Абстрактный Java-класс, выполняющий основную работу. Конкретный класс-наследний должен реализовать в нём два метода, уникальных для каждого случая.

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
* Сервлет для получения документа с сервера.
*
*

Потомки этого класса должны реализовать следующие методы:

*
* populateIdentity(HttpServletRequest)
* Чтение из запроса данных, которые будут участвовать в поиске
* документа.
* getDocument(HttpServletRequest, Object)
* Получение непосредственно документа на клиента.
*
*
*

* Параметры: либо набор параметров для получения документа с EJB (поиск
* на сервере по этим параметрам), либо параметр с именем
* AbstractGetFileAJAXWay#DSID (идентификатор, полученный после первого запроса
* сервера) для непосредственной выдачи документа клиенту.
*

Варианты JSON-ответа первого шага:

*


    *
    Успешное получение документа с EJB:

*
*
*
Ошибка получения документа с EJB:

*
*
*

*/
public abstract class AbstractGetFileAJAXWay extends HttpServlet <

public static final String DS ;

public class GetFileAJAXWayException extends Exception <
public GetFileAJAXWayException() < super(); >
public GetFileAJAXWayException(String msg) < super(msg); >
public GetFileAJAXWayException(Throwable thw) < super(thw); >
public GetFileAJAXWayException(String msg, Throwable thw) < super(msg, thw); >
>

Илон Маск рекомендует:  Ifs iterated function systems

public interface IFileContainer extends Serializable <
public String getFileName();
public String getContentType();
public long getFileLength();
public byte[] getFileContent();
>

/**
* Точка входа в сервлет.
*
* @param req HTTP-запрос.
* @param resp HTTP-ответ.
* @throws ServletException
* @throws IOException
*/
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException <

// Выдача документа клиенту.
String ds >
// Выдача документа клиенту.
if (ds > 0) <
try <
deliverDocument(dsid, req, resp);
> catch (GetFileAJAXWayException e) <
e.printStackTrace();
throw new ServletException(e);
>
>
// Запрос документа с сервера.
else if (req.getParameterMap().size() > 0) <
try <
Object > retrieveDocument(identity, req, resp);
> catch (GetFileAJAXWayException e) <
e.printStackTrace();
throw new ServletException(e);
>
>
// Чёрти что.
else <
final String err = «Неизвестный режим работы!»;
log(err);
sendFailureReply(err, resp);
return;
>
>

/**
* Получение документа с сервера и сохранение его в сессии для последующего забора.
* @param identity Объект с данными, которые участвуют в поиске документа. * @param req HTTP-запрос.
* @param resp HTTP-ответ.
* @throws ServletException
* @throws IOException
*/
private void retrieveDocument
(Object identity, HttpServletRequest req, HttpServletResponse resp)
throws IOException <

// Сессия.
HttpSession session = req.getSession(false);

// Получение документа с помощью метода, реализованного в наследнике.
IFileContainer cont;
try <
cont = getDocument(req, identity);
> catch (Exception e) <
final String err = «Ошибка получения документа с сервера: »
+ e.getMessage() + «!»;
log(err);
sendFailureReply(err, resp);
return;
>

// Уникальный идентификатор объекта.
final String ds > new long[] < cont.hashCode(),
cont.getFileLength(),
session.hashCode() >);

// Сохранение документа в пользовательской сессии.
session.setAttribute(dsid, cont);

// Выдача клиенту сообщения о результате работы.
sendSuccessReply(dsid, resp);
>


/**
* Выдача ранее полученного документа клиенту.
* @param dsid Идентификатор документа в сессии.
* @param req HTTP-запрос.
* @param resp HTTP-ответ.
* @throws ServletException
* @throws IOException
*/
private void deliverDocument
(String dsid, HttpServletRequest req, HttpServletResponse resp)
throws GetFileAJAXWayException, IOException <

// Сессия.
HttpSession session = req.getSession(false);

// Есть ли такой документ?
Object sessobj = session.getAttribute(dsid);
if (sessobj == null) <
throw new GetFileAJAXWayException(«Нет объекта \»» + DSID + «\» в сессии!»);
> else if (!(sessobj instanceof IFileContainer)) <
throw new GetFileAJAXWayException(«Неверный объект \»» + DSID + «\» в сессии!»);
>

// Удаление документа из сессии.
session.removeAttribute(dsid);

// Документ.
IFileContainer document = (IFileContainer) sessobj;

// Выдача файла.
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentLength((int) document.getFileLength());
resp.setContentType(document.getContentType());
resp.setHeader(«Content-Transfer-Encoding», «binary»);
/* // По стандарту — в IE не работает
String filename = «=?windows-1251?Q?» + new org.apache.commons.codec.net.QuotedPrintableCodec().encode(document.getFileName(), «Cp1251») + «?=»;
resp.setHeader(«Content-Disposition», «attachment; filename=\»» + filename + «\»»);
*/
/* // Обещали работу в IE — фиг
String filename = java.net.URLEncoder.encode(document.getFileName(), «Cp1251»).replaceAll(«\\+», » «);
resp.setHeader(«Content-Disposition», «attachment; filename=\»» + filename + «\»»);
*/
/**/ // По-тупому
String filename = document.getFileName();
int dotpos = filename.lastIndexOf(‘.’);
if (dotpos > -1)
filename = «file.» + filename.substring(dotpos + 1);
else
filename = «file.dat»;
resp.setHeader(«Content-Disposition», «attachment; filename=\»» + filename + «\»»);
/**/
OutputStream out = resp.getOutputStream();
out.write(document.getFileContent());
out.flush();
out.close();
>

/**
* Уникальный номер документа, положенного в сессию для последующего забора.
*
* @param trashheap Набор произвольных чисел для генерации случайного результата.
* Может быть null, в этом случае в генерации не участвует.
* @return Уникальный идентификатор документа в сессии.
*/
private String dsid(long[] trashheap) <
long ds > if (trashheap != null && trashheap.length > 0)
for (int i = 0; i return Long.toString(Math.abs(new Random(dsid).nextLong()), 10);
>

/**
* Экранирование символов в строках для присоединения их к строке формата JSON.
* @param subject Исходная строка.
* @return Результат.
*/
private String escapeJSON(String subject) <
if (subject == null || subject.length() == 0)
return «»;
return subject.replaceAll(«\»», «\\\»»)
.replaceAll(«\\\\», «\\\\»)
.replaceAll(«[\n\r]», «\\\\n»);
>

/**
* Формирование и отправка JSON-сообщения об успешном завершении работы.
* @param dsid Идентификатор документа в сессии, который (документ) впоследствие можно забрать.
* @param resp HTTP-ответ.
* @throws ServletException
* @throws IOException
*/
private void sendSuccessReply(String dsid, HttpServletResponse resp)
throws IOException <
String ds
+ escapeJSON(dsid) + «\»>»;

/**
* Формирование и отправка JSON-сообщения об ошибке работы.
* @param reason Строка ошибки.
* @param resp HTTP-ответ.
* @throws ServletException
* @throws IOException
*/
private void sendFailureReply(String reason, HttpServletResponse resp)
throws IOException <
String reasonJSON = » <\"result\":\"failure\",\"reason\":\""
+ escapeJSON(reason) + «\»>»;

/**
* Отправка сообщения клиенту.
* @param json Отправляемая строка.
* @param resp HTTP-ответ.
* @throws IOException
*/
private void sendAnyReply(String json, HttpServletResponse resp)
throws IOException <

final byte[] result_bytes = json.getBytes(«UTF-8»);
final int CHUNK = 1024;
final BufferedOutputStream output = new BufferedOutputStream(
resp.getOutputStream(), CHUNK);

resp.setStatus(HttpServletResponse.SC_OK);
resp.setHeader(«Content-Encoding», «UTF-8»);
resp.setContentType(«text/plain; charset=UTF-8»);
resp.setContentLength(result_bytes.length);

int bytes_pos = 0, bytes_chunk = 0;
do <
bytes_chunk = bytes_pos + CHUNK

Класс-наследник, реализующий требуемую для конкретного случая логику.

public class ConcreteDocumentRetrievalServlet extends AbstractGetFileAJAXWay <

public ConcreteDocumentRetrievalServlet() <
super();
>

public Object populateIdentity(HttpServletRequest req)
throws GetFileAJAXWayException <
// Код чтения данных из запроса.
return null;
>

public IFileContainer getDocument(HttpServletRequest req, Object identity)
throws GetFileAJAXWayException <
// Код получения файла из серверного хранилища.
return null;
>
>

Примерный JSP-файл, осуществляющий взаимодействие с сервлетом.

Передача бинарного файла клиенту из jsp

Потому что это нелогично. Ты не можешь взять тебе то, чего тебе не дают.

wF = File.createTextFile(«C://файл.xxx»);
Вот из-за этого весь баг. Из соображений безопаснопасности — ты не можешь получить доступ к файловой системе юзера.
И это не целесообразно зачем его туда сохранять?

25.06.2008, 15:28 #5

Потому что это нелогично. Ты не можешь взять тебе то, чего тебе не дают.

wF = File.createTextFile(«C://файл.xxx»);
Вот из-за этого весь баг. Из соображений безопаснопасности — ты не можешь получить доступ к файловой системе юзера.
И это не целесообразно зачем его туда сохранять?

Д это не важно «wF = File.createTextFile(«C://файл.xxx»);» ,
Почему я решил, что запрос на бинарные файлы игнорируется?

В процессе написания столь простого скрипта, естественно, ни в какие файлы я сначала не чего не писал, а использовал просто использовал метод «document.write(rez)». Так вот (проверял на локальном сервере), туда положил файл, скажем, «XXXX.xxx», посылаю запрос на получение вышеизложенным методом. Так как файл не текстовый, не чего не приходит и «document.write(rez)» об этом мне сигнализирует.
Стоит только тупо открыть этот файл в блокноте и сохранить его (в этом же блокноте не чего не меняя), всё приходит до последнего символа.

Это наводит на мысль, XMLHttpRequest, не умеет читать бинарные файлы.
Какие мысли?

Java Server Pages

Введение

Технология Java Server Pages (JSP) является составной частью единой технологии создания бизнес-приложений J2EE. JSP — это альтернативная методика разработки приложений, динамически генерирующих ответ на те или иные запросы клиента. Прежде чем JSP документ будет использован, специальная процедура преобразует его в соответствующий сервлет. В свою очередь, сервлет, как правило, пишется на языке Java и реализует определенный интерфейс. Далее, сервлет также не является самостоятельным приложением и функционирует, только будучи помещен в соответствующий web-контейнер. Web-контейнер обеспечивает обмен данными между сервлетом и клиентами, берет на себя выполнение таких функций, как создание программной среды для функционирующего сервлета, идентификацию и авторизацию клиентов, организацию сессии для каждого из них.


На настоящий момент реализована трансляция JSP страницы в сервлет, программный код которого пишется на языке Java. Однако авторы спецификации Java Server Pages оставляют возможность реализации JSP и на других языках программирования.

Соотношение между сервлетами бизнес-приложения и адресами URL на сервере задается в дескрипторе размещения. Технология реализации сервлетов обсуждается в отдельной статье. Сейчас же важно отметить тот факт, что программный код, используемый для написания сервлетов, не всегда удобен для динамической генерации текстовых документов в ответ на запрос клиента. Например, фрагмент сервлета, где осуществляется генерация динамической HTML страницы, может выглядеть следующим образом:

Как видим, каждой строке HTML документа в сервлете соответствует определенный фрагмент программного кода, что не способствует простоте разработки и сопровождения бизнес-приложений.

Удобнее разделить динамическую и статическую части генерируемой web-страницы. Для создания динамической части по-прежнему будет использоваться Java или другой язык программирования. Статическую же часть имеет смысл оформить как текстовый документ — Java Server Page (JSP страницу), оформленную в соответствии с требованиями HTML, XML или другого стандарта разметки. Фактически, JSP страница можно рассматривать как шаблон или прообраз динамической страницы, которую остается дополнить динамическими элементами. Для описания динамической составляющей, в технологии JSP предусмотрено два основных механизма: компоненты JavaBean и библиотеки дополнительных тэгов. Как результат, технология JSP предполагает параллельную работу над приложением двух разных специалистов: программиста и ответственного за верстку документов (web мастера), которые отвечают, соответственно, за разработку динамической и статической частей документов, генерируемых в ответ на запросы клиентов.

Как уже говорилось, перед тем, как использовать JSP страницу, ее необходимо преобразовать в соответствующий сервлет. Такое преобразование может выполняться либо в момент, когда JSP страница помещается на сервер, либо когда клиент первый раз обращается к этой странице. Поскольку процедура преобразования довольно трудоемка и занимает много времени, то выполняется она обычно только один раз. Все же последующие обращения клиента к JSP странице сервер автоматически переадресует на сервлет, который был получен в результате ее преобразования.

Сервлет, полученный после преобразования JSP страницы, функционируют в рамках стандартного контейнера сервлетов и используют строго регламентированный интерфейс. Поэтому эта технология не зависит от каких-либо особенностей той или иной аппаратной платформы. С другой стороны, поскольку JSP технологии может строиться на базе интерпретируемого языка Java, то это дает гарантию портируемости приложений, построенных на технологии JSP, на любую платформу, где можно установить виртуальную Java машину.

JSP страница

Как правило, JSP страница хранится в отдельном файле с расширением .jsp. Большая часть содержимого JSP страницы преобразуется в сервлете в набор инструкций out.println(). Пример JSP страницы:

Динамическая составляющая JSP страницы представлена тремя типами специальных элементов: директивами, action и скриптами. Подробнее каждый из них рассматривается в соответствующем разделе.

Директивы

Поскольку web контейнер, прежде чем использовать JSP страницу, предоставленную разработчиками бизнес-приложения, транслирует ее в соответствующий сервлет, имеет смысл предоставить возможность оставлять на JSP странице директивы, которые будут управлять процессом трансляции. Директивы имеют синтаксис

Рассмотрим некоторые из таких директив

Директива page. Декларирует ряд свойств JSP страницы. Синтаксис директивы:

Опишем некоторые наиболее интересные параметры данной директивы:

  • import — Как уже говорилось, JSP страница перед использованием должна быть преобразована в программный код — класс, соответствующего сервлета. В свою очередь, класс сервлета может обращаться к другим классам из стандартных библиотек Java или классам из других пакетов. По умолчанию, класс сервлета, получаемый после трансляции JSP страницы, может иметь связь с пакетами java.lang, java.servlet, java.servlet.jsp и java.servlet.http. Если для класса сервлета требуется обеспечить связь с другими пакетами, например, с xbcat.util как в приведенном выше примере JSP страницы, последнюю следует дополнить директивой page, имеющей атрибут import с названием соответствующего пакета.
  • session — Если для связи с клиентом используется протокол HTTP, то для каждого сеанса по умолчанию создается объект session, позволяющий сохранять информацию об этом клиенте в интервале между его обращениями к серверу. С другой стороны, если атрибут session был указан со значением false, это позволяет отказаться от создания объекта сессии и использовать освободившиеся ресурсы сервера для решения других задач.
  • buffer — Содержимое страницы, созданной в ответ на запрос клиента, сервлет передает в поток вывода out, откуда оно затем передается web контейнером непосредственно клиенту. Чтобы получить более оптимальный режим передачи, в этом потоке предусмотрен режим буферизации. При этом объем буфера по умолчанию составляет 8 килобайт. Параметр buffer директивы page позволяет либо задать другой объем буфера, либо вообще отказаться от режима буферизации, передав атрибуту значение «none».
  • isThreadSafe — Согласно спецификации сервлетов, web контейнер по умолчанию позволяет одному и тому же экземпляру сервлета параллельно обрабатывать запросы сразу от нескольких клиентов. При этом каждому из запросов выделяется отдельный трэд. Между тем, в некоторых случаях бывает полезно запретить параллельную обработку запросов. (Соответствующий контроллер в web контейнере выстраивает приходящие запросы в очередь и передает их сервлету на обработку строго по одному.) Для этого достаточно использовать атрибут isThreadSafe, со значением false.
  • pageEncoding — Позволяет разработчику приложения декларировать кодировку, которая должна использоваться в документе, передаваемом клиенту. По умолчанию считается, что страница имеет кодировку ISO-8859-1.
  • contentType — В ответ на запрос клиента, JSP страница по умолчанию генерирует документ типа HTML. Вместе с тем, область применения технологии Java Server Pages гораздо шире, поскольку она позволяет генерировать любые другие типы текстовых документов: XML, WML, VRML и т.д. MIME-тип генерируемого документа декларируется атрибутом contentType. Как уже понятно, по умолчанию этот атрибут имеет значение «test/html». Вместе с типом документа, спецификация JSP позволяет в том же атрибуте указывать также кодировку генерируемого документа.

Директива taglib. Позволяет использовать на JSP страницах дополнительные тэги, созданные разработчиком приложения (custom тэги). Синтаксис директивы:

где, uri — абсолютный или относительный адрес URI, уникальным образом идентифицирующий дескриптор библиотеки тэгов, связанных с указанным префиксом. Указанный префикс используется для идентификации соответствующих custom тэгов.

Процедуру создания custom тэгов мы рассмотрим позднее.

Директива include. Используется для помещения в JSP страницу текстов и программного кода из других источников. Подстановка выполняется в момент, трансляции JSP страницы в соответствующий сервлет. Пример использования директивы:

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

Фрагмент программного кода на JSP странице (скрипт)

Скрипт, как и остальные элементы, привносит в конечный документ динамическую составляющую. Однако, в отличие от них, скрипт — программный код, помещенный непосредственно в текст JSP страницы. Скрипт может производить вычисления или манипулировать объектами, что позволяет наглядно связывать характеристики генерируемой страницы с параметрами запроса клиента и бизнес-правилами приложения. Элементы скриптов бывают трех типов: декларации, скриплеты и выражения.

Декларации

После преобразования JSP страницы в сервлет большая часть ее содержимого попадает в метод _jspService(), который вызывается всякий раз, когда появляется необходимость обработать заказ клиента. Декларация на JSP странице чаще всего используется для того, чтобы объявить дополнительные атрибуты и методы в классе сервлета, которые будут доступны при обработке любого запроса клиента. Декларации имеют синтаксис .

Примеры деклараций на JSP странице:

Скриплеты

Скриплет может содержать программный код и декларации локальных переменных, которые будут использованы для обработки запросов клиентов. Фактически, скриплет — это фрагмент программного кода из будущего сервлета, который в свое время будет помещен в метод _jspService(). Являясь частью сервлета, скриплет получает доступ к объекту response и, соответственно, может самостоятельно формировать определенную часть конечной динамической страницы. Однако чаще всего скриплеты используются не для этого, а для того, чтобы управлять объектами бизнес-логики и логикой приложения.

Скриплет имеет синтаксис . Пример использования скриплетов в содержимом JSP страницы:

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

Выражения

Часто страница, передаваемая клиенту, содержит результаты вычислений или обращений к тем или иным методам и атрибутам определенных классов. Любой из таких динамических элементов можно преобразовать в строку и представить на JSP странице с помощью вызова out.println в соответствующем скриплете:

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

Другой пример использования выражения в теле JSP страницы:


JSP страницы и объекты

В ходе обработки запросов, JSP страница может получать доступ к объектам, расположенным на сервере, создавать их и модифицировать. Доступ к объектам осуществляется через элементы скриптов и action. Каждый создаваемый в приложении объект имеет определенное время существования, которое декларируется в соответствующем атрибуте. Спецификацией предусматривается четыре интервала:

  • page — Объект, чье время существования определяется как page, доступен в пределах только той JSP страницы, где он был создан. Все ссылки на этот объект должны быть освобождены сразу же после того, как запрос клиента был обработан.
  • request — Объект, чье время существования определяется как request, доступен для всех страниц, связанных с обработкой данного запроса. В частности, если имеет место переадресация обработки на новую JSP страницу, данный объект будет доступен и на прежней, и на новой странице. Как и в предыдущем случае, ссылки на объект после обработки запроса должны быть освобождены.
  • session — Объект с областью видимости session доступен для всех страниц, обрабатывающих запросы, связанные с определенной сессией (сеансом связи с конкретным клиентом). Ссылки на объекты, связанные с сессией, помещаются в объект session. По окончании сеанса связи ссылки должны быть освобождены.
  • application — Наиболее общая область видимости. Объекты, имеющие область существования application, не привязаны к какой-либо отдельной странице или сеансу связи и доступны со всех JSP страниц данного приложения.

JSP страница всегда имеет доступ к определенному набору объектов, создаваемых web контейнером по умолчанию:

  • request — Объект, содержащий запрос клиента. Относится к классу javax.servlet.ServletRequest или другому наследующему его классу. Например, для протокола HTTP это будет объект класса javax.servlet.http.HttpServletRequest. Область видимости объекта — request.
  • response — Объект, в который сервлет будет помещать ответ на запрос пользователя. Относится к классу javax.servlet.ServletResponse или другому наследующему его классу. Например, для протокола HTTP это будет объект класса javax.servlet.http.HttpServletResponse. Область видимости объекта — request.
  • pageContext — Объект, определяющий контекст JSP страницы. Область видимости объекта — page
  • session — Объект, создаваемый контейнером для идентификации клиента, а также хранения персональных объектов. Создается контейнером для протокола HTTP и является экземпляром класса javax.servlet.http.HttpSession.
  • application — Объект, связанный с конфигурацией сервлета, соответствующего данной JSP странице. Область видимости объекта — application.
  • out — Объект, содержащий выходной поток сервлета. Информация, посылаемая в этот поток, будет передана клиенту. Объект является экземпляром класса javax.servlet.jsp.JspWriter. Например, большая часть статического шаблона на JSP странице, в идеале, должна быть записана в виде соответствующего набора команд out.println(). Область видимости объекта — page.
  • config — Объект, связанный с конфигурацией сервлета. Является экземпляром класса javax.servlet.ServletConfig. Для JSP страницы область видимости объекта config — page.
  • page — Объект, связанный с обработкой данной страницы. Область видимости — page

Элементы action

Независимо от того, какой тип будет иметь документ, генерируемый в ответ на запрос пользователя, в общем случае, JSP страница содержит текст и тэги. Очевидно, что последние соответствуют типу генерируемого документа: HTML, XML и т.д. Кроме того, в теле JSP страницы могут содержаться фрагменты программного кода на языке Java, которые должны войти в состав сервлета, получаемого после трансляции: декларации, скриплеты и выражения. Идея заключается в том, чтобы дополнить набор тэгов стандартной разметки специальными тэгами — элементами action, за которыми разработчик бизнес-приложения может скрыть часть программного кода, относящегося к приложению, либо некоторые дополнительные инструкции.

Заметим, что с точки зрения специалиста по верстке документов, элементы action являются такими же тэгами, как и все остальные, а потому допустимо их совместное использование с другими элементами:

Рассмотрим некоторые из этих элементов.

Стандартные элементы action

Стандартные элементы action выглядят как обычные тэги, название которых начинается с сочетания символов jsp:, например . Согласно терминологии XML, это означает, что стандартные элементы action в технологии JSP принадлежат пространству имен jsp.

jsp:useBean

Элемент jsp:useBean позволяет использовать на JSP странице объекты, соответствующие компонентам JavaBean. Элемент содержит параметр, который связывает с компонентом некий уникальный идентификатор. Последний затем будет использоваться при обращениях к этому объекту:

В данном примере создается объект класса com.myco. В дальнейшем, чтобы обратиться к нему, достаточно воспользоваться идентификатором «customer». Например:

По умолчанию, объекты, связанные с элементом JavaBean, по умолчанию имеют область видимости page. Разработчик JSP страницы может указать более продолжительное время существования объекта JavaBean, воспользовавшись при написании элемента jsp:useBean элементом scope. Возможные значения этого атрибута — page, request, session и application — мы обсуждали несколько ранее во время разговора об области видимости объектов, связанных с JSP страницей.

Мы не будем рассматривать остальные атрибуты элемента jsp:useBean. Приведем лишь еще один пример его использования:

Внутреннее устройство элементов JavaBean будет рассмотрено нами в отдельной статье.

Любой класс должен давать доступ к некоторым из своих атрибутов и методов. Отличие элемента JavaBean заключается в том, что доступ к атрибутам у него унифицирован и реализуется на JSP странице с помощью элементов jsp:setProperty и jsp:getProperty.

Элемент jsp:getProperty берет экземпляр Bean, извлекает значение указанного атрибута, преобразует его в случае необходимости в строку и помещает в поток данных, передаваемых клиенту. Например, согласно следующей записи

в генерируемый документ помещается значение свойства name из экземпляра Bean, имеющего идентификатор user.

Элемент jsp:setProperty, в отличие от предыдущего, не извлекает, а задает новое значение атрибута. Например:

Помимо явного задания новых значений, элемент jsp:setProperty позволяет заносить в атрибут объекта значение, извлеченное из запроса клиента. Например:

Данная запись означает, что среди данных, полученных от клиента, находится параметр login и его значение передается для помещения в атрибут name объекта Bean, имеющего идентификатор «user».

Наконец, когда названия полей в запросе клиента совпадают с названиями атрибутов объекта Bean, предусмотрен еще один вариант, когда разом осуществляется перенос всех значений. Например:

jsp:include

Подобно директиве include, данный элемент позволяет помещать в тело динамически генерируемой страницы статический и динамический материал из внешнего источника. При этом, хотя заимствованный таким образом материал обрабатывается в том же контексте, что и текущая страница, ему предоставляется доступ только к выходному потоку сервлета. Например, код, включаемый в JSP страницу, не должен обращаться к cookies или использовать собственные заголовки, декларирующие кодировку или тип документа.

Отличие директивы include от элемента jsp:include заключается в том, что для нее включаемый материал не может быть динамическим, а поиск и обработка возможных динамических фрагментов осуществляется не отдельно, а после включения, со всей страницей.

Пример использования элемента jsp:include:

jsp:forward

Данный элемент позволяет переадресовать дальнейшее формирование динамической страницы на другую JSP страницу, сервлет или использовать для завершения заранее приготовленный текст. Например:

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


В заключение следует заметить, что есть две основные схемы обработки запросов клиента:

В первом случае, обработка запроса клиента и формирование в ответ динамической страницы производятся в рамках одной JSP страницы или сервлета. Последняя, в случае необходимости, может обращаться к объектам JavaBean или импортировать материал из внешних источников с помощью директивы include или элемента jsp:include.

Во втором случае, обработка производится в два этапа. Сперва управление подается на сервлет или JPS страницу, осуществляющую собственно обработку запроса. Например, из запроса клиента извлекаются данные и помещаются в базу данных или атрибуты определенных объектов. Затем управление передается на отдельную JSP страницу или сервлет, ответственные за генерацию динамической страницы для последующей передачи ее клиенту. При этом между обработкой запроса и генерацией новой страницы необязательно должна существовать какая-либо взаимосвязь. Например, это может быть всего лишь возврат клиента на главную страницу по завершении какой-либо процедуры.

Дополнительные наборы тэгов

Такие протоколы разметки текстовых документов, как HTML, имеют строго регламентированный набор тэгов. Вместе с тем, в ходе разработки документов часто возникает потребность использовать дополнительные, специальные тэги, которые хотя и не были заявлены в соответствующие спецификации, но зато в большей степени соответствуют предметной области бизнес-приложения. С одной стороны, подобные дополнительные или custom тэги можно рассматривать как своеобразные макросы, которые перед передачей документа клиенту будут заменены эквивалентной комбинацией стандартных тэгов. В другом варианте, за custom тэгом может стоять определенный фрагмент программного кода. Например, вполне обычный одинарный тэг может оказаться счетчиком посещений или меню, содержимое которого зависит от той роли, которую данный клиент играет в бизнес-процессе.

Построение custom тэгов связано с написанием определенного программного кода. Технология JSP предусматривает размещение этого кода в отдельном программном модуле — библиотеке custom тэгов. Разработка подобных библиотек может быть поручена сторонним компаниям. Подключение JSP страницы к той или иной библиотеке custom тэгов осуществляется с помощью ранее описанной директивы taglib. Указанная директива связывает дескриптор соответствующей библиотеки с определенным префиксом, который, в свою очередь, идентифицирует в теле JSP страницы все custom тэги из данной библиотеки. Так, директива

объявляет, что в JSP странице используется библиотека дополнительных тэгов, название каждого из которых начинается с префикса dscat. Например:

Программный код данной библиотеки описывается дескриптором exttags.tld. Мы не будем здесь останавливаться на правилах написания дескриптора библиотеки, а рассмотрим лишь один из возможных примеров его реализации:

Создание библиотеки custom тэгов

Custom тэги без обработки содержимого

Программный код для поддержки custom тэга — это специальным образом написанный экземпляр Java класса, который вызывается web контейнером всякий раз, когда требуется обработать JSP страницу, содержащую соответствующий тэг.

В простейшем случае, для поддержки custom тэга можно взять какой-либо из классов бизнес-приложения и дополнить его методами, соответствующими интерфейсу Tag. Если же внешних объектов использовать не надо, то в качестве базового класса можно использовать TagSupport. Эти и другие стандартные классы и интерфейсы находятся в пакете javax.servlet.jsp.tagext.

Пример класса, осуществляющего поддержку custom тэга:

Методы класса, который осуществляет обработку custom тэга, вызываются в определенной последовательности. Когда в JSP странице обработка доходит до открывающего custom тэга, для его обработки вызывается метод doStartTag(). Когда обработка доходит до соответствующего закрывающего тэга, вызывается метод doEndTag(). Для обработки той части JSP страницы, которая заключена между этими двумя тэгами, используются методы doInitBody() и doAfterBody().

Помимо того, что метод doStartTag() может осуществлять какую-либо обработку запроса, большое значение имеет возвращаемое им значение. Если это SKIP_BODY, то информация, заключенная между соответствующими открывающим и закрывающим тэгами, будет игнорироваться, а обработка JSP страницы сразу перейдет на закрывающий тэг. Чтобы содержимое custom тэга все же обрабатывалось, медот должен возвратить EVAL_BODY_INCLUDE. Аналогично, если метод doEndTag() возвратит значение SKIP_PAGE, то оставшаяся часть JSP страницы после закрывающего тэга будет проигнорирована. Чтобы не допустить этого, метод должен возвратить значение EVAL_PAGE.

В некоторых случаях бывает необходимо показать содержимое custom тэга не один, а несколько раз. В этом случае, класс, осуществляющий обработку тэга, должен реализовывать интерфейс IterationTag, либо использовать в качестве родителя класс TagSupport. Чтобы повторить вывод содержимого custom тэга еще раз, необходимо, чтобы методы doStartTag и doAfterBody возвращали EVAL_BODY_AGAIN.

Custom тэги с обработкой содержимого

Если требуется доступ к содержимому custom тэга, то соответствующий Java класс должен реализовывать интерфейс BodyTag или же наследовать класс BodyTagSupport. И в том, и в другом случае класс может реализовать методы doInitBody и doAfterBody.

Метод doInitBody вызывается сразу после того, как выявлено содержимое тэга, но до того, как оно будет обработано. Обычно этот метод используется когда необходимо выполнить инициализацию класса в зависимости от содержимого custom тэга.

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

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

Непосредственно для доступа к содержимому custom тэга технологией предусмотрено два метода: getString и getReader.

Атрибуты в custom тэгах

Помимо информации в промежутке между открывающим и закрывающим тэгами, custom тэг может иметь некоторые атрибуты, которые также могут оказывать влияние на порядок обработки запроса клиента. Для каждого из таких атрибутов в классе, реализующем custom тэг, должен быть указан соответствующий атрибут, а также два метода get и set. Например, если custom тэг имеет вид

то реализующий этот custom тэг класс должен содержать следующий код:

Атрибуты custom тэга также необходимо декларировать в дескрипторе библиотеки custom тэгов.

Следует заметить, что в этом разделе мы рассмотрели лишь наиболее часто используемые методы, связанные с обработкой custom тэгов. К примеру, неосвещенными остались такие важные темы, как интерфейс TryCatchFinally и абстрактный класс BodyContent.

Передача двоичного файла по байтовому массиву с использованием TCP в java

Я пытаюсь передать двоичный файл с сервера клиенту по блокам байтов за раз. Тем не менее, у меня проблема, когда она застревает при передаче 8kb. Файл обычно больше, чем 1mb, а массив байтов имеет размер 1024. Я считаю, что он должен что-то делать с моим циклом while, так как он не закрывает мое соединение. Любая помощь? Благодаря

Ваши петли должны проверять count >= 0 , а не count > 0 , а потоки и сокет должны быть закрыты в блоке finally. Помимо этого, код выглядит хорошо для меня.

Что вы подразумеваете под словом «он застрял в передаче 8kb»? Любое исключение?

Можно ли скачать бинарный файл из JSP ?

я думаю, что это вполне возможно, но я не уверен.

у меня нет возможности использовать сервлет непосредственно, так что я вынужден использовать JSP ( давнюю историю, в короткое время, вы не хотите слышать )

Поэтому я думаю, что-то вроде следующего:

не ставьте слишком много внимания код. Он только демонстрирует эту идею. Он пишет bynary массив jsp поток вывода.

возможно ли это? Делает это звучит разумно? Есть ли JSTL или другая вещь, которая обрабатывает что?

Илон Маск рекомендует:  Что такое код moverel
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL
25.06.2008, 21:18 #6