wps 呼叫方拒绝呼叫_呼叫我或异步REST

wps 呼叫方拒绝呼叫

本文是使用Spring Boot + Java 8制作的工作正常的异步REST应用程序的非常简单的示例。SpringBoot使开发Web应用程序几乎非常容易,但是为了简化任务,我从Spring存储库中举了一个例子,称为rest- service ,将其分叉到我自己的存储库中 ,并出于我的目的对其进行了更改,以创建两个应用程序:客户端和服务器。

我们的服务器应用程序将是一个简单的REST Web服务,它将查询GitHub以获取一些用户数据并将其返回。 我们的客户端应用程序还将是REST Web服务……将查询第一个应用程序!

服务器代码基本上由服务和控制器组成。 该服务使用带有@Async批注的异步方法,如下所示。

@Service
public class GitHubLookupService {

    private static final Logger logger = LoggerFactory.getLogger(GitHubLookupService.class);

    private final RestTemplate restTemplate;

    public GitHubLookupService(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    @Async
    CompletableFuture<User> findUser(String user) throws InterruptedException {
        logger.info("Looking up " + user);
        String url = String.format("https://api.github.com/users/%s", user);
        User results = restTemplate.getForObject(url, User.class);
        // Artificial delay of 1s for demonstration purposes
        Thread.sleep(1000L);
        return CompletableFuture.completedFuture(results);
    }

}

服务器控制器:

@RestController
public class GitHubController {

    private final GitHubLookupService lookupService;

    @Autowired
    public GitHubController(GitHubLookupService lookupService) {
        this.lookupService = lookupService;
    }

    @RequestMapping("/user/{name}")
    public CompletableFuture<TimedResponse<User>> findUser(@PathVariable(value = "name") String name) throws InterruptedException, ExecutionException {
        long start = System.currentTimeMillis();
        ServerResponse response = new ServerResponse(Thread.currentThread().getName());
        return lookupService.findUser(name)
                .thenApply(user -> {
                    response.setData(user);
                    response.setTimeMs(System.currentTimeMillis() - start);
                    response.setCompletingThread(Thread.currentThread().getName());
                    return response;
                });
    }

}

我们这里拥有的是来自Java 8的简单CompletableFuture ,借助thenApply()我们将其转换为所需的格式,该格式允许我们添加有关当前线程的一些数据,以确保执行真正异步发生,也就是说,完成工作的线程不是开始工作的线程。 我们可以确定这一点,运行应用程序并检查调用结果:

marina@Marinas-MacBook-Pro:~$ http http://localhost:8080/user/mchernyavskaya
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Date: Mon, 02 Oct 2017 18:07:54 GMT
Transfer-Encoding: chunked

{
    "completingThread": "SimpleAsyncTaskExecutor-1",
    "data": {
        "avatar_url": "https://avatars2.githubusercontent.com/u/538843?v=4",
        "company": "OLX",
        "location": "Berlin, Germany",
        "name": "Maryna Cherniavska",
        "url": "https://api.github.com/users/mchernyavskaya"
    },
    "error": false,
    "startingThread": "http-nio-8080-exec-1",
    "timeMs": 2002
}

现在,我们需要创建一个将调用服务器应用程序客户端应用 程序 。 在Spring中有一个非常方便的用于消费REST的类,称为RestTemplate 。 但是,RestTemplate是同步的,我们在服务器应用程序中进行的所有不错的异步处理对客户端应用程序完全没有帮助。 这两个应用程序是完全独立的。 客户端应用程序只知道它将处理一个相当长时间的调用。 由于客户端应用程序知道这一点,并且由于它可能不想在服务器应用程序整个查询期间都占用线程,因此我们也将使其异步。 AsyncRestTemplate即将解救!

我们的客户端应用程序将更加简单,并将主要由控制器代码组成 。 要在一台本地计算机上运行两个应用程序,我们需要使用-Dserver.port = 8082参数更改服务器的端口。 因此,我们的服务器现在位于localhost:8080上,客户端位于localhost:8082上。

客户端控制器主要如下。

@RestController
public class GitHubController {
    private static final String BASE_URL = "http://localhost:8080/";

    private final AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();

    @RequestMapping("/async/user/{name}")
    public ListenableFuture<ClientResponse> findUserAsync(@PathVariable(value = "name") String name)
            throws InterruptedException, ExecutionException {
        long start = System.currentTimeMillis();
        ClientResponse clientResponse = new ClientResponse(Thread.currentThread().getName());
        ListenableFuture<ResponseEntity<ServerResponse>> entity = asyncRestTemplate.getForEntity(BASE_URL + name, ServerResponse.class);
        entity.addCallback(new ListenableFutureCallback<ResponseEntity<ServerResponse>>() {
            @Override
            public void onFailure(Throwable ex) {
                clientResponse.setError(true);
                clientResponse.setCompletingThread(Thread.currentThread().getName());
                clientResponse.setTimeMs(System.currentTimeMillis() - start);
            }

            @Override
            public void onSuccess(ResponseEntity<ServerResponse> result) {
                clientResponse.setData(result.getBody());
                clientResponse.setCompletingThread(Thread.currentThread().getName());
                clientResponse.setTimeMs(System.currentTimeMillis() - start);
            }
        });

    }
}

我们正在获取服务器响应,并将其包装到有关时序和当前线程的更多数据中,以更好地了解发生了什么。 AsyncRestTemplate给了我们一个ListenableFuture ,但是我们用它完成了一个CompletableFuture ,因为它允许我们手动控制将来返回的时刻,并在此过程中转换输出。

当我们调用客户服务时,它返回以下数据:

marina@Marinas-MacBook-Pro:~$ http http://localhost:8082/async/user/mchernyavskaya
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Date: Mon, 02 Oct 2017 18:28:36 GMT
Transfer-Encoding: chunked

{
    "completingThread": "SimpleAsyncTaskExecutor-1",
    "data": {
        "completingThread": "SimpleAsyncTaskExecutor-3",
        "data": {
            "avatar_url": "https://avatars2.githubusercontent.com/u/538843?v=4",
            "company": "OLX",
            "location": "Berlin, Germany",
            "name": "Maryna Cherniavska",
            "url": "https://api.github.com/users/mchernyavskaya"
        },
        "error": false,
        "startingThread": "http-nio-8080-exec-7",
        "timeMs": 1403
    },
    "error": false,
    "startingThread": "http-nio-8082-exec-3",
    "timeMs": 1418
}

您可以在此处阅读有关Spring中异步方法的更多信息,但是这个简单的示例应该可以帮助您了解事物的工作方式。 完整的代码在存储库中 。 希望它有一定用处!

翻译自: https://www.javacodegeeks.com/2017/10/call-asynchronous-rest.html

wps 呼叫方拒绝呼叫

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值