1

我正在使用Kohsuke GitHub-API从我的 Java(服务器端)应用程序连接到 GitHub,并且我想使用OkHttp缓存来自 GitHub 的响应的能力。当我为它编写测试时,这非常有效,但它在应用程序本身中不起作用,我不知道为什么会这样。我设法将问题追溯到创建 URLConnection 对象时,该对象的 useCache 变量设置为 false,但我不知道为什么。它可能与服务器配置或类似的东西有关吗?

我将不胜感激任何想法,甚至向任何方向轻推,因为坦率地说,我没有任何想法......谢谢

提供者:

public class GitHubProvider implements Provider<GitHub> {

@Override
public GitHub get() {
    GitHub gitHub = null;
    HttpResponseCache cache = null;

    OkHttpClient okHttpClient = new OkHttpClient();
    File cacheDir = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString());

    try {
        cache = new HttpResponseCache(cacheDir, 10L * 1024 * 1024);
    } catch (IOException e) {
        // NOTHING
    }
    okHttpClient.setResponseCache(cache);

    try {
        gitHub = GitHub.connectUsingPassword("user", "password");
    } catch (Exception e) {
        // NOTHING
    }
    gitHub.setConnector(new OkHttpConnector(okHttpClient));

    return gitHub;
}
}

测试(作品):

@RunWith(JukitoRunner.class)
public class SoftwareComponentServiceTest {

public static class Module extends TestModule {
    @Override
    protected void configureTest() {
        bind(GitHub.class).toProvider(GitHubProvider.class);
    }
}

@Inject
GitHub gitHub;

@Test
public void testInjectedGitHubResponseCache() {
    try {
        GHUser ghUser = gitHub.getUser("user");
        GHRepository repository = ghUser.getRepository("repository");

        int limit = gitHub.getRateLimit().remaining;
        repository.getFileContent("README.md");

        assertEquals(limit - 1, gitHub.getRateLimit().remaining);

        repository.getFileContent("README.md");

        assertEquals(limit - 1, gitHub.getRateLimit().remaining);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

应用程序中使用的服务(不起作用):

@Singleton
@RequiresAuthentication
public class SoftwareComponentService {

@Inject
GitHub gitHub;

public List<SoftwareComponent> findAll() {
    List<SoftwareComponent> softwareComponentList = new ArrayList<SoftwareComponent>();

    try {
        GHUser ghUser = gitHub.getUser("user");
        List<GHRepository> repositories = ghUser.listRepositories().asList();

        for (int i = 0; i < repositories.size(); i++) {
            GHRepository repository = repositories.get(i);
            if (!repository.getName().startsWith("sc_")) {
                continue;
            }
            softwareComponentList.add(new SoftwareComponent(repository.getName(), repository.getDescription()));
        }
    } catch (IOException e) {
        // NOTHING
    }
    return softwareComponentList;
}
}
4

2 回答 2

4

原因

创建 URLConnection 对象时,它的useCache变量设置为false,因为它的defaultUseCaches变量在初始化时也被Tomcat 服务器设置为false。Tomcat 通过其JreMemoryLeakPreventionListener类执行此操作,因为使用 java.net.URLConnections 从 JAR 文件中读取资源有时会导致 JAR 文件被锁定urlCacheProtection变量)。他们为解决此问题而实施的解决方法是默认禁用 URLConnection 缓存(!?!?)。

解决方案

此解决方法的解决方法是创建一个虚拟URLConnection 并使用其 setDefaultUseCaches() 方法来更改每个后续创建的 URLConnection 的默认值(如 Jesse Wilson 所建议的那样)。

URL url = new URL("jar:file://dummy.jar!/");
URLConnection uConn = url.openConnection();
uConn.setDefaultUseCaches(true);

非常感谢 Jesse Wilson 为我指明了正确的方向!

于 2014-05-26T15:40:32.500 回答
1

有一种疯狂的方法URLConnection.setDefaultUseCaches()可以在全球范围内进行。这是一个像静态方法一样工作的实例方法:它为每个人设置属性。

于 2014-05-21T13:06:44.577 回答