Java 使用Jersey 2.0,如何为每个请求注册一个可绑定实例?

Java 使用Jersey 2.0,如何为每个请求注册一个可绑定实例?,java,dependency-injection,jersey,jersey-2.0,Java,Dependency Injection,Jersey,Jersey 2.0,…如果实例需要手动构造,可能是由第三方工厂类构造?之前,(Jersey 1.x),您会这样做: public class MyInjectableProvider extends PerRequestTypeInjectableProvider<Context, MyInjectable> { public MyInjectableProvider() { super(MyInjectable.class); } @Override

…如果实例需要手动构造,可能是由第三方工厂类构造?之前,(Jersey 1.x),您会这样做:

public class MyInjectableProvider extends PerRequestTypeInjectableProvider<Context, MyInjectable> {
    public MyInjectableProvider() {
        super(MyInjectable.class);
    }

    @Override
    public Injectable<MyInjectable> getInjectable(ComponentContext ic, Context context) {
        MyInjectable myInjectableInstance = //...

        return new Injectable<MyInjectable>() {
            @Override
            public MyInjectable getValue() {
                return myInjectableInstance;
            }
        };
    }
}
这“似乎有效”,但也似乎有点不清楚。例如,从不调用dispose()。此外,该绑定似乎隐式地表现为RequestScope。将配置修改为
bindFactory(this).to(MyInjectable.class).in(RequestScoped.class)似乎没有实际更改行为。我是否遗漏了什么,或者这是预期的解决方案?

代替了
工厂。dispose(T)
,向injectable
CloseableService注册可以实现您想要的大部分功能。需要一个
CloseableFactory
适配器
CloseableService
closes()
退出请求范围时所有注册的资源

有关特定示例,请参见下面的
连接工厂

import org.glassfish.hk2.api.Factory;
import org.glassfish.jersey.server.CloseableService;

import javax.inject.Inject;
import javax.ws.rs.InternalServerErrorException;
import java.sql.Connection;
import java.sql.SQLException;

import static com.google.common.base.Preconditions.checkNotNull;

public class ConnectionFactory implements Factory<Connection> {
    private final CloseableService closeableService;

    @Inject
    public ConnectionFactory(CloseableService closeableService) {
        this.closeableService = checkNotNull(closeableService);
    }

    public Connection provide() {
        final Connection connection;
        try {
            connection = acquireConnection();
        } catch (SQLException e) {
            throw new InternalServerErrorException(e);
        }
        try {
            closeableService.add(new CloseableConnection(connection));
        } catch (Throwable t) {
            closeQuietly(connection);
            throw runtime(t);
        }
        return connection;
    }

    public void dispose(Connection connection) {
        closeQuietly(connection);
    }

    private static RuntimeException runtime(Throwable t) {
        throw ConnectionFactory.<RuntimeException>unchecked(t);
    }

    private static <T extends Throwable> T unchecked(Throwable t) throws T {
        throw (T) t;
    }

    private static void closeQuietly(Connection connection) {
        try {
            connection.close();
        } catch (SQLException ignore) {}
    }
}

我也面临着同样的问题。你的“编辑”很有帮助。非常感谢。在阅读你文章的最后一段之前,我也发现,
dispose
从来不会在请求后调用。你找到原因了吗?你好,你在项目中使用的是哪个DI框架?因为我可以提供几个例子,说明我们如何使用guice和weld进行工作。对于guice,使用guice persist,其中EntityManager是请求的作用域。使用Weld,我们提供了请求范围。我们将存储库注入JAX资源。每个存储库,注入EM,用于解决数据库操作。默认范围是请求范围。当然,明确声明这一点并不会改变这一点。例如,您可以使用
singleton.class
将其声明为singleton作用域,或者您不喜欢此解决方案的什么?是否希望工厂返回的
RequestScoped
值不会传递到同一工厂
dispose
方法?@PavelBucek问题在于。
public class MyResourceConfig extends ResourceConfig {
    public MyResourceConfig() {
        register(new MyInjectableProvider());
    }
}
import org.glassfish.hk2.api.Factory;
import org.glassfish.jersey.server.CloseableService;

import javax.inject.Inject;
import javax.ws.rs.InternalServerErrorException;
import java.sql.Connection;
import java.sql.SQLException;

import static com.google.common.base.Preconditions.checkNotNull;

public class ConnectionFactory implements Factory<Connection> {
    private final CloseableService closeableService;

    @Inject
    public ConnectionFactory(CloseableService closeableService) {
        this.closeableService = checkNotNull(closeableService);
    }

    public Connection provide() {
        final Connection connection;
        try {
            connection = acquireConnection();
        } catch (SQLException e) {
            throw new InternalServerErrorException(e);
        }
        try {
            closeableService.add(new CloseableConnection(connection));
        } catch (Throwable t) {
            closeQuietly(connection);
            throw runtime(t);
        }
        return connection;
    }

    public void dispose(Connection connection) {
        closeQuietly(connection);
    }

    private static RuntimeException runtime(Throwable t) {
        throw ConnectionFactory.<RuntimeException>unchecked(t);
    }

    private static <T extends Throwable> T unchecked(Throwable t) throws T {
        throw (T) t;
    }

    private static void closeQuietly(Connection connection) {
        try {
            connection.close();
        } catch (SQLException ignore) {}
    }
}
import java.io.Closeable;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import static com.google.common.base.Preconditions.checkNotNull;

public final class CloseableConnection implements Closeable {
    private final Connection connection;

    public CloseableConnection(Connection connection) {
        this.connection = checkNotNull(connection);
    }

    public void close() throws IOException {
        try {
            connection.close();
        } catch (SQLException e) {
            throw new IOException(e);
        }
    }
}