【问题标题】:Should I use HttpURLConnection or RestTemplate [duplicate]我应该使用 HttpURLConnection 还是 RestTemplate [重复]
【发布时间】:2018-12-15 16:55:44
【问题描述】:

我应该在Spring 项目中使用HttpURLConnection 还是更好地使用RestTemplate? 换句话说,什么时候使用每个更好?

【问题讨论】:

    标签: java spring


    【解决方案1】:

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

    RestTemplate 有助于使用 REST api,HttpURLConnection 与 HTTP 协议一起使用。

    您在问什么更好用。答案取决于您要达到的目标:

    • 如果您需要使用REST api,请坚持使用RestTemplate
    • 如果您需要使用 http 协议,请使用 HttpURLConnectionOkHttpClient、Apache 的 HttpClient,或者如果您使用 Java 11,则可以尝试其 HttpClient

    此外,RestTemplate 使用 HttpUrlConnection/OkHttpClient/... 来完成其工作(请参阅 ClientHttpRequestFactorySimpleClientHttpRequestFactoryOkHttp3ClientHttpRequestFactory


    为什么不应该使用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 是苦行僧。

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


    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

    GETting 发帖:

    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:

    用于执行 HTTP 请求的同步客户端,通过底层 HTTP 客户端库(例如 JDK {@code HttpURLConnection}、Apache HttpComponents 等)公开一个简单的模板方法 API。

    让我们做同样的事情

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

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

    所以回答你的问题:

    什么时候使用每个更好?

    • 需要消耗REST api?使用RestTemplate
    • 需要使用 http 吗?使用一些HttpClient

    还值得一提:

    【讨论】:

      猜你喜欢
      • 2011-05-08
      • 2021-03-30
      • 1970-01-01
      • 2013-01-30
      • 2011-08-08
      • 2020-08-23
      • 2020-03-15
      • 1970-01-01
      • 2018-09-05
      相关资源
      最近更新 更多