springboot使用okhttp实现POSTGET同步和异步下载请求

springboot使用okhttp实现POSTGET同步和异步下载请求

  • 整体描述
  • 具体实现
    • 1. 引入okhttp的maven
    • 2. 创建OkHttp回调类
    • 3. 创建上传下载回调类
      • 1. 上传文件回调类
      • 2. 下载文件回调类
    • 4. 创建OkHttp基础类
    • 5. 业务层逻辑
      • 1. 上传单个文件,异步请求,binary-stream方式
      • 2.上传单个文件,异步请求,form-data方式
      • 3.下载文件方法,同步请求
      • 4.下载文件方法,异步请求
      • 5.POST方法,同步请求
      • 6.GET方法,同步请求
    • 6. 后续处理

整体描述

在springboot框架中使用okhttp实现post和get请求,有时候请求时间过长,可以使用同步和异步的方式,同步请求时间过长可以使用单独线程,避免主页面卡顿。
本文主要对Okhttp进行二次封装,方便在工程中直接调用。

具体实现

1. 引入okhttp的maven

okhttp有一些基于kotlin的代码,还有引入一个kotlin的资源:

        
        
            com.squareup.okhttp3
            okhttp
            4.7.2
        
        
            com.squareup.okio
            okio
            2.7.0-alpha.lockfree.2
        
        
        
            org.jetbrains.kotlin
            kotlin-stdlib
            1.3.50
        

2. 创建OkHttp回调类

此类用于处理Okhttp的返回结果,分为完成和失败。

public interface ServiceListener {

    /**
     * onCompleted
     * @param data
     */
    void onCompleted(String data);

    /**
     * onError
     * @param msg
     */
    void onError(String msg);

}

3. 创建上传下载回调类

创建上传和下载的回调类,用于接收上传文件和下载文件的结果。

1. 上传文件回调类

public interface FileUploadListener {

    /**
     * 下载完成回调
     *
     * @param fileUploadResponse 下载完成信息
     */
    void onCompleted(FileUploadResponse fileUploadResponse);

    /**
     * 下载错误回调
     *
     * @param msg 下载错误信息
     */
    void onError(String msg);
}

2. 下载文件回调类

public interface FileDownloadListener {

    /**
     * 下载成功之后的文件
     *
     * @param file 下载的文件
     */
    void onDownloadSuccess(File file);

    /**
     * 下载进度
     *
     * @param progress 下载进度
     */
    void onDownloading(int progress);

    /**
     * 下载异常信息
     *
     * @param e 异常
     */
    void onDownloadFailed(Exception e);
}

4. 创建OkHttp基础类

此类用于二次封装okhttp方法,其中包括port,get,上传下载,同步异步等。具体每个方法都有注释,就不特别说明了。
以上两个类一般放在commom包中,以便在业务层调用。

public class OkHttpUtils {

    private static final Logger log = LoggerFactory.getLogger(OkHttpUtils.class);

    private static final OkHttpClient OK_HTTP_CLIENT;

    private static final CloseableHttpClient CLOSEABLE_HTTP_CLIENT;

    private static final String STATUS_CODE = "HTTP STATUS CODE:";

    public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");

    public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");

    static {
        // 创建okHttpClient
        OK_HTTP_CLIENT = new OkHttpClient
                .Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .build();

        // 创建closeableHttpClient
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        CLOSEABLE_HTTP_CLIENT = httpClientBuilder.build();
    }

    /**
     * get请求
     */
    public static String get(String url) throws IOException {
        String result = "";
        Request request = new Request.Builder().url(url).build();
        try (Response response = OK_HTTP_CLIENT.newCall(request).execute()) {
            if (response.isSuccessful()) {
                result = response.body().string();
            }
        }
        return result;
    }

    /**
     * post请求,body通过form格式请求
     *
     * @param url           请求地址
     * @param authorization 请求头验证
     * @param bodyParamMap  请求Body
     */
    public static String post(String url, String authorization, Map bodyParamMap) throws IOException {
        String result = "";
        FormBody.Builder builder = new FormBody.Builder();
        if (bodyParamMap != null && bodyParamMap.size() > 0) {
            for (String key : bodyParamMap.keySet()) {
                builder.add(key, bodyParamMap.get(key));
            }
        }
        RequestBody formBody = builder.build();
        Request request = new Request
                .Builder()
                .addHeader("content-type", "application/x-www-form-urlencoded")
                .addHeader("Authorization", authorization)
                .url(url)
                .post(formBody)
                .build();
        try (Response response = OK_HTTP_CLIENT.newCall(request).execute();
             InputStream inputStream = response.body().byteStream();
             BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
            log.debug(STATUS_CODE + response.code());
            StringBuilder buffer = new StringBuilder();
            String str;
            while ((str = br.readLine()) != null) {
                buffer.append(str);
            }
            result = buffer.toString();
        }
        return result;
    }

    /**
     * post请求,body通过json格式请求
     *
     * @param url           请求地址
     * @param authorization 请求头验证,取消
     * @param sRequestBody  请求Body
     */
    public static String post(String url, String authorization, String sRequestBody) throws IOException {
        String result = "";
        RequestBody body = RequestBody.create(sRequestBody,MEDIA_TYPE_JSON);
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Authorization", authorization)
                .post(body)
                .build();
        try (Response response = OK_HTTP_CLIENT.newCall(request).execute()) {
            log.debug(STATUS_CODE + response.code());
            if (response.isSuccessful()) {
                result = response.body().string();
            }
        }
        return result;
    }

    /**
     * 上传单个文件
     * 同步请求,form-data方式
     *
     * @param url           请求地址
     * @param authorization 请求头验证
     * @param file          文件
     */
    public static String uploadFileSynchronize(String url, String authorization, File file) throws IOException {
        String result = "";
        RequestBody fileBody = RequestBody.create(file, MediaType.parse("application/octet-stream"));
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("mfile", file.getName(), fileBody)
                .addFormDataPart("type", "png")
                .build();
        Request request = new Request.Builder()
                .url(url)
                .addHeader("content-type", "multipart/form-data")
                .addHeader("Authorization", authorization)
                .post(requestBody)
                .build();
        try (Response response = OK_HTTP_CLIENT.newCall(request).execute()) {
            log.debug(STATUS_CODE + response.code());
            if (response.isSuccessful()) {
                result = Objects.requireNonNull(response.body()).string();
            }
        }
        return result;
    }

    /**
     * post请求,上传单个文件
     * 异步请求
     * 此方法时间可能较长,使用单独线程将结果放在回调中返回
     *
     * @param url             请求地址
     * @param authorization   请求头验证
     * @param file            文件
     * @param serviceListener 请求结果回调
     */
    public static void uploadFileAsynchronous(String url, String authorization, File file, ServiceListener serviceListener) {
        RequestBody fileBody = RequestBody.create(file, MediaType.parse("application/octet-stream"));
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("mfile", file.getName(), fileBody)
                .addFormDataPart("type", "png")
                .build();

        Request request = new Request.Builder()
                .url(url)
                .addHeader("content-type", "multipart/form-data")
                .addHeader("Authorization", authorization)
                .post(requestBody)
                .build();
        OK_HTTP_CLIENT.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                serviceListener.onError(e.getMessage());
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                try (InputStream inputStream = response.body().byteStream();
                     BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
                    log.debug(STATUS_CODE + response.code());
                    StringBuilder buffer = new StringBuilder();
                    String str;
                    while ((str = br.readLine()) != null) {
                        buffer.append(str);
                    }
                    serviceListener.onCompleted(buffer.toString());
                } catch (IOException e) {
                    log.error(e.toString());
                    serviceListener.onError(e.getMessage());
                }
            }
        });
    }

    /**
     * post请求,上传多个文件
     * 此方法时间可能较长,使用单独线程将结果放在回调中返回
     *
     * @param url             请求地址
     * @param authorization   请求头验证
     * @param fileNames       文件完整路径
     * @param serviceListener 请求结果回调
     */
    public static void uploadFilesAsynchronous(String url, String authorization, List fileNames, ServiceListener serviceListener) {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        for (String fileName : fileNames) {
            File file = new File(fileName);
            RequestBody requestBody = RequestBody.create(file, MediaType.parse("application/octet-stream"));
            builder.addFormDataPart("mfile", file.getName(), requestBody);
        }
        Request request = new Request.Builder()
                .url(url)
                .addHeader("content-type", "multipart/form-data")
                .addHeader("Authorization", authorization)
                .post(builder.build())
                .build();
        OK_HTTP_CLIENT.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                serviceListener.onError(e.getMessage());
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                try (InputStream inputStream = response.body().byteStream();
                     BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
                    log.debug(STATUS_CODE + response.code());
                    StringBuilder buffer = new StringBuilder();
                    String str;
                    while ((str = br.readLine()) != null) {
                        buffer.append(str);
                    }
                    serviceListener.onCompleted(buffer.toString());
                } catch (IOException e) {
                    log.error(e.toString());
                    serviceListener.onError(e.getMessage());
                }
            }
        });
    }

    /**
     * 下载文件
     * 异步请求
     *
     * @param url          下载连接
     * @param destFileDir  下载的文件储存目录
     * @param destFileName 下载文件名称,后面记得拼接后缀
     * @param listener     下载监听
     */
    public static void downloadFilesAsynchronous(String url, String destFileDir, String destFileName, FileDownloadListener listener) {

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

        //异步请求
        OK_HTTP_CLIENT.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                // 下载失败监听回调
                listener.onDownloadFailed(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                //储存下载文件的目录
                File dir = new File(destFileDir);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(dir, destFileName);
                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    fos = new FileOutputStream(file);
                    long sum = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        //下载中更新进度条
                        listener.onDownloading(progress);
                    }
                    fos.flush();
                    //下载完成
                    listener.onDownloadSuccess(file);
                } catch (Exception e) {
                    listener.onDownloadFailed(e);
                } finally {

                    try {
                        if (is != null) {
                            is.close();
                        }
                        if (fos != null) {
                            fos.close();
                        }
                    } catch (IOException e) {

                    }

                }
            }
        });
    }

    /**
     * 下载文件
     * 同步请求
     *
     * @param url          下载连接
     * @param destFileDir  下载的文件储存目录
     * @param destFileName 下载文件名称,后面记得拼接后缀
     */
    public static String downloadSynchronize(String url, String destFileDir, String destFileName) throws IOException {
        String result = "";
        Request request = new Request.Builder()
                .url(url)
                .build();

        try (Response response = OK_HTTP_CLIENT.newCall(request).execute()) {
            InputStream is = null;
            byte[] buf = new byte[2048];
            int len = 0;
            FileOutputStream fos = null;
            //储存下载文件的目录
            log.info("filePath:" + destFileDir + destFileName);
            File dir = new File(destFileDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            File file = new File(dir, destFileName);
            try {
                is = response.body().byteStream();
                long total = response.body().contentLength();
                fos = new FileOutputStream(file);
                long sum = 0;
                while ((len = is.read(buf)) != -1) {
                    fos.write(buf, 0, len);
                    sum += len;
                    int progress = (int) (sum * 1.0f / total * 100);
                    //下载中更新进度条
                }
                fos.flush();
                //下载完成
                result = file.getPath();
                log.info("downloadSynchronize finish:{}", file.getPath());
            } catch (Exception e) {
                log.info("downloadSynchronize error:{}", e.getMessage());
            } finally {
                log.info("downloadSynchronize finally");
                try {
                    if (is != null) {
                        is.close();
                    }
                    if (fos != null) {
                        fos.close();
                    }
                } catch (IOException e) {
                    log.info("downloadSynchronize IOException:{}", e.getMessage());
                }

            }
        }
        return result;
    }

    /**
     * 根据地址获得数据的输入流,以数据流方式上传
     *
     * @param host            上传host
     * @param imgUrl          文件url
     * @param authorization   请求头验证
     * @param serviceListener 请求结果回调
     */
    public static void uploadFileStreamAsynchronous(String host, String imgUrl, String authorization, ServiceListener serviceListener) {
        HttpPost post = new HttpPost(host);
        InputStream inputStream = null;
        post.setHeader("content-type", "application/octet-stream");
        post.setHeader("Authorization", authorization);
        try {
            inputStream = getInputStreamByUrl(imgUrl);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            builder.addBinaryBody("mfile", inputStream, ContentType.create("multipart/form-data"), "wKgBP2CwWGuAPWdJAAvySPq-Jpo973.jpg");
            //4)构建请求参数 普通表单项
            HttpEntity entity = builder.build();
            post.setEntity(entity);
            //发送请求
            HttpResponse response = CLOSEABLE_HTTP_CLIENT.execute(post);
            entity = response.getEntity();
            if (entity != null) {
                inputStream = entity.getContent();
                //转换为字节输入流
                BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, Consts.UTF_8));
                String body = null;
                while ((body = br.readLine()) != null) {
                    log.info("uploadFile:{}" , body);
                    serviceListener.onCompleted(body);
                }
            }
        } catch (FileNotFoundException e) {
            log.error("FileNotFoundException:{}" , e.getMessage());
            e.printStackTrace();
            serviceListener.onError(e.getMessage());
        } catch (ClientProtocolException e) {
            log.error("ClientProtocolException:{}" , e.getMessage());
            e.printStackTrace();
            serviceListener.onError(e.getMessage());
        } catch (IOException e) {
            log.error("IOException:{}" , e.getMessage());
            e.printStackTrace();
            serviceListener.onError(e.getMessage());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 根据地址获得数据的输入流
     *
     * @param strUrl 网络连接地址
     * @return url的输入流
     */
    public static InputStream getInputStreamByUrl(String strUrl) {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(strUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(20 * 1000);
            final ByteArrayOutputStream output = new ByteArrayOutputStream();
            IOUtils.copy(conn.getInputStream(), output);
            return new ByteArrayInputStream(output.toByteArray());
        } catch (Exception e) {
            log.error(e + "");
        } finally {
            try {
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (Exception e) {
                log.error(e + "");
            }
        }
        return null;
    }
}

5. 业务层逻辑

由于是基于springboot框架,业务层一般在service层,添加方法,在impl里实现具体业务。

1. 上传单个文件,异步请求,binary-stream方式

如果不需要token,可以把access_token参数去掉。
service类:

    /**
     * 上传单个文件
     * 异步请求,binary-stream方式
     *
     * @param fileUrl         文件url
     * @param serviceListener 结果回调
     */
    public void uploadFileStreamAsynchronous(String fileUrl, ServiceListener serviceListener);

impl类实现:

    @Override
    public void uploadFileStreamAsynchronous(String fileUrl, ServiceListener serviceListener) {
        OkHttpUtils.uploadFileStreamAsynchronous(uploadFilesUrl, fileUrl, access_token, new ServiceListener() {
            @Override
            public void onCompleted(String data) {
                serviceListener.onCompleted(data);
            }

            @Override
            public void onError(String msg) {
                serviceListener.onError(msg);
            }
        });
    }

2.上传单个文件,异步请求,form-data方式

如果不需要token,可以把access_token参数去掉。
service类:

    /**
     * 上传单个文件
     * 异步请求,form-data方式
     *
     * @param filePath           文件路径
     * @param fileUploadListener 结果回调
     * @throws IOException 异常
     */
    public void uploadFileAsynchronous(String filePath, FileUploadListener fileUploadListener) throws IOException;

impl类实现:

    @Override
    public void uploadFileAsynchronous(String filePath, FileUploadListener fileUploadListener) {
        File file = new File(filePath);
        OkHttpUtils.uploadFileAsynchronous(uploadFilesUrl, access_token, file, new ServiceListener() {
            @Override
            public void onCompleted(String data) {
                FileUploadResponse fileUploadResponse = JSON.parseObject(data, new TypeReference() {
                });
                if (ApiConstants.CODE_SUCCESS.equals(fileUploadResponse.getErrcode())) {
                    fileUploadListener.onCompleted(fileUploadResponse);
                } else {
                    fileUploadListener.onError(data);
                }
            }

            @Override
            public void onError(String msg) {
                fileUploadListener.onError(msg);
            }
        });
    }

3.下载文件方法,同步请求

service类:

    /**
     * 下载文件方法
     * 同步请求
     *
     * @param url          下载连接
     * @param destFileDir  下载的文件储存目录
     * @param destFileName 下载文件名称,后面记得拼接后缀
     * @return String  返回结果
     * @throws Exception 异常
     */
    public String downloadSynchronize(String url, String destFileDir, String destFileName) throws Exception;

impl类实现:

    @Override
    public String downloadSynchronize(String url, String destFileDir, String destFileName) throws Exception {
        String result = "";
        result = OkHttpUtils.downloadSynchronize(url, destFileDir, destFileName);
        return result;
    }

4.下载文件方法,异步请求

service类:

    /**
     * 下载文件方法
     * 异步请求
     *
     * @param url          下载连接
     * @param destFileDir  下载的文件储存目录
     * @param destFileName 下载文件名称,后面记得拼接后缀
     * @param listener     下载监听
     */
    public void downloadFilesAsynchronous(String url, String destFileDir, String destFileName, FileDownloadListener listener);

impl类实现:

    @Override
    public void downloadFilesAsynchronous(String url, String destFileDir, String destFileName, FileDownloadListener fileDownloadListener) {
        OkHttpUtils.downloadFilesAsynchronous(url, destFileDir, destFileName, new FileDownloadListener() {
            @Override
            public void onDownloadSuccess(File file) {
                log.info("downloadFiles onDownloadSuccess:{}", file.getName());
                fileDownloadListener.onDownloadSuccess(file);
            }

            @Override
            public void onDownloading(int progress) {
                fileDownloadListener.onDownloading(progress);
            }

            @Override
            public void onDownloadFailed(Exception e) {
                log.info("downloadFiles onDownloadFailed:{}", e.toString());
                fileDownloadListener.onDownloadFailed(e);
            }
        });
    }

5.POST方法,同步请求

如果不需要token,可以把access_token参数去掉。
service类:

    /**
     * POST
     * 同步请求
     *
     * @param sRequestBody 传入信息的String
     * @return String  返回结果
     * @throws IOException 异常
     */
    public String post(String sRequestBody) throws IOException;

impl类实现:

    @Override
    public String post(String sRequestBody) throws IOException {
        String result = "";
        result = OkHttpUtils.post(url, access_token, sRequestBody);
        return result;
    }

6.GET方法,同步请求

如果不需要token,可以把access_token参数去掉。
service类:

    /**
     * GET
     * 同步请求
     *
     * @param sRequestBody 传入信息的String
     * @return String  返回结果
     * @throws IOException 异常
     */
    public String get(String url) throws IOException;

impl类实现:

    @Override
    public String get(String url) throws IOException {
        String result = "";
        result = OkHttpUtils.get(url);
        return result;
    }

6. 后续处理

到这里基本上常用的POST和GET上传下载的功能就实现了。使用请求时还需要验证headers,token等操作,还有上传下载进行同步操作时,如果文件比较大,直接在主线程操作会使页面卡住,等待完成才能操作,不是很友好,这里可以使用线程操作,这些等之后有时间整理下再写一篇。

你可能感兴趣的:(java,后端,spring,boot,java,post,get)