寻找使用Spring的ThreadPoolTask​​Executor和Jersey客户端Web服务调用的正确方法

时间:2013-06-24 14:17:18

标签: java spring connection threadpoolexecutor jersey-client

我正在开发一个Web应用程序,其中一个要求是调用通过Jersey客户端完成的外部Web服务。现在我想在一个单独的线程中调用此Web服务api,以便不会阻止UI等待WS响应。我还希望能够只记录Web服务调用返回的响应,我不会在任何业务逻辑中使用响应。 为此,我创建了一个spring managed bean,它将保存对spring ThreadPoolTaskExecutor的引用。配置如下:

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="5" />
    <property name="maxPoolSize" value="10" />
    <property name="queueCapacity" value="25" />
</bean>

<bean id="updateEmailSubscriptionClient" class="com.myorg.MyClass">
    <constructor-arg ref="taskExecutor" />
</bean>

MyClass有一个实现runnable的内部类,用于生成将执行实际webservice调用并记录响应的线程,所有这些都是异步完成的,因此不会阻止UI。 MyClass看起来像这样:

public class MyClass {
    private Client jClient; //The jersey client
    private TaskExecutor taskExecutor;

    public MyClass(TaskExecutor taskExecutor){
        this.taskExecutor = taskExecutor;
        ClientConfig cc = new DefaultClientConfig();

        //Initialize jersey client config here ...

        jClient = Client.create(cc);

    }

    public void makeWSCall(){

        //Do some stuff

        taskExecutor.execute(new WorkerClass());
    }

    private class WorkerClass implements Runnable{

        void run(){
            WebResource webResource = jClient.resource(myResource);

            //Setup webresource here with headers, mime etc....

            try{
                String resp = webResource.post(String.class);

                //Log the response here ...

            }catch(UniformInterfaceException e){

                 //Do something ...
            }

        }  

    }
}

从上面的代码中可以看出,尝试是在WorkerClass的run方法中将jersey客户端调用放到WS中,该方法实现Runnable。公共方法makeWSCall然后,taskExecutor会在调用时WorkerClass执行新的taskExecutor对象。我的问题/疑虑如下:

  1. 这是解决手头问题的好方法吗?使用我们的公共域名网站对多个客户有效吗?
  2. 我没有在Spring配置文件中为run()提供任何destroy方法。有必要吗?
  3. 如果WorkerClass的{​​{1}}方法会抛出异常,会发生什么?该线程是否可以再次从池中获得?
  4. 任何其他问题或更好的想法。
  5. 请注意,我尝试使用Jersey的AsyncWebResource,但我仍然需要从仍然会阻止UI的帖子上返回的Future对象获取响应。此外,我们使用的是旧版本的jersey客户端(1.0.2),并且可能无法使用其中一些较新的功能。升级到较新版本目前超出了该项目的范围。

    修改 我在Spring中阅读了关于@Async注释的内容,我认为这比使用实现runnable的内部类更好。我认为解决这个问题的方法是将WorkerClass中的代码转移到makeWSCall,使用@Async注释makeWSCall,在spring配置文件中进行必要的更改。但是,如果在应用程序上下文中定义了另一个执行程序会发生什么。 Spring如何知道在哪个执行器中运行我的@Async方法?

    修改 我最终使用@Async注释工作正常。另一个问题是关闭连接。如何确保在返回响应后关闭连接。我可以在getEntity对象上调用ClientResponse来确保连接已关闭(根据球衣文档)。但是,如果getEntity中存在异常,或者甚至在我的网络资源上执行实际发布请求时,连接是否仍会关闭,或者我是否必须明确执行此操作?在我的泽西版本中,close()没有ClientResponse方法。我应该如何在例外情况下关闭连接?

0 个答案:

没有答案