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使用详解

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