У меня есть типичный сервер REST Spring Boot:
…
@SpringBootApplication
public class MyService {
public static void main(String[] args) {
SpringApplication.run(MyService.class, args);
}
}
Я включаю org.springframework.boot:spring-boot-starter-web
вместе с de.flapdoodle.embed:de.flapdoodle.embed.mongo.spring30x
, чтобы встроить MongoDB для тестирования и запуска в среде IDE. Это приложение запускается нормально из полученного JAR-файла.
Однако я хочу отключить автоматическую настройку встроенного сервера MongoDB; вместо этого я хочу включить его только для определенных профилей. Мой первый шаг — исключить EmbeddedMongoAutoConfiguration
:
…
import de.flapdoodle.embed.mongo.spring.autoconfigure.EmbeddedMongoAutoConfiguration;
@SpringBootApplication(exclude = {EmbeddedMongoAutoConfiguration.class})
public class MyService {
public static void main(String[] args) {
SpringApplication.run(MyService.class, args);
}
}
Пока все хорошо — приложение все еще работает. Теперь я хочу убедиться, что встроенные классы MongoDB не будут распространяться вместе с приложением, потому что я планирую включить только EmbeddedMongoAutoConfiguration
в IDE (на основе профиля). Поэтому я обновляю свой POM следующим образом:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<excludeGroupIds>de.flapdoodle,de.flapdoodle.embed,de.flapdoodle.graph,
de.flapdoodle.java8,de.flapdoodle.reverse</excludeGroupIds>
</configuration>
</execution>
</executions>
</plugin>
Внезапно приложение больше не запускается, говоря:
***************************
APPLICATION FAILED TO START
***************************
Description:
Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.
Action:
Check your application's dependencies for a supported servlet web server.
Check the configured web application type.
Почему исключение неиспользуемых файлов классов не позволяет приложению определить ServletWebServerFactory
?
Я предполагаю, что когда я укажу @SpringBootApplication(exclude = {EmbeddedMongoAutoConfiguration.class})
, Spring запутается, если класс EmbeddedMongoAutoConfiguration
отсутствует. Вместо того, чтобы думать: «Эй, класс даже не существует, поэтому мне не нужно ничего делать, чтобы его исключить», Spring вместо этого думает: «Я хочу исключить этот класс, но его даже нет, поэтому я не не знаю, что делать!" И вместо того, чтобы выдать ошибку и сказать «Я не могу создать приложение», он просто не создает необходимые bean-компоненты и оставляет это на потом, чтобы приложение могло сказать: «Ой, у меня нет ServletWebServerFactory
и я понятия не имею, почему бы и нет».
Кто-нибудь знает способ, которым я могу динамически исключать EmbeddedMongoAutoConfiguration
таким образом, чтобы это не путало Spring, если EmbeddedMongoAutoConfiguration
на самом деле даже не присутствует в дистрибутиве?
Замечательный! Я сделаю больше тестов, но на данный момент это, похоже, сработало! @M.Deinum M.Deinum, если вы хотите добавить это как ответ, я могу пометить его как правильный. Кстати, excludeName
поддерживает подстановочные знаки? Просто любопытно.
Если вы проверите javadoc для @SpringBootApplication, вы увидите exclude
и excludeName
. Первый принимает массив классов, второй — массив String
. Первый из-за классов будет автоматически пытаться загрузить класс, так как он является частью байткода (из-за импорта), второй будет делать это лениво.
В вашем случае вы хотите excludeName
вместо exclude
. excludeName
принимает полное имя класса, который вы хотите исключить.
@SpringBootApplication(excludeName = "de.flapdoodle.embed.mongo.spring.autoconfigure.EmbeddedMongoAutoConfiguration"})
Будет делать свое дело.
Кажется, это работает. Большое спасибо! Я обновил свою запись в блоге Embedded MongoDB только в IDE с использованием Spring Boot 3.x этой информацией. Очень признателен.
Используйте
String
с именем класса вместо жесткого кодирования класса таким образом. Использование строки делает ее динамической, жесткое кодирование делает ее обязательной. Для этого используйтеexcludeName
вместоexclude
.