Причина любой истории важнее всего
В любой профессии девушки имеют абсолютное преимущество. Не говоря уже об ИТ-индустрии, если в отделе есть женщины-программисты, это должно быть сладкое удовольствие, и о нем хорошо позаботятся.
Однажды перед этим только что приехавшая девушка столкнулась с проблемой, и стиль рисования вдруг изменился на картинку выше, и группа собралась вокруг, но конечный результат не был идеальным, так что мне все равно пришлось выйти (немного хвастаясь здесь).
Сестра столкнулась с проблемой конфликта пакетов Jar. Сообщение об ошибке вызвано: java.lang.ClassNotFoundException. Ошибка связана либо с отсутствием пакета Jar, либо с конфликтом.
На самом деле, такого рода конфликты часто встречаются на работе, например: Вызвано:java.lang.NoSuchMethodError Эта информация об исключении также вызвана конфликтом.Чтобы решить конфликт, вы должны знать, где конфликт (кажется, быть чушью).
Большинство из них используют Maven для управления зависимыми файлами JAR. Сегодняшняя статья в основном объясняет, как решить проблему конфликта зависимостей, вызванную Maven.
Обзор Мавена
Maven readme
Maven — это инструмент для создания и управления Java-проектами. Для направления Java Maven почти всегда трогают и используют. Конечно, есть и другие инструменты для замены Maven, такие как Ant и Gradle.
Раньше я знакомился с веб-проектом Java, созданным с помощью Grails, который использует Gradle для управления зависимостями. Что касается Ant, то я видел его в некоторых старых проектах, когда только работал, и почти не видел потом.
Адрес документации Maven:maven.apache.org
Использование Maven позволяет нам быстро создавать новый проект, а также очень удобно интегрировать и управлять несколькими сторонними фреймворками. Когда нам нужен фреймворк, мы можем искать информацию об этом фреймворке, а затем настраивать его в свой проект.
Адрес поиска:mvnrepository.com
Например, если мы хотим использовать Spring Boot, помимо получения версии зависимостей в документации Spring, мы также можем найти и выбрать соответствующую версию, как показано ниже:
Вы можете видеть, что по умолчанию используется режим зависимости Maven, вам нужно только скопировать все содержимое зависимости в файл pom.xml проекта. Справа есть много других зависимостей, таких как Gradle.
Транзит зависимостей Maven
Сегодня я в основном рассказываю о том, как решить проблему конфликта пакетов Jar, когда Maven занимается управлением зависимостями.Прежде чем ее решать, давайте разберемся с базовыми знаниями.
На приведенном выше рисунке показана транзитивность зависимостей Maven.Во-первых, проект B опирается на две среды, Spring и Guava. Тогда проект A зависит от проекта B, поэтому проект A также зависит от фреймворков Spring и Guava.
Логика выбора транзитивного пакета Jar зависимостей
Перенос зависимостей приведет к тому, что проект будет зависеть от многих других версий Jars.Как в этом случае выбирать пакеты Jar?
Есть два правила:
- Разные расстояния, близкие к первому приоритету
- То же расстояние, первое имеет приоритет
Как показано на рисунке ниже, проект зависит от проекта A и проекта B, а A и B зависят от Guava соответственно, но с точки зрения иерархии зависимостей проект B имеет более мелкий уровень, поэтому Guava18.0 будет предпочтительнее.
Если расстояние одинаковое, предпочтительным будет тот, который определен спереди.Как показано на рисунке ниже, как проект A, так и проект B зависят от версий Guava15.0 и Guava18.0 соответственно, но порядок проекта A находится перед проектом B. Поэтому версия Guava15.0 будет предпочтительнее.
Транзитивность зависимостей часто приводит к конфликтам пакетов Jar.Например, проект A на рисунке ниже зависит от Guava15.0, а затем от проекта B. Проект B зависит от Guava18.0, поэтому проект A будет одновременно зависеть от Guava15. .0 и Гуава18.0.
Если просто использовать методы и классы, не совместимые с младшей версией, будет ошибка выбора, потому что Maven выберет неглубокие зависимости по глубине дерева зависимостей, то есть 15.0.0.
конфликтный случай
Ниже приведена типичная проблема конфликта пакетов Jar.Если Jar имеет несколько версий, возникнут конфликты.
В сообщении об ошибке вы можете увидеть, что метод com.google.common.collect.fluentiterable.Concat не может быть найден. Он в настоящее время загружен из Guava-18.0.jar. Как мы можем решить эту проблему?
Description:
An attempt was made to call the method com.google.common.collect.FluentIterable.concat(Ljava/lang/Iterable;Ljava/lang/Iterable;)Lcom/google/common/collect/FluentIterable; but it does not exist. Its class, com.google.common.collect.FluentIterable, is available from the following locations:
jar:file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jar!/com/google/common/collect/FluentIterable.class
It was loaded from the following location:
file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jar
Action:
Correct the classpath of your application so that it contains a single, compatible version of com.google.common.collect.FluentIterable
Решение: диагностика подвесного троса
Найдите конфликтующие JAR-файлы и посмотрите, от каких версий зависит текущий проект.
Eclipse
В Eclipse вы можете дважды щелкнуть файл pom, войти в представление зависимостей, ввести имя jar-файла, который вы хотите найти, и вы можете увидеть, какие фреймворки в текущем проекте зависят от искомого jar-файла и его версии. вы ищете.
Idea
Вы можете установить вспомогательный плагин maven в Idea для просмотра связанной информации о зависимостях.По умолчанию конфликты будут отображать конфликтующие зависимости текущего проекта.Конечно, мы также можем напрямую просматривать древовидные зависимости для анализа конфликтов.
команда maven
Без использования подключаемого модуля средства разработки мы можем напрямую использовать команду Maven для просмотра зависимостей текущего проекта.Командная строка входит в каталог проекта, который вы хотите проанализировать, и выполняет следующую команду, чтобы сохранить результат анализа в файл:
mvn dependency:tree > tree.log
Зависимая информационная структура после выполнения выглядит следующим образом:
Я искал гуаву и обнаружил, что smjdbctemplate опирается на версию 18.0.Этот фреймворк представляет собой фреймворк, инкапсулированный мной на основе jdbctemplate.
Наблюдение за идеями решения
На самом деле очевидно, что сообщение об ошибке говорит нам, что метод concat не может быть найден в 18.0, поэтому 18.0 нельзя использовать.В ходе предыдущего анализа было обнаружено, что smjdbctemplate напрямую зависит от guava.18.0.jar. решение состоит в том, чтобы поместить smjdbctemplate в исключенный Guava.
<dependency>
<groupId>com.github.yinjihuan</groupId>
<artifactId>smjdbctemplate</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
Существует также способ определить, от какой версии зависит текущий проект, по глубине дерева зависимостей, как показано ниже:
18.0 является самым мелким, и он должен зависеть от него Фактически, непосредственно просматривая зависимости Maven в Eclipse, вы можете указать, от каких фреймворков и информации о версии зависит текущий проект, как показано ниже:
Когда мы исключаем 18.0 и затем смотрим на зависимую версию 20.0, как показано ниже:
По глубине дерева зависимостей 20.0 и 19.0 — это один уровень, но 20.0 предшествует 19.0, поэтому версия 20.0 предпочтительнее.
Снова взглянув на файл pom в проекте, обнаруживается, что порядок объявления swagger находится перед apollo.
Если скорректировать порядок, то он будет зависеть от версии 19.0.
Суммировать
Благодаря моим тщательным и терпеливым объяснениям девушка, наконец, решила проблему, с которой столкнулась, и вы можете догадаться, что произошло дальше. 😆
Такого рода проблемы неизбежны: чем больше трехсторонних фреймворков вы используете, тем выше вероятность конфликта. Когда вы столкнетесь с проблемой, успокойтесь и тщательно проанализируйте ее, а также используйте инструменты, которые помогут вам устранить проблему.
Конечно, когда мы полагаемся на сторонние фреймворки в наших собственных проектах, мы также должны обратить внимание на проблему версии, особенно для многомодульных проектов, каждый подмодуль зависит от другой версии, что чревато проблемами. обычно рекомендуется использовать dependencyManagement в родительском pom.Для единообразного управления версией подмодуль напрямую использует версию, определенную в родительском pom.
Кроме того, option можно использовать для установки необязательных зависимостей.Например, если вы хотите инкапсулировать общий модуль Common, в этом модуле много общих функций.Зависимости проекта A должны использовать только функцию A, а зависимости проекту B нужно использовать только функцию B. Каждая функция зависит от стороннего Jar. Если вы ничего не делаете в это время, пока вы полагаетесь на свой общий модуль Common, вы также будете косвенно зависеть от стороннего Jar этих двух функций. В настоящее время эту проблему можно решить, установив необязательный = true.Я завишу от вашего общего модуля Common.Если я хочу использовать функцию A, то я должен отобразить трехсторонние зависимости, требуемые функцией A.
Если вам интересно, вы можете подписаться на мой публичный аккаунт в WeChat.обезьяний мир, читать больше технических статей в первый раз. У меня также есть открытый исходный код на моем GitHub.github.com/yinjihuan