Когда использовать аннотацию @Singleton в Джерси?
Я разрабатываю веб-службу RESTful и, читая документацию в Джерси, наткнулся на аннотацию @Singleton
В моем веб-сервисе я в основном возвращаю данные на основе уникальных ключей, предоставляемых в качестве параметра. Аналогия будет возвращать всю информацию Студента при передаче Student_Id.
Итак, мой вопрос: когда @Singleton
подходит для таких веб-сервисов?
Согласно документации для @RequestScoped
Если ресурс используется более одного раза в обработке запроса, всегда будет использоваться один и тот же экземпляр.
Тогда в этом случае мы не должны @Singleton
использовать @Singleton
правильно?
Также могут быть случаи использования, когда мы должны создать новый экземпляр для каждого запроса?
Я посмотрел этот пост, но на мой вопрос не ответил.
Ответы
Ответ 1
По умолчанию Джерси создает новый экземпляр класса ресурсов для каждого запроса. Поэтому, если вы не комментируете класс ресурсов Джерси, он неявно использует область @RequestScoped
. В документация Джерси:
Жизненный цикл по умолчанию (применяется, если аннотация отсутствует). В этом scope экземпляр ресурса создается для каждого нового запроса и используется для обработки этого запроса. Если ресурс используется более одного времени в обработке запроса, всегда будет использоваться один и тот же экземпляр. Это может произойти, когда ресурс является дополнительным ресурсом, возвращается больше раз во время согласования. В этой ситуации только на сервера.
В большинстве случаев вы используете этот параметр по умолчанию, поэтому вы не используете область @Singleton
. Вы также можете создать класс ресурса singleton Jersey, используя аннотацию @Singleton
. Затем вам нужно зарегистрировать одноэлементный класс в классе MyApplication
, например,
@Path("/resource")
@Singleton
public class JerseySingletonClass {
//methods ...
}
public class MyApplication extends ResourceConfig {
/*Register JAX-RS application components.*/
public MyApplication () {
register(JerseySingletonClass.class);
}
}
Ответ 2
В большинстве случаев @RequestScoped
умолчанию @RequestScoped
должен быть достаточным для ваших нужд.
@Singleton
может находиться в состоянии. У меня возникла проблема, когда моя конечная точка была аннотирована как @Singleton
поэтому она повторно использовала тот же EntityManager
во время одновременных вызовов. После удаления @Singleton
во время одновременных вызовов используются разные экземпляры объектов EntityManager
. Если последующие вызовы конечной точки, возможно, будет использоваться предыдущий/старый EntityManager
. - Джерси, Guice и Hibernate - Безопасность потока EntityManager
Ответ 3
На самом деле используется прецедент, описанный в руководстве "Джерси-2" для использования SseBroadcaster при обслуживании событий Server-Sent, в этом приведенном примере
Класс ресурсов BroadcasterResource аннотируется аннотацией @Singleton, в которой указано, что для выполнения всех входящих запросов в/широковещательный канал используется только один экземпляр класса ресурсов. Это необходимо, так как мы хотим сохранить единую ссылку на приложение для частного вещательного поля, чтобы мы могли использовать один и тот же экземпляр для всех запросов. Клиенты, которые хотят прослушивать события SSE, сначала отправляют запрос GET в BroadcasterResource, который обрабатывается методом ресурса listenToBroadcast().
Используя @Singleton
, приложение будет содержать только один SseBroadcaster
для всех входящих запросов, одного такого вещателя достаточно, чтобы обслуживать несколько клиентов, поэтому его нужно создать только один раз!
JAX-RS SSE API определяет SseBroadcaster, который позволяет передавать отдельные события нескольким клиентам.
Ответ 4
Я пришел к этому вопросу, потому что впервые у меня был случай, когда я не использовал аннотацию @Singleton.
Singleton - это шаблон проектирования, его следует использовать, если:
- Объект, который вы "одиночка", сохраняет состояние, которое должно быть общим и уникальным (пример: глобальный счетчик)
- Обычно я разрабатываю REST API без сохранения состояния, все обрабатывается в методе (полное закрытие): поэтому, как правило, все мои ресурсы являются одиночными (вариант использования: лучшая производительность)
Тем не менее, сегодня я нашел этот вариант использования для того, чтобы не использовать Singleton:
@Path("/someendpoint/{pathparam}/somethingelse/")
//@Singleton
public class MyResource {
@PathParam("pathparam")
private String pathparam;
}
Используя это, я привязываю параметр path к своему экземпляру, поэтому он должен быть RequestScoped. В общем, я бы поместил аннотацию @PathParam в каждый метод, поэтому @Singleton был бы прав в классе.
Я не уверен в производительности, однако создание и уничтожение объекта не является бесплатной операцией.