使用 Jersey CDI 自动关闭数据库连接?
Close database connections automatically with Jersey CDI?
我想将实现 AutoClosable 的对象注入到 jersey 资源,并在请求结束时由框架自动关闭它。
基本上这是一个数据库连接提供程序,打开的连接应该在请求结束时关闭。
使用 @inject
注释时,对象不会关闭。
这可能吗?如何实现?
我认为您正在寻找 @Disposes
注释。
@Disposes
注释标识 disposer 方法 的处置参数,允许应用程序对 producer 返回的对象执行自定义清理方法 或生产者领域。作用域结束时自动调用 disposer 方法。
我不知道你的数据库连接提供者是什么样的,但这个例子会让你大致了解如何使用 @Disposes
注释:
public class Resources {
@Produces
@UserDatabase
@RequestScoped
@PersistenceContext
private EntityManager em;
public void close(@Disposes @UserDatabase EntityManager em) {
em.close();
}
}
您可以使用 CloseableService
The service may be used within the scope of a request to add instances of Closeable
that are to be closed when the request goes out of scope, more specifically after the request has been processed and the response has been returned.
您可以将此服务注入到 Factory
中,您可以在其中创建您的提供商。只需要在Factory
里面的CloseableService
添加provider,请求结束就会关闭
public class ConnectionProviderFactory implements Factory<ConnectionProvider> {
@Inject
private CloseableService closeableService;
@Override
public ConnectionProvider provider() {
ConnectionProvider provider = new ConnectionProvider();
closeableService.add(provider);
return provider;
}
@Override
public void dispose(ConnectionProvider provider) {
}
}
然后只需在您的活页夹中注册工厂
bindFactory(ConnectionProviderFactory.class)
.to(ConnectionProvider.class)
.in(RequestScoped.class);
请注意 Factory
class 有一个 dispose
方法。我不是 100% 确定它是如何工作的细节,因为我有过这样的经历,有时 被 调用,有时不被调用。我发现 CloseableService
更可靠。也许有一天我会四处挖掘,尝试为自己解开 dispose
方法的谜团。
更新
不太确定您在做什么不同,但下面是使用 Jersey 测试框架的完整测试。 运行 它与任何其他 JUnit 测试一样。唯一的区别是我使用 Closeable
而不是 AutoCloseable
import java.io.Closeable;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.CloseableService;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class InjectCloseableTest extends JerseyTest {
public static final String CONNECTION_MSG = "Connection";
public static class ConnectionProvider implements Closeable {
private static final Logger LOGGER
= Logger.getLogger(ConnectionProvider.class.getName());
public String getConnection() {
return CONNECTION_MSG;
}
@Override
public void close() {
LOGGER.info("---- Closing Connection ----");
}
}
@Path("connection")
public static class ConnectionResource {
@Inject
ConnectionProvider connectionProvider;
@GET
public String get() {
return connectionProvider.getConnection();
}
}
public static class ConnectionProviderFactory implements Factory<ConnectionProvider> {
@Inject
CloseableService closeableService;
@Override
public ConnectionProvider provide() {
ConnectionProvider provider = new ConnectionProvider();
closeableService.add(provider);
return provider;
}
@Override
public void dispose(ConnectionProvider t) {}
}
@Override
public ResourceConfig configure() {
return new ResourceConfig(ConnectionResource.class)
.register(new LoggingFilter(Logger.getAnonymousLogger(), true))
.register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(ConnectionProviderFactory.class)
.to(ConnectionProvider.class)
.in(RequestScoped.class);
}
});
}
@Test
public void doit() {
Response response = target("connection").request().get();
assertEquals(200, response.getStatus());
assertEquals(CONNECTION_MSG, response.readEntity(String.class));
response.close();
}
}
这是您需要 运行 它的唯一依赖项。
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey2.version}</version>
<scope>test</scope>
</dependency>
我想将实现 AutoClosable 的对象注入到 jersey 资源,并在请求结束时由框架自动关闭它。
基本上这是一个数据库连接提供程序,打开的连接应该在请求结束时关闭。
使用 @inject
注释时,对象不会关闭。
这可能吗?如何实现?
我认为您正在寻找 @Disposes
注释。
@Disposes
注释标识 disposer 方法 的处置参数,允许应用程序对 producer 返回的对象执行自定义清理方法 或生产者领域。作用域结束时自动调用 disposer 方法。
我不知道你的数据库连接提供者是什么样的,但这个例子会让你大致了解如何使用 @Disposes
注释:
public class Resources {
@Produces
@UserDatabase
@RequestScoped
@PersistenceContext
private EntityManager em;
public void close(@Disposes @UserDatabase EntityManager em) {
em.close();
}
}
您可以使用 CloseableService
The service may be used within the scope of a request to add instances of
Closeable
that are to be closed when the request goes out of scope, more specifically after the request has been processed and the response has been returned.
您可以将此服务注入到 Factory
中,您可以在其中创建您的提供商。只需要在Factory
里面的CloseableService
添加provider,请求结束就会关闭
public class ConnectionProviderFactory implements Factory<ConnectionProvider> {
@Inject
private CloseableService closeableService;
@Override
public ConnectionProvider provider() {
ConnectionProvider provider = new ConnectionProvider();
closeableService.add(provider);
return provider;
}
@Override
public void dispose(ConnectionProvider provider) {
}
}
然后只需在您的活页夹中注册工厂
bindFactory(ConnectionProviderFactory.class)
.to(ConnectionProvider.class)
.in(RequestScoped.class);
请注意 Factory
class 有一个 dispose
方法。我不是 100% 确定它是如何工作的细节,因为我有过这样的经历,有时 被 调用,有时不被调用。我发现 CloseableService
更可靠。也许有一天我会四处挖掘,尝试为自己解开 dispose
方法的谜团。
更新
不太确定您在做什么不同,但下面是使用 Jersey 测试框架的完整测试。 运行 它与任何其他 JUnit 测试一样。唯一的区别是我使用 Closeable
AutoCloseable
import java.io.Closeable;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.CloseableService;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class InjectCloseableTest extends JerseyTest {
public static final String CONNECTION_MSG = "Connection";
public static class ConnectionProvider implements Closeable {
private static final Logger LOGGER
= Logger.getLogger(ConnectionProvider.class.getName());
public String getConnection() {
return CONNECTION_MSG;
}
@Override
public void close() {
LOGGER.info("---- Closing Connection ----");
}
}
@Path("connection")
public static class ConnectionResource {
@Inject
ConnectionProvider connectionProvider;
@GET
public String get() {
return connectionProvider.getConnection();
}
}
public static class ConnectionProviderFactory implements Factory<ConnectionProvider> {
@Inject
CloseableService closeableService;
@Override
public ConnectionProvider provide() {
ConnectionProvider provider = new ConnectionProvider();
closeableService.add(provider);
return provider;
}
@Override
public void dispose(ConnectionProvider t) {}
}
@Override
public ResourceConfig configure() {
return new ResourceConfig(ConnectionResource.class)
.register(new LoggingFilter(Logger.getAnonymousLogger(), true))
.register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(ConnectionProviderFactory.class)
.to(ConnectionProvider.class)
.in(RequestScoped.class);
}
});
}
@Test
public void doit() {
Response response = target("connection").request().get();
assertEquals(200, response.getStatus());
assertEquals(CONNECTION_MSG, response.readEntity(String.class));
response.close();
}
}
这是您需要 运行 它的唯一依赖项。
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey2.version}</version>
<scope>test</scope>
</dependency>