Spring 的异步HTTP请求AsyncRestTemplate

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangchao858/article/details/86709750

如果你是第一次看到这篇文章,那么我建议你先去看一下上一篇《Spring 的异步HTTP请求AsyncRestTemplate》

还是那个套路

熟悉使用RestTemplate的,不会觉得AsyncRestTemplate很难,因为的确很相似。在Spring 看来,你只管写同步的代码,异步的执行交给它处理就可以了。

配置依旧在

默认的有时难以满足多变的需求,于是配置自定义参数排上用场:

	@Bean
	public AsyncRestTemplate asyncRestTemplate() {
		SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
		//设置链接超时时间
		factory.setConnectTimeout(100);
		//设置读取资料超时时间
		factory.setReadTimeout(200);
		//设置异步任务(线程不会重用,每次调用时都会重新启动一个新的线程)
		factory.setTaskExecutor(new SimpleAsyncTaskExecutor());
		return new AsyncRestTemplate(factory);
	}
  • 设置合理的超时时间对于HTTP请求至关重要,单位为毫秒
  • 异步任务可能需要配置线程池

化繁为简

如果需要对异步请求的返回值做处理,需要手动实现回调,而在回调里面实现逻辑看起来会很臃肿。

		entity.addCallback(new SuccessCallback<ResponseEntity<String>>() {
			@Override
			public void onSuccess(ResponseEntity<String> result) {
				log.info("A");
			}
		}, new FailureCallback() {
			@Override
			public void onFailure(Throwable ex) {
				log.info("B");
			}
		});

这时如果能用上Java 8 的lambda表示式,代码可以如此简单:

	public String demo3() {
		String url = "http://localhost:8080/teacher/1";
		log.info("Start");
		ListenableFuture<ResponseEntity<Teacher>> entity = asyncRestTemplate.getForEntity(url, Teacher.class);
		entity.addCallback(result -> log.info(result.getBody().getName()),(e) -> log.error(e.getMessage()));
		log.info("C");
		return "End";
	}

一行代码可以替代之前的十多行,代码更整洁了,可读性可高了不少。

为了能证明之前设置的超时时间有效,我在需要调用的请求代码中加入一行:

TimeUnit.SECONDS.sleep(3); // 暂停3秒

调用demo3(),查看控制台:

22:36:29.844  INFO 2732 --- [nio-8080-exec-1] c.c.t.web.AsyncTeacherController  : Start
22:36:29.926  INFO 2732 --- [nio-8080-exec-1] c.c.t.web.AsyncTeacherController  : C
22:36:29.926  INFO 2732 --- [nio-8080-exec-1] c.c.t.web.AsyncTeacherController  : End
22:36:30.132 ERROR 2732 --- [cTaskExecutor-1] c.c.t.web.AsyncTeacherController  : Read timed out

回调函数的第一个参数是成功以后执行的代码,没有在控制台看到相关信息,说明没有执行。
最后一行的输出不是来自主线程,并且打印的是错误信息:超时。

异步发送数据

我已经实现了一个接受数据的HTTP接口:

	@PostMapping("/save/teacher")
	public Teacher save(@RequestBody Teacher teacher){
		log.info(teacher.toString());
		return teacher;
	}

发送数据的逻辑,需要使用到 POST 请求:

	public String demo4() {
		String url = "http://localhost:8080/save/teacher";
		//设置Header
		MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
		headers.add("Content-Type", "application/json;charset=UTF-8");
		HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
		Teacher teacher = new Teacher().setId(4).setName("Kelly");
		//异步发送
		ListenableFuture<ResponseEntity<Teacher>> entity = asyncRestTemplate.postForEntity(url, httpEntity, Teacher.class, teacher);
		entity.addCallback(result -> log.info(result.getBody().getName()),(e) -> log.error(e.getMessage()));
		log.info("C");
		return "End";
	}

猜你喜欢

转载自blog.csdn.net/jiangchao858/article/details/86709750