在Java项目中使用OkHttp构建高可用的外卖霸王餐API客户端
在Java项目中使用OkHttp构建高可用的外卖霸王餐API客户端在对接美团外卖霸王餐这类高并发、强时效性的第三方服务时API客户端的稳定性至关重要。本文将基于OkHttp客户端通过连接池管理、统一拦截器、异步回调及熔断降级策略构建一个健壮且易于维护的Java API客户端。1. 项目依赖与基础配置首先确保pom.xml中引入了OkHttp和相关工具库。dependenciesdependencygroupIdcom.squareup.okhttp3/groupIdartifactIdokhttp/artifactIdversion4.10.0/version/dependencydependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.83/version/dependencydependencygroupIdorg.slf4j/groupIdartifactIdslf4j-api/artifactIdversion1.7.36/version/dependency/dependencies2. 定义核心数据模型在baodanbao.com.cn.model包下定义通用的响应结构和业务请求体。通用响应类packagecom.baodanbao.cn.model;publicclassApiResponseT{privateintstatus;privateStringmsg;privateTresult;publicbooleanisSuccess(){returnthis.status200;}// Getter和Setter省略}霸王餐活动查询请求packagecom.baodanbao.cn.model.request;publicclassQueryCampaignRequest{privateStringpartnerId;privateStringtimestamp;privateStringtoken;privateStringshopPoiId;privateIntegerpage;privateIntegerpageSize;// Getter和Setter}3. 构建OkHttpClient实例利用OkHttp的连接池和拦截器机制统一处理日志、重试和头部信息。packagecom.baodanbao.cn.config;importokhttp3.ConnectionPool;importokhttp3.Interceptor;importokhttp3.OkHttpClient;importokhttp3.Response;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjava.io.IOException;importjava.util.concurrent.TimeUnit;ConfigurationpublicclassOkHttpConfig{BeanpublicOkHttpClientbawangcanHttpClient(){returnnewOkHttpClient.Builder().connectTimeout(5,TimeUnit.SECONDS).readTimeout(10,TimeUnit.SECONDS).writeTimeout(10,TimeUnit.SECONDS).connectionPool(newConnectionPool(5,5,TimeUnit.MINUTES))// 添加日志拦截器.addInterceptor(newLoggingInterceptor())// 添加公共参数拦截器.addInterceptor(newCommonHeaderInterceptor()).build();}// 日志拦截器staticclassLoggingInterceptorimplementsInterceptor{OverridepublicResponseintercept(Chainchain)throwsIOException{Requestrequestchain.request();longstartTimeSystem.nanoTime();Responseresponsechain.proceed(request);longendTimeSystem.nanoTime();// 实际项目中应使用loggerSystem.out.println(String.format(API调用: %s 耗时: %.1fms,request.url(),(endTime-startTime)/1e6d));returnresponse;}}// 公共头部拦截器staticclassCommonHeaderInterceptorimplementsInterceptor{OverridepublicResponseintercept(Chainchain)throwsIOException{Requestoriginalchain.request();Requestrequestoriginal.newBuilder().header(Content-Type,application/json).header(User-Agent,Baodanbao-Client/1.0).method(original.method(),original.body()).build();returnchain.proceed(request);}}}4. 封装业务客户端创建专门的服务类来处理具体的API调用逻辑。packagecom.baodanbao.cn.service;importcom.alibaba.fastjson.JSON;importcom.baodanbao.cn.config.OkHttpConfig;importcom.baodanbao.cn.model.ApiResponse;importcom.baodanbao.cn.model.request.QueryCampaignRequest;importcom.baodanbao.cn.util.SignatureUtil;importokhttp3.*;importjava.io.IOException;importjava.util.concurrent.CompletableFuture;publicclassMeituanBawangcanService{privatefinalOkHttpClientclient;privatefinalStringbaseUrlhttps://api.meituan.com/bawangcan;privatefinalStringpartnerIdyour_partner_id;privatefinalStringpartnerSecretyour_secret_key;publicMeituanBawangcanService(){this.clientnewOkHttpConfig().bawangcanHttpClient();}/** * 异步查询霸王餐活动列表 */publicCompletableFutureApiResponseStringqueryCampaignsAsync(StringshopPoiId){returnCompletableFuture.supplyAsync(()-{try{QueryCampaignRequestrequestbuildQueryRequest(shopPoiId);StringjsonJSON.toJSONString(request);StringsignSignatureUtil.sign(json,partnerSecret);RequestBodybodyRequestBody.create(json,MediaType.get(application/json; charsetutf-8));RequesthttpRequestnewRequest.Builder().url(baseUrl/query).post(body).addHeader(X-PARTNER-ID,partnerId).addHeader(X-SIGNATURE,sign).build();try(Responseresponseclient.newCall(httpRequest).execute()){if(response.isSuccessful()response.body()!null){StringresponseBodyresponse.body().string();returnJSON.parseObject(responseBody,newcom.alibaba.fastjson.TypeReferenceApiResponseString(){});}else{thrownewIOException(API调用失败状态码: (response!null?response.code():null));}}}catch(Exceptione){// 在实际项目中这里应该集成熔断器如Hystrix或SentinelSystem.err.println(调用异常: e.getMessage());ApiResponseStringerrorResponsenewApiResponse();errorResponse.setStatus(500);errorResponse.setMsg(服务调用异常);returnerrorResponse;}});}privateQueryCampaignRequestbuildQueryRequest(StringshopPoiId){QueryCampaignRequestreqnewQueryCampaignRequest();req.setPartnerId(partnerId);req.setTimestamp(String.valueOf(System.currentTimeMillis()/1000));req.setShopPoiId(shopPoiId);req.setPage(1);req.setPageSize(10);// Token可以基于时间戳生成req.setToken(java.util.UUID.randomUUID().toString());returnreq;}}5. 签名工具类确保请求的安全性。packagecom.baodanbao.cn.util;importjava.security.MessageDigest;publicclassSignatureUtil{publicstaticStringsign(Stringcontent,Stringsecret){try{MessageDigestmdMessageDigest.getInstance(MD5);md.update((contentsecret).getBytes());byte[]digestmd.digest();StringBuildersbnewStringBuilder();for(byteb:digest){sb.append(String.format(%02x,b0xff));}returnsb.toString().toUpperCase();}catch(Exceptione){thrownewRuntimeException(签名生成失败,e);}}}6. 使用示例publicclassApplication{publicstaticvoidmain(String[]args){MeituanBawangcanServiceservicenewMeituanBawangcanService();service.queryCampaignsAsync(shop_123456).whenComplete((result,throwable)-{if(throwable!null){System.err.println(异步调用发生错误: throwable.getMessage());}else{System.out.println(API响应状态: result.getStatus());System.out.println(API响应数据: result.getResult());}});// 保持主线程存活以观察异步结果try{Thread.sleep(5000);}catch(InterruptedExceptione){e.printStackTrace();}}}本文著作权归 俱美开放平台 转载请注明出处