Итак, Джерси ничего не знает о Гисе.Он уже использует свою собственную структуру DI, HK2.Есть пара вещей, которые вы можете сделать.Вы можете либо связать Guice с HK2, чтобы HK2 мог находить службы, которые связаны внутри Guice, либо можно просто связать свои классы ресурсов внутри Guice и зарегистрировать экземпляры этих ресурсов с помощью Jersey.
Tie Guiceс HK2
Чтобы связать Guice с HK2, вам нужно использовать Guice HK2 Bridge .Сначала вам нужно добавить следующую зависимость
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>guice-bridge</artifactId>
<version>${hk2.version}</version>
</dependency>
Чтобы hk2.version
взглянул на ваши зависимости в Джерси (вы можете запустить mvn dependency:tree
и посмотреть, какая версия HK2 Jersey используется).Вы хотите убедиться, что используете точно такую же версию.
Следующее, что вам нужно сделать, это программно связать две системы.Один из способов сделать это - внутри Feature
.
public class GuiceFeature implements Feature {
@Override
public boolean configure(FeatureContext context) {
// This is the way in Jersey 2.26+ to get the ServiceLocator.
// In earlier versions, use
// ServiceLocatorProvider.getServiceLocator(context);
ServiceLocator locator = InjectionManagerProvider.getInjectionManager(context)
.getInstance(ServiceLocator.class);
Injector injector = Guice.createInjector(new AccountResourceModule());
GuiceBridge.getGuiceBridge().initializeGuiceBridge(locator);
GuiceIntoHK2Bridge guiceBridge = locator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(injector);
return true;
}
}
Тогда просто зарегистрируйте функцию на Джерси.
ResourceConfig packageConfig = new ResourceConfig()
.packages("ca.ulaval.glo4002.trading")
.register(GuiceFeature.class);
И все.Он должен работать, как я уже тестировал.
Связывать ресурсы с Guice
При указанной конфигурации Джерси будет создавать экземпляры ваших классов ресурсов (@Path
аннотированныйклассы).Причина, по которой нам нужен мост, заключается в том, что Jersey тесно связан с HK2, поэтому, когда мы внедряем наши классы ресурсов, при создании экземпляра Jersey вызывает HK2, чтобы попытаться найти все зависимости для ресурса.
В этом случае мы не будем полагаться на Джерси для создания экземпляра ресурса.Мы свяжем ресурс с Guice и позволим Guice создать экземпляр, когда мы его запросим.Мы будем использовать этот экземпляр для регистрации на Джерси.
Сначала свяжите ресурс
public class AccountResourceModule extends AbstractModule {
@Override
protected void configure() {
bind(AccountService.class);
bind(AccountResource.class);
}
}
Также убедитесь, что аннотация @Inject
в классе ресурсов com.google.inject.Inject
.
Получить экземпляр ресурса и зарегистрировать его
Injector injector = Guice.createInjector(new AccountResourceModule());
AccountResource accountResource = injector.getInstance(AccountResource.class);
ResourceConfig config = new ResourceConfig()
.register(accountResource);
Возможно, вам придется найти более чистый способ сделать это, так как вы этого не хотитенужно сделать это для каждого ресурса, который у вас есть.Но в этом суть того, что вам нужно сделать.
Обновление
Итак, вот быстрая реализация, чтобы очистить второе решение.Мы можем рекурсивно сканировать пакет, чтобы получить все аннотированные классы @Path
, а затем связать их в Guice и зарегистрировать их на Джерси.
С этой SO-записи , которую мы можем использоватьбиблиотека Reflections позволяет легко получить все классы.Просто добавьте следующую зависимость
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>
Затем создайте немного вспомогательных классов
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.Path;
import org.reflections.Reflections;
public class ResourceClassHelper {
private static Set<Class<?>> resourceClasses;
public static Set<Class<?>> getResourceClasses() {
if (resourceClasses != null) {
return resourceClasses;
}
// the package to scan for @Path classes "com.example"
Reflections reflections = new Reflections("com.example");
resourceClasses = reflections.getTypesAnnotatedWith(Path.class);
resourceClasses = Collections.unmodifiableSet(resourceClasses);
return resourceClasses;
}
}
Затем в вашем модуле Guice
public class AccountResourceModule extends AbstractModule {
@Override
protected void configure() {
bind(AccountService.class);
ResourceClassHelper.getResourceClasses().forEach(this::bind);
}
}
И ваш ресурс регистрации
Injector injector = Guice.createInjector(new AccountResourceModule());
ResourceConfig config = new ResourceConfig();
ResourceClassHelper.getResourceClasses()
.forEach(cls -> config.register(injector.getInstance(cls)));