简体   繁体   English

如何:使用Play Framework 2.1为初学者访问RESTful Web服务

[英]How to: Accessing RESTful Web Services with Play Framework 2.1 for Beginners

I am fairly new to many of the concepts and technologies being used in this question so I would appreciate a little understanding and help for a beginner from the community. 我对这个问题中使用的许多概念和技术都相当新,所以我希望对社区初学者有一点了解和帮助。 I am using the Play Framework version 2.1.3 and I need to POST data to a RESTful web service so that it can be inserted into a remote database. 我正在使用Play Framework 2.1.3版,我需要将数据POST到RESTful Web服务,以便可以将其插入远程数据库。 An XML response will be returned indicating either success or failure. 将返回XML响应,指示成功或失败。

I am sure you are aware that the documentation for the Play Framework is quite lacking and is in no way helpful to beginners, therefore I am unsure of how to accomplish this task with best practices in mind. 我相信您知道Play Framework的文档非常缺乏,对初学者没有任何帮助,因此我不确定如何在考虑最佳实践的情况下完成此任务。 I am looking for a Java solution to this problem, I do not have the time at present to learn the Scala language. 我正在寻找这个问题的Java解决方案,我目前没有时间学习Scala语言。 My experience with Web Services is fairly limited, normally I would implement a DAO design pattern (or use one of the many available ORM libraries depending on needs) within my application and use JDBC to connect directly to the database. 我对Web服务的经验相当有限,通常我会在我的应用程序中实现DAO设计模式(或根据需要使用许多可用的ORM库之一)并使用JDBC直接连接到数据库。 That is not an option here. 这不是一个选择。

My first question would have to be, is there a recommended design pattern for accessing web services? 我的第一个问题是,是否有推荐的访问Web服务的设计模式? Then, considering the Play MVC framework, how would one best implement such a design pattern, package the data (assuming the application has already captured and validated data from the user), send it off and process the responses back to the user? 然后,考虑到Play MVC框架,如何最好地实现这样的设计模式,打包数据(假设应用程序已经捕获并验证了用户的数据),将其发送出去并将响应处理回用户?

I know it is a fairly lengthy question however my intention behind this is to create a knowledge base of sorts for beginners who can easily come in with limited experience, read, understand and replicate what they find here to produce a working solution. 我知道这是一个相当冗长的问题,但我的目的是为初学者创建一个知识库,他们可以很容易地获得有限的经验,阅读,理解和复制他们在这里找到的东西,以产生一个有效的解决方案。 Having searched the web quite extensively, I have found a few disjointed snippets but nothing concrete involving these technologies and no up-to-date tutorials. 在广泛搜索网页后,我发现了一些脱节的片段,但没有具体涉及这些技术,也没有最新的教程。 Thank you for your time. 感谢您的时间。

Creating requests is straight-forward. 创建请求很简单。 First you provide a URL. 首先,您提供一个URL。 There are various methods to add content types, query parameters, timeouts, etc. to the request. 有多种方法可以向请求添加内容类型,查询参数,超时等。 Then you choose a request type and optionally add some content to send. 然后,您选择一个请求类型,并可选择添加一些要发送的内容。 Examples: 例子:

WSRequestHolder request = WS.url("http://example.com");
request.setQueryParameter("page", "1");
Promise<Response> promise = request.get();
Promise<Response> promise = WS.url("http://example.com").post(content);

The complicated part is to send it and use the response of the request. 复杂的部分是发送它并使用请求的响应。 I assume you have a controller that should return a Result to the user, based on the web service's response. 我假设您有一个控制器,应该根据Web服务的响应将Result返回给用户。 The result is usually a rendered template or maybe just a status code. 结果通常是渲染模板或可能只是状态代码。

Play avoids blocking by using Futures and Promises . 播放通过使用期货和承诺避免阻止。 The controller's async method takes a Promise<Result> and returns a result (the future value) at some point later. 控制器的async方法接受Promise<Result>并在稍后的某个时刻返回结果(未来值)。 A simple to use promise is provided by the get and post methods shown above. 上面显示的getpost方法提供了一个简单易用的承诺。 You don't need to care about their implementation, you just need to know that they promise to provide a Response once the request is complete. 您不需要关心它们的实现,只需要知道它们承诺在请求完成后提供Response

Notice the problem here: When creating a request with WS.url("...").get() it will give you a Promise<Response> even though async takes a Promise<Result> . 注意这里的问题:当用WS.url("...").get()创建一个请求时, WS.url("...").get()它会给你一个Promise<Response>即使async接受一个Promise<Result> Here you have to implement another promise yourself, which will convert the response to a result using the map method. 在这里,您必须自己实现另一个承诺,它将使用map方法将响应转换为结果。 If you follow the Play documentation, this will look a bit confusing, because Java doesn't has closures (yet) and everything has to be wrapped in a class. 如果您遵循Play文档,这看起来会有点令人困惑,因为Java没有闭包(但是)并且所有内容都必须包含在类中。 You don't have to use anonymous classes inside the method call though. 您不必在方法调用中使用匿名类。 If you prefer more clean code, you also can do it like this: 如果您更喜欢更干净的代码,您也可以这样做:

return async( 
  request                 
  .get()                   // returns a `Promise<Response>`
  .map(resultFromResponse) // map takes a `Function<Response, Result>` and
                           // returns the `Promise<Result>` we need
);

The object resultFromResponse may look like follows. 对象resultFromResponse可能如下所示。 It's actually just like a cumbersome definition of some kind of callback method that takes a Response as only argument and returns a Result . 它实际上就像某种回调方法的繁琐定义,它将Response作为唯一参数并返回Result

Function<Response, List<T>> resultFromResponse = 
    new Function<Response /* 1st parameter type */, Result /* return type */>() {
        @Override
        public Result apply(Response response) {
            // example: read some json from the response
            String message = response.asJson().get("message");
            Result result = ok(message);
            return result;
        }
    };

As @itsjeyd pointed out in the comments, when calling webservices in Play 2.2.x you don't wrap the call in async any more. 正如@itsjeyd在评论中指出的那样,当在Play 2.2.x中调用webservices时,你不再将该调用包装成async You simply return the Promise<Result> : 您只需返回Promise<Result>

public static Promise<Result> index() {
    return request.get().map(resultFromResponse);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM