rest客户端的Java?
有了JSR 311及其实现,我们有一个通过Rest展示Java对象的强大标准。 然而,在客户端,似乎缺less了与Apache Axis for SOAP相媲美的东西 – 这就隐藏了Web服务,并将数据透明地编组回Java对象。
你如何创buildJava RESTful客户端? 使用HTTPConnection并手动parsing结果? 或者是针对Jersey或Apache CXR的专业客户端?
这是一个老问题(2008),所以现在比以前有更多的select:
- Apache CXF有三个不同的REST客户端选项
- 泽西岛 (上面提到)。
- Spring也有自己的RestTemplate
- Commons HTTP Client为较旧的Java项目构build自己的。
更新大约在2014年:
-
Async-http-client by Sonatype。 Ning Async-http-client 。
提供NIO支持的新的孩子(虽然我真的不认为这真的提高了服务器的客户端性能)。
- Apache HTTP组件(4.2)Fluent适配器 – 比旧的Commons HTTP Client 3更好,并且更容易用于构build自己的REST客户端。 您必须使用类似Jackson的JSONparsing支持,并且可以使用HTTP组件URIBuilder来构造类似于Jersey / JAX-RS Rest客户端的资源URI 。 HTTP组件也支持NIO,但是由于REST的简短请求性质,我怀疑你会比BIO获得更好的性能。
2016年更新 :
- OkHttp – 支持更新的HTTP协议(SPDY和HTTP2)。 适用于Android。 不幸的是,它不提供真正的基于反应器循环的asynchronous选项(参见上面的Ning和HTTP组件)。 但是,如果您使用较新的HTTP2协议,这是一个问题较less(假设连接计数是问题)。
- 改造 – 将自动创build基于类似于泽西岛和CXF扩展的接口存根的客户端。 使用OkHttp。
- Apache HttpComponents 5将会拥有HTTP2的支持
关于selectHTTP / REST客户端的警告。 确保检查你的框架堆栈用于HTTP客户端,它是如何进行线程化的,并且最好使用相同的客户端(如果它提供的话)。 也就是说,如果你使用像Vert.x或者Play这样的东西,你可能想要使用它的支持客户端来参与框架提供的任何总线或者反应器循环,否则就要为可能有趣的线程问题做好准备。
正如我在这个线程中提到的,我倾向于使用实现了JAX-RS的Jersey ,并带有一个不错的REST客户端。 好的是,如果您使用JAX-RS实现RESTful资源,则Jersey客户端可以重用JAXB / XML / JSON / Atom等实体提供者 – 这样您就可以在服务器端重复使用相同的对象在客户端使用unit testing。
例如, 这里是 Apache Camel项目的 一个unit testing用例 ,它从RESTful资源(使用JAXB对象端点)查找XML负载。 资源(uri)方法在这个只使用Jersey客户端API的基类中定义。
例如
clientConfig = new DefaultClientConfig(); client = Client.create(clientConfig); resource = client.resource("http://localhost:8080"); // lets get the XML as a String String text = resource("foo").accept("application/xml").get(String.class);
顺便说一句,我希望未来版本的JAX-RS可以在Jersey中添加一个很好的客户端API
您可以使用标准的Java SE API:
private void updateCustomer(Customer customer) { try { URL url = new URL("http://www.example.com/customers"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setInstanceFollowRedirects(false); connection.setRequestMethod("PUT"); connection.setRequestProperty("Content-Type", "application/xml"); OutputStream os = connection.getOutputStream(); jaxbContext.createMarshaller().marshal(customer, os); os.flush(); connection.getResponseCode(); connection.disconnect(); } catch(Exception e) { throw new RuntimeException(e); } }
或者,您可以使用由JAX-RS实现(如Jersey)提供的REST客户端API。 这些API更容易使用,但需要在类path上添加额外的jar。
WebResource resource = client.resource("http://www.example.com/customers"); ClientResponse response = resource.type("application/xml");).put(ClientResponse.class, "<customer>...</customer."); System.out.println(response);
有关更多信息,请参阅
您还可以检查Restlet ,它具有完整的客户端function,更多面向REST的低层库(如HttpURLConnection或Apache HTTP Client(我们可以将其用作连接器))。
最好的问候,杰罗姆Louvel
如果您只希望调用REST服务并parsing响应,则可以尝试Rest Assured
// Make a GET request to "/lotto" String json = get("/lotto").asString() // Parse the JSON response List<String> winnderIds = with(json).get("lotto.winners.winnerId"); // Make a POST request to "/shopping" String xml = post("/shopping").andReturn().body().asString() // Parse the XML Node category = with(xml).get("shopping.category[0]");
你可以试试拉帕 。 让我们知道你的意见。 随时logging问题或预期的function。
我想指出2个更多的select:
- 基于VRaptornetworking框架的Restfulie具有非常好的超媒体支持,服务器端和客户端实现。
- RESTEasy有一个基于JAX-RS代理的客户端实现。
我最近从广场上试过Retrofit Library,它很棒,你可以很容易地调用你的rest API。 基于注释的configuration允许我们摆脱很多锅炉板的编码。
我使用Apache HTTPClient来处理事物的所有HTTP方面。
我为将XMLparsing为对象模型的XML内容编写XML SAXparsing器。 我相信Axis2也公开了XML – > Model方法(Axis 1很讨厌这个部分)。 XML生成器非常简单。
在我看来,编码并不需要很长时间,而且效率很高。
OkHttp与Retrofit结合使用时也是轻量级且强大的。 这适用于一般Java使用以及Android。
OkHttp : http : //square.github.io/okhttp/
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); OkHttpClient client = new OkHttpClient(); String post(String url, String json) throws IOException { RequestBody body = RequestBody.create(JSON, json); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); return response.body().string(); }
改造 : http : //square.github.io/retrofit/
public interface GitHubService { @GET("/users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); }
从jcabi-http尝试JdkRequest
(我是一个开发人员)。 这是如何工作的:
String body = new JdkRequest("http://www.google.com") .header("User-Agent", "it's me") .fetch() .body()
查看这个博客文章的更多细节: http : //www.yegor256.com/2014/04/11/jcabi-http-intro.html
现在有一段时间了,我一直在使用Resty :
JSONResource jsonResource = new Resty().json(uri);
在这里可以find一些例子。
我写了一个将java接口映射到远程JSON REST服务的库:
https://github.com/ggeorgovassilis/spring-rest-invoker
public interface BookService { @RequestMapping("/volumes") QueryResult findBooksByTitle(@RequestParam("q") String q); @RequestMapping("/volumes/{id}") Item findBookById(@PathVariable("id") String id); }
试着看看http-rest-client
https://github.com/g00dnatur3/http-rest-client
这是一个简单的例子:
RestClient client = RestClient.builder().build(); String geocoderUrl = "http://maps.googleapis.com/maps/api/geocode/json" Map<String, String> params = Maps.newHashMap(); params.put("address", "beverly hills 90210"); params.put("sensor", "false"); JsonNode node = client.get(geocoderUrl, params, JsonNode.class);
该库负责json序列化和绑定。
这是另一个例子,
RestClient client = RestClient.builder().build(); String url = ... Person person = ... Header header = client.create(url, person); if (header != null) System.out.println("Location header is:" + header.value());
最后一个例子,
RestClient client = RestClient.builder().build(); String url = ... Person person = client.get(url, null, Person.class); //no queryParams
干杯!
虽然它很简单,创build一个HTTP客户端,并作出任何要求。 但是如果你想利用一些自动生成的客户端,你可以使用WADL来描述和生成代码。
你可以使用RestDescribe来生成和编译WSDL,你可以使用这个在php,ruby,python,java和C#中生成客户端。 它生成干净的代码,并且在代码生成之后有一个很好的改变,你可以在这个工具背后find好的文档和底层的想法。
wintermute上提到了一些有趣而有用的WADL工具 。
你可以使用java.net.URL
public class URL { public URL(java.lang.String s) throws java.net.MalformedURLException {} public java.net.URLConnection openConnection() throws java.io.IOException {} ... }
从一个URL,你可以创build一个HttpURLConnection,允许你调用特定的
requests. Here's an example of doing a simple GET request: URL url = new URL("http://example.com/customers/1"); connection = (HttpURLConnection) getUrl.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "application/xml"); if (connection.getResponseCode() != 200) { throw new RuntimeExceptioin("Operation failed: " + connection.getResponseCode()); } System.out.println("Content-Type: " + connection.getContentType()); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line = reader.readLine(); while (line != null) { System.out.println(line); line = reader.readLine(); } connection.disconnect();
jersey的例子rest客户端:
添加依赖项:
<!-- jersey --> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-json</artifactId> <version>1.8</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> <version>1.8</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.8</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20090211</version> </dependency>
ForGetMethod并传递两个参数:
Client client = Client.create(); WebResource webResource1 = client .resource("http://localhost:10102/NewsTickerServices/AddGroup/" + userN + "/" + groupName); ClientResponse response1 = webResource1.get(ClientResponse.class); System.out.println("responser is" + response1);
GetMethod传递一个参数并获取列表的响应:
Client client = Client.create(); WebResource webResource1 = client .resource("http://localhost:10102/NewsTickerServices/GetAssignedUser/"+grpName); //value changed String response1 = webResource1.type(MediaType.APPLICATION_JSON).get(String.class); List <String > Assignedlist =new ArrayList<String>(); JSONArray jsonArr2 =new JSONArray(response1); for (int i =0;i<jsonArr2.length();i++){ Assignedlist.add(jsonArr2.getString(i)); }
在上面它返回一个列表,我们正在接受列表,然后将其转换为Json数组,然后将Json数组转换为列表。
如果Post Request传递Json对象作为参数:
Client client = Client.create(); WebResource webResource = client .resource("http://localhost:10102/NewsTickerServices/CreateJUser"); // value added ClientResponse response = webResource.type(MediaType.APPLICATION_JSON).post(ClientResponse.class,mapper.writeValueAsString(user)); if (response.getStatus() == 500) { context.addMessage(null, new FacesMessage("User already exist ")); }