Java 从调用方类停止异步Spring方法
我有一个类,它调用RESTWeb服务从服务器接收文件。在传输字节时,我创建了一个异步任务,它检查与服务器的连接是否正常,以便在出现错误时允许停止连接。 此异步任务有一个我必须停止的循环: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
@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);