2010-05-01 4 views
9

У меня есть ресурс Джерси, доступ к базе данных. В основном он открывает соединение с базой данных при инициализации ресурса. Выполняет запросы по методам ресурса.Когда использовать @Singleton в ресурсе Джерси

Я заметил, что, когда я не использую @Singleton, база данных открыта при каждом запросе. И мы знаем, что открытие соединения действительно дорогое?

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

Мой код ресурса выглядит следующим образом:

//Use @Singleton here or not? 
@Path(/myservice/) 
public class MyResource { 

    private ResponseGenerator responser; 
    private Log logger = LogFactory.getLog(MyResource.class); 

    public MyResource() { 
     responser = new ResponseGenerator(); 
    } 

    @GET 
    @Path("/clients") 
    public String getClients() { 

     logger.info("GETTING LIST OF CLIENTS"); 

     return responser.returnClients(); 
    } 

    ... 
    // some more methods 
    ... 

} 

И я подключиться к базе данных, используя код, подобный этому:

public class ResponseGenerator { 
    private Connection conn; 
    private PreparedStatement prepStmt; 
    private ResultSet rs; 

    public ResponseGenerator(){ 
     Class.forName("org.h2.Driver"); 
     conn = DriverManager.getConnection("jdbc:h2:testdb"); 
    } 

    public String returnClients(){ 
     String result; 
     try{ 
      prepStmt = conn.prepareStatement("SELECT * FROM hosts"); 

      rs = prepStmt.executeQuery(); 

      ... 
      //do some processing here 
      ... 
     } catch (SQLException se){ 
      logger.warn("Some message"); 
     } finally { 
      rs.close(); 
      prepStmt.close(); 
      // should I also close the connection here (in every method) if I stick to per request 
      // and add getting of connection at the start of every method 
      // conn.close(); 
     } 

     return result 
    } 

    ... 
    // some more methods 
    ... 

} 

Некоторые замечания по наилучшей практике кода будет также полезно ,

+0

Как насчет пула соединений? Почему бы вам не использовать это? –

ответ

-4

Вы можете использовать фреймворк, такой как Spring with Jersey, который я описал в аналогичном post. Единственное различие заключается в том, что вместо того, чтобы вводить сервисный компонент, вы должны вводить объединенный DataSource, и это можно легко настроить с помощью c3p0.

Пример applicationContext.xml, обратите внимание, что в поле «scope» установлен прототип, который эквивалентен одноэлементному выражению Spring.

<bean id="pooledDataSource" scope="prototype" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 
    <property name="jdbcUrl" value="${jpa.url}" /> 
    <property name="user" value="${jpa.username}" /> 
    <property name="password" value="${jpa.password}" /> 
    <property name="initialPoolSize" value="1" /> 
    <property name="minPoolSize" value="1" /> 
    <property name="maxPoolSize" value="3" /> 
    <property name="idleConnectionTestPeriod" value="500" /> 
    <property name="acquireIncrement" value="1" /> 
    <property name="maxStatements" value="50" /> 
    <property name="numHelperThreads" value="1" /> 
</bean> 

В вашем MyResource.java вы просто добавили бы следующее, а Spring введет его соответствующим образом.

private DataSource pooledDataSource; 
public void setPooledDataSource(DataSource pooledDataSource) { 
    this.pooledDataSource = pooledDataSource; 
} 

Тогда вы можете сменить ResponseGenerator, чтобы принять DataSource и использовать его для запроса базы данных.

0

Вместо того, чтобы думать о том, чтобы сделать ресурс одиночным, сосредоточьтесь больше на управлении бэкэнд, объекты типа обслуживания, такие как ваш класс ResponseGenerator, как одиночные точки, которые, очевидно, не должны создаваться по каждому запросу.

делающая ресурс синглтон, а это один из способов управления ResponseGenerator как синглтон, но это не единственные и не обязательно лучший способ, увидеть Access external objects in Jersey Resource class и How to wire in a collaborator into a Jersey resource? способов инъекционного это в не-одноплодные ресурсы.

Обратите внимание, что ваш класс ResponseGenerator должен работать, прежде чем он будет функционировать как одноэлементный, независимо от того, вводится ли он в ресурс для каждого запроса или создается экземпляром одного ресурса. Он не является потокобезопасным, и вы должны открыть одно соединение при запуске и повторно использовать его в запросах, что не сработает, вы должны использовать пул соединений, чтобы эффективно поднимать + безопасное повторное использование соединений по запросам.

Некоторые комментарии по лучшим практикам для кода также будут полезны.

Вы получите лучшие ответы на http://codereview.stackexchange.com, но:

  • ResponseGenerator является плохим название класса (почти все в веб-приложения генератор ответов).

  • Не используйте String в качестве возвращаемого типа вашего сервиса и объекта, используйте соответствующие типизированные объекты (например, похоже, что вы возвращаете java.util.List чего-то).

  • Не проглатывайте SQLException, пузырь его, чтобы позволить Джерси генерировать код ответа серии 5xx в вашем ресурсе.

  • Использовать конечные переменные элемента.

  • Ваш объект должен быть статическим.

Смежные вопросы