有了JSR 311及其实现,我们有了一个强大的标准,可以通过REST公开Java对象。但是,在客户端,似乎缺少与SOAP的Apache Axis类似的东西-隐藏了Web服务并将数据透明地封送回Java对象的东西。
您如何创建Java RESTful客户端?使用HTTPConnection和手动解析结果?还是专业客户(例如Jersey或Apache CXR)?
有了JSR 311及其实现,我们有了一个强大的标准,可以通过REST公开Java对象。但是,在客户端,似乎缺少与SOAP的Apache Axis类似的东西-隐藏了Web服务并将数据透明地封送回Java对象的东西。
您如何创建Java RESTful客户端?使用HTTPConnection和手动解析结果?还是专业客户(例如Jersey或Apache CXR)?
Answers:
这是一个古老的问题(2008年),所以现在有比以前更多的选择:
更新(项目在2020年仍处于活动状态):
关于选择HTTP / REST客户端的警告。确保检查您的框架堆栈用于HTTP客户端的方式,如何进行线程化,并且如果提供了该客户端,最好使用相同的客户端。那就是说,如果您使用Vert.x或Play之类的东西,则可能希望尝试使用其支持客户端来参与框架提供的任何总线或反应堆循环...否则,为可能发生的有趣线程问题做好准备。
正如我在该线程中提到的那样,我倾向于使用实现JAX-RS并带有一个不错的REST客户端的Jersey。不错的事情是,如果您使用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版本能像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易于使用,但在类路径上需要其他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);
有关更多信息,请参见:
如果您只想调用REST服务并解析响应,则可以尝试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]");
我想指出另外2个选项:
JdkRequest
从jcabi-http(我是开发人员)尝试。它是这样工作的:
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
我最近尝试了Square的Retrofit库,它很棒,您可以非常轻松地调用rest API。基于注释的配置使我们摆脱了很多样板代码。
我使用Apache HTTPClient处理所有HTTP方面的事情。
我为XML内容编写了XML SAX解析器,该解析器将XML解析为您的对象模型。我相信Axis2还公开了XML-> Model方法(Axis 1烦人地隐藏了这部分)。XML生成器非常简单。
我认为编写代码不会花很长时间,而且效率很高。
与Retrofit结合使用时,OkHttp既轻巧又强大。这对于一般的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);
}
既然没有人提及,这里是另一种:Feign,由Spring Cloud使用。
虽然创建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);
}
尝试查看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 Array,然后将其转换为List。
如果Post Request将Json Object作为参数传递:
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 "));
}
我大部分时间都使用RestAssured来解析rest服务响应并测试服务。除了“确保放心”外,我还使用以下库与Resful服务进行通信。
一个。泽西岛休息客户
我目前正在使用https://github.com/kevinsawicki/http-request,我喜欢它们的简单性和示例的显示方式,但是当我阅读以下内容时,我大多被卖掉了:
有哪些依赖性?
没有。该库的目标是成为带有某些内部静态类的单个类。测试项目确实需要Jetty才能针对实际的HTTP服务器实现测试请求。
它解决了Java 1.6项目中的一些问题。至于将json解码为对象,gson就是无敌的:)