如何为Java创建REST客户端?

通过JSR 311及其实现,我们有了一个通过REST公开Java对象的强大标准。然而,在客户端,似乎缺少了一些类似于Apache Axis for SOAP的东西——隐藏web服务并将数据透明地封送回Java对象的东西。

如何创建Java RESTful客户端?使用HTTPConnection和手动解析结果?或者专门的客户端,例如Jersey或Apache CXR?

408393 次浏览

我使用Apache HTTPClient来处理所有HTTP方面的事情。

我为XML内容编写XML SAX解析器,用于将XML解析为对象模型。我认为Axis2还公开了XML -> Model方法(Axis 1隐藏了这一部分,令人恼火)。XML生成器非常简单。

在我看来,它不需要很长时间来编码,而且非常高效。

正如我在这个线程中提到的,我倾向于使用泽西岛,它实现了JAX-RS,并附带了一个很好的REST客户端。好的事情是,如果您使用JAX-RS实现RESTful资源,那么Jersey客户端可以重用JAXB/XML/JSON/Atom等实体提供程序,因此您可以在服务器端重用与在客户端单元测试中使用相同的对象。

例如,下面是一个单元测试用例来自Apache Camel项目,它从RESTful资源(使用JAXB对象Endpoints)中查找XML有效负载。resource(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添加一个很好的客户端API,就像Jersey的那样

你也可以检查Restlet,它具有完整的客户端功能,比HttpURLConnection或Apache HTTP Client(我们可以利用它们作为连接器)等底层库更面向REST。

< p >最诚挚的问候, 杰罗姆Louvel < / p >
你可以试试拉伯。让我们知道你的反馈。

您可以使用标准的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更容易使用,但在类路径上需要额外的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);

有关更多信息,请参阅:

这是一个老问题(2008年),所以现在的选择比当时多得多:

  • Apache CXF有三个不同的REST客户端选项
  • 球衣(上面提到的)。
  • Spring RestTemplate春天WebClient取代
  • 公共HTTP客户端 . Apache HTTP Components (4.2) Fluent适配器 - JDK的基本替换,被这个列表中的其他几个候选JDK使用。比旧的Commons HTTP Client 3更好,更容易用于构建自己的REST客户端。你必须使用类似Jackson JSON解析支持的东西,你可以使用类似于Jersey/JAX-RS Rest客户端的HTTP组件URIBuilder用于构造资源uri。HTTP组件也支持NIO,但考虑到REST的短请求特性,我怀疑您能否获得比BIO更好的性能。Apache HttpComponents 5支持HTTP/2。
  • OkHttp - JDK的基本替换,类似于http组件,在这个列表中被其他几个候选组件使用。支持更新的HTTP协议(SPDY和HTTP2)。适用于Android。不幸的是,它没有提供一个真正的基于反应器循环的异步选项(参见上面的Ning和HTTP组件)。然而,如果你使用更新的HTTP2协议,这就不是什么问题了(假设连接数是问题)。
  • Ning Async-http-client -提供NIO支持。以前称为Async-http-client by Sonatype
  • 底层http客户端的假的包装器(okhttp, apache httpcomponents)。基于类似于某些Jersey和CXF扩展的接口存根自动创建客户端。强弹簧集成。
  • < a href = " http://square.github。io /改进/ noreferrer“rel = >改造< / > -底层http客户端的包装器(okhttp)。基于类似于某些Jersey和CXF扩展的接口存根自动创建客户端。
  • 截击 .包装器为jdk http客户端,由谷歌
  • google-http包装器用于jdk http客户端或apache httpcomponents
  • Unirest包装jdk http客户端,由kong
  • Resteasy JakartaEE包装器用于jdk http客户端,由jboss, jboss框架的一部分
  • apache httpcomponents的jcabi-http包装器,jcabi集合的一部分
  • apache httpcomponents的restlet包装器,restlet框架的一部分
  • 放心包装器与断言,便于测试

关于选择HTTP/REST客户端的一个警告。确保检查你的框架栈为HTTP客户端使用了什么,它是如何执行线程的,如果它提供了一个客户端,最好使用相同的客户端。这是如果你使用像Vert。你可能想尝试使用它的后台客户端来参与框架提供的任何总线或反应器循环…否则,请为可能出现的有趣的线程问题做好准备。

如果你只想调用REST服务并解析响应,你可以尝试请放心

// 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]");

我想指出另外两个选项:

试试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

尽管创建一个HTTP客户端并进行重新测试很简单。但是如果你想利用一些自动生成的客户端,你可以使用WADL来描述和生成代码。

您可以使用RestDescribe来生成和编译WSDL,您可以使用它在php、ruby、python、java和c#中生成客户端。它可以生成干净的代码,并且在代码生成之后,你必须对它进行一些调整,你可以在在这里工具背后找到良好的文档和潜在的思想。

在wintermute中提到了一些有趣和有用的WADL工具

我写了一个库,将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);
}

我最近从square尝试了改造库,它很棒,你可以很容易地调用你的rest API。 基于注释的配置使我们摆脱了大量的锅炉板编码

试着看看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

干杯!

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传递一个参数并获取List的响应:

       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 "));
}

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);
}

由于没有人提到,这里有另一个:假装,由春云使用。

我大部分时间使用RestAssured来解析其余服务响应和测试服务。除了Rest Assured之外,我还使用下面的库来与Resful服务进行通信。

一。Jersey Rest客户端

b。Spring创建RestTemplate

c。Apache HTTP客户端

我目前正在使用https://github.com/kevinsawicki/http-request,我喜欢他们的简单性和示例显示的方式,但当我读到:

依赖关系是什么?

一个也没有。这个库的目标是成为带有一些内部静态类的单个类。测试项目确实需要Jetty,以便根据实际的HTTP服务器实现测试请求。

这解决了Java 1.6项目中的一些问题。至于将json解码为对象,gson是无敌的:)