何时在Jersey资源中使用@Singleton

dex*_*ter 10 java database web-services jersey

我有一个访问数据库的Jersey资源.基本上它在资源的初始化中打开数据库连接.对资源的方法执行查询.

我观察到当我不使用@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
    ...

}
Run Code Online (Sandbox Code Playgroud)

我使用类似于此的代码连接到数据库:

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

}
Run Code Online (Sandbox Code Playgroud)

关于代码最佳实践的一些评论也会有所帮助.

Ale*_*ton -4

最好的选择是使用 Spring 和 Jersey 之类的框架,我在类似的文章中概述了这一点。唯一的区别是,您不是注入服务 bean,而是注入池数据源,并且可以使用c3p0轻松配置它。

示例 applicationContext.xml,注意“范围”设置为原型,相当于 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>
Run Code Online (Sandbox Code Playgroud)

在 MyResource.java 中,您只需添加以下内容,Spring 就会适当地注入它。

private DataSource pooledDataSource;
public void setPooledDataSource(DataSource pooledDataSource) {
    this.pooledDataSource = pooledDataSource;
}
Run Code Online (Sandbox Code Playgroud)

然后您可以更改 ResponseGenerator 以接受数据源并使用它来查询数据库。