okhttp application example - synchronous and asynchronous calls of encapsulation tools

The script of life, you have already seen it in heaven
why you chose this script
It's because there is something in your life that you think is worth it
Project github address

1. Add pom dependencies

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.10.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>
    </dependencies>

2. Create related classes

/**
 * 测试okhttp的get与post请求
 */
@SpringBootApplication
public class OkhttpTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(OkhttpTestApplication.class, args);
    }

}
/**
 * @Description: 用户实体类
 * @author: lh
 * @date: 2023年03月20日 21:09
 */
public class User {
    private String name; // 用户名
    private int password; // 密码

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPassword() {
        return password;
    }

    public void setPassword(int password) {
        this.password = password;
    }
}
/**
 * @Description: 返回响应实体类
 * @author: lh
 * @date: 2023年03月20日 21:11
 */
public class BaseResponse {
    private int code; // 响应状态码
    private String msg; // 响应消息体

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}
/**
 * @Description: 用户控制层
 * @author: lh
 * @date: 2023年03月20日 21:13
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/login")
    public BaseResponse login(@RequestParam String name, @RequestParam int password)
    {
        BaseResponse response = new BaseResponse();
        if (name.equals("li") && password == 123456)
        {
            response.setCode(200);
            response.setMsg("登录成功,欢迎使用");
        } else {
            response.setCode(500);
            response.setMsg("登录失败,请检查用户名密码后重试");
        }

        return response;
    }

    @PostMapping("register")
    public BaseResponse register(@RequestBody User user)
    {
        BaseResponse response = new BaseResponse();
        if (user != null)
        {
            response.setCode(200);
            response.setMsg("用户注册成功");
        } else {
            response.setCode(500);
            response.setMsg("注册失败,请检查后重试");
        }

        return response;
    }
}

3. Use postman to request a test

http://localhost:8080/user/login?name=li&password=123456

{
    "code": 200,
    "msg": "登录成功,欢迎使用"
}
http://localhost:8080/user/register

{"name":"li","password":123456}

{
    "code": 200,
    "msg": "用户注册成功"
}

4. Use okhttpClient to test

@SpringBootTest
class OkhttpTestApplicationTests {
    @Test
    public void testGet() {
        // 1.创建一个okHttpClient
        OkHttpClient okHttpClient = new OkHttpClient();
        // 2.创建一个httpUrl
        HttpUrl url = Objects.requireNonNull(HttpUrl.parse("http://localhost:8080/user/login")).newBuilder()
                .addQueryParameter("name", "li")
                .addQueryParameter("password", "123456")
                .build();
        // 3.创建一个request
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        // 4.执行请求命令
        try {
            Response response = okHttpClient.newCall(request).execute();
            System.out.println(Objects.requireNonNull(response.body()).string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testPost() {
        // 1.创建一个okHttpClient
        OkHttpClient okHttpClient = new OkHttpClient();
        // 2.创建一个url
        String url = String.format("http://localhost:8080/user/register");
        // 3.指定传输type为JSON
        MediaType Json = MediaType.get("application/json");
        // 4.创建request
        User user = new User();
        user.setName("li");
        user.setPassword(123456);
        String jsonString = JSONObject.toJSONString(user);
        RequestBody body = RequestBody.create(jsonString, Json);
        Request request = new Request.Builder().url(url)
                .post(body)
                .build();
        // 5.执行请求命令
        try {
            Response response = okHttpClient.newCall(request).execute();
            System.out.println(response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

5. Encapsulate an okhttp tool class

package com.example.okhttp.utils;

import com.alibaba.fastjson.JSON;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * @Description: okhttp工具类
 * @author: lh
 * @date: 2023年03月21日 20:46
 */
public class OkHttpUtils {
    private static volatile OkHttpClient okHttpClient = null;
    private static volatile Semaphore semaphore = null;
    private Map<String, String> headerMap;
    private Map<String, String> paramMap;
    private String url;
    private Request.Builder request;

    /**
     * 初始化okHttpClient,并且允许https访问
     */
    private OkHttpUtils() {
        if (okHttpClient == null) {
            synchronized (OkHttpClient.class) {
                if (okHttpClient == null) {
                    // 设置代理方式
//                    Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8080));
                    TrustManager[] trustManagers = buildTrustManagers();
                    okHttpClient = new OkHttpClient.Builder()
                            //设置连接超时时间
                            .connectTimeout(15, TimeUnit.SECONDS)
                            //写入超时时间
                            .writeTimeout(20, TimeUnit.SECONDS)
                            //从连接成功到响应的总时间
                            .readTimeout(20, TimeUnit.SECONDS)
                            //跳过ssl认证(https)
                            .sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager) trustManagers[0])
                            .hostnameVerifier((hostName, session) -> true)
                            .retryOnConnectionFailure(true)
//                            .proxy(proxy)//代理ip
                            //设置连接池  最大连接数量  , 持续存活的连接
                            .connectionPool(new ConnectionPool(50, 10, TimeUnit.MINUTES))
                            .build();
                    addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
                }
            }
        }
    }

    /**
     * 用于异步请求时,控制访问线程数,返回结果
     *
     */
    private static Semaphore getSemaphoreInstance() {
        //只能1个线程同时访问
        synchronized (OkHttpUtils.class) {
            if (semaphore == null) {
                semaphore = new Semaphore(0);
            }
        }
        return semaphore;
    }

    /**
     * 创建OkHttpUtils
     *
     */
    public static OkHttpUtils builder() {
        return new OkHttpUtils();
    }

    /**
     * 添加url
     *
     * @param url 地址
     */
    public OkHttpUtils url(String url) {
        this.url = url;
        return this;
    }

    /**
     * 添加参数
     *
     * @param key   参数名
     * @param value 参数值
     */
    public OkHttpUtils addParam(String key, String value) {
        if (paramMap == null) {
            paramMap = new LinkedHashMap<>(16);
        }
        paramMap.put(key, value);
        return this;
    }

    /**
     * 添加请求头
     *
     * @param key   参数名
     * @param value 参数值
     */
    public OkHttpUtils addHeader(String key, String value) {
        if (headerMap == null) {
            headerMap = new LinkedHashMap<>(16);
        }
        headerMap.put(key, value);
        return this;
    }

    /**
     * 初始化get方法
     *
     */
    public OkHttpUtils get() {
        request = new Request.Builder().get();
        StringBuilder urlBuilder = new StringBuilder(url);
        if (paramMap != null) {
            urlBuilder.append("?");
            try {
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    urlBuilder.append(URLEncoder.encode(entry.getKey(), "utf-8")).
                            append("=").
                            append(URLEncoder.encode(entry.getValue(), "utf-8")).
                            append("&");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            urlBuilder.deleteCharAt(urlBuilder.length() - 1);
        }
        request.url(urlBuilder.toString());
        return this;
    }

    /**
     * 初始化post方法
     *
     * @param isJsonPost true等于json的方式提交数据,类似postman里post方法的raw
     *                   false等于普通的表单提交
     */
    public OkHttpUtils post(boolean isJsonPost) {
        RequestBody requestBody;
        if (isJsonPost) {
            String json = "";
            if (paramMap != null) {
                json = JSON.toJSONString(paramMap);
            }
            requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        } else {
            FormBody.Builder formBody = new FormBody.Builder();
            if (paramMap != null) {
                paramMap.forEach(formBody::add);
            }
            requestBody = formBody.build();
        }
        request = new Request.Builder().post(requestBody).url(url);
        return this;
    }

    public OkHttpUtils put() {
        String json = "";
        if (paramMap != null) {
            json = JSON.toJSONString(paramMap);
        }
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);

        request = new Request.Builder().put(requestBody).url(url);
        return this;
    }

    public OkHttpUtils del() {
        String json = "";
        if (paramMap != null) {
            json = JSON.toJSONString(paramMap);
        }
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        request = new Request.Builder().delete(requestBody).url(url);
        return this;
    }

    /**
     * 同步请求
     *
     */
    public String sync() {
        setHeader(request);
        try {
            Response response = okHttpClient.newCall(request.build()).execute();
            assert response.body() != null;
            return Objects.requireNonNull(response.body()).string();
        } catch (IOException e) {
            e.printStackTrace();
            return "请求失败:" + e.getMessage();
        }
    }

    /**
     * 异步请求,有返回值
     */
    public String async() {
        StringBuilder buffer = new StringBuilder("");
        setHeader(request);
        okHttpClient.newCall(request.build()).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                buffer.append("请求出错:").append(e.getMessage());
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                assert response.body() != null;
                buffer.append(Objects.requireNonNull(response.body()).string());
                getSemaphoreInstance().release();
            }
        });
        try {
            getSemaphoreInstance().acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return buffer.toString();
    }

    /**
     * 异步请求,带有接口回调
     *
     * @param callBack 回调
     */
    public void async(ICallBack callBack) {
        setHeader(request);
        okHttpClient.newCall(request.build()).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                callBack.onFailure(call, e.getMessage());
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                assert response.body() != null;
                callBack.onSuccessful(call, Objects.requireNonNull(response.body()).string());
            }
        });
    }

    /**
     * 为request添加请求头
     *
     * @param request 请求
     */
    private void setHeader(Request.Builder request) {
        if (headerMap != null) {
            try {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    request.addHeader(entry.getKey(), entry.getValue());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 生成安全套接字工厂,用于https请求的证书跳过
     *
     * @return SSLSocketFactory
     */
    private static SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {
        SSLSocketFactory ssfFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ssfFactory;
    }

    private static TrustManager[] buildTrustManagers() {
        return new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
        };
    }

    /**
     * 自定义一个接口回调 - 发送异步请求时可以实现这个接口
     */
    public interface ICallBack {
        /**
         * 接口正常调用返回的内容
         *
         * @param call 回调
         * @param data 返回数据
         */
        void onSuccessful(Call call, String data);

        /**
         * 接口错误返回的内容
         *
         * @param call     回调
         * @param errorMsg 错误信息
         */
        void onFailure(Call call, String errorMsg);

    }
}

6. Use the encapsulated tool class to make a request

@SpringBootTest
class OkhttpTestApplicationTests {

    @Test
    public void testOkhttpGet() {
        String res = OkHttpUtils.builder()
                .url("http://localhost:8080/user/login")
                .addParam("name", "li").addParam("password", "123456")
                .get()
                .sync();
        System.out.println(res);
    }

    @Test
    public void testOkhttpPost() {
        String res = OkHttpUtils.builder()
                .url("http://localhost:8080/user/register")
                .addParam("name", "li").addParam("password", "123456")
                .post(true)
                .sync();
        System.out.println(res);
    }

    @Test
    public void testOkhttpAsync() {
        OkHttpUtils.builder()
                .url("http://localhost:8080/user/register")
                .addParam("name", "li").addParam("password", "123456")
                .post(true)
                .async(new AsyncHttpServiceImpl());
    }


    //回调实现类
    public class AsyncHttpServiceImpl implements OkHttpUtils.ICallBack {
        @Override
        public void onSuccessful(Call call, String data) {
            // 接口正常返回的内容
            System.out.println("onSuccessful" + data);
        }

        @Override
        public void onFailure(Call call, String errorMsg) {
            //接口错误返回的内容
            System.out.println("onFailure" + errorMsg);
        }
    }
}

Guess you like

Origin blog.csdn.net/2301_76354366/article/details/129805860