public class OkHttpUtil { private static OkHttpUtil instance; private Logger logger = LoggerFactory.getLogger(OkHttpUtil.class); private OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectionPool(new ConnectionPool(15, 5, TimeUnit.MINUTES)) .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) .connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .readTimeout(20, TimeUnit.SECONDS) .addInterceptor(new RetryIntercepter(2)) .addInterceptor(new HttpLoggingInterceptor()) .build(); public synchronized static OkHttpUtil getInstance() { if (instance == null) { instance = new OkHttpUtil(); } return instance; } /** * json body post / async * * @param json * @param url * @param callback */ public void post(String json, String url, Callback callback) { //MediaType 设置Content-Type 标头中包含的媒体类型值 RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json); Request request = new Request.Builder() .url(url)//请求的url .post(requestBody) .build(); //创建/Call Call mCall = okHttpClient.newCall(request); mCall.enqueue(callback); } /** * json body post / sync * * @param json * @param url * @return * @throws IOException */ public Response post(String json, String url) throws IOException { RequestBody requestBody = FormBody.create(MediaType.parse("application/x-www-form-urlencoded"), json); Request request = new Request.Builder() .url(url)//请求的url .post(requestBody) .build(); //创建/Call Call mCall = okHttpClient.newCall(request); return mCall.execute(); } /** * json body post / sync * * @param xml * @param url * @return * @throws IOException */ public Response postXml(String xml, String url) throws IOException { RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml;charset=UTF-8"), xml); Request request = new Request.Builder() .url(url)//请求的url .post(requestBody) .build(); //创建/Call Call mCall = okHttpClient.newCall(request); return mCall.execute(); } /** * get by url and param / sync * * @param map * @param url * @return * @throws IOException */ public Response get(Map<String, Object> map, String url) throws IOException { String urlNameString; if (map == null) { urlNameString = url; } else { urlNameString = url + "?" + getUrlParamsFromMap(map); } Request request = new Request.Builder() .url(urlNameString) .get() .build(); Call call = okHttpClient.newCall(request); return call.execute(); } /** * get by url / sync * * @param url * @return * @throws IOException */ public Response get(String url) throws IOException { String urlNameString = url; Request request = new Request.Builder() .url(urlNameString) .get() .build(); Call call = okHttpClient.newCall(request); return call.execute(); } /** * get add cookie / sync * * @param map * @param url * @param cookie * @return * @throws IOException */ public Response get(Map<String, Object> map, String url, String cookie) throws IOException { String urlNameString = url + "?" + getUrlParamsFromMap(map); Request request = new Request.Builder() .url(urlNameString) .header("cookie", cookie) .get() .build(); Call call = okHttpClient.newCall(request); return call.execute(); } /** * get and add cookie / async * * @param map * @param url * @param cookie * @param callback */ public void get(Map<String, Object> map, String url, String cookie, Callback callback) { String urlNameString = url + "?" + getUrlParamsFromMap(map); final Request request = new Request.Builder() .header("cookie", cookie) .url(urlNameString)//请求的url .get()//设置请求方式,get()/post() 查看Builder()方法知,在构建时默认设置请求方式为GET .build(); //构建一个请求Request对象 //创建/Call Call call = okHttpClient.newCall(request); //加入队列 异步操作 call.enqueue(callback); } /** * get / async * * @param map * @param url * @param callback */ public void get(Map<String, Object> map, String url, Callback callback) { String urlNameString = url + "?" + getUrlParamsFromMap(map); final Request request = new Request.Builder() .url(urlNameString)//请求的url .get()//设置请求方式,get()/post() 查看Builder()方法知,在构建时默认设置请求方式为GET .build(); //构建一个请求Request对象 //创建/Call Call call = okHttpClient.newCall(request); //加入队列 异步操作 call.enqueue(callback); } /** * description:将map转换成url参数格式: name1=value1&name2=value2 * * @param map * @return */ private String getUrlParamsFromMap(Map<String, Object> map) { try { if (null != map) { StringBuilder stringBuilder = new StringBuilder(); for (Map.Entry<String, Object> entry : map.entrySet()) { stringBuilder.append(entry.getKey()).append("=") .append(entry.getValue()).append("&"); } String content = stringBuilder.toString(); if (content.endsWith("&")) { content = content.substring(0, content.length() - 1); } return content; } } catch (Exception e) { logger.error("get url param error : ", e); } return ""; } /** * async down load file */ public void downloadFileAsyn(String url, Callback callback) { final Request request = new Request.Builder() .url(url) .get() .build(); //创建/Call Call call = okHttpClient.newCall(request); call.enqueue(callback); } /** * 下载fastdfs * @param url * @return */ public byte[] downloadFile(String url) { final Request request = new Request.Builder() .url(url) .get() .build(); //创建/Call Call call = okHttpClient.newCall(request); try { Response response = call.execute(); if (response.isSuccessful()) { return response.body().bytes(); } } catch (Exception e) { logger.error("down load error", e); } return null; } /** * 上传fastdfs文件 * @param fileByte * @param fileName * @param uploadUrl * @return */ public String uploadFastDfsFile(byte[] fileByte, String fileName, String uploadUrl) { try { RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), fileByte); RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", fileName, fileBody) .build(); final Request request = new Request.Builder() .url(uploadUrl) .post(requestBody) .build(); //创建/Call Call call = okHttpClient.newCall(request); Response response = call.execute(); return response.body().string(); } catch (IOException e) { logger.error("upload error ", e); } return ""; } }
/** * 重试拦截器 */ public class RetryIntercepter implements Interceptor { private Logger logger = LoggerFactory.getLogger(RetryIntercepter.class); //最大重试次数 private int maxRetry = 2; // 延迟 ms private long delay = 300; // 叠加延迟 ms private long increaseDelay = 200; public RetryIntercepter(int maxRetry) { this.maxRetry = maxRetry; } public RetryIntercepter(int maxRetry, long delay, long increaseDelay) { this.maxRetry = maxRetry; this.delay = delay; this.increaseDelay = increaseDelay; } @Override public Response intercept(Chain chain) throws IOException { RetryWrapper retryWrapper = proceed(chain); while (retryWrapper.isNeedReTry()) { retryWrapper.retryNum++; try { Thread.sleep(delay + (retryWrapper.retryNum - 1) * increaseDelay); } catch (InterruptedException e) { logger.error("thread interrupted exception ",e); Thread.currentThread().interrupt(); } proceed(chain, retryWrapper.request, retryWrapper); } return retryWrapper.response == null ? chain.proceed(chain.request()) : retryWrapper.response; } private RetryWrapper proceed(Chain chain) throws IOException { Request request = chain.request(); RetryWrapper retryWrapper = new RetryWrapper(request, maxRetry); proceed(chain, request, retryWrapper); return retryWrapper; } private void proceed(Chain chain, Request request, RetryWrapper retryWrapper) throws IOException { try { Response response = chain.proceed(request); retryWrapper.setResponse(response); } catch (SocketException | SocketTimeoutException | UnknownHostException e) { //e.printStackTrace(); logger.error("proceed network error : ",e); } } static class RetryWrapper { volatile int retryNum = 0; Request request; Response response; private int maxRetry; public RetryWrapper(Request request, int maxRetry) { this.request = request; this.maxRetry = maxRetry; } public void setResponse(Response response) { this.response = response; } public boolean isSuccessful() { return response != null && response.isSuccessful(); } public boolean isNeedReTry() { return !isSuccessful() && retryNum <= maxRetry; } public void setRetryNum(int retryNum) { this.retryNum = retryNum; } public void setMaxRetry(int maxRetry) { this.maxRetry = maxRetry; } } }
异步发起请求
/** *异步处理线程池 */ private final ExecutorService matchThreadPool = new ThreadPoolExecutor(4, 8, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(5000), new ThreadFactoryBuilder().setNameFormat("matchSkipRecordPool-%d").build(), new ThreadPoolExecutor.DiscardPolicy());
public class RecordSaveThread implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(RecordSaveThread.class); private final RecordDao RecordDao; private final List<RecordDO> records; public static RecordSaveThread getInstance(RecordDao RecordDao, List<RecordDO> records) { return new RecordSaveThread(RecordDao, records); } private RecordSaveThread(RecordDao RecordDao, List<RecordDO> records) { this.RecordDao = RecordDao; this.records = records; //this.mdcContext = mdcContext; } @Override public void run() { StopWatch stopWatch = new StopWatch(); try { stopWatch.start(); //设置父线程的MDC上下文,传递TraceId // mdcContext.setMdcContext(); //批量插入剔除记录 RecordDao.insertRecord(records); } catch (Exception e) { LOGGER.error("批量插入剔除记录异常, 订单号: {}", records.get(0).getCusOrderId(), e); } finally { stopWatch.stop(); LOGGER.info("保存剔除记录, 订单号: {}, 耗时: {}ms", records.get(0).getCusOrderId(), stopWatch.getTotalTimeMillis()); } } }
<!-- https://mvnrepository.com/artifact/io.reactivex.rxjava2/rxjava --> <dependency> <groupId>io.reactivex.rxjava2</groupId> <artifactId>rxjava</artifactId> <version>2.2.4</version> </dependency>
public void checkMatchConditions(final Short matchStep, List<JSONObject> capitalPlans,
final JSONObject matchParams, final List<MatchedPlanVO> matchedPlanList, final List<String> matchFailedCps) {
final String orderId = matchParams.getString("cusOrderId");
//多线程并发获取参数
final boolean printLog = isPrintLog();
//如果用信模式为2.0,则调用风控接口查询用户资方可用资方额度、总额度、已用额度
getFundCreditList(matchParams);
//批量获取补充资金计划余额信息
fetchAndPopulateCapitalBalance(capitalPlans);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
Flowable.fromIterable(capitalPlans)
.onBackpressureBuffer(capitalPlans.size())
.observeOn(Schedulers.computation())
.parallel()//开启线程数
.runOn(Schedulers.computation())
.map(new Function<JSONObject, MatchedPlanVO>() {
@Override
public MatchedPlanVO apply(JSONObject capitalPlan) {
})
.sequential()
.blockingSubscribe
(new Consumer<MatchedPlanVO>() {
@Override
public void accept(MatchedPlanVO matchedPlanVO) {
matchedPlanList.add(matchedPlanVO);
if (matchedPlanVO.getMatchStatus() == MatchStatusEnum.MATCH_FAIL.getValue()) {
matchFailedCps.add(matchedPlanVO.getCapitalPlanId());
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) {
log.error("订单:[" + orderId + "],校验资金计划异常:" + throwable.getMessage(), throwable);
}
});
stopWatch.stop();
log.info("订单:[{}],校验资金计划耗时:{}ms", orderId, stopWatch.getTotalTimeMillis());
}