基于HttpUrlConnection的简单封装SimpleHttp

本文介绍了如何基于HttpUrlConnection对网络请求进行简单封装,包括定义请求方法枚举、响应实体和回调接口,以及实现同步和异步请求,特别地,异步请求利用AsyncTask在主线程回调结果,方便UI操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、封装前准备
1.1、定义一个请求方法的枚举类型
package com.gau.simplehttp.http;

public enum HttpMethod {
    GET, POST
}
1.2、定义一个响应结果实体,用于接收服务器返回的数据
package com.gau.simplehttp.http;

public class Response {

    private final int code;
    private final String message;
    private final String method;
    private final String contentType;
    private final int contentLength;
    private final String body;

    public Response(Builder builder) {
        this.code = builder.code;
        this.message = builder.message;
        this.method = builder.method;
        this.contentType = builder.contentType;
        this.contentLength = builder.contentLength;
        this.body = builder.body;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public String getMethod() {
        return method;
    }

    public String getContentType() {
        return contentType;
    }

    public int getContentLength() {
        return contentLength;
    }

    public boolean isSuccessful() {
        return this.code >= 200 && this.code < 300;
    }

    public String getBody() {
        return body;
    }

    public static class Builder {
        private int code;
        private String message;
        private String method;
        private String contentType;
        private int contentLength;
        private String body;

        public Builder code(int code) {
            this.code = code;
            return this;
        }

        public Builder message(String message) {
            this.message = message;
            return this;
        }

        public Builder method(String method) {
            this.method = method;
            return this;
        }

        public Builder contentType(String contentType) {
            this.contentType = contentType;
            return this;
        }

        public Builder contentLength(int contentLength) {
            this.contentLength = contentLength;
            return this;
        }

        public Builder body(String body) {
            this.body = body;
            return this;
        }

        public Response build() {
            return new Response(this);
        }

    }

}
1.3、定义一个请求回调,其中Response为自己定义的响应结果
public interface HttpCallback {
    void onComplete(Response response);

    void onError(Throwable e);
}
2、封装ing
2.1、请求体的封装
package com.gau.simplehttp.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class Request {

    private final static int CONNECT_TIME_OUT_MILLISECOND = 10000;
    private final static int READ_TIME_OUT_MILLISECOND = 20000;

    private String url;
    private List<String> params;
    private List<String> headers;
    private String string;
    private HttpMethod method;

    private HttpURLConnection connection;
    private static HttpCallback mHttpCallback;

    private Request(Builder builder) {
        this.url = builder.url;
        this.params = builder.params;
        this.headers = builder.headers;
        this.method = builder.method;
        this.string = builder.string;
    }

    public static Request newRequest(Builder builder) {
        return newRequest(builder, null);
    }

    public static Request newRequest(Builder builder, HttpCallback httpCallback) {
        mHttpCallback = httpCallback;
        return new Request(builder);
    }

    /*
     * 异步请求
     */
    public void executeAsync() {
        HttpAsyncTask asyncTask = new HttpAsyncTask(this, connection, mHttpCallback);
        asyncTask.execute();
    }

    /*
     * 同步请求
     */
    public Response execute() throws IOException {
        if (method == HttpMethod.POST) {
            post();
        } else {
            get();
        }
        return response(connection);
    }

    /*
     * get请求
     */
    private void get() throws IOException {
        URL requestUrl = new URL(getUrl(url));
        connection = (HttpURLConnection) requestUrl.openConnection();
        connection.setRequestMethod(String.valueOf(method));
        connection.setConnectTimeout(CONNECT_TIME_OUT_MILLISECOND);
        connection.setReadTimeout(READ_TIME_OUT_MILLISECOND);
        connection.setDoInput(true);
        connection.setUseCaches(false);
        connectHeaders();
        connection.connect();
    }

    /*
     * get请求拼接url
     */
    private String getUrl(String url) {
        StringBuilder sb = new StringBuilder();
        sb.append(url).append("?");
        for (int i = 0; i < params.size(); i += 2) {
            sb.append(params.get(i));
            sb.append("=");
            sb.append(params.get(i + 1));
            sb.append("&");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    /*
     * post请求
     */
    private void post() throws IOException {
        URL requestUrl = new URL(url);
        connection = (HttpURLConnection) requestUrl.openConnection();
        connection.setRequestMethod(String.valueOf(method));
        connection.setConnectTimeout(CONNECT_TIME_OUT_MILLISECOND);
        connection.setReadTimeout(READ_TIME_OUT_MILLISECOND);
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);
        connectHeaders();
        connection.connect();
        postBody();
    }

    /*
     * post请求上传数据
     */
    private void postBody() throws IOException {
        postForm();
        postString();
    }

    /*
     * 上传表单
     */
    private void postForm() throws IOException {
        if (params != null && params.size() > 0) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < params.size(); i += 2) {
                sb.append(params.get(i));
                sb.append("=");
                sb.append(params.get(i + 1));
                sb.append("&");
            }
            sb.deleteCharAt(sb.length() - 1);
            connection.getOutputStream().write(sb.toString().getBytes("GBK"));
        }
    }

    /*
     * 上传字符串,如json字符串
     */
    private void postString() throws IOException {
        if (string != null && !string.isEmpty()) {
            connection.getOutputStream().write(string.getBytes("GBK"));
        }
    }

    /*
     * 设置请求头
     */
    private void connectHeaders() {
        if (headers != null && headers.size() > 0) {
            for (int i = 0; i < headers.size(); i += 2) {
                connection.setRequestProperty(headers.get(i), headers.get(i + 1));
            }
        }
    }

    /*
     * 获取响应结果
     */
    private Response response(HttpURLConnection connection) throws IOException {
        Response resp = new Response.Builder()
                .code(connection.getResponseCode())
                .message(connection.getResponseMessage())
                .method(connection.getRequestMethod())
                .contentType(connection.getContentType())
                .contentLength(connection.getContentLength())
                .body(getResponseBody(connection.getInputStream()))
                .build();
        connection.disconnect();
        return resp;
    }

    /*
     * 获取响应的数据
     */
    private String getResponseBody(InputStream stream) {
        StringBuilder sb = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(stream));
        String line;
        try {
            while ((line = br.readLine()) != null) {
                sb.append(line).append("\r\n");
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    public static class Builder {

        private String url;
        private List<String> params = new ArrayList<>();
        private List<String> headers = new ArrayList<>();
        private HttpMethod method = HttpMethod.GET;
        private String string;

        public Builder url(String url) {
            if (url == null || url.isEmpty()) {
                throw new IllegalArgumentException("url can not be null or empty");
            }
            this.url = url;
            return this;
        }

        public Builder method(HttpMethod method) {
            this.method = method;
            return this;
        }

        public Builder params(String key, String value) {
            params.add(key);
            params.add(value);
            return this;
        }

        public Builder headers(String key, String values) {
            headers.add(key);
            headers.add(values);
            return this;
        }

        public Builder string(String string) {
            this.string = string;
            return this;
        }

        public Request build() {
            return new Request(this);
        }

    }

}

Request包含同步请求和异步请求两种方式,其中异步请求采用的是AsyncTask实现。

2.2、异步的实现
package com.gau.simplehttp.http;

import android.os.AsyncTask;

import java.io.IOException;
import java.net.HttpURLConnection;

public class HttpAsyncTask extends AsyncTask<Void, Void, Response> {

    private Request request;
    private HttpURLConnection connection;
    private HttpCallback httpCallback;
    private Exception exception;

    public HttpAsyncTask(Request request, HttpURLConnection connection, HttpCallback httpCallback) {
        this.connection = connection;
        this.request = request;
        this.httpCallback = httpCallback;
    }

    @Override
    protected Response doInBackground(Void... params) {
        try {
            if (request != null) {
                return request.execute();
            }
        } catch (IOException e) {
            if (connection != null) {
                connection.disconnect();
            }
            exception = e;
        }
        return null;
    }

    @Override
    protected void onPostExecute(Response response) {
        super.onPostExecute(response);
        if (response == null) {
            if (httpCallback != null) {
                if (exception != null) {
                    httpCallback.onError(exception);
                } else {
                    httpCallback.onError(new Exception("UnKnown Exception"));
                }
            }
        } else {
            if (httpCallback != null) {
                httpCallback.onComplete(response);
            }
        }
    }
}

ps: 回调的结果是直接回调到主线程中,所以可以在回调方法里直接对UI进行操作。

3、测试代码
// 同步请求
new Thread(new Runnable() {
    @Override
    public void run() {
        Request.Builder builder = new Request.Builder().url("https://www.baidu.com");
        Request request = Request.newRequest(builder);
        try {
            Response response = request.execute();
            if (response != null) {
                if (response.isSuccessful()) {
                    Log.e(TAG, "response is success:" + response.getBody());
                } else {
                    Log.e(TAG, "response is fail:" + response.getBody());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

// 异步请求
Request.Builder build = new Request.Builder()
                            .url("http://10.0.3.2:8080/TestProject/TestServlet")
                            .method(HttpMethod.POST)
                            .headers("User-Agent", "guochao-1.0")
                            .params("param1", "hello world")
                            .params("param2","bye bye world")
                            .string("{\"json\":\"string\"}");
Request.newRequest(build, new HttpCallback() {
    @Override
    public void onComplete(Response response) {
        Log.e(TAG, "onComplete/response:" + response.getBody());
    }

    @Override
    public void onError(Throwable e) {
        Log.e(TAG, "onError:" + e.getMessage());
    }
}).executeAsync();

请求的参数可以通过调用builder.params("","")传递,请求头通过builder.headers("","")设置,最后通过request.execute()同步发送请求或request.executeAsync()异步发起请求。

github地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值