Лучшие практики использования Lombok
Когда использовать Lombok:
Для сокращения шаблонного кода (геттеры, сеттеры, конструкторы).
Для улучшения читаемости кода.
Как избежать злоупотребления:
Не используйте Lombok для сложной логики.
Избегайте чрезмерного использования аннотаций, таких как @Data или @AllArgsConstructor.
Совместимость с другими библиотеками:
Lombok может конфликтовать с Jackson, Hibernate и другими библиотеками. Будьте осторожны с аннотациями, которые генерируют методы.
Проблемы и ограничения Lombok
Проблемы с поддержкой в IDE:
Некоторые IDE могут некорректно обрабатывать код с Lombok. Убедитесь, что плагин Lombok установлен и настроен.
Ограничения при использовании с другими инструментами:
Например, Jackson может не работать с @Data, если не настроены правильные геттеры и сеттеры.
Отладка:
Поскольку сгенерированный код не отображается в исходниках, отладка может быть сложнее. Убедитесь, что ваша IDE поддерживает Lombok.
#Java #Training #Spring #Lombok #Best_practices
Когда использовать Lombok:
Для сокращения шаблонного кода (геттеры, сеттеры, конструкторы).
Для улучшения читаемости кода.
Как избежать злоупотребления:
Не используйте Lombok для сложной логики.
Избегайте чрезмерного использования аннотаций, таких как @Data или @AllArgsConstructor.
Совместимость с другими библиотеками:
Lombok может конфликтовать с Jackson, Hibernate и другими библиотеками. Будьте осторожны с аннотациями, которые генерируют методы.
Проблемы и ограничения Lombok
Проблемы с поддержкой в IDE:
Некоторые IDE могут некорректно обрабатывать код с Lombok. Убедитесь, что плагин Lombok установлен и настроен.
Ограничения при использовании с другими инструментами:
Например, Jackson может не работать с @Data, если не настроены правильные геттеры и сеттеры.
Отладка:
Поскольку сгенерированный код не отображается в исходниках, отладка может быть сложнее. Убедитесь, что ваша IDE поддерживает Lombok.
#Java #Training #Spring #Lombok #Best_practices
👍2
Работа с временными зонами
Почему важно хранить даты в UTC?
Универсальность: UTC — это стандарт, который не зависит от временных зон.
Согласованность: данные, хранящиеся в UTC, можно легко конвертировать в любую временную зону.
Избежание путаницы: исключаются ошибки, связанные с переходом на летнее время или разными временными зонами.
Пример конвертации из UTC в локальное время:
Обработка временных зон в веб-приложениях
Как принимать время от пользователя и конвертировать его в UTC?
Принимайте время от пользователя с указанием его временной зоны.
Используйте ZonedDateTime для конвертации в UTC.
Пример:
Проблемы с временными зонами
Неоднозначность времени при переходе на летнее время:
Например, в некоторых зонах время 2:30 может быть дважды (при переходе на зимнее время).
Решение:
Используйте ZonedDateTime и методы, которые учитывают такие случаи.
Разные форматы временных зон:
Например, "UTC+3" и "Europe/Moscow" могут означать одно и то же, но лучше использовать стандартные идентификаторы (например, "Europe/Moscow").
Ошибки при конвертации:
Убедитесь, что вы всегда знаете, в какой временной зоне находятся данные.
#Java #Training #Medium #Date #Best_Practicies
Почему важно хранить даты в UTC?
Универсальность: UTC — это стандарт, который не зависит от временных зон.
Согласованность: данные, хранящиеся в UTC, можно легко конвертировать в любую временную зону.
Избежание путаницы: исключаются ошибки, связанные с переходом на летнее время или разными временными зонами.
Пример конвертации из UTC в локальное время:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class UTCToLocalTime {
public static void main(String[] args) {
// Текущий момент в UTC
Instant now = Instant.now();
System.out.println("UTC: " + now);
// Конвертация в локальное время (например, для Москвы)
ZonedDateTime localTime = now.atZone(ZoneId.of("Europe/Moscow"));
System.out.println("Московское время: " + localTime);
}
}
Обработка временных зон в веб-приложениях
Как принимать время от пользователя и конвертировать его в UTC?
Принимайте время от пользователя с указанием его временной зоны.
Используйте ZonedDateTime для конвертации в UTC.
Пример:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class UserTimeToUTC {
public static void main(String[] args) {
// Время, введенное пользователем (например, 2023-10-15T14:30)
LocalDateTime userTime = LocalDateTime.parse("2023-10-15T14:30");
// Временная зона пользователя (например, Нью-Йорк)
ZoneId userZone = ZoneId.of("America/New_York");
ZonedDateTime userZonedTime = ZonedDateTime.of(userTime, userZone);
// Конвертация в UTC
ZonedDateTime utcTime = userZonedTime.withZoneSameInstant(ZoneId.of("UTC"));
System.out.println("UTC время: " + utcTime);
}
}
Проблемы с временными зонами
Неоднозначность времени при переходе на летнее время:
Например, в некоторых зонах время 2:30 может быть дважды (при переходе на зимнее время).
Решение:
Используйте ZonedDateTime и методы, которые учитывают такие случаи.
Разные форматы временных зон:
Например, "UTC+3" и "Europe/Moscow" могут означать одно и то же, но лучше использовать стандартные идентификаторы (например, "Europe/Moscow").
Ошибки при конвертации:
Убедитесь, что вы всегда знаете, в какой временной зоне находятся данные.
#Java #Training #Medium #Date #Best_Practicies
👍1
Расширенные темы и интеграции Maven
CI/CD интеграция
Maven широко используется в CI/CD-пайплайнах для автоматизации сборки, тестирования и развертывания. Рассмотрим интеграцию с популярными системами и связанные процессы, такие как GPG-подпись и развертывание артефактов.
Jenkins, GitLab CI, GitHub Actions с Maven
Jenkins:
Конфигурация: Создайте задачу (Job) типа "Freestyle" или "Pipeline". В Freestyle добавьте шаг "Invoke top-level Maven targets":mvn clean install
В Pipeline используйте Jenkinsfile:
Параллельность: Используйте флаг -T для параллельной сборки модулей, например, -T 4.
Плагины: Используйте maven-release-plugin для автоматизации релизов:mvn release:prepare release:perform
GitLab CI:
Конфигурация: Определите .gitlab-ci.yml:
Кэширование: Кэшируйте ~/.m2/repository для ускорения:
GitHub Actions:
Конфигурация: Создайте .github/workflows/maven.yml:name:
Артефакты: Используйте действие actions/upload-artifact для сохранения JAR/WAR.
В памяти: CI/CD-системы запускают Maven как Java-процесс, загружая POM-модель, зависимости и плагины в оперативную память. Параллельная сборка (-T) увеличивает пиковое потребление памяти, так как одновременно обрабатываются несколько модулей. Кэширование ~/.m2/repository снижает сетевые запросы, но требует места на диске.
Работа с GPG Signing, Artifact Deployment
GPG Signing:GPG-подпись артефактов необходима для публикации в Maven Central. Используется maven-gpg-plugin.
Настройка в POM.xml:
Шаги:
Установите GPG и создайте ключ: gpg --gen-key.
Опубликуйте публичный ключ: gpg --keyserver keyserver.ubuntu.com --send-keys <key-id>.
Настройте ~/.m2/settings.xml с GPG-паролем:
Подпишите артефакты:
В памяти: Плагин maven-gpg-plugin загружает GPG-ключи и артефакты в память для подписи, что увеличивает потребление ресурсов, особенно для крупных JAR/WAR.
Artifact Deployment:Развертывание артефактов в репозиторий (например, Nexus, Maven Central) выполняется через maven-deploy-plugin:
Запуск: mvn deploy.
SNAPSHOT vs Release: SNAPSHOT-версии (1.0.0-SNAPSHOT) обновляются в репозитории, релизные версии (1.0.0) публикуются однократно.
В памяти: Плагин maven-deploy-plugin загружает артефакт и его метаданные в память перед отправкой в репозиторий. Сетевые операции могут замедлить процесс, но потребление памяти минимально.
#Java #middle #Maven #Best_practics
CI/CD интеграция
Maven широко используется в CI/CD-пайплайнах для автоматизации сборки, тестирования и развертывания. Рассмотрим интеграцию с популярными системами и связанные процессы, такие как GPG-подпись и развертывание артефактов.
Jenkins, GitLab CI, GitHub Actions с Maven
Jenkins:
Конфигурация: Создайте задачу (Job) типа "Freestyle" или "Pipeline". В Freestyle добавьте шаг "Invoke top-level Maven targets":mvn clean install
В Pipeline используйте Jenkinsfile:
pipeline {
agent any
tools {
maven 'Maven 3.8.6'
jdk 'JDK11'
}
stages {
stage('Build') {
steps {
sh 'mvn clean install'
}
}
}
}
Параллельность: Используйте флаг -T для параллельной сборки модулей, например, -T 4.
Плагины: Используйте maven-release-plugin для автоматизации релизов:mvn release:prepare release:perform
GitLab CI:
Конфигурация: Определите .gitlab-ci.yml:
stages:
- build
build:
stage: build
image: maven:3.8.6-openjdk-11
script:
- mvn clean install
artifacts:
paths:
- target/*.jar
Кэширование: Кэшируйте ~/.m2/repository для ускорения:
cache:
paths:
- ~/.m2/repository
GitHub Actions:
Конфигурация: Создайте .github/workflows/maven.yml:name:
Maven Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Build with Maven
run: mvn clean install
- name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
Артефакты: Используйте действие actions/upload-artifact для сохранения JAR/WAR.
В памяти: CI/CD-системы запускают Maven как Java-процесс, загружая POM-модель, зависимости и плагины в оперативную память. Параллельная сборка (-T) увеличивает пиковое потребление памяти, так как одновременно обрабатываются несколько модулей. Кэширование ~/.m2/repository снижает сетевые запросы, но требует места на диске.
Работа с GPG Signing, Artifact Deployment
GPG Signing:GPG-подпись артефактов необходима для публикации в Maven Central. Используется maven-gpg-plugin.
Настройка в POM.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
Шаги:
Установите GPG и создайте ключ: gpg --gen-key.
Опубликуйте публичный ключ: gpg --keyserver keyserver.ubuntu.com --send-keys <key-id>.
Настройте ~/.m2/settings.xml с GPG-паролем:
<server>
<id>gpg.passphrase</id>
<passphrase>{encrypted-passphrase}</passphrase>
</server>
Подпишите артефакты:
mvn clean deploy -Dgpg.passphrase=<passphrase>.
В памяти: Плагин maven-gpg-plugin загружает GPG-ключи и артефакты в память для подписи, что увеличивает потребление ресурсов, особенно для крупных JAR/WAR.
Artifact Deployment:Развертывание артефактов в репозиторий (например, Nexus, Maven Central) выполняется через maven-deploy-plugin:
<distributionManagement>
<repository>
<id>nexus</id>
<url>https://nexus.example.com/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus</id>
<url>https://nexus.example.com/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
Запуск: mvn deploy.
SNAPSHOT vs Release: SNAPSHOT-версии (1.0.0-SNAPSHOT) обновляются в репозитории, релизные версии (1.0.0) публикуются однократно.
В памяти: Плагин maven-deploy-plugin загружает артефакт и его метаданные в память перед отправкой в репозиторий. Сетевые операции могут замедлить процесс, но потребление памяти минимально.
#Java #middle #Maven #Best_practics
👍1
Archetypes
Архетипы — это шаблоны проектов, которые позволяют быстро создавать структуру с предопределенными файлами, зависимостями и конфигурацией. Maven предоставляет встроенные архетипы, такие как maven-archetype-quickstart.
Использование:
Создание собственного архетипа
Создайте проект с желаемой структурой:
В archetype-metadata.xml опишите структуру:
Сгенерируйте архетип:
Установите архетип:
Используйте архетип:
В памяти: Архетипы загружают шаблонные файлы и их метаданные в память. Плагин maven-archetype-plugin парсит archetype-metadata.xml и заменяет переменные (например, ${groupId}), что требует минимальных ресурсов, но может быть затратным для сложных архетипов с большим количеством файлов.
Использование Maven Wrapper (mvnw)
Maven Wrapper (mvnw) — это скрипт, который обеспечивает использование конкретной версии Maven, независимо от установленной на машине. Он включает файлы mvnw (или mvnw.cmd для Windows), .mvn/wrapper/maven-wrapper.jar и .mvn/wrapper/maven-wrapper.properties.
Установка:
Использование:
В памяти: mvnw запускает Maven как отдельный Java-процесс, загружая maven-wrapper.jar в память. Это добавляет небольшой overhead, но гарантирует согласованность сборки. Кэширование Maven в .m2/repository минимизирует сетевые запросы.
Нюансы:
Храните mvnw и .mvn в репозитории для обеспечения воспроизводимости.
Обновляйте версию Maven в maven-wrapper.properties для поддержки новых функций.
Поддержка Java версий
Maven поддерживает проекты с разными версиями Java через maven-compiler-plugin:
Многомодульные проекты
Каждый модуль может использовать разные версии Java, указав собственную конфигурацию плагина.
Toolchains: Для кросс-компиляции используйте ~/.m2/toolchains.xml:
Укажите toolchain в POM.xml:
#Java #middle #Maven #Best_practics
Архетипы — это шаблоны проектов, которые позволяют быстро создавать структуру с предопределенными файлами, зависимостями и конфигурацией. Maven предоставляет встроенные архетипы, такие как maven-archetype-quickstart.
Использование:
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4
Пользователь вводит groupId, artifactId, version, и Maven генерирует проект.
Создание собственного архетипа
Создайте проект с желаемой структурой:
my-archetype/
├── src/
│ └── main/
│ └── resources/
│ ├── archetype-resources/
│ │ ├── src/main/java/App.java
│ │ └── pom.xml
│ └── META-INF/maven/
│ └── archetype-metadata.xml
└── pom.xml
В archetype-metadata.xml опишите структуру:
<archetype-descriptor>
<fileSets>
<fileSet filtered="true" packaged="true">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>
Сгенерируйте архетип:
mvn archetype:create-from-project
Результат появится в target/generated-sources/archetype.
Установите архетип:
cd target/generated-sources/archetype
mvn install
Используйте архетип:
mvn archetype:generate -DarchetypeGroupId=com.example -DarchetypeArtifactId=my-archetype -DarchetypeVersion=1.0
В памяти: Архетипы загружают шаблонные файлы и их метаданные в память. Плагин maven-archetype-plugin парсит archetype-metadata.xml и заменяет переменные (например, ${groupId}), что требует минимальных ресурсов, но может быть затратным для сложных архетипов с большим количеством файлов.
Использование Maven Wrapper (mvnw)
Maven Wrapper (mvnw) — это скрипт, который обеспечивает использование конкретной версии Maven, независимо от установленной на машине. Он включает файлы mvnw (или mvnw.cmd для Windows), .mvn/wrapper/maven-wrapper.jar и .mvn/wrapper/maven-wrapper.properties.
Установка:
mvn -N wrapper:wrapper -Dmaven=3.8.6
Создает mvnw, который загружает указанную версию Maven.
Использование:
./mvnw clean install
Скрипт проверяет .mvn/wrapper/maven-wrapper.properties, загружает нужную версию Maven и выполняет команду.
В памяти: mvnw запускает Maven как отдельный Java-процесс, загружая maven-wrapper.jar в память. Это добавляет небольшой overhead, но гарантирует согласованность сборки. Кэширование Maven в .m2/repository минимизирует сетевые запросы.
Нюансы:
Храните mvnw и .mvn в репозитории для обеспечения воспроизводимости.
Обновляйте версию Maven в maven-wrapper.properties для поддержки новых функций.
Поддержка Java версий
Maven поддерживает проекты с разными версиями Java через maven-compiler-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
Многомодульные проекты
Каждый модуль может использовать разные версии Java, указав собственную конфигурацию плагина.
Toolchains: Для кросс-компиляции используйте ~/.m2/toolchains.xml:
<toolchains>
<toolchain>
<type>jdk</type>
<provides>
<version>11</version>
</provides>
<configuration>
<jdkHome>/path/to/jdk11</jdkHome>
</configuration>
</toolchain>
</toolchains>
Укажите toolchain в POM.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-toolchains-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>toolchain</goal>
</goals>
</execution>
</executions>
<configuration>
<toolchains>
<jdk>
<version>11</version>
</jdk>
</toolchains>
</configuration>
</plugin>
#Java #middle #Maven #Best_practics
👍2
Расширение Maven
Extensions
Расширения Maven — это JAR-файлы, которые добавляют функциональность, например, кастомные жизненные циклы или обработчики репозиториев.
Они указываются в .mvn/extensions.xml:
Создание:
Создайте проект с зависимостью maven-core.
Реализуйте интерфейс, например, org.apache.maven.AbstractMavenLifecycleParticipant.
Упакуйте как JAR и установите в репозиторий.
В памяти: Расширения загружаются через Plexus, увеличивая потребление памяти из-за дополнительных классов и их зависимостей.
Интернальные API Maven
Maven предоставляет API (maven-core, maven-plugin-api) для создания плагинов и расширений.
Пример использования org.apache.maven.project.MavenProject для доступа к модели проекта:
В памяти: Интернальные API загружают объекты POM-модели и контекста сборки, что может быть ресурсоемким для сложных операций, таких как анализ зависимостей.
Логирование и отладка:
Флаг -X: Включает отладочный режим, выводя подробную информацию о сборке, плагинах, зависимостях и реакторе:
Флаг -e: Выводит стек вызовов при ошибках:
Плагины для отладки:
mvn help:effective-pom: Показывает итоговую модель POM.
mvn dependency:tree: Анализирует зависимости.
mvn help:effective-settings: Показывает настройки settings.xml.
В памяти: Отладочные флаги создают дополнительные структуры данных для логов, увеличивая временное потребление памяти.
Сравнение и миграция с Ant/Gradle
Ant
Сравнение:
Ant: Императивный подход, где задачи определяются вручную в XML (build.xml). Нет встроенного управления зависимостями или жизненного цикла.
Maven: Декларативный подход с жизненным циклом и автоматическим разрешением зависимостей.
Миграция:
Перенесите задачи Ant в плагины Maven (например, maven-antrun-plugin для запуска Ant-скриптов).
Преобразуйте зависимости в POM.xml с помощью <dependency>.
Используйте mvn ant:ant для генерации build.xml из Maven для обратной совместимости.
Gradle
Сравнение:
Gradle: Гибридный подход (декларативный + императивный), использует Groovy/Kotlin DSL. Более гибкий, но сложнее в освоении.
Maven: Стандартизированный XML, проще для новичков, но менее гибкий.
Gradle быстрее благодаря инкрементальной сборке и кэшированию.
Миграция:
Используйте build.gradle с плагином maven-publish для публикации артефактов в Maven-репозитории.
Конвертируйте POM.xml в build.gradle с помощью инструментов, таких как gradle init.
Перенесите зависимости из <dependencyManagement> в dependencies Gradle.
В памяти: Ant использует меньше памяти из-за отсутствия сложных моделей, но требует больше ручной работы. Gradle может потреблять больше памяти из-за Groovy/Kotlin и сложных скриптов. Maven занимает среднюю позицию, но его POM-модель и граф зависимостей требуют значительных ресурсов в крупных проектах.
#Java #middle #Maven #Best_practics
Extensions
Расширения Maven — это JAR-файлы, которые добавляют функциональность, например, кастомные жизненные циклы или обработчики репозиториев.
Они указываются в .mvn/extensions.xml:
<extensions>
<extension>
<groupId>com.example</groupId>
<artifactId>custom-extension</artifactId>
<version>1.0</version>
</extension>
</extensions>
Создание:
Создайте проект с зависимостью maven-core.
Реализуйте интерфейс, например, org.apache.maven.AbstractMavenLifecycleParticipant.
Упакуйте как JAR и установите в репозиторий.
В памяти: Расширения загружаются через Plexus, увеличивая потребление памяти из-за дополнительных классов и их зависимостей.
Интернальные API Maven
Maven предоставляет API (maven-core, maven-plugin-api) для создания плагинов и расширений.
Пример использования org.apache.maven.project.MavenProject для доступа к модели проекта:
@Mojo(name = "custom")
public class CustomMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}")
private MavenProject project;
public void execute() throws MojoExecutionException {
getLog().info("Project artifact: " + project.getArtifactId());
}
}
В памяти: Интернальные API загружают объекты POM-модели и контекста сборки, что может быть ресурсоемким для сложных операций, таких как анализ зависимостей.
Логирование и отладка:
-X, -e
Флаг -X: Включает отладочный режим, выводя подробную информацию о сборке, плагинах, зависимостях и реакторе:
mvn package -X
Увеличивает объем логов, что может замедлить выполнение и потребовать больше памяти для буферизации вывода.
Флаг -e: Выводит стек вызовов при ошибках:
mvn package -e
Полезно для диагностики, минимально влияет на память.
Плагины для отладки:
mvn help:effective-pom: Показывает итоговую модель POM.
mvn dependency:tree: Анализирует зависимости.
mvn help:effective-settings: Показывает настройки settings.xml.
В памяти: Отладочные флаги создают дополнительные структуры данных для логов, увеличивая временное потребление памяти.
Сравнение и миграция с Ant/Gradle
Ant
Сравнение:
Ant: Императивный подход, где задачи определяются вручную в XML (build.xml). Нет встроенного управления зависимостями или жизненного цикла.
Maven: Декларативный подход с жизненным циклом и автоматическим разрешением зависимостей.
Миграция:
Перенесите задачи Ant в плагины Maven (например, maven-antrun-plugin для запуска Ant-скриптов).
Преобразуйте зависимости в POM.xml с помощью <dependency>.
Используйте mvn ant:ant для генерации build.xml из Maven для обратной совместимости.
Gradle
Сравнение:
Gradle: Гибридный подход (декларативный + императивный), использует Groovy/Kotlin DSL. Более гибкий, но сложнее в освоении.
Maven: Стандартизированный XML, проще для новичков, но менее гибкий.
Gradle быстрее благодаря инкрементальной сборке и кэшированию.
Миграция:
Используйте build.gradle с плагином maven-publish для публикации артефактов в Maven-репозитории.
Конвертируйте POM.xml в build.gradle с помощью инструментов, таких как gradle init.
Перенесите зависимости из <dependencyManagement> в dependencies Gradle.
В памяти: Ant использует меньше памяти из-за отсутствия сложных моделей, но требует больше ручной работы. Gradle может потреблять больше памяти из-за Groovy/Kotlin и сложных скриптов. Maven занимает среднюю позицию, но его POM-модель и граф зависимостей требуют значительных ресурсов в крупных проектах.
#Java #middle #Maven #Best_practics
👍2
Maven Best Practices: от Apache и Spring
Apache Best Practices
Централизация конфигурации: Используйте <dependencyManagement> и <pluginManagement> в родительском POM.
Минимизация зависимостей: Исключайте ненужные транзитивные зависимости через <exclusions>.
Профили: Используйте профили для окружений (dev, prod).
Кэширование: Настройте CI/CD для кэширования ~/.m2/repository.
Плагины: Используйте последние версии плагинов и проверяйте их совместимость.
Spring Best Practices
Spring Boot BOM: Используйте spring-boot-starter-parent или spring-boot-dependencies для управления версиями:
Минимизация конфигурации: Полагайтесь на автоконфигурацию Spring Boot вместо ручной настройки плагинов.
Плагины: Используйте spring-boot-maven-plugin для создания исполняемых JAR:
В памяти: Spring Boot BOM увеличивает объем POM-модели из-за большого числа зависимостей, но упрощает управление версиями. Плагин spring-boot-maven-plugin загружает дополнительные данные для создания "fat JAR", что может быть ресурсоемким.
Нюансы и внутренние механизмы
Управление памятью:
Maven загружает POM-модели, настройки и зависимости в память, создавая графы для модулей и артефактов. Крупные проекты с сотнями зависимостей могут потреблять гигабайты памяти.
Параллельная сборка (-T) и отладка (-X) увеличивают пиковое потребление.
Оптимизируйте с помощью -pl, -am и JVM-флагов (-Xmx).
Кэширование:
Локальный репозиторий (~/.m2/repository) снижает сетевые запросы, но требует периодической очистки устаревших SNAPSHOT-версий.
CI/CD-кэширование ускоряет сборку, но увеличивает использование диска.
Безопасность:
Шифруйте пароли для репозиториев с помощью mvn --encrypt-password.
Ограничивайте доступ к ~/.m2/settings-security.xml (chmod 600).
Производительность:
Инкрементальная сборка минимизирует повторные компиляции, но требует точной настройки временных меток в target.
Gradle может быть быстрее для инкрементальных сборок, но Maven проще для стандартизированных проектов.
Отладка:
Используйте -X для анализа реактора и зависимостей.
Проверяйте конфликты с mvn dependency:tree -Dverbose.
Анализируйте итоговую конфигурацию с mvn help:effective-pom.
#Java #middle #Maven #Best_practics
Apache Best Practices
Централизация конфигурации: Используйте <dependencyManagement> и <pluginManagement> в родительском POM.
Минимизация зависимостей: Исключайте ненужные транзитивные зависимости через <exclusions>.
Профили: Используйте профили для окружений (dev, prod).
Кэширование: Настройте CI/CD для кэширования ~/.m2/repository.
Плагины: Используйте последние версии плагинов и проверяйте их совместимость.
Spring Best Practices
Spring Boot BOM: Используйте spring-boot-starter-parent или spring-boot-dependencies для управления версиями:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
Минимизация конфигурации: Полагайтесь на автоконфигурацию Spring Boot вместо ручной настройки плагинов.
Плагины: Используйте spring-boot-maven-plugin для создания исполняемых JAR:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
В памяти: Spring Boot BOM увеличивает объем POM-модели из-за большого числа зависимостей, но упрощает управление версиями. Плагин spring-boot-maven-plugin загружает дополнительные данные для создания "fat JAR", что может быть ресурсоемким.
Нюансы и внутренние механизмы
Управление памятью:
Maven загружает POM-модели, настройки и зависимости в память, создавая графы для модулей и артефактов. Крупные проекты с сотнями зависимостей могут потреблять гигабайты памяти.
Параллельная сборка (-T) и отладка (-X) увеличивают пиковое потребление.
Оптимизируйте с помощью -pl, -am и JVM-флагов (-Xmx).
Кэширование:
Локальный репозиторий (~/.m2/repository) снижает сетевые запросы, но требует периодической очистки устаревших SNAPSHOT-версий.
CI/CD-кэширование ускоряет сборку, но увеличивает использование диска.
Безопасность:
Шифруйте пароли для репозиториев с помощью mvn --encrypt-password.
Ограничивайте доступ к ~/.m2/settings-security.xml (chmod 600).
Производительность:
Инкрементальная сборка минимизирует повторные компиляции, но требует точной настройки временных меток в target.
Gradle может быть быстрее для инкрементальных сборок, но Maven проще для стандартизированных проектов.
Отладка:
Используйте -X для анализа реактора и зависимостей.
Проверяйте конфликты с mvn dependency:tree -Dverbose.
Анализируйте итоговую конфигурацию с mvn help:effective-pom.
#Java #middle #Maven #Best_practics
👍2
Тонкая настройка JVM через переменные окружения
Control Groups (cgroups) — механизм ядра Linux для ограничения, учета и изоляции использования ресурсов (CPU, память, дисковый I/O) группой процессов. Docker использует cgroups для ограничения ресурсов контейнера.
Как это влияет на JVM?
- Если в контейнере установлен лимит памяти (--memory=512m), JVM не видит его по умолчанию и пытается выделить память, превышающую лимит.
Решение:
Как это работает:
- JVM читает лимиты из /sys/fs/cgroup/memory/memory.limit_in_bytes (путь внутри cgroup контейнера).
- При старте выделяет heap через mmap с учетом лимита.
Критические ошибки:
- Если -Xmx превышает лимит cgroups, JVM упадет с Native memory allocation (mmap) failed.
- Для контейнеров никогда не используйте `-Xmx` без учета cgroups.
Пример: Java-сервис с ENV и логами в volume
docker-compose.yml
Концептуальное объяснение:
1. Сеть app_net:
- Создает bridge-сеть через docker network create.
- Контейнеры app и db получают IP в подсети 172.18.0.0/16 и могут общаться по именам (db:5432).
2. Том pg_data:
- Хранится в /var/lib/docker/volumes/pg_data/_data.
- При старте PostgreSQL инициализирует данные в этом каталоге.
3. Логирование:
- Драйвер json-file пишет логи в /var/lib/docker/containers/<id>/<id>-json.log.
- При достижении 50m файл ротируется, сохраняя 3 архива.
Код Java-приложения:
Почему это работает:
- Переменные DB_URL и DB_PASSWORD передаются через process namespace, что безопаснее hardcode.
- Том app_logs изолирует логи от жизненного цикла контейнера — данные сохраняются после docker-compose down.
- JVM учитывает лимиты cgroups благодаря -XX:MaxRAMPercentage.
Best practices
1. Сети:
- Bridge — для локальной разработки,
- Overlay/CNI — для продакшена,
- Host — только для специфических задач.
2. Volumes:
- Named volumes — для БД и персистентных данных,
- Bind mounts — только для разработки (hot-reload).
3. Секреты:
- Всегда используйте Vault или Kubernetes Secrets в продакшене,
- Избегайте .env для секретов — он не шифруется.
4. Логирование:
- Настройте централизованное логирование (Fluentd + Elasticsearch),
- Используйте gelf или fluentd вместо json-file в продакшене.
5. JVM:
- Всегда ограничивайте память через -XX:MaxRAMPercentage,
- Проверяйте лимиты cgroups через cat /sys/fs/cgroup/memory/memory.limit_in_bytes.
#Java #middle #Docker #best
Control Groups (cgroups) — механизм ядра Linux для ограничения, учета и изоляции использования ресурсов (CPU, память, дисковый I/O) группой процессов. Docker использует cgroups для ограничения ресурсов контейнера.
Как это влияет на JVM?
- Если в контейнере установлен лимит памяти (--memory=512m), JVM не видит его по умолчанию и пытается выделить память, превышающую лимит.
Решение:
environment:
JAVA_TOOL_OPTIONS: "-XX:MaxRAMPercentage=75.0"
- -XX:MaxRAMPercentage указывает JVM использовать 75% от лимита cgroups, а не от общей памяти хоста.
Как это работает:
- JVM читает лимиты из /sys/fs/cgroup/memory/memory.limit_in_bytes (путь внутри cgroup контейнера).
- При старте выделяет heap через mmap с учетом лимита.
Критические ошибки:
- Если -Xmx превышает лимит cgroups, JVM упадет с Native memory allocation (mmap) failed.
- Для контейнеров никогда не используйте `-Xmx` без учета cgroups.
Пример: Java-сервис с ENV и логами в volume
docker-compose.yml
version: '3.8'
services:
app:
build: ./app
environment:
DB_URL: jdbc:postgresql://db:5432/mydb
DB_PASSWORD: ${DB_PASSWORD}
volumes:
- app_logs:/app/logs
logging:
driver: json-file
options:
max-size: "50m"
networks:
- app_net
db:
image: postgres:15
environment:
POSTGRES_DB: mydb
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pg_data:/var/lib/postgresql/data
networks:
- app_net
volumes:
app_logs:
driver: local
pg_data:
networks:
app_net:
driver: bridge
Концептуальное объяснение:
1. Сеть app_net:
- Создает bridge-сеть через docker network create.
- Контейнеры app и db получают IP в подсети 172.18.0.0/16 и могут общаться по именам (db:5432).
2. Том pg_data:
- Хранится в /var/lib/docker/volumes/pg_data/_data.
- При старте PostgreSQL инициализирует данные в этом каталоге.
3. Логирование:
- Драйвер json-file пишет логи в /var/lib/docker/containers/<id>/<id>-json.log.
- При достижении 50m файл ротируется, сохраняя 3 архива.
Код Java-приложения:
public class Main {
public static void main(String[] args) {
String dbUrl = System.getenv("DB_URL"); // Чтение из process namespace
try (Connection conn = DriverManager.getConnection(
dbUrl, "user", System.getenv("DB_PASSWORD"))) {
// Запись в файловый лог
try (FileWriter fw = new FileWriter("/app/logs/application.log", true)) {
fw.write("DB connection established\n");
}
}
}
}
Почему это работает:
- Переменные DB_URL и DB_PASSWORD передаются через process namespace, что безопаснее hardcode.
- Том app_logs изолирует логи от жизненного цикла контейнера — данные сохраняются после docker-compose down.
- JVM учитывает лимиты cgroups благодаря -XX:MaxRAMPercentage.
Best practices
1. Сети:
- Bridge — для локальной разработки,
- Overlay/CNI — для продакшена,
- Host — только для специфических задач.
2. Volumes:
- Named volumes — для БД и персистентных данных,
- Bind mounts — только для разработки (hot-reload).
3. Секреты:
- Всегда используйте Vault или Kubernetes Secrets в продакшене,
- Избегайте .env для секретов — он не шифруется.
4. Логирование:
- Настройте централизованное логирование (Fluentd + Elasticsearch),
- Используйте gelf или fluentd вместо json-file в продакшене.
5. JVM:
- Всегда ограничивайте память через -XX:MaxRAMPercentage,
- Проверяйте лимиты cgroups через cat /sys/fs/cgroup/memory/memory.limit_in_bytes.
#Java #middle #Docker #best
👍3🔥1