Java 从调用方类停止异步Spring方法

Java 从调用方类停止异步Spring方法,java,spring,asynchronous,Java,Spring,Asynchronous,我有一个类,它调用RESTWeb服务从服务器接收文件。在传输字节时,我创建了一个异步任务,它检查与服务器的连接是否正常,以便在出现错误时允许停止连接。 此异步任务有一个我必须停止的循环: @Component public class ConnectionTest { @Async //Check connection with the server, if for three attemp it failes, throw exception public void

我有一个类,它调用RESTWeb服务从服务器接收文件。在传输字节时,我创建了一个异步任务,它检查与服务器的连接是否正常,以便在出现错误时允许停止连接。 此异步任务有一个我必须停止的循环:

@Component
public class ConnectionTest {

    @Async
    //Check connection with the server, if for three attemp it failes, throw exception
    public void checkServerConnection(String serverIp) throws Exception{
        int count=0;
        for(;;Thread.sleep(7000)){
            try{
                System.out.println("TEST");
                URL url = new URL(serverIp);
            HttpURLConnection con = (HttpURLConnection) url
                    .openConnection();
            con.connect();
            if (con.getResponseCode() == 200){
                System.out.println("Connection established!!");
            }
                if (count>0) count=0;
            }catch(Exception e){
                count++;
                if (count==3)   
                    throw new Exception("Connection error");
            }
        }
    }
}
但是,如何从调用方停止此方法

@Autowired 
    private ConnectionTest connectionTest;

    @Override
    public Response getFile(String username, String password, String serverIp, String toStorePath, String filePath){


        ResponseEntity<byte[]> responseEntity = null;
        try{
            //it is used to check if connection of the client with the server goes down
            connectionTest.checkServerConnection();
            RestClient restClient = new RestClient(username, password);     

            //          SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            //          requestFactory.setBufferRequestBody(false);     
            //          restClient.setRequestFactory(requestFactory);
            //          RestTemplate restClient = new RestTemplate();
            responseEntity  = restClient.getForEntity(serverIp + "client/file/?filePath={filePath}", byte[].class, filePath);   

            //TODO kill async task and return false
异步连接检查:

@Component
public class ConnectionTest {

    private boolean stop;

    @Async
    //Check connection with the server, if for three attemp it failes, throw exception
    /**
     * 
     * @param serverIp
     * @throws IOException
     */
    public Future<Boolean> checkServerConnection(String serverIp)  throws IOException {
        int count=0;
        stop = false;
        while (!stop){
            try{
                Thread.sleep(7000);
                System.out.println("TEST");
                //java.net.InetAddress.getByName(SERVER_ADDRESSS);
                URL url = new URL(serverIp);
                HttpURLConnection con = (HttpURLConnection) url
                        .openConnection();
                con.connect();
                if (count>0) count=0;
            }catch(Exception e){
                count++;
                System.out.println(count);
                if (count==3)   
                    return new AsyncResult<Boolean>(stop);
            }
        }
        return new AsyncResult<Boolean>(stop);
    }

    /**
     * @return the stop
     */
    public boolean isStop() {
        return stop;
    }

    /**
     * @param stop the stop to set
     */
    public void setStop(boolean stop) {
        this.stop = stop;
    }
}
@组件
公共类连接测试{
私有布尔停止;
@异步的
//检查与服务器的连接,如果三次尝试失败,则抛出异常
/**
* 
*@param-serverIp
*@抛出异常
*/
公共未来checkServerConnection(字符串serverIp)引发IOException{
整数计数=0;
停止=错误;
当(!停止){
试一试{
睡眠(7000);
系统输出打印(“测试”);
//java.net.InetAddress.getByName(服务器地址);
URL=新URL(服务器IP);
HttpURLConnection con=(HttpURLConnection)url
.openConnection();
con.connect();
如果(计数>0)计数=0;
}捕获(例外e){
计数++;
系统输出打印项次(计数);
如果(计数=3)
返回新的异步结果(停止);
}
}
返回新的异步结果(停止);
}
/**
*@返回车站
*/
公共布尔isStop(){
返回站;
}
/**
*@param停止要设置的停止
*/
公共无效设置停止(布尔停止){
this.stop=停止;
}
}
下载异步:

@Component
public class DownloadAsync {

    @Async
    public Future<ResponseEntity<byte[]>> makeRequest(String username, String password, String serverIp, String filePath){
        RestClient restClient = new RestClient(username, password);
        ResponseEntity<byte[]> response= restClient.getForEntity(serverIp + "client/file/?filePath={filePath}", byte[].class, filePath);    
        return new AsyncResult<ResponseEntity<byte[]>>(response);
    }
}
@组件
公共类下载异步{
@异步的
公共未来makeRequest(字符串用户名、字符串密码、字符串服务器IP、字符串文件路径){
RestClient RestClient=新的RestClient(用户名、密码);
ResponseEntity response=restClient.getForEntity(serverIp+“client/file/?filePath={filePath}”,字节[]。类,filePath);
返回新的异步结果(响应);
}
}

当处理
@Async
方法时,一个好的做法是从该方法返回
未来
对象,因为您需要客户端和任务代码之间的连接点。

让您的任务方法返回一个
未来的

public Future<Integer> checkServerConnection(String serverIp) {
    // other code here
    return new AsyncResult<>(count);
}
Future<Integer> checkTask = connectionTest.checkServerConnection();
最后,在客户端代码中,让我们获得
未来的

public Future<Integer> checkServerConnection(String serverIp) {
    // other code here
    return new AsyncResult<>(count);
}
Future<Integer> checkTask = connectionTest.checkServerConnection();

首先,我不想再让这个问题复杂化了,所以我要给你们一个关于这个问题的高层次的描述。特别是,看看在android中如何使用发布代理非常优雅地完成这项工作

基本上,发布委托由两部分组成。首先,一个被重写的方法用于发布更改,另一个方法用于接收更改。接收更改的时间间隔取决于队列中当前的“块”大小和数据大小,但通常,您可以将此视为接收发布事件的最佳尝试

这是一幅高层次的大画面

异步任务

  • 后台(随时间下载) 后台(发布下载进度)

  • 发布接收器(接收下载的更新[可能以百分比为单位] 从这里做出决定

我并没有忽略Spring上下文的重要性,但我认为一旦你收到这篇文章,你就会接受它的适用性,不管框架如何

最好的, 移动设备开发

处,升起一些标志,异步实例可以读取并对其作出反应。是否有一个Spring方法来停止任务?我已经搜索了,但没有成功。问题是,方法体本身不能通过代理来增强(它肯定是用于实现异步功能的)如果它进入循环,您唯一的选择就是中断线程。我不是Spring专家,所以我不知道您是否可以访问执行该方法的线程,即使可以,也不知道它是否明智(例如,在内部,可能会使用一组线程来执行任务,您不应该中断这些线程)。我有一个异常问题,它不能从我的getFile方法捕获,因为它是异步异常,现在我不知道如何中断get file方法。我想是这样的,但可能异常是中断web服务的唯一方法call@luca将对rest客户机的调用包装到另一个异步任务中,这样就可以得到
Future
,如果
checkTask
引发异常,则取消它。我已使用工作代码进行了更新。当我取消任务时,rest请求会停止?是的,它应该停止。但是,请确保不要在
restClient.getForEntity()中创建更多线程
方法,因为它们可能会继续工作。
AsyncResult
cancel
-方法只返回
false
,因此它实际上不起任何作用。
// Check if the task was completed including by an exception being thrown.
checkTask.isDone();

// Get the task result.
Integer count = checkTask.get(); // Note: this is a blocking method.

// If the task was finished by throwing an exception,
// get() method will also throw an exception.
// You can get the cause exception like this:
if (checkTask.isDone()) {
    try {
        checkTask.get();
    } catch(Exception e) {
        Exception cause = e.getCause(); // this will be your new Exception("Connection error")
    }
}

// Not recommended, but you can also cancel the task:
checkTask.cancel(mayInterruptIfRunning);