Распределенные вычисления
Технологии распределенных систем. Реализация системного программного обеспечения промежуточного слоя. Простой протокол доступа к объектам. Инсталляция сервера приложений. Исходный код Web-сервиса. Процесс взаимодействия между клиентом и Web-сервером.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 13.08.2011 |
Размер файла | 1,9 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ
КУРСОВОЙ ПРОЕКТ ПО ОПЕРАЦИОННЫМ СИСТЕМАМ И СРЕДАМ И СИСТЕМНОМУ ПРОГРАММИРОВАНИЮ
ТЕМА: РАСПРЕДЕЛЕННЫЕ ВЫЧИСЛЕНИЯ
Студента БГУИР, ФНиДО
Информатика, группа 702021с
Дядькина Семена Викторовича
Минск 2011
Оглавление
1. Постановка задачи
2. Мобильные агенты
3. Web-сервисы
4. Клиент для web-сервиса
5. JavaMail API - отправка почты
6. Java Mail API - получение почты.
Список литературы
1. Постановка задачи.
Тогда можно так и сформулировать задачу: сервер, способный принимать "задания", выполнять их и отсылать обратно ответ (результат). Если есть несколько таких "серверов заданий" (предполагается, что на различных машинах в сети, то получаем как раз распределенную систему вычислений, а в более широком смысле - решения задач, у которых ожидается большая сложность (длительность выполнения). Основная проблема, которую нужно решить - как формализовать само "задание" таким образом, чтобы можно было его эффективно распределить по исполнителям, а потом "собрать" отдельные "частные" результаты в один общий. Если не использовать готовые платформы для распределенных вычислений (а они существуют), не трогать "облака" и т.п., то передавать надо исполняемый файл с исходными данными и параметрами, указывающими, что именно следует делать. В идеале, код передается в некотором "промежуточном" языке, который может быть выполнен в различных системах, но при этом достаточно эффективно, чтобы не "съесть" эффект от распараллеливания, т.е. просто интерпретатор может и не подойти. Скорее что-то вроде Java или .NET, при условии что имеется соответствующая виртуальная машина. В нашем случае можно упростить до обычного исполняемого файла и считать, что работы в ОС одного семейства нам хватит. Конечно, можно компилировать исполняемый файл из исходника сразу на "своей" платформе, но возиться в рамках курсового с компилятором будет все-таки излишне (хотя запусть тот же gcc не проблема, сложнее правильно обработать все ошибки и нештатные ситуации). Передаваемые параметры тоже можно сделать достаточно несложными, но универсальными: пересылка серверу 1 исполняемого файла, 1 (или несколько?) файла(ов) исходных данных для него и строки параметров для него же; интерпретация параметров будет на совести самого исполняемого файла.
Например (условно) "перемножитель матриц": исполняемый файл умеет перемножить 1 строку на 1 столбец, их номера выбираются параметрами, нужны 2 блока (файла) данных (2 исходные матрицы), результат -1 число, элемент новой матрицы, возвращается "заказчику" задания вместе с указанием его координат для "сборки" этой матрицы. (Пример не очень удачный, потому что операция умножения сравнительно простая, и бОльшую часть работы составят "накладные расходы" на декомпозицию задания, пересылку и сборку.)
Вырисовываются компоненты системы: 1 "центральный" сервер, который умеет "разобрать" задание, раздать его, дождаться "частных" результатов, собрать конечный результат; несколько исполнительных серверов (экземпляры одной программы), которые выполняют каждый свою часть обработки; некий "клиент", который может принять задание от пользователя и показать конечный результат.В общем, в рамках этого еще много можно уточнять, что-то упрощать, что-то дополнить. В любом случае, задача все же учебная, обязательное получение вполне завершенного и готового к реальному применению продукта не предполагается. Хотя стремиться к этому надо. Устраивает такая постановка задачи?
Красивую формулировку темы и "дележку" ее на 2 предмета обдумаем отдельно.
2. Мобильные агенты
Идея рассматриваемой модели (рис 2.1) состоит в том, что зачастую, как это ни парадоксально, клиент сам в состоянии выполнить ту задачу, решение которой он запросил у сервера, более того, данные, необходимые для решения этой задачи, располагаются на клиенте. В таком случае для разгрузки сервера (и очень часто - для снижения сетевого трафика) целесообразно решать эту задачу на клиенте. Но как это сделать, если у клиента нет соответствующего программного модуля, содержащего необходимую функциональность? Ответ таков - этот модуль нужно клиенту отправить. Клиент, получив модуль (этот модуль называется мобильным агентом), может выполнить его локально, решив таким образом задачу. В качестве примера можно рассмотреть взаимодействие браузера и веб-сервера, возвращающего страницу, которая содержит апплет. Апплет также передается клиенту и выполняется в браузере (т.е. на клиенте), выполняя какие-то значимые для пользователя действия. Основная проблема для такого подхода состоит в сложности реализации механизма передачи и выполнения мобильных агентов, а также контроля безопасности3). Однако, современные средства middleware (Java, например) такими возможностями обладают.
Рис. 2.1. Мобильные агенты
3. Web-сервисы
Web-сервисы - новое слово в технологии распределенных систем. Спецификация Open Net Environment (ONE) корпорации Sun Microsystems и инициатива .Net корпорации Microsoft обеспечивают инфраструктуры для написания и развертывания Web-сервисов. В настоящий момент имеется несколько определений Web-сервиса. Web-сервисом может быть любое приложение, имеющее доступ к Web, например, Web-страница с динамическим содержимым. В более узком смысле Web-сервис - это приложение, которое предоставляет открытый интерфейс, пригодный для использования другими приложениями в Web. Спецификация ONE Sun требует, чтобы Web-сервисы были доступны через HTTP и другие Web-протоколы, чтобы дать возможность обмениваться информацией посредством XML-сообщений и чтобы их можно было найти через специальные сервисы - сервисы поиска. Для доступа к Web-сервисам разработан специальный протокол - Simple Object Access Protocol (SOAP), который представляет средства взаимодействия на базе XML для многих Web-сервисов. Web-сервисы особенно привлекательны тем, что могут обеспечить высокую степень совместимости между различными системами.
Гипотетический Web-сервис, разработанный в соответствии с архитектурой ONE Sun, может принимать форму, в которой реестр сервисов публикует описание Web-сервиса в виде документа Universal Description, Discovery and Integration (UDDI).
Огромный потенциал Web-сервисов определяется не технологией, примененной для их создания. HTTP, XML и другие протоколы, используемые Web-сервисами, не новы. Функциональная совместимость и масштабируемость Web-сервисов подразумевает, что разработчики могут быстро создавать большие приложения и более крупные Web-сервисы из меньших Web-сервисов. Спецификация Sun Open Net Environment описывает архитектуру для создания интеллектуальных Web-сервисов. Интеллектуальные Web-сервисы задействуют общее операционное окружение.
Для того чтобы создать приложение, являющееся Web-сервисом, необходимо применить целый ряд технологий.
Взаимосвязь этих технологий условно представлена на рис. 3.1.
Рис. 3.1. Взаимосвязь технологий
По сути, Web-сервисы являются одним из вариантов реализации компонентной архитектуры, при которой приложение рассматривается как совокупность компонентов, взаимодействующих друг с другом. Как уже неоднократно говорилось, взаимодействие компонент, выполняющихся на разных платформах, представляет собой достаточно сложную задачу, в частности, требует разработки коммуникационного протокола, учитывающего особенности передачи данных между различными платформами. Одной из основных идей, положенных в основу рассматриваемой технологии Web-сервисов, является отказ от бинарного коммуникационного протокола. Обмен сообщениями между компонентами системы осуществляется посредством передачи XML-сообщений. Поскольку XML-сообщения представляют собой текстовые файлы, транспортный протокол передачи может быть самый различный - XML-сообщения можно передавать по HTTP-, SMTP-, FTP-протоколам, причем использование различных транспортных протоколов прозрачно для приложений. Как уже говорилось, протокол, обеспечивающий возможность взаимодействия Web-сервисов, называется SOAP (Simple Object Access Protocol). Он определен на основе XML. SOAP обеспечивает взаимодействие распределенных систем, независимо от объектной модели или используемой платформы. Данные в рамках SOAP передаются в виде XML-документов особого формата. SOAP не навязывает какого-либо определенного транспортного протокола. Однако в реальных приложениях наиболее часто реализуется передача SOAP-сообщений по протоколу HTTP. Также широко распространено использование в качестве транспортного протокола SMTP, FTP и даже "чистого" TCP. Итак, SOAP определяет механизм, с помощью которого Web-сервисы могут вызывать функции друг друга. В каком-то смысле работа этого протокола напоминает вызов удаленной процедуры - вызывающая сторона знает имя Web-сервиса, имя его метода, параметры, которые метод принимает, оформляет вызов этого метода в виде SOAP-сообщения и отсылает его Web-сервису.
Однако описанный подход годится лишь в том случае, если заранее известны "сигнатуры" методов, которые реализует Web-сервис. Но как быть, если это не так? Для решения этой проблемы в модель Web-сервиса введен дополнительный слой - слой описания интерфейсов сервисов. Этот слой представлен в виде описания WSDL.
Согласно определению W3C, "WSDL - формат XML для описания сетевых сервисов как набора конечных операций, работающих при помощи сообщений, содержащих документно-ориентированную или процедурно-ориентированную информацию". Документ WSDL полностью описывает интерфейс Web-сервиса с внешним миром. Он предоставляет информацию об услугах, которые можно получить, воспользовавшись методами сервиса, и способах обращения к этим методам. Таким образом, в случае если сигнатура метода Web-сервиса точно не известна (например, она изменилась со временем), у целевого Web-сервиса может быть запрошено WSDL-описание - файл, в котором эта информация будет содержаться.
Следующим слоем технологии является сервис Universal Description, Discovery and Integration (UDDI). Эта технология предполагает ведение реестра Web-сервисов. Подключившись к этому реестру, потребитель сможет найти Web-сервисы, которые наилучшим образом подходят для решения его задач. Технология UDDI дает возможность поиска и публикации нужного сервиса, причем эти операции могут быть выполнены как человеком, так и другим Web-сервисом или специальной программой-клиентом. UDDI, в свою очередь, также представляет собой Web-сервис.
Таким образом, Web-сервисы являются еще одной реализацией системного программного обеспечения промежуточного слоя. Отличительной чертой этой технологии является ее независимость от используемого программного и аппаратного обеспечения, а также использование широко применяемых открытых стандартов (таких как XML) и стандартных коммуникационных протоколов.
В настоящее время Web-сервисы являются очень активно продвигаемой технологией и позиционируются как средство решения целого ряда задач.
Следует отметить, что с их применением могут строиться и так называемые "стандартные" приложения, где в качестве Web-сервиса оформляется серверная часть.
Простой протокол доступа к объектам (SOAP)
Базовым протоколом, обеспечивающим взаимодействие в среде Web-сервисов, является протокол SOAP.
Протокол SOAP разработали корпорации IBM, Lotus Development Corporation, Microsoft, Develop-Mentor и Userland Software. Этот протокол основан на HTTP-XML. Он позволяет приложениям взаимодействовать между собой через Internet, используя для этого XML-документы, называемые сообщениями SOAP. Протокол SOAP совместим с любой объектной моделью, поскольку он включает только те функции и методы, которые абсолютно необходимы для формирования коммуникационной инфраструктуры. Таким образом, SOAP является независимым от платформы и конкретных приложений, а для его реализации может применяться любой язык программирования. SOAP поддерживает практически любой транспортный протокол. SOAP также поддерживает любые методы кодирования данных, которые позволяют приложениям, основанным на SOAP, посылать в сообщениях SOAP информацию практически любого типа (например, изображения, объекты, документы и т.д.).
Сообщение SOAP содержит конверт, который описывает содержимое, предполагаемого получателя сообщения и требования к обработке сообщения. Необязательный элемент header (заголовок) сообщения SOAP содержит инструкции по обработке для приложений, которые принимают сообщение. Заголовок также может содержать информацию о маршрутизации. С помощью заголовка header поверх SOAP могут надстраиваться более сложные протоколы. Записи в заголовке могут модульно расширять сообщение для таких задач, как аутентификация, управление транзакциями и проведение платежей. Тело SOAP-сообщения содержит специфичные для приложения данные, предназначенные для предполагаемого получателя сообщения.
Начало работы с Web-сервисами.
Технология Web-сервисов - очень серьезная технология в том смысле, что для того, чтобы ее продемонстрировать, необходимо выполнить достаточно много разного рода подготовительных действий.
Как и в других случаях, когда мы знакомились с новой технологией, вначале мы рассмотрим простой пример и на нем проиллюстрируем все основные особенности проектирования и реализации Web-сервисов, и лишь затем перейдем к реализации нашего приложения.
Web-сервисы для своего выполнения требуют определенной среды или сервера приложений. В настоящий момент имеется большое количество таких серверов, как коммерческих, так и общедоступных, обладающих большей или меньшей функциональностью. В приведенных ниже примерах используется один из таких серверов, разработанный фирмой Sun, - Sun Java System Application Server, который может быть загружен с сайта производителя. Соответственно, весь материал, относящийся к развертыванию и конфигурированию Web-сервисов, адаптирован именно для этого сервера приложений. Для других серверов процедуры, которые необходимо провести для выполнения этих действий, могут отличаться.
Инсталляция сервера приложений
Sun Java System Application Server поставляется в виде инсталляционного пакета, сформированного для инсталляции на основных используемых платформах.
Для наших целей вполне подойдет инсталляция с параметрами по умолчанию. Необходимо только обратить внимание на три параметра:
· основной порт, на котором будут приниматься запросы сервером (по умолчанию 8080). Этот порт будет указываться в адресе при вызове методов сервисов;
· порт административной консоли (по умолчанию 4848) - с её помощью мы будем развертывать и тестировать Web-сервис;
· пароль для административной учетной записи - для инсталляции Web-сервиса в сервере приложений нужны административные права.
После установки Sun Java System Application Server может быть запущен с помощью командного файла asadmin (на платформе Windows этот командный файл называется asadmin.bat).
Рис. 3.2. Регистрация в административной консоли
Подробная информация может быть получена при обращении и регистрации в административной консоли (рис. 3.2).
Установка необходимых приложений
Для проекта воспользуемся кодом, поставляемым в составе пакета The Java Web Services Tutorial (он может быть загружен с сайта фирмы Sun). Пакет представляет собой архив, содержащий развернутую документацию по разработке Web-сервисов и несколько примеров. Вот одним из этих примеров, называющимся helloservice, мы и воспользуемся в качестве шаблона для реализации проекта.
Этот пример представляет собой реализацию простейшего Web-сервиса, который содержит единственный метод, принимающий и возвращающий значение типа String. Пример располагается в папке <tutorial.home> /examples/jaxws/helloservice, где <tutorial.home> - директория, в которую был установлен пакет The Java Web Services Tutorial.
Прежде чем компилировать, устанавливать и выполнять пример, необходимо настроить некоторые параметры, которые определены в файле build.properties, лежащем в <tutorial.home>/examples/common. Определить нужно следующие параметры:
· javaee.home - параметр, указывающий на корень установки сервера приложений;
· javaee.tutorial.home - параметр, указывающий на корень установки пакета The Java Web Services Tutorial.
В случае если установка сервера проводилась по умолчанию, никаких других изменений в этом файле делать не нужно. В случае если Sun Java System Application Server установлен в директории H:/Java/AppServer/, а The Java Web Services Tutorial - в директории H:/Java/wstutorial20_new/, файл build.properties будет иметь следующий вид:
javaee.home=H:/Java/AppServer/
]avaee.tutorial.home= H:/Java/jwstutorial20_new/
admin.password.file=${javaee.tutorial.home}/exаmples/common/admin-
password.txt
admin.host=localhost
admin.user=admin
admin.port=4848
https.port=8181
domain.resources="domain.resources"
domain.resources.port=8080
# Database properties are in derby.properties
db.vendor=derby
Листинг 3.1. Файл build.properties
Для того чтобы иметь возможность инсталлировать разработанный Web-сервис в сервер приложений, необходимо также в файле admin-password.txt (находящемся в <tutorial.home>/examples/common/) указать пароль для учетной записи администратора.
Исходный код Web-сервиса
После того, как указанные настройки будут закончены, можно приступить непосредственно к примеру.
Файл с исходным кодом Web-сервиса располагается в директории src, называется Hello.java и имеет следующий вид (пример 3.2):
package helloservice.endpoint;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService()
public class Hello {
private String message = new String("Hello, ");
@WebMethod()
public String sayHello(String name) {
return message + name + ".";
}
private static int clientRequestCount=0;
private int A[][] = {{1,2,3}, {4,5,6}, {7,8,9}};
private int B[][] = {{1,2,3}, {4,5,6}, {7,8,9}};
private static int i=0, j=0;
//возврат координат позиции элемента для вычисления
@WebMethod()
public int getIPos() {return i;}
@WebMethod()
public int getJPos() {return j;}
//вычисляем отдельный элемент результирующей матрицы C=A*B
@WebMethod()
public int GetMultMatrixElement() {
int result=0;
clientRequestCount++;
for (int r=0; r<A.length; r++)
result+=A[i][r]*B[r][j];
SetPosition();
return result;
}
/*вычислим номер i,j элемента для вычисления в зависимости от
номера запроса клиента*/
private void SetPosition()
{
if (j>=B.length-1)
{j=0; i++;}
else j++;
//проверка и переход к новому умножению матриц
if (clientRequestCount>A.length*B[0].length-1)
{i=0; j=0; clientRequestCount=0;}
}
}
Листинг 3.2. Файл Hello.java
Первое, что обращает на себя внимание, - удивительная краткость написанного кода. Но не стоит обольщаться: дело в том, что технология разработки Web-сервисов, которую мы будем использовать, просто скрывает от разработчика большую часть работы по реализации Web-сервиса. Фактически, все, что должен сделать разработчик, - реализовать код самих вызываемых методов; абсолютно всю работу по реализации механизмов, позволяющих вызывать эти методы удаленно, берет на себя используемая нами технология.
Итак, рассмотрим пример подробнее.
Во-первых, определяется пакет, в который будет помещен класс Hello, пакет называется helloservice.endpoint . Затем импортируются две аннотации - javax.jws.WebMethod и javax.jws.WebService. Поскольку механизм аннотаций является в java относительно новым, видимо имеет смысл сказать о нем несколько слов.
Аннотации java предоставляют разработчику механизм, позволяющий включать в код некие метаданные. Метаданные - это дополнительная информация, которая может быть добавлена к классам, интерфейсам, полям и методам - так называемые "данные о данных". Метаданные доступны как на этапе компиляции, так и во время исполнения через механизм рефлексии. Вот эти данные, которые мы можем добавить к классам, интерфейсам, полям и методам, и называются аннотациями.
Для аннотации вводится понятие области видимости, или времени жизни. Область видимости выбирается из перечисления java.lang.annotation. RetentionPolicy и может принимать следующие значения:
· SOURCE - аннотация будет удалена компилятором;
· CLASS - аннотация будет записана в байт-код класса, но не будет использоваться Java-машиной;
· RUNTIME - аннотация будет записана в байт-код и будет доступна во время исполнения через механизм рефлексии.
Одна из замечательных возможностей, которую открывает перед разработчиками механизм аннотаций, заключается в том, что с их помощью могут быть построены средства автоматического внесения в код нужной функциональности.
В нашем конкретном примере аннотации используются именно с этой целью. Ориентируясь на них, специальная утилита wsgen генерирует классы-обертки, выполняющие всю техническую работу.
Первая аннотация, которая используется применительно ко всему классу, - аннотация WebService. Эта аннотация нужна для того чтобы указать, что данный класс в дальнейшем будет опубликован в качестве Web-сервиса. Есть некоторые ограничения, связанные с применением этой аннотации. Методы, которые предполагается опубликовать, должны быть аннотированы как javax.jws.WebMethod, они должны быть объявлены как static или final. В качестве принимаемых и возвращаемых параметров должны использоваться параметры совместимых с JAX-B типов (все примитивные типы могут использоваться в качестве параметров). Класс, реализующий Web-сервис, не может быть объявлен как final, кроме того, он не должен быть абстрактным, должен иметь публичный конструктор по умолчанию и не переопределять метод finalize. Все эти ограничения связаны с тем, что разрабатываемый класс будет выполняться не самостоятельно, а будет, фактически, встроен в сервер, следовательно, сервер должен полностью контролировать процесс его создания (загрузки) и уничтожения. В случае если при загрузке и/или выгрузке объекта необходимо предпринимать какие-то дополнительные действия, могут применяться аннотации javax.annotation.PostConstruct и javax.annotation.PreDestroy. Метод, аннотированный как PostConstruct, будет вызван сервером приложений до того, как объекту первый раз будет передан запрос клиента. Метод, аннотированный как PreDestroy, вызывается перед уничтожением объекта.
Собственно, на этом разработка Web-сервиса заканчивается. Следующее, что необходимо сделать, - откомпилировать его, пропустить через утилиту wsgen для генерации вспомогательных классов, создать war-file, содержащий в себе откомпилированное приложение и необходимые ресурсы, и затем разместить и зарегистрировать его на сервере приложений.
В комплекте с примерами, поставляемыми в пакете The Java Web Services Tutorial, поставляются также скрипты для их компиляции. Эти скрипты предназначены для специального инструментального средства компиляции, которое называется ant (исполняющая часть ant устанавливается вместе с Sun Java System Application Server).
Разработчики примеров для пакета The Java Web Services Tutorial постарались на славу, и теперь для компиляции и установки приложения необходимо выполнить лишь несколько простых команд.
Компиляция и инсталляция на сервере приложений
Итак, первое, что предстоит сделать, - откомпилировать приложение. Для компиляции в настройках сборки определена специальная цель (target) - build.
Набрав в командной строке команду asant build (asant - вызов командного файла, запускающего ant, build - имя цели, которую он должен выполнить), получим следующий вывод:
Buildfile: build.xml
javaee-home-test:
init: и т. д.
Первое, что делается для компиляции программы, - создается специальная директория build, в которую будут помещены откомпилированные модули. Она создается в текущей директории. Затем вызывается компилятор javac, который компилирует наш класс Hello.java, а результат компиляции кладет в директорию build. Поскольку класс Hello определен в пакете helloservice.endpoint, в директории build будет создана соответствующая система каталогов и файл Hello.class будет помещен в каталог ./build/ helloservice/endpoint.
Следующим шагом вызывается утилита wsgen, которая формирует вспомогательные классы. По умолчанию исходные коды этих классов после компиляции уничтожаются, однако, выставив опцию keep=true (эта и другие опции могут быть установлены в файле build.properties), исходные коды можно сохранить. Помещаются они в пакет jaxws того же пакета, которому принадлежит и класс. Соответственно, для нашего примера исходные файлы (а затем и откомпилированные классы) будут располагаться в директории ./build/ helloservice/endpoint/jaxws. После того как утилита wsgen отработала, мы имеем откомпилированный пакет helloservice.endpoint.jaxws, содержащий необходимые вспомогательные классы. На этом шаге компиляция нашего Web-сервиса закончена. Следующим этапом необходимо подготовить модуль развертывания. В нашем случае это делается с помощью команды:
asant create-war
Создается отдельный каталог assemble, в нем создается каталог war, в котором формируется файл hello-jaxws.war. Этот файл представляет собой архив, в который помещены откомпилированные файлы нашего приложения и некоторые вспомогательные файлы. Теперь у нас полностью готов модуль развертывания, который мы можем инсталлировать в сервере приложений. Инсталляция может быть выполнена командой:
asant deploy
Чтобы убедиться в том, что инсталляция приложения прошла успешно, можно воспользоваться консолью администратора:
Рис. 3.3. Проверка инсталляции приложения
В процессе инсталляции, кроме прочего, был сгенерирован WSDL-файл, описывающий установленный Web-сервис. Как уже говорилось, этот файл содержит полное описание Web-сервиса, включая названия его методов, а также количество и типы передаваемых и возвращаемых параметров. Этот файл является важной составляющей частью технологии, поскольку он позволяет строить приложения, осуществляющие динамические вызовы методов Web-сервисов. Кроме того, этот файл может быть использован для автоматической генерации вспомогательных классов (классов-proxy) для обращения к Web-сервису.
WSDL-файл для нашего Web-сервиса может быть получен по адресу http://localhost:8080/helloservice/hello?wsdl
<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3.1-hudson-417-SNAPSHOT. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3.1-hudson-417-SNAPSHOT. --><definitions targetNamespace="http://endpoint.helloservice/" name="HelloService"><types><xsd:schema><xsd:import namespace="http://endpoint.helloservice/" schemaLocation="http://localhost:8080/helloservice/hello?xsd=1"/></xsd:schema></types><message name="sayHello"><part name="parameters" element="tns:sayHello"/></message><message name="sayHelloResponse"><part name="parameters" element="tns:sayHelloResponse"/></message><message name="GetMultMatrixElement"><part name="parameters" element="tns:GetMultMatrixElement"/></message><message name="GetMultMatrixElementResponse"><part name="parameters" element="tns:GetMultMatrixElementResponse"/></message><message name="getIPos"><part name="parameters" element="tns:getIPos"/></message><message name="getIPosResponse"><part name="parameters" element="tns:getIPosResponse"/></message><message name="getJPos"><part name="parameters" element="tns:getJPos"/></message><message name="getJPosResponse"><part name="parameters" element="tns:getJPosResponse"/></message><portType name="Hello"><operation name="sayHello"><input message="tns:sayHello"/><output message="tns:sayHelloResponse"/></operation><operation name="GetMultMatrixElement"><input message="tns:GetMultMatrixElement"/><output message="tns:GetMultMatrixElementResponse"/></operation><operation name="getIPos"><input message="tns:getIPos"/><output message="tns:getIPosResponse"/></operation><operation name="getJPos"><input message="tns:getJPos"/><output message="tns:getJPosResponse"/></operation></portType><binding name="HelloPortBinding" type="tns:Hello"><soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/><operation name="sayHello"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation><operation name="GetMultMatrixElement"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation><operation name="getIPos"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation><operation name="getJPos"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output></operation></binding><service name="HelloService"><port name="HelloPort" binding="tns:HelloPortBinding"><soap:address location="http://localhost:8080/helloservice/hello"/></port></service></definitions>
Листинг 3.3. WSDL-файл Web-сервиса Hello
Тестирование Web-сервиса
Итак, наш Web-сервис успешно инсталлирован. Осталось только убедиться в том, что он действительно работает. Чуть позже мы напишем специальное приложение-клиент, которое будет обращаться к нашему Web-сервису, а пока воспользуемся средствами, предоставляемыми нам Sun Java System Application Server. Дело в том, что этот сервер приложений способен самостоятельно динамически выстроить среду для вызова методов инсталлированных в нем Web-сервисов. Всей необходимой информацией, а именно: имена публикуемых методов, количество и тип принимаемых и возвращаемых методами параметров - он обладает.
Для того чтобы воспользоваться указанной возможностью, нужно выбрать нужный нам сервис в списке сервисов (в правой части окна браузера) и нажать кнопку "Test" (рис. 3.4).
Рис. 3.4. Тестирование Web-сервиса
распределительный система web сервер
Откроется новое окно браузера, в котором отобразится динамически построенная сервером страница. На этой странице перечислены все опубликованные методы Web-сервиса и реализован интерфейс для их вызова
Кроме всего прочего, на результирующей странице отобразятся SOAP-сообщения, соответственно, отправленные Web-сервису и пришедшие от него в качестве ответа.
Таким образом, разработанный нами Web-сервис успешно инсталлирован в сервере приложений и может обрабатывать запросы клиентов, в чем мы убедились, использовав тестовое окружение, предоставляемое сервером приложений.
4. Клиент для web-сервиса
Механизм взаимодействия с web-сервисами
При написании Web-сервисов с помощью инструментария, предоставляемого java, не оставляет ощущение какого-то подвоха - уж слишком просто оказывается это сделать! На самом деле, как и при использовании любого другого хорошего промежуточного программного обеспечения (middleware), простота эта кажущаяся - очень много действий за разработчика делает сама среда. И в данном случае процесс взаимодействия между клиентом и Web-сервисом в реальности выглядит следующим образом (см. рис. 4.1)
Рис. 4.1. Процесс взаимодействия между клиентом и Web-сервисом
Причем разработчик реализует только функциональную начинку (на схеме - слои, находящиеся над красной линией). Stubs и Ties формируются автоматически утилитами wsgen и wsimport. Сгенерированные этими утилитами классы используют библиотеки поддержки jax-rpc, входящие в состав java. Сервлет, который принимает http-запросы, содержащие SOAP-пакеты, генерируется автоматически сервером приложений.
Клиент
Теперь, когда Web-cервис готов к работе, можно приступить к реализации клиента для него.
Класс клиента будет выглядеть следующим образом (пример 4.1).
package javaapplication3;
import javax.mail.*;
import java.io.UnsupportedEncodingException;
import javax.xml.ws.WebServiceRef;
import java.io.*;
/**
*
* @author neutrino
*/
public class Main {
@WebServiceRef(wsdlLocation="http://localhost:8080/helloservice/hello?wsdl")
static HelloService service;
public static void main(String args[]) throws MessagingException, UnsupportedEncodingException,
IOException {
try {
Main client = new Main();
client.doTest(args);
} catch(Exception e) {
e.printStackTrace();
}
TestMail.receiveMessage();
TestMail.outResultToConsole();
System.out.println("ok");
}
public void doTest(String[] args) {
try {
service = new HelloService();
System.out.println("Retrieving the port from the following service: " + service);
Hello port = service.getHelloPort();
System.out.println("Invoking the sayHello operation on the port.");
String name;
if (args.length > 0) {
name = args[0];
} else {
name = "Neutrino";
}
String response = port.sayHello(name);
System.out.println(response);
//вызов методов распределенного вычисления
int i = port.getIPos();
int j = port.getJPos();
int matrixElement = port.getMultMatrixElement();
System.out.println("matrix["+i+"]["+j+"]="+matrixElement);
//отправить результаты по почте
EmailClient.setContent("matrix["+i+"]["+j+"]="+matrixElement);
EmailClient.sendSimpleMessage();
} catch(Exception e) {
e.printStackTrace();
}
}
}
Листинг 4.1. Клиентское приложение
Hello - интерфейс, в котором объявлены все методы Web-сервиса. Клиентская заглушка (proxy класс), передающий вызовы Web-сервису, реализует этот интерфейс, и со стороны клиента все выглядит так, как будто он непосредственно вызывает методы Web-сервиса. HelloService - сервисный класс, который создает клиентский proxy. Кроме того, для каждого метода и возвращаемого значения генерируются свои вспомогательные классы.
Для того чтобы вспомогательные классы могли быть сгенерированы, нужно указать файл WSDL, в котором описан нужный Web-сервис. Для этого служит специальная аннотация WebServiceRef , свойство wsdlLocation которой указывает на местоположение этого файла.
5. JavaMail API - отправка почты
JavaMail API - это свободно распространяемая библиотека, с помощью которой приложение может получать доступ к почтовым серверам, позволяя создавать, отправлять и получать электронные письма, в том числе и с вложениями, а также удалять письма с сервера.
Данная библиотека поддерживает следующие протоколы:
· SMTP, сокращение от Simple Mail Transfer Protocol, протокол, который определяет механизм для доставки электронной почты. Любой клиент электронной почты, при передаче почты, соединяется с сервером SMTP, который, в свою очередь, доставляет сообщение на сервер SMTP получателя. А затем получатель извлекает сообщение с помощью POP или IMAP.
· POP, сокращение от Post Office Protocol. В настоящее время его третья версия известна как POP3. Большинство почтовых серверов используют этот протокол, чтобы обеспечить получение сообщений пользователем. В действительности POP3 гарантирует лишь, что каждый пользователь имеет свой собственный почтовый ящик.
· IMAP, сокращение от Internet Message Access Protocol. Представляет собой более продвинутый протокол для получения сообщений. При использовании IMAP, почтовый сервер должен поддерживать этот протокол. IMAP предоставляет клиентскому приложению доступ к удаленным хранилищам сообщений, как если бы они были локальные. По сравнению с POP, IMAP значительно сильнее нагружает сервер.
Для понимания принципов использования библиотеки JavaMail API необходимо определить несколько ключевых понятий:
Message - абстрактный класс, который представляет собой сообщения электронной почты. JavaMail реализует RFC822 и MIME стандарты обмена сообщениями. MimeMessage класс расширяет Message для работы с сообщениями, имеющими MIME-тип.
Структура сообщения:
· Простое сообщение имеет один объект контента:
· Multipart сообщение представляет собой контейнер объектов BodyPart. Структура BodyPart объекта похожа на структуру Message объекта. Каждый объект BodyPart содержит атрибуты и содержимое, но атрибуты Bodypart объекта ограничиваются теми, которые определены в интерфейсе Part. Содержимое BodyPart объекта - это DataHandler, который содержит либо данные или другой Multipart объект.
Store - абстрактный класс, который представляет собой хранилище сообщений поддерживаемых почтовым сервером и сгруппированных по владельцу. Store использует отдельный протокол доступа.
Folder - абстрактный класс, который предоставляет возможность иерархически организовывать сообщения. Папки могут содержать сообщения и другие папки. Почтовый сервер по умолчанию предоставляет каждому пользователю папку, а пользователи обычно, создают и заполняют вложенные подпапки.
Transport - абстрактный класс, который представляет собой спецификацию протокола передачи. Transport использует объект конкретного протокола передачи, чтобы отправить сообщение.
Session - класс, который определяет основные сессии почты. Чтобы передать значения в объект сессии, могут быть использованы Properties.
Authenticator - класс, который обеспечивает доступ к защищенным ресурсам с помощью имени пользователя и пароля. Ресурсами, может быть что угодно, начиная от простых файлов на серверах. Для JavaMail, ресурс - это сервер. Приложения используют этот класс при получении сессии. Когда требуется авторизация, система будет вызывать метод подкласса (например, getPasswordAuthentication). Этот метод подкласса может делать запросы аутентификации.
Теперь пришло время посмотреть, как все это работает.
Скачиваем библиотеку тут и импортируем ее в проект:
http://www.oracle.com/technetwork/java/index-138643.html
Теперь с помощью JavaMail API можно отправлять простые сообщения, содержащие в заголовке позицию вычисленного элемента, а в теле его значение:
package javaapplication3;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
/**
*
* @author neutrino
*/
public class EmailClient {
static final String ENCODING = "UTF-8";
private static String subject = "Subject";
private static String content = "Test";
public static String smtpHost="smtp.yandex.ru";
public static String from="neutrino.test@yandex.ru";
public static String to="neutrino.test@yandex.ru";
public static String login="neutrino.test";
public static String password="dsxbcktybz123";
public static String smtpPort="25";
public static void sendSimpleMessage()
throws MessagingException, UnsupportedEncodingException {
Authenticator auth = new MyAuthenticator(login, password);
Properties props = System.getProperties();
props.put("mail.smtp.port", smtpPort);
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.auth", "true");
props.put("mail.mime.charset", ENCODING);
Session session = Session.getDefaultInstance(props, auth);
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
msg.setSubject(getSubject());
msg.setText(getContent());
Transport.send(msg);
}
/**
* @return the subject
*/
public static String getSubject() {
return subject;
}
/**
* @param aSubject the subject to set
*/
public static void setSubject(String aSubject) {
subject = aSubject;
}
/**
* @return the content
*/
public static String getContent() {
return content;
}
/**
* @param aContent the content to set
*/
public static void setContent(String aContent) {
content = aContent;
}
}
class MyAuthenticator extends Authenticator {
private String user;
private String password;
MyAuthenticator(String user, String password) {
this.user = user;
this.password = password;
}
public PasswordAuthentication getPasswordAuthentication() {
String user = this.user;
String password = this.password;
return new PasswordAuthentication(user, password);
}
}
Листинг 5.1. Почтовый клиент. Отправка писем.
Итак, сначала нам необходимо узнать параметры почтового сервера с которого мы будем отправлять письмо, а именно надо узнать хост SMTP протокола и его порт (обычно это 25 порт). Далее указываем свои существующие данные для авторизации на сервере, а также адрес получателя (в моем примере я для простоты отправлял письмо самому себе).
Для отправки письма нам необходимо:
· получить текущую сессию
· создать новое сообщение
· установить поля сообщения
· отправить его
Для получения сессии используется метод Session.getDefaultInstance(Properties props, Authenticator authenticator) который возвращает объект сессии по умолчанию. Если по умолчанию он до сих пор не установлен, то новый объект сессии будет создан и установлен как объект по умолчанию.
Параметр props - атрибуты новой сессии
Параметр authenticator - объект Authenticator, который используется для того, чтобы проверить права доступа пользователя.
После получения сессии можно создать новое сообщение и задать его поля. Далее все просто - отправляем наше сообщение с помощью статического метода класса Transport.
6. Java Mail API - получение почты
Теперь получим письма, которые мы сами себе отправили.
package javaapplication3;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.search.FlagTerm;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Properties;
import java.util.*;
/**
*
* @author neutrino
*/
public class TestMail {
static final String ENCODING = "UTF-8";
public static String subject = "Subject";
public static String content = "Test";
public static String smtpHost="smtp.yandex.ru";
public static String address="neutrino.test@yandex.ru";
public static String user="neutrino.test";
public static String password="dsxbcktybz123";
public static String smtpPort="25";
public static String host="pop3.yandex.ru";
public static LinkedList<MessageBean> resultListMessages;
public static void receiveMessage() throws MessagingException, IOException {
Authenticator auth = new MyAuthenticator(user, password);
Properties props = System.getProperties();
props.put("mail.user", user);
props.put("mail.host", host);
props.put("mail.debug", "false");
props.put("mail.store.protocol", "pop3");
props.put("mail.transport.protocol", "smtp");
Session session = Session.getDefaultInstance(props, auth);
Store store = session.getStore();
store.connect();
Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE);
Message[] messages = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
ArrayList<String> attachments = new ArrayList<String>();
resultListMessages = getPart(messages, attachments);
inbox.setFlags(messages, new Flags(Flags.Flag.SEEN), true);
inbox.close(false);
store.close();
}
private static LinkedList<MessageBean> getPart(Message[] messages, ArrayList <String> attachments) throws MessagingException, IOException {
LinkedList<MessageBean> listMessages = new LinkedList<MessageBean>();
SimpleDateFormat f = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
for (Message inMessage : messages) {
attachments.clear();
if (inMessage.isMimeType("text/plain")) {
MessageBean message = new MessageBean(inMessage.getMessageNumber(), MimeUtility.decodeText(inMessage.getSubject()), inMessage.getFrom()[0].toString(), null, f.format(inMessage.getSentDate()), (String) inMessage.getContent(), false, null);
listMessages.add(message);
} else if (inMessage.isMimeType("multipart/*")) {
Multipart mp = (Multipart) inMessage.getContent();
MessageBean message = null;
for (int i = 0; i < mp.getCount(); i++) {
Part part = mp.getBodyPart(i);
if ((part.getFileName() == null || part.getFileName() == "") && part.isMimeType("text/plain")) {
message = new MessageBean(inMessage.getMessageNumber(), inMessage.getSubject(), inMessage.getFrom()[0].toString(), null, f.format(inMessage.getSentDate()), (String) part.getContent(), false, null);
} else if (part.getFileName() != null || part.getFileName() != ""){
if ((part.getDisposition() != null) && (part.getDisposition().equals(Part.ATTACHMENT))) {
attachments.add(saveFile(MimeUtility.decodeText(part.getFileName()), part.getInputStream()));
if (message != null) message.setAttachments(attachments);
}
}
}
listMessages.add(message);
}
}
return listMessages;
}
private static String saveFile(String filename, InputStream input) {
String path = "attachments\\"+filename;
try {
byte[] attachment = new byte[input.available()];
input.read(attachment);
File file = new File(path);
FileOutputStream out = new FileOutputStream(file);
out.write(attachment);
input.close();
out.close();
return path;
} catch (IOException e) {
e.printStackTrace();
}
return path;
}
public static void outResultToConsole()
{
//вывод результатов на консоль
Iterator i = resultListMessages.iterator();
while(i.hasNext())
{
MessageBean item = (MessageBean) i.next();
System.out.println(item.getContent());
}
}
}
Листинг 6.1. Почтовый клиент. Отправка писем.
Итак, о том, что тут делается. Для начала определим общую идею как все должно работать в теории и что для этого необходимо:
· получаем текущую сессию
· получаем доступ к хранилищу сообщений
· получаем доступ к папке входящих сообщений в этом хранилище
· извлекаем из папки все сообщения и начинаем их обработку, т.е извлечение полей сообщений
· закрываем за собой папку и хранилище
Что нового в коде:
1. Появился класс MessageBean - там мы будем сохранять данные из сообщения. Это сделано для удобства ибо в результате выполнения данного метода вы получите аккуратную коллекцию входящих сообщений с которыми можете потом делать что хотите.
2. Появился метод getPart, в котором собственно выполняется обработка полученных сообщений, а именно: проверка типа сообщения, в соответствии с которым потом извлекается его содержимое, также данный метод формирует список экземпляров бина сообщения, который собственно и возвращается главному методу.
3. Появился метод saveFile который сохраняет вложения из писем в каталог attachments. Тут все просто, так что описывать в подробностях не буду.
4. Появился новый параметр pop3Host который содержит хост POP3 протокола, для входящей почты.
Приступим к более детальному осмотру кода.
Сначала как всегда мы получаем текущую сессию (обратите внимание что свойства, которые мы передаем внутрь метода getDefaultInstance, изменились). После этого из сессии мы получаем хранилище и подключаемся к нему используя метод connect класса Service. Далее мы можем получить из хранилища папку с входящими сообщениями используя метод getFolder, в данном случае мы получаем папку по ее имени. Этот метод по умолчанию возвращает нам закрытую папку, поэтому мы открываем ее на чтение и запись.
Теперь у нас есть доступ к папке. В данном примере, для того чтобы получить письма из папки я использовал поиск внутри каталога, критерием поиска был флаг письма, показывающий, что оно новое и еще не было прочитано, но на серверах POP3 эта функция не поддерживается (возвращаются вообще все письма), так что для получения писем можно использовать простой метод inbox.getMessages(); Оба этих метода возвращают массив сообщений, который передается внутрь метода getPart(), в котором, как уже было сказано выше выполняется проверка типа сообщения:
- Если это простое сообщение, то создается экземпляр бина, поля которого инициализируется содержимым сообщения
- Если это Multipart сообщение, то мы получаем содержимое письма как Multipart и начинаем просматривать части сообщений:
· Если часть содержит простой контент, то он сохраняется в полях бина
· Если часть содержит вложение, то выполняется метод saveFile(), который сохраняет вложение, а путь к нему сохраняет в бине.
Осталось только удалить за собой письма с сервера…
public static void deleteMessage(int n) throws MessagingException, IOException {
Authenticator auth = new MyAuthenticator(user, password);
Properties props = System.getProperties();
props.put("mail.user", user);
props.put("mail.host", host);
props.put("mail.debug", "false");
props.put("mail.store.protocol", "pop3");
props.put("mail.transport.protocol", "smtp");
Session session = Session.getDefaultInstance(props, auth);
Store store = session.getStore();
store.connect();
Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE);
inbox.setFlags(n, n, new Flags(Flags.Flag.DELETED), true);
inbox.close(true);
store.close();
}
Что надо сделать для удаления письма:
· получаем текущую сессию
· получаем доступ к хранилищу сообщений
· получаем доступ к папке входящих сообщений в этом хранилище
· устанавливаем флаг сообщения DELETED = true
· обязательно закрываем за собой папку и хранилище
Номер сообщения можно получить с помощью метода getMessageNumber(). Итак зная номер сообщения мы устанавливаем у него флаг и все…теперь главное не забыть закрыть папку и хранилище, ибо именно в этот момент происходит удаление.
Список литературы
1. А.Н. Свистунов, Построение распределенных систем на Java., www.intuit.ru
2. http://www.quizful.net/post/java-mail-api
Размещено на Allbest.ru
Подобные документы
Характеристики распределенных систем баз данных, формируемые путем "интеграции" разнородных аппаратных и программных средств. Концепция дифференциального файла для различных приложений. Сравнение разных технологий файлового сервера и "клиент-сервера".
курсовая работа [411,9 K], добавлен 28.05.2015Разработка API взаимодействия клиентских приложений с сервером СУБД через Pipe под Windows. Устройство и характеристики СУБД SQLite. Методы WinAPI для передачи данных. Реализация взаимодействия через PIPE. Результат работы серверного приложения.
курсовая работа [596,3 K], добавлен 09.05.2014Виды архитектуры распределенных информационных систем. Сущность синхронного и асинхронного, блокирующего и неблокирующего взаимодействия в распределенных информационных системах. Основные проблемы и принципы реализации удаленного вызова процедур.
реферат [26,4 K], добавлен 22.06.2011Правила настройки параметров разрешений и общих строк протокола SNMP в целях предотвращения несанкционированного доступа к информации. Требования к обработке ошибок на уровне сервера. Шифрование личных данных, архивация и восстановление приложений.
курсовая работа [1,0 M], добавлен 13.11.2011Анализ видов обеспечения автоматизированных систем предприятия. Средства программирования распределенных систем обработки информации. Изучение особенностей использования технологии распределенных объектов. Эксплуатация программного обеспечения системы.
отчет по практике [486,0 K], добавлен 23.11.2014Сетевые соединения для передачи команд и данных между клиентом и сервером. Появление первых клиентских FTP-приложений. Графические пользовательские интерфейсы. Вход в FTP сервер. Настройка, подключение и вход в файловый сервер с клиентских компьютеров.
курсовая работа [2,6 M], добавлен 25.11.2014Определение, свойства и характеристики распределенных систем баз данных. Основная задача систем управления ими. Архитектура распределения СУБД. Сравнение технологий файлового сервера и "клиент-сервера". Стратегия распределения данных по узлам сети ЭВМ.
курсовая работа [601,3 K], добавлен 24.05.2015Рассмотрение эффективности корпоративной сервисной шины и веб-сервисов. Ознакомление со стеком технологий веб-сервисов. Исследование и характеристика процесса взаимодействия между потребителем и провайдером сервиса, который задается с помощью интерфейса.
дипломная работа [596,0 K], добавлен 22.08.2017Общие сведения о стандартизированном протоколе передачи данных FTP. Модель построения протокола обмена информацией, его применение в автоматических системах оплаты через интернет. Управляющее соединение между клиентом и сервером, программное обеспечение.
презентация [96,0 K], добавлен 15.12.2010Протокол для поддержания системы передачи сообщений, обеспечение непрерывной работы SMTP-сервера. Примеры использования команды LIST, работа через протокол POP3, особенности авторизации. Условия работы режима "обновление". Пример сеанса с POP3 сервером.
реферат [16,1 K], добавлен 03.05.2010