2016-11-15 4 views
2

Я делал проекты с использованием Spring Rest. Теперь у нас есть небольшой проект отдыха и планируем сделать с Джерси JAX-RS. Я новичок в этом и упомянул SO и другие блоги, чтобы успешно реализовать Rest api с инъекцией зависимости.JAX-RS зависимая инъекция

У вас есть следующий код.

AppConfig.java

import javax.ws.rs.ApplicationPath; 
import javax.ws.rs.core.Application; 

@ApplicationPath("/") 
public class AppConfig extends Application {  
    @Override 
    public Set<Class<?>> getClasses() { 
     System.out.println("AppConfig"); 
     final Set<Class<?>> s = new HashSet<Class<?>>(); 
     s.add(Controller.class); 
     s.add(AppFeature.class); 
     return s; 
    } 
} 

AppBinder.java

import org.glassfish.hk2.utilities.binding.AbstractBinder; 

public class AppBinder extends AbstractBinder { 
    @Override 
    protected void configure() { 
     System.out.println("AppBinder"); 
     bind(ReflectionService.class).to(ReflectionService.class); 
    } 
} 

AppFeature.java

import javax.ws.rs.core.Feature; 
import javax.ws.rs.core.FeatureContext; 

public class AppFeature implements Feature { 
    @Override 
    public boolean configure(FeatureContext context) { 
     System.out.println("AppFeature"); 
     context.register(new AppBinder()); 
     return true; 
    } 
} 

Controller.java

@Path("/") 
public class Controller { 
    @Inject 
    Service service;  
    public Controller(){ 
     System.out.println("Controller created"); 
    } 
    // other methods 
} 

Service.java

@Singleton 
public class Service  
    public Service(){ 
     System.out.println("Service instance created"); 
    } 
    // other methods 
} 

Я полагаю, что каждый экземпляр контроллера и услуг создается на Tomcat 8 запуска сервера и зависимостей инъекции делается. Но во время запуска, получил это на консоли

INFO: Регистрация приложения сервлет-Джерси, названный com.sample.auto2.AppConfig, при отображении сервлетов/*, с классом приложений одного и того же имени.

AppConfig

AppConfig

15 ноября 2016 12:22:20 PM org.glassfish.jersey.server.ApplicationHandler ИНИЦИАЛИЗИРУЙТЕ INFO: Инициирование Джерси приложения, версия Джерси: 2,6 2014-02-18 21:52:53 ...

AppFeature

AppBinder

15 ноября 2016 года 12:22:21 PM org.apache.catalina.startup.HostConfig deployDirectory

Каждый раз, мы посылаем запрос, получил следующее консоли

Сервис экземпляр, созданный

Контроллер создан

Мои вопросы

  1. Сервис, конструкторы контроллера вызываются всякий раз, когда мы отправляем запрос на получение ; он создает экземпляры в каждом запросе или только вызов конструктора?
  2. Почему System.out в AppConfig называется дважды?
  3. Есть ли лучший способ для настройки моего небольшого проекта, который не имеет доступа к db и только трех конечных точек?

EDIT:

В соответствии с ссылки, представленные @Harikrishnan, добавил @Singleton для Controller класса. Теперь конструкторы вызываются только один раз (по первому запросу - Почему бы не во время запуска сервера!).

Но почему конструктор класса обслуживания вызвал каждый запрос (раньше, чем добавлять @Singleton к контроллеру), даже если его singleton? Остаются и другие проблемы.

EDIT 2:

Благодаря @peeskillet. Так что это результаты для меня.

  1. Это называется конструкторами только один раз при первом же запросе

    bind(ReflectionService.class).to(ReflectionService.class).in(Singleton.class); 
    bind(Controller.class).to(Controller.class).in(Singleton.class); 
    
  2. Это дает ошибку по запросу HTTP

    bind(ReflectionService.class).to(ReflectionService.class).in(Immediate.class); 
    
    java.lang.IllegalStateException: Could not find an active context for org.glassfish.hk2.api.Immediate 
    

    Но это нормально, потому что

  3. Это называется конструктор при запуске сервера и только один раз

    bind(new ReflectionService()).to(ReflectionService.class); 
    bind(new Controller()).to(Controller.class); 
    
  4. Таким образом, при запуске выполняется инъекция, но ошибка 404 при запросе HTTP. (Мысль контроллер сконфигурирован в AppBinder, то почему в AppConfig)

    @ApplicationPath("/") 
    public class AppConfig extends ResourceConfig {  
        public AppConfig() { 
         register(new AppBinder()); 
        } 
    } 
    
  5. И это делает его работать, как вы сказали!

    @ApplicationPath("/") 
    public class AppConfig extends ResourceConfig {   
        public AppConfig() { 
         register(new AppBinder()); 
         register(Controller.class); 
        } 
    } 
    

НАКОНЕЦ ЭТО ВСЕ Я НУЖЕН

public class AppBinder extends AbstractBinder { 
    @Override 
    protected void configure() { 
     bind(new ReflectionService()).to(ReflectionService.class); 
     bind(new Controller()).to(Controller.class); 
    } 
} 

@ApplicationPath("/") 
public class AppConfig extends ResourceConfig {  
    public AppConfig() { 
     register(new AppBinder()); 
     register(Controller.class); 
    } 
} 

ответ

3

Service, Конструкторы Controller вызывается всякий раз, когда мы отправляем http-запрос; создает ли экземпляры в каждом запросе или просто вызывает конструктор?

К сожалению, @Singleton не имеет никакого эффекта при связывании с использованием AbstractBinder. Мы должны явно сказать, что это должно быть одноэлементно

bind(ReflectionService.class).to(ReflectionService.class).in(Singleton.class); 

поведение по умолчанию является «на поиск» область применения, что означает, что создается новый экземпляр каждый раз, когда услуга запрашиваемую

(в самый первый запрос - почему бы не во время запуска сервера!)

Так оно и работает. Существует также ImmediateScope, который заставит его быть создан при запуске

bind(ReflectionService.class).to(ReflectionService.class).in(ImmediateScope.class) 

Или вы можете просто использовать экземпляр вместо класса, и он автоматически будет одноэлементно

bind(new ReflectionService()).to(ReflectionService.class) 

Услуги , Конструкторы контроллера вызываются всякий раз, когда мы отправляем запрос http; создает ли экземпляры в каждом запросе или просто вызывает конструктор?

Это поведение по умолчанию. Новый экземпляр класса ресурсов для каждого запроса. Как упоминалось выше, если вы хотите только один раз, например, то пометить его как @Singleton

Почему System.out в AppConfig вызывается дважды?

Не уверен, что, вероятно, просто необходимо для Джерси внутренней обработки на начальной загрузке

Есть ли лучший способ для создания моего небольшого проекта, который не имеет никакого доступа к БД и только три почтовым оконечных?

Ваш набор вверх это хорошо, но если вы используете Джерси, то вы должны использовать ResourceConfig (расширение Application) класс вместо Application

@ApplicationPath("/") 
public class AppConfig extends ResourceConfig { 
    public AppConfig() { 
     register(new AppBinder()); 
     register(Controller.class); 
    } 
} 

С этим, вам не нужно обернуть AppBinder в документе AppFeature. Джерси уже знает, как обрабатывать AppBinder

+0

Спасибо @peeskillet. Это было очень полезно. Я также хотел бы отметить мои наблюдения. Не могу сказать, слишком долго. Так что редактируйте свой ответ. –

+0

Я только что редактировал ваш пост, а не добавлял его в свою. Ох и для немедленного объема. Я забыл, что вам также нужно настроить [this] (http://stackoverflow.com/a/28123656/2587435). Также вам не нужно добавлять контроллер в связующее –

+0

Удаление контроллера из связующего создает его объект по каждому запросу без '@ Singleton'. Затем добавление '@ Singleton' создает его только один раз при первом запросе. Но я нуждаюсь в нем во время запуска сервера и работал с добавлением контроллера для связывания. Есть ли проблема для этого? –

0

По умолчанию Джерси создает новый экземпляр класса ресурса для каждого запроса. Так что, если вы не аннотировать класс ресурсов Джерси, он неявно использует @RequestScoped объем

Пожалуйста, ознакомьтесь с https://stackoverflow.com/a/20505899/721597

Также обратите внимание на Jersey 2 singleton dependency injection creates multiple instances