2010-12-14 3 views
5

У нас есть несколько приложений, которые используют HTTP-клиент Apache 3 для создания HTTP-запросов. Недавно мы также начали создавать клиенты веб-сервисов, которые используют HTTPClient 4 по разным причинам. Позиция Apache заключается в том, что «основные выпуски не соответствуют обратному». Хотя мне бы хотелось обновить все наши проекты, чтобы использовать версию 4, это просто невозможно.Доступ к нескольким версиям пакета в Java

Итак, хотя мой основной вопрос довольно общий, мой конкретный вопрос. Как использовать HTTPClient версии 3 и 4 в одном приложении? В нашем случае приложение может быть веб-интерфейсом, рабочим столом или командной строкой.

Я прочитал SO question for java-dynamically-load-multiple-versions-of-same-class, который кажется полукруглым, но мне все равно, о динамической части. На самом деле, я бы хотел, чтобы JARs были отправлены с помощью приложения (например, WEB-INF/lib для веб-приложений). Также я вижу, что OSGi много упоминается в вопросах, подобных этому, но, похоже, он чрезмерен или, возможно, слишком сложный (возможно, простой пример мог бы доказать обратное).

В конце концов, я хочу, чтобы иметь возможность вручить команду набор банок, что они могут упасть в, и он просто работает независимо от их проекта с использованием HTTP Client 3.

+1

Это случай, когда архитектурное управление было бы хорошей идеей: принять решение либо придерживаться версии 3, либо перенести все на версию 4. Теперь вам придется заплатить за реализацию решения для пэчворка, и это будет просто ухудшаться со временем. – Anon

+1

@ Анон: Не обижайся, но, не зная ситуации, я бы не советовал делать такое заявление. Я сказал «по разным причинам», чтобы отразить такие комментарии. –

+0

OSGi, по крайней мере, работает (вам нужно решить, является ли его излишним или нет), я не знаю какого-либо тривиального способа сделать это, кроме как иметь два веб-сервера, по одному для каждой версии библиотеки. –

ответ

5

Как уже было сказано, вы можете создать несколько загрузчиков классов и загрузить две версии в отдельности. Эта часть достаточно проста.

Проблема заключается в том, что это по существу разделяет ваше «пространство класса», и все равно будет очень сложно ссылаться на v3 из некоторых частей вашего приложения, обращаясь к v4 из других частей вашего приложения. Вам нужно разделить ваше приложение очень ... так почему бы просто не разбить его и доставить два приложения?

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

1

использовать несколько загрузчиков классов, по одному для каждого HTTP-клиент, которого вы хотите охватить.

Самый простой способ - расширить URLClassLoader и взломать его для жесткого кодирования пути к классам для каждой версии отдельно. Тогда вам просто нужно убедиться, что остальная часть кода знает, какую версию HTTP-клиента использовать (и обращается к правильному загрузчику классов, чтобы добраться до него).

+0

Как это работает для webapp, где JARs должны поставляться с WARs? –

+0

Вы отправляете все версии каждой библиотеки, на которые ссылаетесь, но помещаете их где-то, кроме web-inf/lib. Ваш пользовательский загрузчик классов выглядит в другом месте. Это не позволяет военному контейнеру напрямую ссылаться на них. –

1

Вы должны использовать отдельные загрузчики классов для v3 и v4. Поместите банки v3 и v4 в отдельные папки за пределами класса приложений. Используйте URLClassLoadedr для загрузки каждой из версий. URL-адрес, который вы передаете каждому из загрузчиков классов, должен содержать URL-адрес для конкретной версии HTTP-клиента.

Но могу ли я дать вам совет? Сначала проверьте, что вам действительно нужно все это, прежде чем вы начнете. Правильно, что версии могут быть несовместимыми. Но есть огромный шанс, что они есть.

+1

Я думаю, вы имеете в виду «огромный шанс, что они есть» не * «Я знаю, что HTTP Client v3 и V4 не играют хорошо вместе. –

2

простой, но простое решение было бы вы получить источники HttpClient3 и HttpClient4 и реорганизовать имена пакетов на что-то вроде

org.apache.commons.httpclient3 для HttpClient3 и org.apache.commons .httpclient4 для HttpClient4, чтобы избежать столкновения. Затем скомпилируйте, сделайте пакет.

Теперь легко переключаться между двумя реализациями, и они не сталкиваются в загрузчике классов.

+1

Хотя это работает на одну банку, это создает больше проблем, чем решает. Например, вам может потребоваться apache.commons.logging, и обе версии будут зависеть от разных версий ведения общедоступных записей (поскольку они были выпущены в разное время). Теперь вы можете переупаковать ведомости сообществ указанным выше образом, но затем вам нужно вернуться и вручную отредактировать весь исходный код в переупакованных http-клиентах для правильной ссылки. Вскоре такое решение становится большим беспорядком. –

+1

Действительно ли они зависят от разных версий ведения общедоступных записей? Последний должен отлично работать с обоими, нет? – Thilo

+2

Обратите внимание, что люди, принадлежащие к обычным людям, идут по этому маршруту. Commons Lang 3 будет использовать имя пакета org.apache.commons.lang3. Если у вас возникнут несовместимые изменения API, новое имя пакета, вероятно, не самая худшая идея. – Thilo

Смежные вопросы