何时在Jersey资源中使用@Singleton [英] When to use @Singleton in a Jersey resource

查看:188
本文介绍了何时在Jersey资源中使用@Singleton的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我观察到,当我不使用@Singleton时,数据库是在每个请求打开。我们知道打开一个连接真的很贵吗?



所以我的问题是,我应该指定资源是单例,还是更好地保持每个请求特别是当资源连接到数据库时?



我的资源代码如下:

  //在这里使用@Singleton吗? 
@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获得客户名单);

return responser.returnClients();
}

...
//其他方法
...

}

我使用类似下面的代码连接到数据库:

  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();

...
//在这里做一些处理
...
} catch(SQLException se){
logger.warn(Some message );
} finally {
rs.close();
prepStmt.close();
//如果我坚持每个请求
//并且在每个方法的开始添加连接,我还应该关闭这里的连接(每个方法)
// conn.close ();
}

返回结果
}

...
//其他方法
...

}

对代码的最佳实践的一些评论也将有所帮助。 p>

解决方案

不是想使资源成为单例,而是更多地关注管理后端,服务类型对象,如 ResponseGenerator 类作为单例,这显然不应该实例化每个请求。



使资源成为单例也是一种管理 ResponseGenerator 作为单例,但它不是唯一的或必然是最好的方法,请参见在Jersey资源类中访问外部对象

p>请注意,您的 ResponseGenerator 类将需要工作之前,它将作为单例,无论是注入到每个请求资源或实例化在单例资源。它不是线程安全的,你将在启动时打开一个连接,并在请求之间重用它,这将不起作用,你应该使用连接池来有效地安全地重用连接跨请求。


有关代码最佳做法的一些评论也很有帮助。



$ b b

您可以在 http://codereview.stackexchange.com
上获得更好的反馈,但




  • ResponseGenerator 是一个不太好的名称应用程序是一个响应生成器)。


  • 不要使用String作为服务和对象的返回类型,使用正确的类型对象're returns a java.util.List of something)。


  • 不要吞下你的SQLException ,


  • 使用最终成员变量。


  • 您的日志对象应该是静态的。



I have a Jersey resource that access the database. Basically it opens a database connection in the initialization of the resource. Performs queries on the resource's methods.

I have observed that when I do not use @Singleton, the database is being open at each request. And we know opening a connection is really expensive right?

So my question is, should I specify that the resource be singleton or is it really better to keep it at per request especially when the resource is connecting to the database?

My resource code looks like this:

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

}

And I connect to the database using a code similar to this:

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

}

Some comments on best practices for the code will also be helpful.

解决方案

Rather than thinking about making the resource a singleton, focus more on managing backend, service type objects like your ResponseGenerator class as singletons, which obviously shouldn't be instantiated every request.

Making the resource a singleton as well is one way of managing ResponseGenerator as a singleton, but it's not the only or necessarily the best way, see Access external objects in Jersey Resource class and How to wire in a collaborator into a Jersey resource? for ways to inject this into non-singleton resources.

Note that your ResponseGenerator class would need work before it would function as a singleton, whether injected into a per-request resource or instantiated in a singleton resource. It's not thread safe, and you would open a single connection on startup and reuse it across requests, which won't work, you should use a connection pool to do the heavy lifting of efficiently + safely reusing connections across requests.

Some comments on best practices for the code will also be helpful.

You'll get better responses on http://codereview.stackexchange.com, but:

  • ResponseGenerator is a poor name for a class (just about everything in a web application is a response generator).

  • don't use String as the return type of your service and object, use proper typed objects (eg it sounds like you're returning a java.util.List of something).

  • Don't swallow your SQLException, bubble it up to allow Jersey to generate a 5xx series response code in your resource.

  • Use final member variables.

  • Your log object should be static.

这篇关于何时在Jersey资源中使用@Singleton的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆