java - 我应该使用 HttpURLConnection 还是 RestTemplate

标签 java spring

我应该使用 HttpURLConnectionSpring项目或者更好用RestTemplate ? 换句话说,什么时候使用每个更好?

最佳答案

HttpURLConnection RestTemplate 是不同种类的野兽。它们在不同的抽象级别上运行。

RestTemplate有助于消耗 REST API 和 HttpURLConnection使用 HTTP 协议(protocol)。

您问的是用什么更好。答案取决于您想要实现的目标:

  • 如果您需要消费REST api 然后坚持 RestTemplate
  • 如果您需要使用 http 协议(protocol),请使用 HttpURLConnection OkHttpClient , Apache 的HttpClient ,或者如果您使用的是 Java 11,您可以尝试其 HttpClient .

此外RestTemplate使用HttpUrlConnection/OkHttpClient/... 完成其工作(参见 ClientHttpRequestFactory SimpleClientHttpRequestFactory OkHttp3ClientHttpRequestFactory

<小时/>

为什么你不应该使用HttpURLConnection

最好展示一些代码:

在下面的示例中JSONPlaceholder使用过

让我们GET一个帖子:

public static void main(String[] args) {
  URL url;
  try {
    url = new URL("https://jsonplaceholder.typicode.com/posts/1");
  } catch (MalformedURLException e) {
    // Deal with it.
    throw new RuntimeException(e);
  }
  HttpURLConnection connection = null;
  try {
    connection = (HttpURLConnection) url.openConnection();
    try (InputStream inputStream = connection.getInputStream();
         InputStreamReader isr = new InputStreamReader(inputStream);
         BufferedReader bufferedReader = new BufferedReader(isr)) {
      // Wrap, wrap, wrap

      StringBuilder response = new StringBuilder();
      String line;
      while ((line = bufferedReader.readLine()) != null) {
        response.append(line);
      }
      // Here is the response body
      System.out.println(response.toString());
    }

  } catch (IOException e) {
    throw new RuntimeException(e);
  } finally {
    if (connection != null) {
      connection.disconnect();
    }
  }
}

现在让我们POST发布内容:

connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-type", "application/json; charset=UTF-8");

try (OutputStream os = connection.getOutputStream();
     OutputStreamWriter osw = new OutputStreamWriter(os);
     BufferedWriter wr = new BufferedWriter(osw)) {
  wr.write("{\"title\":\"foo\", \"body\": \"bar\", \"userId\": 1}");
}

如果需要响应:

try (InputStream inputStream = connection.getInputStream();
     InputStreamReader isr = new InputStreamReader(inputStream);
     BufferedReader bufferedReader = new BufferedReader(isr)) {
  // Wrap, wrap, wrap

  StringBuilder response = new StringBuilder();
  String line;
  while ((line = bufferedReader.readLine()) != null) {
    response.append(line);
  }

  System.out.println(response.toString());
}

可以看到 HttpURLConnection 提供的 api是苦行僧。

你总是要处理“低级”InputStream , Reader , OutputStream , Writer ,但幸运的是还有其他选择。

<小时/>

OkHttpClient

OkHttpClient减轻疼痛:

GET正在发帖:

OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
    .url("https://jsonplaceholder.typicode.com/posts/1")
    .build();
Call call = okHttpClient.newCall(request);
try (Response response = call.execute();
     ResponseBody body = response.body()) {

  String string = body.string();
  System.out.println(string);
} catch (IOException e) {
  throw new RuntimeException(e);
}

POST发表帖子:

Request request = new Request.Builder()
    .post(RequestBody.create(MediaType.parse("application/json; charset=UTF-8"),
        "{\"title\":\"foo\", \"body\": \"bar\", \"userId\": 1}"))
    .url("https://jsonplaceholder.typicode.com/posts")
    .build();

Call call = okHttpClient.newCall(request);

try (Response response = call.execute();
     ResponseBody body = response.body()) {

  String string = body.string();
  System.out.println(string);
} catch (IOException e) {
  throw new RuntimeException(e);
}

容易多了,对吧?

Java 11 的 HttpClient

GET编辑帖子:

HttpClient httpClient = HttpClient.newHttpClient();

HttpResponse<String> response = httpClient.send(HttpRequest.newBuilder()
    .uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
    .GET()
    .build(), HttpResponse.BodyHandlers.ofString());

System.out.println(response.body());

POST发表帖子:

HttpResponse<String> response = httpClient.send(HttpRequest.newBuilder()
    .header("Content-Type", "application/json; charset=UTF-8")
    .uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
    .POST(HttpRequest.BodyPublishers.ofString("{\"title\":\"foo\", \"body\": \"barzz\", \"userId\": 2}"))
    .build(), HttpResponse.BodyHandlers.ofString());
<小时/>

RestTemplate

根据其javadoc:

Synchronous client to perform HTTP requests, exposing a simple, template method API over underlying HTTP client libraries such as the JDK {@code HttpURLConnection}, Apache HttpComponents, and others.

我们也做同样的事情

首先为了方便起见Post类已创建。 (当 RestTemplate 读取响应时,它会使用 Post 将其转换为 HttpMessageConverter )

public static class Post {
  public long userId;
  public long id;
  public String title;
  public String body;

  @Override
  public String toString() {
    return new ReflectionToStringBuilder(this)
        .toString();
  }
}

GET发帖。

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Post> entity = restTemplate.getForEntity("https://jsonplaceholder.typicode.com/posts/1", Post.class);
Post post = entity.getBody();
System.out.println(post);

POST发表帖子:

public static class PostRequest {
  public String body;
  public String title;
  public long userId;
}

public static class CreatedPost {
  public String body;
  public String title;
  public long userId;
  public long id;

  @Override
  public String toString() {
    return new ReflectionToStringBuilder(this)
        .toString();
  }
}

public static void main(String[] args) {

  PostRequest postRequest = new PostRequest();
  postRequest.body = "bar";
  postRequest.title = "foo";
  postRequest.userId = 11;


  RestTemplate restTemplate = new RestTemplate();
  CreatedPost createdPost = restTemplate.postForObject("https://jsonplaceholder.typicode.com/posts/", postRequest, CreatedPost.class);
  System.out.println(createdPost);
}
<小时/>

所以回答你的问题:

When it is better to use each ?

  • 需要消耗REST应用程序编程接口(interface)?使用RestTemplate
  • 需要使用 http 吗?使用一些HttpClient .
<小时/>

还值得一提的是:

关于java - 我应该使用 HttpURLConnection 还是 RestTemplate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53795268/

相关文章:

java - 是否可以为 @Valid 参数异常创建多个自定义验证消息?

java - 如何创建包含多个单个字母的随机长度字符串?

java - 如何使用外部映射将 json 转换为 json

java - 使用 MapStruct 将 2 个字符串字段映射到 OffsetDateTime

java - HTTP 状态 500 - 实例化 servlet 类 org.springframework.web.servlet.DispatcherServlet 时出错

java - 缺少后退按钮 Material 主题

java - openGL 中的 VBO

java - Chromecast-ing 一个 WebView?

java - 在 Spring Boot 中使用 JWT 进行简单例份验证

java - bean 的 Autowiring 问题