• Okhttp3 网络请求框架与 Gson


    Maven环境 :

          <dependency>
                <groupId>com.squareup.okhttp3</groupId>
                <artifactId>okhttp</artifactId>
                <version>3.14.1</version>
            </dependency>
    
            <dependency>
                <groupId>com.squareup.okhttp</groupId>
                <artifactId>logging-interceptor</artifactId>
                <version>2.7.5</version>
            </dependency>

    logging-interceptor 是Okhttp拦截器,用于打印 Log 日志。

    代码 :

    我采用的是实体类请求方式,一般请求都是使用HashMap作为Formbody,我来说一下我这么做的原因 :
    1. 如果参数有改动,那么HashMap的 put 方法是不会报错的,而实体类的set会报错,这在代码量大,复杂的时候很容易维护。
    2. HashMap 的put需要手动填写Key值,这毫无疑问是影响编码体验和效率的,特别是在请求参数繁杂的情况下。

    通用请求工具类 :

    public class OkHttpUtil {
        
        private static OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new LoggingInterceptor()).build();
    
        public static Response sendPostRequest(String url, Object parameter) throws IOException {
    
            Map<String, Object> map = ReqUtil.ParameToMap(parameter);
    
            //动态添加参数
            FormBody.Builder params = new FormBody.Builder();
            //遍历参数,KV对应。
            for (Map.Entry<String, Object> mapping : map.entrySet()) {
                params.add(mapping.getKey(), String.valueOf(mapping.getValue()));
            }
    
            Request request = new Request.Builder()
                    .url(url)
                    .post(params.build())
                    .build();
    
            return okHttpClient.newCall(request).execute();
        }
    }
    

    这里的 ReqUtil.ParameToMap(parameter) 会对传入的对象进行反射获取所有属性和值并转换成HashMap。

    addInterceptor(new LoggingInterceptor()).build() 加入请求日志拦截器。

    对象转HashMap ParameToMap 工具类

    class ReqUtil {
    	@SuppressWarnings("unchecked")
        static <K, V> Map<K, V> ParameToMap(Object javaBean) {
    		Map<K, V> ret = new HashMap<K, V>();
            try {
                Method[] methods = javaBean.getClass().getDeclaredMethods();
                for (Method method : methods) {
                    if (method.getName().startsWith("get")) {
                        String field = method.getName();
                        field = field.substring(field.indexOf("get") + 3);
                        field = field.toLowerCase().charAt(0) + field.substring(1);
                        Object value = method.invoke(javaBean, (Object[]) null);
                        ret.put((K) field, (V) (null == value ? null : value));
                    }
                }
            } catch (Exception e) {
            }
            return ret;
        }
    }

    请求拦截器,打印请求信息及 Formbody :

    public class LoggingInterceptor implements Interceptor {
        private Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
    
        public Response intercept(Chain chain) throws IOException {
            // 这个chain里面包含了request和response,所以你要什么都可以从这里拿
            Request request = chain.request();
    
            long t1 = System.nanoTime();// 请求发起的时间
            logger.info(String.format("发送请求 %s on %s%n%s", request.url(), chain.connection(), request.headers()));
    //            logger.info("请求参数:{
     +" + request.body().writeTo(); + "
    }");
            StringBuilder bodyLog = new StringBuilder();
            if (request.body() instanceof FormBody) {
                FormBody body = (FormBody) request.body();
                for (int i = 0; i < body.size(); i++) {
                    bodyLog.append(body.encodedName(i)).append("=").append(body.encodedValue(i)).append(",");
                }
                bodyLog.delete(bodyLog.length() - 1, bodyLog.length());
                logger.info("请求参数:" + bodyLog.toString());
            }
    //		System.out.println(String.format("发送请求 %s on %s%n%s", request.url(), chain.connection(), request.headers()));
            Response response = chain.proceed(request);
    
            long t2 = System.nanoTime();// 收到响应的时间
    
            // 这里不能直接使用response.body().string()的方式输出日志
            // 因为response.body().string()之后,response中的流会被关闭,程序会报错,我们需要创建出一
            // 个新的response给应用层处理
            ResponseBody responseBody = response.peekBody(1024 * 1024);
    
            logger.info(String.format("接收响应: [%s] %n返回json:【%s】 %.1fms%n%s", response.request().url(),
                    responseBody.string(), (t2 - t1) / 1e6d, response.headers()));
    
            return response;
    
        }
    
    }
    

    使用 :

     public static ResponseBody registerUser(RegisterParameter registerParameter) throws IOException {
            return OkHttpUtil.sendPostRequest(Origin.register, registerParameter).body();
        }

    效果 :

    Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2dd98b52]
    2019-06-03 21:29:28.367 INFO 7884 --- [p-nio-80-exec-3] c.s.g.m.n.r.LoggingInterceptor : 发送请求 https://api.ttlock.com.cn/v3/user/list on null
    2019-06-03 21:29:28.367 INFO 7884 --- [p-nio-80-exec-3] c.s.g.m.n.r.LoggingInterceptor : 请求参数:date=1559568568366,clientId=63eb3d5111b443969f4224cb2db65076,endDate=0,pageNo=1,pageSize=10,clientSecret=17a8d3cc6227e79fdeb3ee09f9bf5f8b,startDate=0
    2019-06-03 21:29:28.621 INFO 7884 --- [p-nio-80-exec-3] c.s.g.m.n.r.LoggingInterceptor : 接收响应: [https://api.ttlock.com.cn/v3/user/list]
    返回json:【{"list":[{"regtime":1559529910000,"userid":"testbl_23"},{"regtime":1559461353000,"userid":"testbl_admin"},{"regtime":1559529920000,"userid":"testbl_admin4"}],"pageNo":1,"pageSize":10,"pages":1,"total":3}】 254.3ms
    Server: Tengine
    Date: Mon, 03 Jun 2019 13:29:30 GMT
    Content-Type: application/json;charset=utf-8
    Content-Length: 203
    Connection: keep-alive

    关于JSON解析嵌套实体类 :

    在 Json 解析这方面,JSONObject 是出场率最高的,但JSONObject 处理解析嵌套数据格式的时候就有些差强人意了,比如这种 :

    @Data
    public class UserPage {
    
        private int pageNo;
        private int pageSize;
        private int pages;
        private int total;
        private List<User> list;
    
    }
    {
        "list":[
            {
                "regtime":1559529910000,
                "userid":"testbl_23"
            },
            {
                "regtime":1559461353000,
                "userid":"testbl_admin"
            },
            {
                "regtime":1559529920000,
                "userid":"testbl_admin4"
            }
        ],
        "pageNo":1,
        "pageSize":10,
        "pages":1,
        "total":3
    }

    如果用 JSONObject解析,List<User> 值会是null,而使用Gson则可以完美解析,不愧是Google家的东西,写的真周全。

  • 相关阅读:
    Mac Finder 里新建文本
    SourceTree 无法查看组织仓库
    Android Gradle 指定 Module 打包
    Mac 下安装安卓 apk 文件
    Android 瘦身之道 ---- so文件
    Android Google AdMob 广告接入示例
    Java 垃圾回收(GC) 泛读
    [麻雀虽小]记 简易Markdown阅读器 开发全过程
    Git 版本回滚
    线程与进程的区别及其通信方式
  • 原文地址:https://www.cnblogs.com/yangchaojie/p/11102351.html
Copyright © 2020-2023  润新知