Java中使用OkHttp進行Http通信 1. 引入依賴 2. 工具類代碼 3. 注意 附錄 推薦閱讀

提供一個OkHttp的工具類方法。

1. 引入依賴

<!-- 通信 -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.8.1</version>
</dependency>
<!-- 序列化方式-->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

2. 工具類代碼

工具類需要創建一個單例的OkHttp的客戶端。

import com.google.gson.Gson;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Base64;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


public class OkHttpUtil {
    public final static Logger logger = LoggerFactory.getLogger(OkHttpUtil.class);
    /**
     * 最大連接時間
     */
    public final static int CONNECTION_TIMEOUT = 5;
    /**
     * JSON格式
     */
    public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
    /**
     * OkHTTP線程池最大空閒線程數
     */
    public final static int MAX_IDLE_CONNECTIONS = 100;
    /**
     * OkHTTP線程池空閒線程存活時間
     */
    public final static long KEEP_ALIVE_DURATION = 30L;
    /**
     * GSON格式
     */
    public static final Gson GSON = new Gson();

    public static String BASE64_PREFIX = "data:image/png;base64,";

    /**
     * client
     * 配置重試
     */
    private final static OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
            .connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
            .connectionPool(new ConnectionPool(MAX_IDLE_CONNECTIONS, KEEP_ALIVE_DURATION, TimeUnit.MINUTES))
            .build();


    /**
     * get請求,無需轉換對象
     *
     * @param url     鏈接
     * @param headers 請求頭
     * @return 響應信息
     */
    public static String get(String url, Map<String, String> headers) {
        try {
            Request.Builder builder = new Request.Builder();
            buildHeader(builder, headers);
            Request request = builder.url(url).build();
            Response response = HTTP_CLIENT.newCall(request).execute();

            if (response.isSuccessful() && Objects.nonNull(response.body())) {
                String result = response.body().string();
                logger.info("執行get請求, url: {} 成功,返回數據: {}", url, result);
                return result;
            }
        } catch (Exception e) {
            logger.error("執行get請求,url: {} 失敗!", url, e);
        }
        return null;
    }


    /**
     * Form表單提交
     *
     * @param url    地址
     * @param params form參數
     * @return
     */
    public static String post(String url, Map<String, String> params) {
        try {

            FormBody.Builder builder = new FormBody.Builder();
            if (!CollectionUtils.isEmpty(params)) {
                params.forEach(builder::add);
            }
            FormBody body = builder.build();
            Request request = new Request.Builder().url(url).post(body).build();
            Response response = HTTP_CLIENT.newCall(request).execute();
            //調用成功
            if (response.isSuccessful() && response.body() != null) {
                return response.body().string();
            }
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }


    /**
     * 簡單post請求
     *
     * @param url     請求url
     * @param headers 請求頭
     * @param json    請求參數
     * @return
     */
    public static String post(String url, Map<String, String> headers, String json) {
        try {
            RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
            Request.Builder builder = new Request.Builder();
            buildHeader(builder, headers);
            Request request = builder.url(url).post(body).build();
            Response response = HTTP_CLIENT.newCall(request).execute();
            if (response.isSuccessful() && Objects.nonNull(response.body())) {
                String result = response.body().string();
                logger.info("執行post請求,url: {}, header: {} ,參數: {} 成功,返回結果: {}", url, headers, json, result);
                return result;
            }
        } catch (Exception e) {
            logger.error("執行post請求,url: {},參數: {} 失敗!", url, json, e);
        }
        return null;
    }


    /**
     * 設置請求頭
     *
     * @param builder .
     * @param headers 請求頭
     */
    private static void buildHeader(Request.Builder builder, Map<String, String> headers) {
        if (Objects.nonNull(headers) && headers.size() > 0) {
            headers.forEach((k, v) -> {
                if (Objects.nonNull(k) && Objects.nonNull(v)) {
                    builder.addHeader(k, v);
                }
            });
        }
    }


    /**
     * 支持嵌套泛型的post請求。
     * <pre>
     *   Type type = new TypeToken<Results<User>>() {}.getType();
     * <pre/>
     *
     * @param url     鏈接
     * @param headers 請求頭
     * @param json    請求json
     * @param type    嵌套泛型
     * @return 響應對象, 可進行強轉。
     */
    public static <T> T post(String url, Map<String, String> headers, String json, Type type) {
        String result = post(url, headers, json);
        if (Objects.nonNull(result) && Objects.nonNull(type)) {
            return GSON.fromJson(result, type);
        }
        return null;
    }
    /**
     * 讀取流,轉換爲Base64
     * 返回base64的照片
     */
    public static String postImg(String url, Map<String, String> headers, String json) {
        RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
        Request.Builder builder = new Request.Builder();
        buildHeader(builder, headers);
        Request request = builder.url(url).post(body).build();
        try {
            Response response = HTTP_CLIENT.newCall(request).execute();
            String contentType = null;
            if (response.body() != null && response.body().contentType() != null) {
                contentType = response.body().contentType().toString();
            }
            if ("image/png".equals(contentType)) {
                //讀取流
                return BASE64_PREFIX + new String(Base64.getEncoder().encode(response.body().bytes()));
            }
        } catch (IOException e) {
            logger.error("", e);
        }
        return null;
    }


    /**
     * 異步獲取照片地址
     */
    public static void downloadImg(String url, String json) {
        RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);

        Request request = new Request.Builder().url(url).post(body).build();

        Call call = HTTP_CLIENT.newCall(request);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //打印異常
                logger.error("", e);
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String s = BASE64_PREFIX + new String(Base64.getEncoder().encode(response.body().bytes()));
                logger.info(s);
            }
        });

    }
}

3. 注意

3.1 Response讀取響應結果

可以通過Response的code來判斷請求是否成功,如果服務器返回的有數據,可以通過Response的body得到一個ResponseBody讀取。

  • response.body().string()一次性將響應體的信息全部讀取並轉換爲String格式;
  • response.body().bytes()一次性讀取響應體的信息到byte[]數組中。

如果數據超過1MB可能會報內存溢出,所以對於超過1MB的數據,建議採用流的方式去讀取,如ResponseBody的byteStream()方法。

OkHttp調用微信小程序二維碼接口照片是黑屏

附錄

  • 被調用者代碼
import com.alibaba.fastjson.JSON;
import com.tellme.pojo.Results;
import com.tellme.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

@Slf4j
@RestController
public class TestOkHttp {

    /**
     * get請求
     */
    @GetMapping("/test/server")
    public String getMsg() {
        return "這是OkHttp的請求";
    }

    /**
     * form表單
     */
    @PostMapping("/test/form")
    public String getFormMsg(User user) {
        log.info(JSON.toJSONString(user));
        return "這是Form的請求" + JSON.toJSONString(user);
    }

    /**
     * post請求
     */
    @PostMapping("/test/user")
    public User getUser(@RequestBody User user) {
        log.info(JSON.toJSONString(user));
        return user;
    }

    /**
     * post請求
     */
    @PostMapping("/test/result")
    public Results getResult(@RequestBody User user) {
        Results<User> results = new Results<>();
        results.setCode(200);
        results.setStatus("OK");
        results.setData(user);
        return results;
    }

    /**
     * 返回照片
     */
    @PostMapping("/test/img")
    public void getResult(HttpServletRequest request,
                          HttpServletResponse response) {
        try {
            File file = new File("/Users/yexuerui/Downloads/二維碼池改造.png");
            FileInputStream inputStream = new FileInputStream(file);
            byte[] data = new byte[(int) file.length()];
            //信息從文件輸入到JVM的數組中
            inputStream.read(data);
            inputStream.close();
            response.setContentType("image/png");
            ServletOutputStream outputStream = response.getOutputStream();
            //信息從JVM的數組輸出到
            outputStream.write(data);
            outputStream.close();
        } catch (FileNotFoundException e) {
            log.error("", e);
        } catch (IOException e) {
            log.error("", e);
        }
    }
}
  • 調用者代碼
@Slf4j
@RestController
public class TestOkHttpController {


    @GetMapping("/test/okHttp")
    public String sendMsg() {
        String url = "http://localhost:8010/test/server";
        Map<String, String> header = new HashMap<>();
        return OkHttpUtil.get(url, header);
    }

    @GetMapping("/test/form")
    public String sendForm() {
        String url = "http://localhost:8010/test/form";
        Map<String, String> params = new HashMap<>();
        params.put("name", "libai");
        params.put("age", "1");
        return OkHttpUtil.post(url, params);
    }


    @GetMapping("/test/user")
    public String sendUser() {
        String url = "http://localhost:8010/test/user";
        User user=new User();
        user.setName("平安");
        user.setAge(12);
        return OkHttpUtil.post(url, null, JSON.toJSONString(user));
    }

    //帶有嵌套泛型的對象
    @GetMapping("/test/result")
    public void sendResult() {
        String url = "http://localhost:8010/test/result";
        User user=new User();
        user.setName("平安");
        user.setAge(12);

        Results<User> results = OkHttpUtil.post(url, null, JSON.toJSONString(user), new TypeToken<Results<User>>() {
        }.getType());
        log.info(JSON.toJSONString(results));
    }


    @GetMapping("/test/img")
    public String sendImg() {
        String url = "http://localhost:8010/test/img";
        return OkHttpUtil.postImg(url, null, "{}");
    }
    //異步調用
    @GetMapping("/test/sync/img")
    public void sendSyncImg() {
        String url = "http://localhost:8010/test/img";
        OkHttpUtil.downloadImg(url,  "{}");
        log.info("請求結束");
    }
}

推薦閱讀

重識OkHttp——更深入瞭解如何使用

OkHttp使用詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章