2010-05-01 9 views
9

Tengo un recurso de Jersey que accede a la base de datos. Básicamente abre una conexión de base de datos en la inicialización del recurso. Realiza consultas sobre los métodos del recurso.Cuándo utilizar @Singleton en un recurso de Jersey

He observado que cuando no uso @Singleton, la base de datos se abre en cada solicitud. Y sabemos que abrir una conexión es realmente costoso ¿verdad?

Así que mi pregunta es, ¿debo especificar que el recurso sea singleton o realmente es mejor mantenerlo en solicitud, especialmente cuando el recurso se está conectando a la base de datos?

Mi código de recursos se ve así:

//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 
    ... 

} 

Y conectarse a la base de datos usando un código similar al siguiente:

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 
    ... 

} 

Algunos comentarios sobre las mejores prácticas para el código también será útil .

+0

¿Qué tal la agrupación de conexiones? ¿Por qué no usas eso? –

Respuesta

-4

Tu mejor opción es utilizar un armazón como Spring con Jersey que esbocé en un post similar. La única diferencia es que en lugar de inyectar un bean de servicio se inyectaría un DataSource agrupado y esto se puede configurar fácilmente usando c3p0.

Ejemplo applicationContext.xml, observe que el "alcance" se establece en prototipo que es equivalente a un singleton en el lenguaje de 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> 

En su MyResource.java simplemente debe agregar lo siguiente y Spring lo inyectará de manera adecuada.

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

entonces usted podría cambiar su ResponseGenerator a aceptar el origen de datos y usar esto para consultar la base de datos.

0

En lugar de pensar en hacer que el recurso sea singleton, concéntrese más en la administración de objetos de tipo servicio, backend, como la clase ResponseGenerator como singletons, lo que obviamente no debería crearse en cada solicitud.

Hacer el recurso de un producto único y es una manera de gestionar ResponseGenerator como un conjunto unitario, pero no es la única ni necesariamente la mejor manera, ver Access external objects in Jersey Resource class y How to wire in a collaborator into a Jersey resource? maneras para que forme recursos no únicos.

Tenga en cuenta que su clase ResponseGenerator necesitaría trabajo antes de que funcione como singleton, ya sea inyectado en un recurso por solicitud o instanciado en un recurso singleton. No es seguro para subprocesos, y abriría una única conexión al inicio y la reutilizaría en las solicitudes, lo que no funcionaría, debería usar un grupo de conexiones para realizar el trabajo pesado de reutilización eficiente y segura de las conexiones entre las solicitudes.

Algunos comentarios sobre las mejores prácticas para el código también serán útiles.

Obtendrá mejores respuestas en http://codereview.stackexchange.com, pero :

  • ResponseGenerator es un nombre pobre para una clase (casi todo en una aplicación web es un generador de respuesta).

  • no use String como el tipo de devolución de su servicio y objeto, use los objetos escritos correctamente (por ejemplo, suena como si estuviera devolviendo un java.util.List de algo).

  • No trague su SQLException, haga burbujas en ella para permitir que Jersey genere un código de respuesta de serie 5xx en su recurso.

  • Use las variables de miembros finales.

  • Su objeto de registro debe ser estático.

Cuestiones relacionadas