From 5ea7fee14294ff42c9a9007605c93903c60cec7b Mon Sep 17 00:00:00 2001 From: jinyu Date: Sat, 30 Jul 2016 14:56:27 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=96=B0=E6=95=B4=E7=90=86HttpClinet?= =?UTF-8?q?=20&=20=E6=96=B0=E5=A2=9EOkHttp=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin4j-base/CHANGE.md | 8 +- weixin4j-base/pom.xml | 12 + .../com/foxinmy/weixin4j/api/BaseApi.java | 4 +- .../java/com/foxinmy/weixin4j/api/MchApi.java | 5 +- .../weixin4j/http/AbstractHttpResponse.java | 2 +- .../foxinmy/weixin4j/http/ContentType.java | 2 + .../com/foxinmy/weixin4j/http/HttpParams.java | 90 ++------ .../foxinmy/weixin4j/http/HttpRequest.java | 14 -- .../com/foxinmy/weixin4j/http/MimeType.java | 4 +- .../weixin4j/http/SimpleHttpClient.java | 28 +-- .../weixin4j/http/SimpleHttpResponse.java | 2 +- .../weixin4j/http/apache/InputStreamBody.java | 6 +- .../http/factory/HttpClientFactory.java | 103 +++++++-- .../http/factory/HttpComponent3Factory.java | 25 -- .../http/factory/HttpComponent4Factory.java | 39 ---- .../http/factory/HttpComponent4_1.java | 119 ---------- .../http/factory/HttpComponent4_2.java | 109 --------- .../http/factory/SimpleHttpClientFactory.java | 14 +- .../http/message/JsonMessageConverter.java | 18 +- .../apache3}/HttpComponent3.java | 214 +++++++++--------- .../apache3/HttpComponent3Factory.java | 80 +++++++ .../apache3}/HttpComponent3Response.java | 8 +- .../apache4}/HttpComponent4.java | 46 +++- .../apache4/HttpComponent4Factory.java | 47 ++++ .../support/apache4/HttpComponent4_1.java | 49 ++++ .../apache4/HttpComponent4_1Factory.java | 105 +++++++++ .../apache4}/HttpComponent4_1Response.java | 6 +- .../support/apache4/HttpComponent4_2.java | 50 ++++ .../apache4/HttpComponent4_2Factory.java | 101 +++++++++ .../apache4}/HttpComponent4_2Response.java | 6 +- .../netty}/Netty4HttpClient.java | 40 ++-- .../netty}/Netty4HttpClientFactory.java | 64 ++++-- .../netty}/Netty4HttpResponse.java | 7 +- .../http/support/okhttp/OkHttpClient2.java | 144 ++++++++++++ .../support/okhttp/OkHttpClient2Factory.java | 85 +++++++ .../http/support/okhttp/OkHttpClient3.java | 144 ++++++++++++ .../support/okhttp/OkHttpClient3Factory.java | 108 +++++++++ .../support/okhttp/OkHttpClientFactory.java | 38 ++++ .../http/support/okhttp/OkHttpResponse2.java | 77 +++++++ .../http/support/okhttp/OkHttpResponse3.java | 75 ++++++ .../http/weixin/WeixinRequestExecutor.java | 171 ++++++++++---- .../http/weixin/WeixinSSLRequestExecutor.java | 56 ----- .../weixin4j/setting/Weixin4jSettings.java | 19 +- .../com/foxinmy/weixin4j/util/IOUtil.java | 21 ++ .../weixin4j/base/test/HttpClientTest.java | 72 ------ .../foxinmy/weixin4j/base/test/PayTest.java | 11 +- .../base/test/http/Apache3HttpClientTest.java | 20 ++ .../test/http/Apache4_1HttpClientTest.java | 19 ++ .../test/http/Apache4_2HttpClientTest.java | 19 ++ .../base/test/http/HttpClientTest.java | 124 ++++++++++ .../base/test/http/NettyHttpClientTest.java | 19 ++ .../base/test/http/OkHttp2ClinetTest.java | 19 ++ .../base/test/http/OkHttp3ClinetTest.java | 19 ++ .../base/test/http/SimpleHttpTest.java | 19 ++ .../src/main/resources/spring-bean.xml | 8 - .../com/foxinmy/weixin4j/mp/api/MediaApi.java | 1 - .../foxinmy/weixin4j/mp/api/PayOldApi.java | 16 +- .../foxinmy/weixin4j/mp/model/OauthToken.java | 1 - .../foxinmy/weixin4j/mp/test/NotifyTest.java | 4 +- .../com/foxinmy/weixin4j/qy/api/MediaApi.java | 1 - .../com/foxinmy/weixin4j/qy/api/PartyApi.java | 2 +- .../com/foxinmy/weixin4j/qy/api/UserApi.java | 18 +- 62 files changed, 1913 insertions(+), 844 deletions(-) delete mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Factory.java delete mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4Factory.java delete mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1.java delete mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2.java rename weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/{factory => support/apache3}/HttpComponent3.java (57%) create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3Factory.java rename weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/{factory => support/apache3}/HttpComponent3Response.java (90%) rename weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/{factory => support/apache4}/HttpComponent4.java (78%) create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4Factory.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1Factory.java rename weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/{factory => support/apache4}/HttpComponent4_1Response.java (93%) create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2Factory.java rename weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/{factory => support/apache4}/HttpComponent4_2Response.java (94%) rename weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/{factory => support/netty}/Netty4HttpClient.java (85%) rename weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/{factory => support/netty}/Netty4HttpClientFactory.java (52%) rename weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/{factory => support/netty}/Netty4HttpResponse.java (92%) create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient2.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient2Factory.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient3.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient3Factory.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClientFactory.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpResponse2.java create mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpResponse3.java delete mode 100644 weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinSSLRequestExecutor.java delete mode 100644 weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/HttpClientTest.java create mode 100644 weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache3HttpClientTest.java create mode 100644 weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache4_1HttpClientTest.java create mode 100644 weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache4_2HttpClientTest.java create mode 100644 weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/HttpClientTest.java create mode 100644 weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/NettyHttpClientTest.java create mode 100644 weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/OkHttp2ClinetTest.java create mode 100644 weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/OkHttp3ClinetTest.java create mode 100644 weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/SimpleHttpTest.java diff --git a/weixin4j-base/CHANGE.md b/weixin4j-base/CHANGE.md index fc34c5f1..bf165d47 100644 --- a/weixin4j-base/CHANGE.md +++ b/weixin4j-base/CHANGE.md @@ -149,4 +149,10 @@ * 2016-05-12 - + 添加MemcacheTokenStorager支持 \ No newline at end of file + + 添加MemcacheTokenStorager支持 + +* 2016-07-30 + + + 重新整理HttpClinet + + + 新增OkHttp实现 \ No newline at end of file diff --git a/weixin4j-base/pom.xml b/weixin4j-base/pom.xml index 83b03486..a9029341 100644 --- a/weixin4j-base/pom.xml +++ b/weixin4j-base/pom.xml @@ -39,6 +39,18 @@ 4.0.30.Final true + + com.squareup.okhttp3 + okhttp + 3.4.1 + true + + + com.squareup.okhttp + okhttp + 2.7.5 + true + redis.clients jedis diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/BaseApi.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/BaseApi.java index 8f4425cb..6152ba55 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/BaseApi.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/BaseApi.java @@ -25,12 +25,12 @@ public abstract class BaseApi { protected final WeixinRequestExecutor weixinExecutor; - protected abstract ResourceBundle weixinBundle(); - public BaseApi() { this.weixinExecutor = new WeixinRequestExecutor(); } + protected abstract ResourceBundle weixinBundle(); + protected String getRequestUri(String key) { String url = weixinBundle().getString(key); Pattern p = Pattern.compile("(\\{[^\\}]*\\})"); diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/MchApi.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/MchApi.java index 088081bd..86f41639 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/MchApi.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/MchApi.java @@ -7,7 +7,6 @@ import java.util.ResourceBundle; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor; -import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor; import com.foxinmy.weixin4j.model.WeixinPayAccount; import com.foxinmy.weixin4j.payment.mch.MerchantResult; import com.foxinmy.weixin4j.sign.WeixinPaymentSignature; @@ -58,8 +57,8 @@ public class MchApi extends BaseApi { */ protected WeixinRequestExecutor createSSLRequestExecutor( InputStream certificate) throws WeixinException { - return new WeixinSSLRequestExecutor(weixinAccount.getCertificateKey(), - certificate); + return weixinExecutor.createSSLRequestExecutor( + weixinAccount.getCertificateKey(), certificate); } /** diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/AbstractHttpResponse.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/AbstractHttpResponse.java index 1b2d94f5..62cb8a4b 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/AbstractHttpResponse.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/AbstractHttpResponse.java @@ -12,7 +12,7 @@ import java.io.InputStream; * @see */ public abstract class AbstractHttpResponse implements HttpResponse { - + protected final static String KEEP_ALIVE = "keep-alive"; private final byte[] content; public AbstractHttpResponse(byte[] content) { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/ContentType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/ContentType.java index 3de279f2..46f4240b 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/ContentType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/ContentType.java @@ -24,12 +24,14 @@ public final class ContentType implements Serializable { private final Charset charset; private static final Charset DEFAULT_CHARSET = Consts.UTF_8; + public static final ContentType APPLICATION_JSON; public static final ContentType APPLICATION_FORM_URLENCODED; public static final ContentType MULTIPART_FORM_DATA; public static final ContentType DEFAULT_BINARY; public static final ContentType DEFAULT_TEXT; static { + APPLICATION_JSON = new ContentType(MimeType.APPLICATION_JSON); APPLICATION_FORM_URLENCODED = new ContentType(MimeType.APPLICATION_FORM_URLENCODED); MULTIPART_FORM_DATA = new ContentType(MimeType.MULTIPART_FORM_DATA); DEFAULT_BINARY = new ContentType(MimeType.APPLICATION_OCTET_STREAM); diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/HttpParams.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/HttpParams.java index f2054038..51d4eccc 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/HttpParams.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/HttpParams.java @@ -12,16 +12,16 @@ import javax.net.ssl.SSLContext; * @author jinyu(foxinmy@gmail.com) * @date 2015年8月13日 * @since JDK 1.6 - * @see */ public final class HttpParams { - - private boolean allowUserInteraction; + /** + * 连接超时时间(单位毫秒) + */ private int connectTimeout; - private int socketTimeout; + /** + * 读取超时时间(单位毫秒) + */ private int readTimeout; - private int chunkSize; - private boolean followRedirects; /** * 代理对象 */ @@ -35,73 +35,26 @@ public final class HttpParams { */ private HostnameVerifier hostnameVerifier; + /** + * connectTimeout = 15000,readTimeout=20000 + */ public HttpParams() { - this(5000, 5000, 5000); + this(15000, 20000); } - public HttpParams(int connectTimeout, int socketTimeout, int readTimeout) { - this.allowUserInteraction = true; + public HttpParams(int connectTimeout, int readTimeout) { this.connectTimeout = connectTimeout; - this.socketTimeout = socketTimeout; this.readTimeout = readTimeout; - this.chunkSize = 4096; - this.followRedirects = false; - } - - public boolean isAllowUserInteraction() { - return allowUserInteraction; - } - - public HttpParams setAllowUserInteraction(boolean allowUserInteraction) { - this.allowUserInteraction = allowUserInteraction; - return this; } public int getConnectTimeout() { return connectTimeout; } - public HttpParams setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - return this; - } - - public int getSocketTimeout() { - return socketTimeout; - } - - public HttpParams setSocketTimeout(int socketTimeout) { - this.socketTimeout = socketTimeout; - return this; - } - public int getReadTimeout() { return readTimeout; } - public HttpParams setReadTimeout(int readTimeout) { - this.readTimeout = readTimeout; - return this; - } - - public int getChunkSize() { - return chunkSize; - } - - public HttpParams setChunkSize(int chunkSize) { - this.chunkSize = chunkSize; - return this; - } - - public boolean isFollowRedirects() { - return followRedirects; - } - - public HttpParams setFollowRedirects(boolean followRedirects) { - this.followRedirects = followRedirects; - return this; - } - public Proxy getProxy() { return proxy; } @@ -130,22 +83,17 @@ public final class HttpParams { } public static HttpParams copy(final HttpParams params) { - return new HttpParams() - .setAllowUserInteraction(params.isAllowUserInteraction()) - .setConnectTimeout(params.getConnectTimeout()) - .setSocketTimeout(params.getSocketTimeout()) - .setReadTimeout(params.getReadTimeout()) - .setChunkSize(params.getChunkSize()) - .setFollowRedirects(params.isFollowRedirects()); + return new HttpParams(params.getConnectTimeout(), + params.getReadTimeout()).setProxy(params.getProxy()) + .setHostnameVerifier(params.getHostnameVerifier()) + .setSSLContext(params.getSSLContext()); } @Override public String toString() { - return "HttpParams [allowUserInteraction=" + allowUserInteraction - + ", connectTimeout=" + connectTimeout + ", socketTimeout=" - + socketTimeout + ", readTimeout=" + readTimeout - + ", chunkSize=" + chunkSize + ", followRedirects=" - + followRedirects + ", proxy=" + proxy + ", sslContext=" - + sslContext + ", hostnameVerifier=" + hostnameVerifier + "]"; + return "HttpParams [connectTimeout=" + connectTimeout + + ", readTimeout=" + readTimeout + ", proxy=" + proxy + + ", sslContext=" + sslContext + ", hostnameVerifier=" + + hostnameVerifier + "]"; } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java index b4391f0f..45b2e76e 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/HttpRequest.java @@ -27,12 +27,6 @@ public class HttpRequest implements HttpMessage { * @return */ private final URI uri; - /** - * 协议参数 - * - * @return - */ - private HttpParams params; /** * 内容参数 */ @@ -59,14 +53,6 @@ public class HttpRequest implements HttpMessage { return uri; } - public HttpParams getParams() { - return params; - } - - public void setParams(HttpParams params) { - this.params = params; - } - public HttpEntity getEntity() { return entity; } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/MimeType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/MimeType.java index 3648f855..f23c7e2f 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/MimeType.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/MimeType.java @@ -11,7 +11,7 @@ import com.foxinmy.weixin4j.util.StringUtil; * @className MimeType * @author jinyu * @date Jul 20, 2016 - * @since JDK 1.8 + * @since JDK 1.6 */ public class MimeType implements Serializable { @@ -33,6 +33,7 @@ public class MimeType implements Serializable { public static final MimeType AUDIO_MP3; public static final MimeType VIDEO_MPEG4; public static final MimeType TEXT_XML; + public static final MimeType TEXT_JSON; static { APPLICATION_FORM_URLENCODED = valueOf("application/x-www-form-urlencoded"); @@ -46,6 +47,7 @@ public class MimeType implements Serializable { AUDIO_MP3 = valueOf("audio/mp3"); VIDEO_MPEG4 = valueOf("video/mpeg4"); TEXT_XML = valueOf("text/xml"); + TEXT_JSON = valueOf("text/json"); } public MimeType(String type) { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/SimpleHttpClient.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/SimpleHttpClient.java index 9ea2cd23..7f870f18 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/SimpleHttpClient.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/SimpleHttpClient.java @@ -13,7 +13,6 @@ import java.util.Map.Entry; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; import com.foxinmy.weixin4j.http.entity.HttpEntity; import com.foxinmy.weixin4j.http.factory.HttpClientFactory; @@ -31,19 +30,15 @@ import com.foxinmy.weixin4j.util.StringUtil; */ public class SimpleHttpClient extends AbstractHttpClient implements HttpClient { - protected HostnameVerifier createHostnameVerifier() { - return new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; + private final HttpParams params; + + public SimpleHttpClient(HttpParams params) { + this.params = params; } protected HttpURLConnection createHttpConnection(HttpRequest request) throws IOException { URI uri = request.getURI(); - HttpParams params = request.getParams(); Proxy proxy = params != null ? params.getProxy() : null; URLConnection urlConnection = proxy != null ? uri.toURL() .openConnection(proxy) : uri.toURL().openConnection(); @@ -59,7 +54,7 @@ public class SimpleHttpClient extends AbstractHttpClient implements HttpClient { sslContext = HttpClientFactory.allowSSLContext(); } if (hostnameVerifier == null) { - hostnameVerifier = createHostnameVerifier(); + hostnameVerifier = HttpClientFactory.AllowHostnameVerifier.GLOBAL; } HttpsURLConnection connection = (HttpsURLConnection) urlConnection; connection.setSSLSocketFactory(sslContext.getSocketFactory()); @@ -81,14 +76,9 @@ public class SimpleHttpClient extends AbstractHttpClient implements HttpClient { HttpURLConnection connection = createHttpConnection(request); String method = request.getMethod().name(); // set parameters - HttpParams params = request.getParams(); if (params != null) { - connection.setAllowUserInteraction(params - .isAllowUserInteraction()); connection.setConnectTimeout(params.getConnectTimeout()); connection.setReadTimeout(params.getReadTimeout()); - connection.setInstanceFollowRedirects(params - .isFollowRedirects()); } connection.setRequestMethod(method); connection.setDoInput(true); @@ -134,14 +124,6 @@ public class SimpleHttpClient extends AbstractHttpClient implements HttpClient { HttpEntity httpEntity = request.getEntity(); if (httpEntity != null) { connection.setUseCaches(false); - // Read Out Exception when connection.disconnect(); - /* - * if (httpEntity.getContentLength() > 0l) { - * connection.setFixedLengthStreamingMode(httpEntity - * .getContentLength()); } else { connection - * .setChunkedStreamingMode(params != null ? params - * .getChunkSize() : 4096); } - */ if (httpEntity.getContentLength() > 0l) { connection.setRequestProperty(HttpHeaders.CONTENT_LENGTH, Long.toString(httpEntity.getContentLength())); diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/SimpleHttpResponse.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/SimpleHttpResponse.java index b5e23e5b..283e4415 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/SimpleHttpResponse.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/SimpleHttpResponse.java @@ -42,7 +42,7 @@ public class SimpleHttpResponse extends AbstractHttpResponse { } else { String connect = connection.getHeaderField("Connection"); protocol = new HttpVersion(version, - "keep-alive".equalsIgnoreCase(connect)); + KEEP_ALIVE.equalsIgnoreCase(connect)); } } return protocol; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/apache/InputStreamBody.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/apache/InputStreamBody.java index 2ee8a89a..a2fea006 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/apache/InputStreamBody.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/apache/InputStreamBody.java @@ -85,7 +85,11 @@ public class InputStreamBody extends AbstractContentBody { } public long getContentLength() { - return this.contentLength; + try { + return Math.max(contentLength, this.in.available()); + } catch (IOException e) { + return -1; + } } public String getFilename() { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpClientFactory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpClientFactory.java index a8c5b7cf..011609db 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpClientFactory.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpClientFactory.java @@ -5,11 +5,18 @@ import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; import javax.net.ssl.X509TrustManager; import com.foxinmy.weixin4j.http.HttpClient; import com.foxinmy.weixin4j.http.HttpClientException; +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.support.apache3.HttpComponent3Factory; +import com.foxinmy.weixin4j.http.support.apache4.HttpComponent4Factory; +import com.foxinmy.weixin4j.http.support.netty.Netty4HttpClientFactory; +import com.foxinmy.weixin4j.http.support.okhttp.OkHttpClientFactory; /** * HttpClient工厂生产类:参考netty的InternalLoggerFactory @@ -29,7 +36,7 @@ public abstract class HttpClientFactory { /** * NettyHttpClient -> ApacheHttpClient(HttpComponent3&4) -> - * SimpleHttpClient(HttpURLConnection) + * OkHttpClient(2&3) -> SimpleHttpClient(HttpURLConnection) * * @return */ @@ -44,7 +51,11 @@ public abstract class HttpClientFactory { try { f = new HttpComponent3Factory(); } catch (Throwable e3) { - f = new SimpleHttpClientFactory(); + try { + f = new OkHttpClientFactory(); + } catch (Throwable e4) { + f = new SimpleHttpClientFactory(); + } } } } @@ -67,7 +78,8 @@ public abstract class HttpClientFactory { */ public static void setDefaultFactory(HttpClientFactory defaultFactory) { if (defaultFactory == null) { - throw new NullPointerException("defaultFactory"); + throw new IllegalArgumentException( + "'defaultFactory' must not be empty"); } HttpClientFactory.defaultFactory = defaultFactory; } @@ -81,6 +93,40 @@ public abstract class HttpClientFactory { return getDefaultFactory().newInstance(); } + /** + * 获取HttpClient实例 + * + * @param params Http参数 + * + * @return HttpClinet实例 + */ + public static HttpClient getInstance(HttpParams params) { + HttpClientFactory clientFactory = getDefaultFactory(); + clientFactory.resolveHttpParams(params); + return clientFactory.newInstance(); + } + + /** + * Resolve the Http Parameter + * + * @param params + * 请求参数 + */ + public void resolveHttpParams(HttpParams params) { + if (params == null) { + throw new IllegalArgumentException("'params' must not be empty"); + } + resolveHttpParams0(params); + } + + /** + * Resolve the Http Parameter + * + * @param params + * 请求参数 + */ + protected abstract void resolveHttpParams0(HttpParams params); + /** * 获取HttpClient实例 * @@ -92,7 +138,7 @@ public abstract class HttpClientFactory { try { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, - new X509TrustManager[] { createX509TrustManager() }, + new X509TrustManager[] { AllowX509TrustManager.GLOBAL }, new java.security.SecureRandom()); return sslContext; } catch (NoSuchAlgorithmException e) { @@ -104,24 +150,39 @@ public abstract class HttpClientFactory { } } - protected static X509TrustManager createX509TrustManager() { - return new X509TrustManager() { - @Override - public X509Certificate[] getAcceptedIssuers() { - return null; - } + public static class AllowX509TrustManager implements X509TrustManager { + public static final X509TrustManager GLOBAL = new AllowX509TrustManager(); - @Override - public void checkServerTrusted( - X509Certificate[] paramArrayOfX509Certificate, - String paramString) throws CertificateException { - } + private AllowX509TrustManager() { + } - @Override - public void checkClientTrusted( - X509Certificate[] paramArrayOfX509Certificate, - String paramString) throws CertificateException { - } - }; + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkServerTrusted( + X509Certificate[] paramArrayOfX509Certificate, + String paramString) throws CertificateException { + } + + @Override + public void checkClientTrusted( + X509Certificate[] paramArrayOfX509Certificate, + String paramString) throws CertificateException { + } + } + + public static class AllowHostnameVerifier implements HostnameVerifier { + public static final HostnameVerifier GLOBAL = new AllowHostnameVerifier(); + + private AllowHostnameVerifier() { + } + + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Factory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Factory.java deleted file mode 100644 index 4428eaa1..00000000 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Factory.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.foxinmy.weixin4j.http.factory; - -import org.apache.commons.httpclient.HttpClient; - -/** - * 使用commons-httpclient3.x - * - * @className HttpComponent3Factory - * @author jinyu(foxinmy@gmail.com) - * @date 2015年8月12日 - * @since JDK 1.6 - * @see - */ -public class HttpComponent3Factory extends HttpClientFactory { - - public HttpComponent3Factory() { - // odd code - Class _dead = HttpClient.class; - } - - @Override - public com.foxinmy.weixin4j.http.HttpClient newInstance() { - return new HttpComponent3(new HttpClient()); - } -} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4Factory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4Factory.java deleted file mode 100644 index 83b93325..00000000 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4Factory.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.foxinmy.weixin4j.http.factory; - -import org.apache.http.util.VersionInfo; - -import com.foxinmy.weixin4j.http.HttpClient; - -/** - * 使用Apache的HttpClient4.x - * - * @className HttpComponent4Factory - * @author jinyu(foxinmy@gmail.com) - * @date 2015年8月12日 - * @since JDK 1.6 - * @see - */ -public class HttpComponent4Factory extends HttpClientFactory { - - private final VersionInfo version; - - public HttpComponent4Factory() { - version = VersionInfo.loadVersionInfo("org.apache.http.client", - HttpClient.class.getClassLoader()); - } - - @Override - public HttpClient newInstance() { - String release = (version != null) ? version.getRelease() - : VersionInfo.UNAVAILABLE; - if (release.startsWith("4.")) { - if (release.startsWith("4.0") || release.startsWith("4.1") - || release.startsWith("4.2")) { - return new HttpComponent4_1(); - } else { - return new HttpComponent4_2(); - } - } - throw new RuntimeException("unknown the HttpClient version:" + release); - } -} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1.java deleted file mode 100644 index 3380119b..00000000 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.foxinmy.weixin4j.http.factory; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import javax.net.ssl.SSLContext; - -import org.apache.http.HttpHost; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.conn.params.ConnRoutePNames; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.ssl.SSLSocketFactory; -import org.apache.http.conn.ssl.X509HostnameVerifier; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.CoreConnectionPNames; -import org.apache.http.params.CoreProtocolPNames; - -import com.foxinmy.weixin4j.http.HttpClientException; -import com.foxinmy.weixin4j.http.HttpHeaders; -import com.foxinmy.weixin4j.http.HttpParams; -import com.foxinmy.weixin4j.http.HttpRequest; -import com.foxinmy.weixin4j.http.HttpResponse; -import com.foxinmy.weixin4j.model.Consts; - -/** - * Requires Apache HttpComponents 4.2 or lower - * - * @className HttpComponent4_1 - * @author jinyu(foxinmy@gmail.com) - * @date 2015年8月18日 - * @since JDK 1.6 - * @see - */ -public class HttpComponent4_1 extends HttpComponent4 { - - private final org.apache.http.client.HttpClient httpClient; - - public HttpComponent4_1() { - this.httpClient = new DefaultHttpClient(); - } - - @Override - public HttpResponse execute(HttpRequest request) throws HttpClientException { - HttpResponse response = null; - try { - HttpRequestBase uriRequest = createHttpRequest(request.getMethod(), - request.getURI()); - boolean useSSL = "https".equals(request.getURI().getScheme()); - SSLContext sslContext = null; - X509HostnameVerifier hostnameVerifier = null; - HttpParams params = request.getParams(); - if (params != null) { - if (params.getProxy() != null) { - InetSocketAddress socketAddress = (InetSocketAddress) params - .getProxy().address(); - HttpHost proxy = new HttpHost(socketAddress.getHostName(), - socketAddress.getPort()); - uriRequest.getParams().setParameter( - ConnRoutePNames.DEFAULT_PROXY, proxy); - useSSL = false; - } - uriRequest.getParams().setIntParameter( - CoreConnectionPNames.SOCKET_BUFFER_SIZE, - params.getChunkSize()); - uriRequest.getParams().setIntParameter( - CoreConnectionPNames.SO_TIMEOUT, - params.getSocketTimeout()); - uriRequest.getParams().setIntParameter( - CoreConnectionPNames.CONNECTION_TIMEOUT, - params.getConnectTimeout()); - uriRequest.getParams().setParameter( - CoreProtocolPNames.HTTP_CONTENT_CHARSET, Consts.UTF_8); - uriRequest.getParams().setParameter( - CoreProtocolPNames.HTTP_ELEMENT_CHARSET, Consts.UTF_8.name()); - uriRequest.getParams().setParameter( - CoreProtocolPNames.STRICT_TRANSFER_ENCODING, Consts.UTF_8); - uriRequest.getParams().setParameter( - HttpHeaders.CONTENT_ENCODING, Consts.UTF_8); - uriRequest.getParams().setParameter(HttpHeaders.ACCEPT_CHARSET, - Consts.UTF_8); - sslContext = params.getSSLContext(); - if (params.getHostnameVerifier() != null) { - hostnameVerifier = new CustomHostnameVerifier( - params.getHostnameVerifier()); - } - } - if (useSSL) { - if (sslContext == null) { - sslContext = HttpClientFactory.allowSSLContext(); - } - if (hostnameVerifier == null) { - hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; - } - SSLSocketFactory socketFactory = new SSLSocketFactory( - sslContext); - socketFactory.setHostnameVerifier(hostnameVerifier); - Scheme scheme = new Scheme("https", socketFactory, 443); - httpClient.getConnectionManager().getSchemeRegistry() - .register(scheme); - } - addHeaders(request.getHeaders(), uriRequest); - addEntity(request.getEntity(), uriRequest); - org.apache.http.HttpResponse httpResponse = httpClient - .execute(uriRequest); - response = new HttpComponent4_1Response(httpResponse, - getContent(httpResponse)); - handleResponse(response); - } catch (IOException e) { - throw new HttpClientException("I/O error on " - + request.getMethod().name() + " request for \"" - + request.getURI().toString() + "\":" + e.getMessage(), e); - } finally { - if (response != null) { - response.close(); - } - } - return response; - } -} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2.java deleted file mode 100644 index d217e93e..00000000 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.foxinmy.weixin4j.http.factory; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import javax.net.ssl.SSLContext; - -import org.apache.http.HttpHost; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.config.RequestConfig.Builder; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.config.ConnectionConfig; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.X509HostnameVerifier; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; - -import com.foxinmy.weixin4j.http.HttpClientException; -import com.foxinmy.weixin4j.http.HttpParams; -import com.foxinmy.weixin4j.http.HttpRequest; -import com.foxinmy.weixin4j.http.HttpResponse; -import com.foxinmy.weixin4j.model.Consts; - -/** - * Requires Apache HttpComponents 4.3 or higher - * - * @className HttpComponent4_2 - * @author jinyu(foxinmy@gmail.com) - * @date 2015年8月18日 - * @since JDK 1.6 - * @see - */ -public class HttpComponent4_2 extends HttpComponent4 { - - private CloseableHttpClient httpClient; - - public HttpComponent4_2() { - this.httpClient = HttpClientBuilder - .create() - .setDefaultConnectionConfig( - ConnectionConfig.custom().setCharset(Consts.UTF_8) - .build()).build(); - } - - @Override - public HttpResponse execute(HttpRequest request) throws HttpClientException { - HttpResponse response = null; - try { - HttpRequestBase uriRequest = createHttpRequest(request.getMethod(), - request.getURI()); - boolean useSSL = "https".equals(request.getURI().getScheme()); - SSLContext sslContext = null; - X509HostnameVerifier hostnameVerifier = null; - HttpParams params = request.getParams(); - if (params != null) { - Builder requestConfig = RequestConfig.custom() - .setSocketTimeout(params.getSocketTimeout()) - .setConnectTimeout(params.getConnectTimeout()) - .setConnectionRequestTimeout(params.getReadTimeout()); - if (params.getProxy() != null) { - InetSocketAddress socketAddress = (InetSocketAddress) params - .getProxy().address(); - HttpHost proxy = new HttpHost(socketAddress.getHostName(), - socketAddress.getPort()); - requestConfig.setProxy(proxy); - useSSL = false; - } - uriRequest.setConfig(requestConfig.build()); - sslContext = params.getSSLContext(); - if (params.getHostnameVerifier() != null) { - hostnameVerifier = new CustomHostnameVerifier( - params.getHostnameVerifier()); - } - } - if (useSSL) { - if (sslContext == null) { - sslContext = HttpClientFactory.allowSSLContext(); - } - if (hostnameVerifier == null) { - hostnameVerifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; - } - httpClient = HttpClients - .custom() - .setHostnameVerifier(hostnameVerifier) - .setDefaultConnectionConfig( - ConnectionConfig.custom() - .setCharset(Consts.UTF_8).build()) - .setSslcontext(sslContext).build(); - } - addHeaders(request.getHeaders(), uriRequest); - addEntity(request.getEntity(), uriRequest); - CloseableHttpResponse httpResponse = httpClient.execute(uriRequest); - response = new HttpComponent4_2Response(httpResponse, - getContent(httpResponse)); - handleResponse(response); - } catch (IOException e) { - throw new HttpClientException("I/O error on " - + request.getMethod().name() + " request for \"" - + request.getURI().toString() + "\":" + e.getMessage(), e); - } finally { - if (response != null) { - response.close(); - } - } - return response; - } -} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/SimpleHttpClientFactory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/SimpleHttpClientFactory.java index bff30c1c..5260c13d 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/SimpleHttpClientFactory.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/SimpleHttpClientFactory.java @@ -1,6 +1,7 @@ package com.foxinmy.weixin4j.http.factory; import com.foxinmy.weixin4j.http.HttpClient; +import com.foxinmy.weixin4j.http.HttpParams; import com.foxinmy.weixin4j.http.SimpleHttpClient; /** @@ -14,8 +15,19 @@ import com.foxinmy.weixin4j.http.SimpleHttpClient; */ public class SimpleHttpClientFactory extends HttpClientFactory { + private volatile SimpleHttpClient httpClient; + private HttpParams params; + + @Override + protected void resolveHttpParams0(HttpParams params) { + this.params = params; + } + @Override public HttpClient newInstance() { - return new SimpleHttpClient(); + if (this.httpClient == null) { + this.httpClient = new SimpleHttpClient(params); + } + return this.httpClient; } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/message/JsonMessageConverter.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/message/JsonMessageConverter.java index 02e2176e..cf0dabc7 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/message/JsonMessageConverter.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/message/JsonMessageConverter.java @@ -29,15 +29,19 @@ public class JsonMessageConverter extends AbstractMessageConverter { private static final int MASK = BRACE | BRACKET; public JsonMessageConverter() { - super(MimeType.APPLICATION_JSON, new MimeType("application", "*+json")); + super(MimeType.APPLICATION_JSON, MimeType.TEXT_JSON, new MimeType( + "application", "*+json")); } @Override public boolean canConvert(Class clazz, HttpResponse response) { if (!super.canConvert(clazz, response)) { - String disposition = response.getHeaders().getFirst(HttpHeaders.CONTENT_DISPOSITION); - String fileName = RegexUtil.regexFileNameFromContentDispositionHeader(disposition); - return (fileName != null && FileUtil.getFileExtension(fileName).equalsIgnoreCase(JSO)); + String disposition = response.getHeaders().getFirst( + HttpHeaders.CONTENT_DISPOSITION); + String fileName = RegexUtil + .regexFileNameFromContentDispositionHeader(disposition); + return (fileName != null && FileUtil.getFileExtension(fileName) + .equalsIgnoreCase(JSO)); } return true; } @@ -48,8 +52,10 @@ public class JsonMessageConverter extends AbstractMessageConverter { } @Override - protected T convertInternal(Class clazz, InputStream body) throws IOException { + protected T convertInternal(Class clazz, InputStream body) + throws IOException { byte[] bytes = IOUtil.toByteArray(body); - return JSON.parseObject(bytes, 0, bytes.length, charset.newDecoder(), clazz); + return JSON.parseObject(bytes, 0, bytes.length, charset.newDecoder(), + clazz); } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3.java similarity index 57% rename from weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3.java rename to weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3.java index 4dc51c6c..5bc7f4a6 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3.java @@ -1,10 +1,8 @@ -package com.foxinmy.weixin4j.http.factory; +package com.foxinmy.weixin4j.http.support.apache3; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Proxy; import java.net.Socket; import java.net.UnknownHostException; import java.util.List; @@ -27,14 +25,12 @@ import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.TraceMethod; import org.apache.commons.httpclient.params.HttpConnectionParams; import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory; -import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; import com.foxinmy.weixin4j.http.AbstractHttpClient; import com.foxinmy.weixin4j.http.HttpClientException; import com.foxinmy.weixin4j.http.HttpHeaders; import com.foxinmy.weixin4j.http.HttpMethod; -import com.foxinmy.weixin4j.http.HttpParams; import com.foxinmy.weixin4j.http.HttpRequest; import com.foxinmy.weixin4j.http.HttpResponse; import com.foxinmy.weixin4j.http.apache.MultipartEntity; @@ -59,11 +55,47 @@ public class HttpComponent3 extends AbstractHttpClient { this.httpClient = httpClient; } - private org.apache.commons.httpclient.HttpMethod createHttpMethod( - HttpMethod method, java.net.URI url) throws HttpClientException { + @Override + public HttpResponse execute(HttpRequest request) throws HttpClientException { + HttpResponse response = null; + try { + org.apache.commons.httpclient.HttpMethod httpMethod = createRequest(request); + httpClient.executeMethod(httpMethod); + response = new HttpComponent3Response(httpMethod); + handleResponse(response); + } catch (IOException e) { + throw new HttpClientException("I/O error on " + + request.getMethod().name() + " request for \"" + + request.getURI().toString() + "\":" + e.getMessage(), e); + } finally { + if (response != null) { + response.close(); + } + } + return response; + } + + /** + * Create HttpMethod + */ + protected org.apache.commons.httpclient.HttpMethod createRequest( + HttpRequest request) throws HttpClientException, IOException { + org.apache.commons.httpclient.HttpMethod httpMethod = createMethod(request); + resolveHeaders(request, httpMethod); + resolveContent(request, httpMethod); + return httpMethod; + } + + /** + * Create HttpMethod + */ + protected org.apache.commons.httpclient.HttpMethod createMethod( + HttpRequest request) throws HttpClientException { + HttpMethod method = request.getMethod(); org.apache.commons.httpclient.HttpMethod httpMethod = null; try { - URI uri = new URI(url.toString(), false, Consts.UTF_8.name()); + URI uri = new URI(request.getURI().toString(), false, + Consts.UTF_8.name()); if (method == HttpMethod.GET) { httpMethod = new GetMethod(); } else if (method == HttpMethod.HEAD) { @@ -85,121 +117,79 @@ public class HttpComponent3 extends AbstractHttpClient { httpMethod.setURI(uri); } catch (IOException e) { throw new HttpClientException("I/O error on " + method.name() - + " setURI for \"" + url.toString() + "\":" + + " setURI for \"" + request.toString() + "\":" + e.getMessage(), e); } return httpMethod; } - @Override - public HttpResponse execute(HttpRequest request) throws HttpClientException { - HttpResponse response = null; - try { - org.apache.commons.httpclient.HttpMethod httpMethod = createHttpMethod( - request.getMethod(), request.getURI()); - boolean useSSL = "https".equals(request.getURI().getScheme()); - SSLContext sslContext = null; - HttpParams params = request.getParams(); - if (params != null) { - Proxy proxy = params.getProxy(); - if (proxy != null) { - InetSocketAddress socketAddress = (InetSocketAddress) proxy - .address(); - httpClient.getHostConfiguration().setProxy( - socketAddress.getHostName(), - socketAddress.getPort()); - useSSL = false; - } - sslContext = params.getSSLContext(); - httpClient.getHttpConnectionManager().getParams() - .setConnectionTimeout(params.getConnectTimeout()); - httpClient.getHttpConnectionManager().getParams() - .setSendBufferSize(params.getChunkSize()); - httpMethod.getParams().setSoTimeout(params.getSocketTimeout()); - httpMethod.getParams().setHttpElementCharset( - Consts.UTF_8.name()); - httpMethod.getParams().setParameter( - "http.protocol.uri-charset", Consts.UTF_8.name()); - // httpMethod.getParams().setUriCharset(Consts.UTF_8.name()); - httpMethod.getParams().setContentCharset(Consts.UTF_8.name()); - } - if (useSSL) { - if (sslContext == null) { - sslContext = HttpClientFactory.allowSSLContext(); - } - Protocol.registerProtocol("https", new Protocol("https", - new SSLProtocolSocketFactory(sslContext), 443)); - } - com.foxinmy.weixin4j.http.HttpHeaders headers = request - .getHeaders(); - if (headers == null) { - headers = new HttpHeaders(); - } - if (!headers.containsKey(HttpHeaders.HOST)) { - headers.set(HttpHeaders.HOST, request.getURI().getHost()); - } - // Add default accept headers - if (!headers.containsKey(HttpHeaders.ACCEPT)) { - headers.set(HttpHeaders.ACCEPT, "*/*"); - } - // Add default user agent - if (!headers.containsKey(HttpHeaders.USER_AGENT)) { - headers.set(HttpHeaders.USER_AGENT, "apache/httpclient3"); - } - for (Entry> header : headers.entrySet()) { - if (HttpHeaders.COOKIE.equalsIgnoreCase(header.getKey())) { + /** + * Resolve Headers + */ + protected void resolveHeaders(HttpRequest request, + org.apache.commons.httpclient.HttpMethod httpMethod) { + com.foxinmy.weixin4j.http.HttpHeaders headers = request.getHeaders(); + if (headers == null) { + headers = new HttpHeaders(); + } + if (!headers.containsKey(HttpHeaders.HOST)) { + headers.set(HttpHeaders.HOST, request.getURI().getHost()); + } + // Add default accept headers + if (!headers.containsKey(HttpHeaders.ACCEPT)) { + headers.set(HttpHeaders.ACCEPT, "*/*"); + } + // Add default user agent + if (!headers.containsKey(HttpHeaders.USER_AGENT)) { + headers.set(HttpHeaders.USER_AGENT, "apache/httpclient3"); + } + for (Entry> header : headers.entrySet()) { + if (HttpHeaders.COOKIE.equalsIgnoreCase(header.getKey())) { + httpMethod.setRequestHeader(header.getKey(), + StringUtil.join(header.getValue(), ';')); + } else { + for (String headerValue : header.getValue()) { httpMethod.setRequestHeader(header.getKey(), - StringUtil.join(header.getValue(), ';')); - } else { - for (String headerValue : header.getValue()) { - httpMethod.setRequestHeader(header.getKey(), - headerValue != null ? headerValue : ""); - } + headerValue != null ? headerValue : ""); } } - HttpEntity entity = request.getEntity(); - if (entity != null) { - if (entity.getContentLength() > 0l) { - httpMethod.addRequestHeader(HttpHeaders.CONTENT_LENGTH, - Long.toString(entity.getContentLength())); - } - if (entity.getContentType() != null) { - httpMethod.addRequestHeader(HttpHeaders.CONTENT_TYPE, - entity.getContentType().toString()); - } - RequestEntity requestEntity = null; - if (entity instanceof MultipartEntity) { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - entity.writeTo(os); - os.flush(); - requestEntity = new ByteArrayRequestEntity( - os.toByteArray(), entity.getContentType() - .toString()); - os.close(); - } else { - requestEntity = new InputStreamRequestEntity( - entity.getContent(), entity.getContentType() - .toString()); - } - ((EntityEnclosingMethod) httpMethod) - .setRequestEntity(requestEntity); - } - httpClient.executeMethod(httpMethod); - response = new HttpComponent3Response(httpMethod); - handleResponse(response); - } catch (IOException e) { - throw new HttpClientException("I/O error on " - + request.getMethod().name() + " request for \"" - + request.getURI().toString() + "\":" + e.getMessage(), e); - } finally { - if (response != null) { - response.close(); - } } - return response; } - private static class SSLProtocolSocketFactory implements + /** + * Resolve Content + */ + protected void resolveContent(HttpRequest request, + org.apache.commons.httpclient.HttpMethod httpMethod) + throws IOException { + HttpEntity entity = request.getEntity(); + if (entity != null) { + if (entity.getContentLength() > 0l) { + httpMethod.addRequestHeader(HttpHeaders.CONTENT_LENGTH, + Long.toString(entity.getContentLength())); + } + if (entity.getContentType() != null) { + httpMethod.addRequestHeader(HttpHeaders.CONTENT_TYPE, entity + .getContentType().toString()); + } + RequestEntity requestEntity = null; + if (entity instanceof MultipartEntity) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + entity.writeTo(os); + os.flush(); + requestEntity = new ByteArrayRequestEntity(os.toByteArray(), + entity.getContentType().toString()); + os.close(); + } else { + requestEntity = new InputStreamRequestEntity( + entity.getContent(), entity.getContentType().toString()); + } + ((EntityEnclosingMethod) httpMethod) + .setRequestEntity(requestEntity); + } + } + + public static class SSLProtocolSocketFactory implements SecureProtocolSocketFactory { private final SSLContext sslContext; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3Factory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3Factory.java new file mode 100644 index 00000000..d7ff0132 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3Factory.java @@ -0,0 +1,80 @@ +package com.foxinmy.weixin4j.http.support.apache3; + +import java.net.InetSocketAddress; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpConnectionManager; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.apache.commons.httpclient.protocol.Protocol; + +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.apache3.HttpComponent3.SSLProtocolSocketFactory; +import com.foxinmy.weixin4j.model.Consts; + +/** + * 使用commons-httpclient3.x + * + * @className HttpComponent3Factory + * @author jinyu(foxinmy@gmail.com) + * @date 2015年8月12日 + * @since JDK 1.6 + */ +public class HttpComponent3Factory extends HttpClientFactory { + + private final HttpClient httpClient; + + public HttpComponent3Factory() { + this(new HttpClient()); + } + + public HttpComponent3Factory(HttpClient httpClient) { + this.httpClient = httpClient; + this.httpClient.getParams().setHttpElementCharset(Consts.UTF_8.name()); + this.httpClient.getParams().setParameter("http.protocol.uri-charset", + Consts.UTF_8.name()); + // httpMethod.getParams().setUriCharset(Consts.UTF_8.name()); + this.httpClient.getParams().setContentCharset(Consts.UTF_8.name()); + } + + /** + * Resolve Parameter + */ + @Override + protected void resolveHttpParams0(HttpParams params) { + if (params.getProxy() != null) { + InetSocketAddress socketAddress = (InetSocketAddress) params + .getProxy().address(); + httpClient.getHostConfiguration().setProxy( + socketAddress.getHostName(), socketAddress.getPort()); + } + if (params.getSSLContext() != null) { + Protocol.registerProtocol("https", new Protocol("https", + new SSLProtocolSocketFactory(params.getSSLContext()), 443)); + } + httpClient.getHttpConnectionManager().getParams() + .setConnectionTimeout(params.getConnectTimeout()); + } + + public void setHttpConnectionManager( + HttpConnectionManager httpConnectionManager) { + if (httpConnectionManager == null) { + throw new IllegalArgumentException( + "'httpConnectionManager' must not be null"); + } + httpClient.setHttpConnectionManager(httpConnectionManager); + } + + public void setHttpClientParams(HttpClientParams httpClientParams) { + if (httpClientParams == null) { + throw new IllegalArgumentException( + "'httpClientParams' must not be null"); + } + httpClient.setParams(httpClientParams); + } + + @Override + public com.foxinmy.weixin4j.http.HttpClient newInstance() { + return new HttpComponent3(httpClient); + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Response.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3Response.java similarity index 90% rename from weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Response.java rename to weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3Response.java index c3d10376..11b6000f 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent3Response.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache3/HttpComponent3Response.java @@ -1,4 +1,4 @@ -package com.foxinmy.weixin4j.http.factory; +package com.foxinmy.weixin4j.http.support.apache3; import java.io.IOException; @@ -54,9 +54,9 @@ public class HttpComponent3Response extends AbstractHttpResponse { } Header connection = httpMethod.getResponseHeader("Connection"); if (protocol == null) { - protocol = new HttpVersion("HTTP", version.getMinor(), - version.getMajor(), connection != null - && "keep-alive".equalsIgnoreCase(connection + protocol = new HttpVersion("HTTP", version.getMajor(), + version.getMinor(), connection != null + && KEEP_ALIVE.equalsIgnoreCase(connection .getValue())); } return protocol; diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4.java similarity index 78% rename from weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4.java rename to weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4.java index cdd7192e..12d64342 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4.java @@ -1,7 +1,8 @@ -package com.foxinmy.weixin4j.http.factory; +package com.foxinmy.weixin4j.http.support.apache4; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.net.URI; import java.security.cert.X509Certificate; import java.util.List; import java.util.Map.Entry; @@ -29,6 +30,7 @@ import com.foxinmy.weixin4j.http.AbstractHttpClient; import com.foxinmy.weixin4j.http.HttpClientException; import com.foxinmy.weixin4j.http.HttpHeaders; import com.foxinmy.weixin4j.http.HttpMethod; +import com.foxinmy.weixin4j.http.HttpRequest; import com.foxinmy.weixin4j.http.apache.MultipartEntity; import com.foxinmy.weixin4j.http.entity.HttpEntity; import com.foxinmy.weixin4j.util.StringUtil; @@ -43,8 +45,25 @@ import com.foxinmy.weixin4j.util.StringUtil; * @see */ public abstract class HttpComponent4 extends AbstractHttpClient { - protected HttpRequestBase createHttpRequest(HttpMethod method, - java.net.URI uri) throws HttpClientException { + + /** + * Create HttpRequest + */ + protected HttpRequestBase createRequest(HttpRequest request) + throws HttpClientException, IOException { + HttpRequestBase httpRequest = createMethod(request); + resolveHeaders(request.getHeaders(), httpRequest); + resolveContent(request.getEntity(), httpRequest); + return httpRequest; + } + + /** + * Create HttpMethod + */ + protected HttpRequestBase createMethod(HttpRequest request) + throws HttpClientException { + HttpMethod method = request.getMethod(); + URI uri = request.getURI(); if (method == HttpMethod.GET) { return new HttpGet(uri); } else if (method == HttpMethod.HEAD) { @@ -65,7 +84,11 @@ public abstract class HttpComponent4 extends AbstractHttpClient { } } - protected void addHeaders(HttpHeaders headers, HttpRequestBase uriRequest) { + /** + * Resolve Headers + */ + protected void resolveHeaders(HttpHeaders headers, + HttpRequestBase httpRequest) { if (headers == null) { headers = new HttpHeaders(); } @@ -77,21 +100,23 @@ public abstract class HttpComponent4 extends AbstractHttpClient { if (!headers.containsKey(HttpHeaders.USER_AGENT)) { headers.set(HttpHeaders.USER_AGENT, "apache/httpclient4"); } - for (Entry> header : headers - .entrySet()) { + for (Entry> header : headers.entrySet()) { if (HttpHeaders.COOKIE.equalsIgnoreCase(header.getKey())) { - uriRequest.setHeader(header.getKey(), + httpRequest.setHeader(header.getKey(), StringUtil.join(header.getValue(), ';')); } else { for (String headerValue : header.getValue()) { - uriRequest.setHeader(header.getKey(), + httpRequest.setHeader(header.getKey(), headerValue != null ? headerValue : ""); } } } } - protected void addEntity(HttpEntity entity, HttpRequestBase uriRequest) + /** + * Resolve Content + */ + protected void resolveContent(HttpEntity entity, HttpRequestBase httpRequest) throws IOException { if (entity != null) { AbstractHttpEntity httpEntity = null; @@ -107,7 +132,8 @@ public abstract class HttpComponent4 extends AbstractHttpClient { entity.getContentLength()); } httpEntity.setContentType(entity.getContentType().toString()); - ((HttpEntityEnclosingRequestBase) uriRequest).setEntity(httpEntity); + ((HttpEntityEnclosingRequestBase) httpRequest) + .setEntity(httpEntity); } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4Factory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4Factory.java new file mode 100644 index 00000000..f76e6147 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4Factory.java @@ -0,0 +1,47 @@ +package com.foxinmy.weixin4j.http.support.apache4; + +import org.apache.http.util.VersionInfo; + +import com.foxinmy.weixin4j.http.HttpClient; +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; + +/** + * 使用Apache的HttpClient4.x + * + * @className HttpComponent4Factory + * @author jinyu(foxinmy@gmail.com) + * @date 2015年8月12日 + * @since JDK 1.6 + */ +public class HttpComponent4Factory extends HttpClientFactory { + + private static HttpClientFactory httpComponentFactory; + static { + VersionInfo version = VersionInfo.loadVersionInfo( + "org.apache.http.client", HttpClient.class.getClassLoader()); + String release = (version != null) ? version.getRelease() + : VersionInfo.UNAVAILABLE; + if (release.startsWith("4.")) { + if (release.startsWith("4.0") || release.startsWith("4.1") + || release.startsWith("4.2")) { + httpComponentFactory = new HttpComponent4_1Factory(); + } else { + httpComponentFactory = new HttpComponent4_2Factory(); + } + } else { + throw new RuntimeException("unknown the HttpComponent version:" + + release); + } + } + + @Override + public HttpClient newInstance() { + return httpComponentFactory.newInstance(); + } + + @Override + protected void resolveHttpParams0(HttpParams params) { + httpComponentFactory.resolveHttpParams(params); + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1.java new file mode 100644 index 00000000..a694ae0f --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1.java @@ -0,0 +1,49 @@ +package com.foxinmy.weixin4j.http.support.apache4; + +import java.io.IOException; + +import org.apache.http.client.methods.HttpRequestBase; + +import com.foxinmy.weixin4j.http.HttpClientException; +import com.foxinmy.weixin4j.http.HttpRequest; +import com.foxinmy.weixin4j.http.HttpResponse; + +/** + * Requires Apache HttpComponents 4.2 or lower + * + * @className HttpComponent4_1 + * @author jinyu(foxinmy@gmail.com) + * @date 2015年8月18日 + * @since JDK 1.6 + * @see + */ +public class HttpComponent4_1 extends HttpComponent4 { + + private final org.apache.http.client.HttpClient httpClient; + + public HttpComponent4_1(org.apache.http.client.HttpClient httpClient) { + this.httpClient = httpClient; + } + + @Override + public HttpResponse execute(HttpRequest request) throws HttpClientException { + HttpResponse response = null; + try { + HttpRequestBase uriRequest = createRequest(request); + org.apache.http.HttpResponse httpResponse = httpClient + .execute(uriRequest); + response = new HttpComponent4_1Response(httpResponse, + getContent(httpResponse)); + handleResponse(response); + } catch (IOException e) { + throw new HttpClientException("I/O error on " + + request.getMethod().name() + " request for \"" + + request.getURI().toString() + "\":" + e.getMessage(), e); + } finally { + if (response != null) { + response.close(); + } + } + return response; + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1Factory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1Factory.java new file mode 100644 index 00000000..287ba0ee --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1Factory.java @@ -0,0 +1,105 @@ +package com.foxinmy.weixin4j.http.support.apache4; + +import java.net.InetSocketAddress; + +import org.apache.http.HttpHost; +import org.apache.http.conn.params.ConnRoutePNames; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.conn.ssl.X509HostnameVerifier; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.params.CoreConnectionPNames; +import org.apache.http.params.CoreProtocolPNames; + +import com.foxinmy.weixin4j.http.HttpClient; +import com.foxinmy.weixin4j.http.HttpHeaders; +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.apache4.HttpComponent4.CustomHostnameVerifier; +import com.foxinmy.weixin4j.model.Consts; + +/** + * 使用Apache的HttpClient<=4.2 + * + * @className HttpComponent4Factory + * @author jinyu(foxinmy@gmail.com) + * @date 2015年8月12日 + * @since JDK 1.6 + */ +public class HttpComponent4_1Factory extends HttpClientFactory { + + private final org.apache.http.client.HttpClient httpClient; + + public HttpComponent4_1Factory() { + this(new DefaultHttpClient()); + } + + public HttpComponent4_1Factory(org.apache.http.client.HttpClient httpClient) { + this.httpClient = httpClient; + } + + @Override + protected void resolveHttpParams0(HttpParams params) { + if (params == null) { + throw new IllegalArgumentException("'params' must not be empty"); + } + if (params.getProxy() != null) { + InetSocketAddress socketAddress = (InetSocketAddress) params + .getProxy().address(); + HttpHost proxy = new HttpHost(socketAddress.getHostName(), + socketAddress.getPort()); + httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, + proxy); + } + httpClient.getParams().setIntParameter( + CoreConnectionPNames.CONNECTION_TIMEOUT, + params.getConnectTimeout()); + httpClient.getParams().setIntParameter( + CoreConnectionPNames.SO_TIMEOUT, + params.getReadTimeout()); + httpClient.getParams().setParameter( + CoreProtocolPNames.HTTP_CONTENT_CHARSET, Consts.UTF_8); + httpClient.getParams().setParameter( + CoreProtocolPNames.HTTP_ELEMENT_CHARSET, Consts.UTF_8.name()); + httpClient.getParams().setParameter( + CoreProtocolPNames.STRICT_TRANSFER_ENCODING, Consts.UTF_8); + httpClient.getParams().setParameter(HttpHeaders.CONTENT_ENCODING, + Consts.UTF_8); + httpClient.getParams().setParameter(HttpHeaders.ACCEPT_CHARSET, + Consts.UTF_8); + if (params.getSSLContext() != null) { + X509HostnameVerifier hostnameVerifier = null; + if (params.getHostnameVerifier() != null) { + hostnameVerifier = new CustomHostnameVerifier( + params.getHostnameVerifier()); + } + if (hostnameVerifier == null) { + hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; + } + SSLSocketFactory socketFactory = new SSLSocketFactory( + params.getSSLContext()); + socketFactory.setHostnameVerifier(hostnameVerifier); + Scheme scheme = new Scheme("https", socketFactory, 443); + httpClient.getConnectionManager().getSchemeRegistry() + .register(scheme); + } + } + + /** + * 设置Http参数 + * + * @see org.apache.http.params.HttpParams + * @param name + * 参数名 + * @param value + * 参数值 + */ + public void setParameter(String name, Object value) { + httpClient.getParams().setParameter(name, value); + } + + @Override + public HttpClient newInstance() { + return new HttpComponent4_1(httpClient); + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1Response.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1Response.java similarity index 93% rename from weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1Response.java rename to weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1Response.java index 12396250..d28ae466 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_1Response.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_1Response.java @@ -1,4 +1,4 @@ -package com.foxinmy.weixin4j.http.factory; +package com.foxinmy.weixin4j.http.support.apache4; import java.io.IOException; @@ -52,8 +52,8 @@ public class HttpComponent4_1Response extends AbstractHttpResponse { Header connection = httpResponse.getFirstHeader("Connection"); protocol = new HttpVersion(version.getProtocol(), version.getMajor(), version.getMinor(), connection != null - && connection.getValue().equalsIgnoreCase( - "keep-alive")); + && KEEP_ALIVE.equalsIgnoreCase(connection + .getValue())); } return protocol; } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2.java new file mode 100644 index 00000000..3eaaa6e3 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2.java @@ -0,0 +1,50 @@ +package com.foxinmy.weixin4j.http.support.apache4; + +import java.io.IOException; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.impl.client.CloseableHttpClient; + +import com.foxinmy.weixin4j.http.HttpClientException; +import com.foxinmy.weixin4j.http.HttpRequest; +import com.foxinmy.weixin4j.http.HttpResponse; + +/** + * Requires Apache HttpComponents 4.3 or higher + * + * @className HttpComponent4_2 + * @author jinyu(foxinmy@gmail.com) + * @date 2015年8月18日 + * @since JDK 1.6 + * @see + */ +public class HttpComponent4_2 extends HttpComponent4 { + + private final CloseableHttpClient httpClient; + + public HttpComponent4_2(CloseableHttpClient httpClient) { + this.httpClient = httpClient; + } + + @Override + public HttpResponse execute(HttpRequest request) throws HttpClientException { + HttpResponse response = null; + try { + HttpRequestBase uriRequest = createRequest(request); + CloseableHttpResponse httpResponse = httpClient.execute(uriRequest); + response = new HttpComponent4_2Response(httpResponse, + getContent(httpResponse)); + handleResponse(response); + } catch (IOException e) { + throw new HttpClientException("I/O error on " + + request.getMethod().name() + " request for \"" + + request.getURI().toString() + "\":" + e.getMessage(), e); + } finally { + if (response != null) { + response.close(); + } + } + return response; + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2Factory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2Factory.java new file mode 100644 index 00000000..698a8487 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2Factory.java @@ -0,0 +1,101 @@ +package com.foxinmy.weixin4j.http.support.apache4; + +import java.net.InetSocketAddress; + +import org.apache.http.HttpHost; +import org.apache.http.client.HttpRequestRetryHandler; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.config.ConnectionConfig; +import org.apache.http.config.SocketConfig; +import org.apache.http.conn.HttpClientConnectionManager; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.protocol.HttpProcessor; + +import com.foxinmy.weixin4j.http.HttpClient; +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.apache4.HttpComponent4.CustomHostnameVerifier; +import com.foxinmy.weixin4j.model.Consts; + +/** + * 使用Apache的HttpClient>=4.3 + * + * @className HttpComponent4Factory + * @author jinyu(foxinmy@gmail.com) + * @date 2015年8月12日 + * @since JDK 1.6 + */ +public class HttpComponent4_2Factory extends HttpClientFactory { + + private volatile CloseableHttpClient httpClient; + private final HttpClientBuilder clientBuilder; + + public HttpComponent4_2Factory() { + this(HttpClients.custom().setDefaultConnectionConfig( + ConnectionConfig.custom().setCharset(Consts.UTF_8).build())); + } + + public HttpComponent4_2Factory(HttpClientBuilder clientBuilder) { + this.clientBuilder = clientBuilder; + } + + @Override + public void resolveHttpParams0(HttpParams params) { + clientBuilder.setDefaultRequestConfig(RequestConfig.custom() + .setConnectTimeout(params.getConnectTimeout()) + .setConnectionRequestTimeout(params.getReadTimeout()).build()); + if (params.getProxy() != null) { + InetSocketAddress socketAddress = (InetSocketAddress) params + .getProxy().address(); + HttpHost proxy = new HttpHost(socketAddress.getHostName(), + socketAddress.getPort()); + clientBuilder.setProxy(proxy); + } + if (params.getHostnameVerifier() != null) { + clientBuilder.setHostnameVerifier(new CustomHostnameVerifier(params + .getHostnameVerifier())); + } + if (params.getSSLContext() != null) { + clientBuilder.setSslcontext(params.getSSLContext()); + } + } + + public HttpComponent4_2Factory setDefaultConnectionConfig( + ConnectionConfig connectionConfig) { + clientBuilder.setDefaultConnectionConfig(connectionConfig); + return this; + } + + public HttpComponent4_2Factory setDefaultSocketConfig( + SocketConfig socketConfig) { + clientBuilder.setDefaultSocketConfig(socketConfig); + return this; + } + + public HttpComponent4_2Factory setConnectionManager( + HttpClientConnectionManager connectionManager) { + clientBuilder.setConnectionManager(connectionManager); + return this; + } + + public HttpComponent4_2Factory setHttpProcessor(HttpProcessor httpprocessor) { + clientBuilder.setHttpProcessor(httpprocessor); + return this; + } + + public HttpComponent4_2Factory retryHandler( + HttpRequestRetryHandler retryHandler) { + clientBuilder.setRetryHandler(retryHandler); + return this; + } + + @Override + public HttpClient newInstance() { + if (httpClient == null) { + this.httpClient = clientBuilder.build(); + } + return new HttpComponent4_2(httpClient); + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2Response.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2Response.java similarity index 94% rename from weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2Response.java rename to weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2Response.java index b9d73f51..8a942458 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/HttpComponent4_2Response.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/apache4/HttpComponent4_2Response.java @@ -1,4 +1,4 @@ -package com.foxinmy.weixin4j.http.factory; +package com.foxinmy.weixin4j.http.support.apache4; import java.io.IOException; @@ -55,8 +55,8 @@ public class HttpComponent4_2Response extends AbstractHttpResponse { Header connection = httpResponse.getFirstHeader("Connection"); protocol = new HttpVersion(version.getProtocol(), version.getMajor(), version.getMinor(), connection != null - && connection.getValue().equalsIgnoreCase( - "keep-alive")); + && KEEP_ALIVE.equalsIgnoreCase(connection + .getValue())); } return protocol; } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClient.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/netty/Netty4HttpClient.java similarity index 85% rename from weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClient.java rename to weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/netty/Netty4HttpClient.java index acafa0dc..866a7743 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClient.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/netty/Netty4HttpClient.java @@ -1,4 +1,4 @@ -package com.foxinmy.weixin4j.http.factory; +package com.foxinmy.weixin4j.http.support.netty; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; @@ -8,7 +8,6 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOption; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultHttpRequest; @@ -16,7 +15,6 @@ import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.ssl.SslHandler; -import io.netty.handler.timeout.ReadTimeoutHandler; import java.io.IOException; import java.net.InetAddress; @@ -25,7 +23,6 @@ import java.net.URI; import java.util.List; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; @@ -37,6 +34,7 @@ import com.foxinmy.weixin4j.http.HttpParams; import com.foxinmy.weixin4j.http.HttpRequest; import com.foxinmy.weixin4j.http.HttpResponse; import com.foxinmy.weixin4j.http.entity.HttpEntity; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.util.SettableFuture; import com.foxinmy.weixin4j.util.StringUtil; @@ -53,25 +51,19 @@ import com.foxinmy.weixin4j.util.StringUtil; public class Netty4HttpClient extends AbstractHttpClient { private final Bootstrap bootstrap; + private final HttpParams params; - public Netty4HttpClient(Bootstrap bootstrap) { + public Netty4HttpClient(Bootstrap bootstrap, HttpParams params) { this.bootstrap = bootstrap; + this.params = params; } @Override - public HttpResponse execute(HttpRequest request) throws HttpClientException { + public HttpResponse execute(final HttpRequest request) + throws HttpClientException { HttpResponse response = null; try { final URI uri = request.getURI(); - final HttpParams params = request.getParams(); - if (params != null) { - bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, - params.getConnectTimeout()); - } - final boolean useProxy = params != null - && params.getProxy() != null; - final boolean useSSL = "https".equals(uri.getScheme()) && !useProxy; - final DefaultHttpRequest uriRequest = createRequest(request); final SettableFuture future = new SettableFuture(); ChannelFutureListener listener = new ChannelFutureListener() { @Override @@ -79,9 +71,8 @@ public class Netty4HttpClient extends AbstractHttpClient { throws Exception { if (channelFuture.isSuccess()) { Channel channel = channelFuture.channel(); - // ssl - SSLContext sslContext = null; - if (useSSL) { + if ("https".equals(uri.getScheme())) { + SSLContext sslContext; if (params != null && params.getSSLContext() != null) { sslContext = params.getSSLContext(); @@ -93,25 +84,20 @@ public class Netty4HttpClient extends AbstractHttpClient { sslEngine.setUseClientMode(true); channel.pipeline().addFirst( new SslHandler(sslEngine)); - if (params != null && params.getReadTimeout() > 0) { - channel.pipeline().addFirst( - new ReadTimeoutHandler(params - .getReadTimeout(), - TimeUnit.MILLISECONDS)); - } } channel.pipeline().addLast(new RequestHandler(future)); + DefaultHttpRequest uriRequest = createRequest(request); channel.writeAndFlush(uriRequest); } else { future.setException(channelFuture.cause()); } } }; - InetSocketAddress address = useProxy ? (InetSocketAddress) params + InetSocketAddress address = params != null + && params.getProxy() != null ? (InetSocketAddress) params .getProxy().address() : new InetSocketAddress( InetAddress.getByName(uri.getHost()), getPort(uri)); - bootstrap.connect(address).syncUninterruptibly() - .addListener(listener); + bootstrap.connect(address).addListener(listener); response = future.get(); handleResponse(response); } catch (IOException e) { diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClientFactory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/netty/Netty4HttpClientFactory.java similarity index 52% rename from weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClientFactory.java rename to weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/netty/Netty4HttpClientFactory.java index 000a0fff..49fa8cd8 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClientFactory.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/netty/Netty4HttpClientFactory.java @@ -1,4 +1,4 @@ -package com.foxinmy.weixin4j.http.factory; +package com.foxinmy.weixin4j.http.support.netty; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; @@ -13,47 +13,70 @@ import io.netty.handler.codec.http.HttpContentDecompressor; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpResponseDecoder; import io.netty.handler.stream.ChunkedWriteHandler; +import io.netty.handler.timeout.ReadTimeoutHandler; + +import java.util.Map; +import java.util.concurrent.TimeUnit; import com.foxinmy.weixin4j.http.HttpClient; +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; /** - * 使用Netty + * 使用Netty4 * * @className Netty4HttpClientFactory * @author jinyu(foxinmy@gmail.com) * @date 2015年8月30日 * @since JDK 1.6 - * @see */ public class Netty4HttpClientFactory extends HttpClientFactory { - /** - * worker线程数,默认设置为cpu的核数 * 4 - */ - private final int workerThreads; + private volatile Bootstrap bootstrap; + private EventLoopGroup eventLoopGroup; + private Map, ?> options; + private HttpParams params; public Netty4HttpClientFactory() { - this(Runtime.getRuntime().availableProcessors() * 4); + this(new NioEventLoopGroup( + Runtime.getRuntime().availableProcessors() * 4)); } - public Netty4HttpClientFactory(int workerThreads) { - this.workerThreads = workerThreads; + public Netty4HttpClientFactory(EventLoopGroup eventLoopGroup) { + this.eventLoopGroup = eventLoopGroup; } - private volatile Bootstrap bootstrap; - @Override - public HttpClient newInstance() { + protected void resolveHttpParams0(HttpParams params) { + this.params = params; + } + + public Netty4HttpClientFactory setOptions(Map, ?> options) { + if (options == null) { + throw new IllegalArgumentException("'options' must not be empty"); + } + this.options = options; + return this; + } + + private Bootstrap getBootstrap() { if (bootstrap == null) { bootstrap = new Bootstrap(); - bootstrap.option(ChannelOption.SO_KEEPALIVE, true).option( - ChannelOption.TCP_NODELAY, true); - EventLoopGroup workerGroup = new NioEventLoopGroup(workerThreads); - bootstrap.group(workerGroup).channel(NioSocketChannel.class) + bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class) .handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); + if (params != null) { + channel.config().setConnectTimeoutMillis( + params.getConnectTimeout()); + if (options != null) { + channel.config().setOptions(options); + } + pipeline.addLast(new ReadTimeoutHandler(params + .getReadTimeout(), + TimeUnit.MILLISECONDS)); + } pipeline.addLast(new HttpClientCodec()); pipeline.addLast(new HttpContentDecompressor()); pipeline.addLast(new ChunkedWriteHandler()); @@ -63,6 +86,11 @@ public class Netty4HttpClientFactory extends HttpClientFactory { } }); } - return new Netty4HttpClient(bootstrap); + return bootstrap; + } + + @Override + public HttpClient newInstance() { + return new Netty4HttpClient(getBootstrap(), params); } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpResponse.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/netty/Netty4HttpResponse.java similarity index 92% rename from weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpResponse.java rename to weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/netty/Netty4HttpResponse.java index 9ff25ff4..551be698 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpResponse.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/netty/Netty4HttpResponse.java @@ -1,4 +1,4 @@ -package com.foxinmy.weixin4j.http.factory; +package com.foxinmy.weixin4j.http.support.netty; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpResponse; @@ -27,7 +27,7 @@ public class Netty4HttpResponse extends AbstractHttpResponse { private HttpVersion protocol; private HttpStatus status; - private volatile HttpHeaders headers; + private HttpHeaders headers; public Netty4HttpResponse(ChannelHandlerContext context, FullHttpResponse response, byte[] content) { @@ -40,11 +40,10 @@ public class Netty4HttpResponse extends AbstractHttpResponse { @Override public HttpHeaders getHeaders() { if (this.headers == null) { - HttpHeaders headers = new HttpHeaders(); + this.headers = new HttpHeaders(); for (Map.Entry entry : this.response.headers()) { headers.add(entry.getKey(), entry.getValue()); } - this.headers = headers; } return this.headers; } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient2.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient2.java new file mode 100644 index 00000000..5344ba1b --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient2.java @@ -0,0 +1,144 @@ +package com.foxinmy.weixin4j.http.support.okhttp; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.List; +import java.util.Map.Entry; + +import okio.BufferedSink; + +import com.foxinmy.weixin4j.http.AbstractHttpClient; +import com.foxinmy.weixin4j.http.HttpClientException; +import com.foxinmy.weixin4j.http.HttpHeaders; +import com.foxinmy.weixin4j.http.HttpMethod; +import com.foxinmy.weixin4j.http.HttpRequest; +import com.foxinmy.weixin4j.http.HttpResponse; +import com.foxinmy.weixin4j.http.entity.HttpEntity; +import com.foxinmy.weixin4j.util.StringUtil; +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.RequestBody; +import com.squareup.okhttp.Response; + +/** + * OkHttp2 + * + * @className OkHttpClient2 + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月25日 + * @since JDK 1.6 + */ +public class OkHttpClient2 extends AbstractHttpClient { + private final OkHttpClient okClient; + + public OkHttpClient2(OkHttpClient okClient) { + this.okClient = okClient; + } + + @Override + public HttpResponse execute(HttpRequest request) throws HttpClientException { + HttpResponse response = null; + try { + Request okRequest = createRequest(request); + Response okResponse = okClient.newCall(okRequest).execute(); + response = new OkHttpResponse2(okResponse, okResponse.body() + .bytes()); + handleResponse(response); + } catch (IOException e) { + throw new HttpClientException("I/O error on " + + request.getMethod().name() + " request for \"" + + request.getURI().toString() + "\":" + e.getMessage(), e); + } finally { + if (response != null) { + response.close(); + } + } + return response; + } + + /** + * create OkRequest + */ + protected Request createRequest(HttpRequest request) + throws HttpClientException { + Request.Builder requestBuilder = createBuilder(request); + resolveHeaders(request.getHeaders(), requestBuilder); + resolveContent(request.getEntity(), request.getMethod(), requestBuilder); + return requestBuilder.build(); + } + + /** + * create Request.Builder + * + * @throws HttpClientException + */ + protected Request.Builder createBuilder(HttpRequest request) + throws HttpClientException { + Request.Builder requestBuilder = new Request.Builder(); + try { + requestBuilder.url(request.getURI().toURL()); + } catch (MalformedURLException e) { + throw new HttpClientException("format URI error", e); + } + return requestBuilder; + } + + /** + * resolve Request.Headers + * */ + protected void resolveHeaders( + com.foxinmy.weixin4j.http.HttpHeaders headers, + Request.Builder requestBuilder) { + if (headers == null) { + headers = new HttpHeaders(); + } + // Add default accept headers + if (!headers.containsKey(HttpHeaders.ACCEPT)) { + headers.set(HttpHeaders.ACCEPT, "*/*"); + } + // Add default user agent + if (!headers.containsKey(HttpHeaders.USER_AGENT)) { + headers.set(HttpHeaders.USER_AGENT, "square/okhttp2"); + } + for (Entry> header : headers.entrySet()) { + if (HttpHeaders.COOKIE.equalsIgnoreCase(header.getKey())) { + requestBuilder.header(header.getKey(), + StringUtil.join(header.getValue(), ';')); + } else { + for (String headerValue : header.getValue()) { + requestBuilder.header(header.getKey(), + headerValue != null ? headerValue : ""); + } + } + } + } + + /** + * resolve Request.Content + */ + protected void resolveContent(final HttpEntity entity, HttpMethod method, + Request.Builder requestBuilder) throws HttpClientException { + RequestBody body = null; + if (entity != null) { + body = new RequestBody() { + + @Override + public long contentLength() throws IOException { + return entity.getContentLength(); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + entity.writeTo(sink.outputStream()); + } + + @Override + public MediaType contentType() { + return MediaType.parse(entity.getContentType().toString()); + } + }; + } + requestBuilder.method(method.name(), body); + } +} \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient2Factory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient2Factory.java new file mode 100644 index 00000000..d8d5d855 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient2Factory.java @@ -0,0 +1,85 @@ +package com.foxinmy.weixin4j.http.support.okhttp; + +import java.net.CookieHandler; +import java.util.concurrent.TimeUnit; + +import com.foxinmy.weixin4j.http.HttpClient; +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.squareup.okhttp.Cache; +import com.squareup.okhttp.ConnectionPool; +import com.squareup.okhttp.Dispatcher; +import com.squareup.okhttp.Dns; +import com.squareup.okhttp.OkHttpClient; + +/** + * 使用OkHttp2 + * + * @className OkHttpClient2Factory + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月25日 + * @since JDK 1.6 + */ +public class OkHttpClient2Factory extends HttpClientFactory { + private final OkHttpClient okClient; + + public OkHttpClient2Factory() { + this(new OkHttpClient()); + } + + public OkHttpClient2Factory(OkHttpClient okClient) { + this.okClient = okClient; + } + + @Override + protected void resolveHttpParams0(HttpParams params) { + okClient.setConnectTimeout(params.getConnectTimeout(), + TimeUnit.MILLISECONDS); + okClient.setReadTimeout(params.getReadTimeout(), TimeUnit.MILLISECONDS); + if (params.getProxy() != null) { + okClient.setProxy(params.getProxy()); + } + if (params.getHostnameVerifier() != null) { + okClient.setHostnameVerifier(params.getHostnameVerifier()); + } + if (params.getSSLContext() != null) { + okClient.setSslSocketFactory(params.getSSLContext() + .getSocketFactory()); + } + } + + public OkHttpClient2Factory setWriteTimeout(int writeTimeout) { + okClient.setWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS); + return this; + } + + public OkHttpClient2Factory setCache(Cache cache) { + okClient.setCache(cache); + return this; + } + + public OkHttpClient2Factory setConnectionPool(ConnectionPool connectionPool) { + okClient.setConnectionPool(connectionPool); + return this; + } + + public OkHttpClient2Factory setCookieHandler(CookieHandler cookieHandler) { + okClient.setCookieHandler(cookieHandler); + return this; + } + + public OkHttpClient2Factory setDispatcher(Dispatcher dispatcher) { + okClient.setDispatcher(dispatcher); + return this; + } + + public OkHttpClient2Factory setDns(Dns dns) { + okClient.setDns(dns); + return this; + } + + @Override + public HttpClient newInstance() { + return new OkHttpClient2(okClient); + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient3.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient3.java new file mode 100644 index 00000000..cdfe50db --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient3.java @@ -0,0 +1,144 @@ +package com.foxinmy.weixin4j.http.support.okhttp; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.List; +import java.util.Map.Entry; + +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.RequestBody; +import okio.BufferedSink; + +import com.foxinmy.weixin4j.http.AbstractHttpClient; +import com.foxinmy.weixin4j.http.HttpClientException; +import com.foxinmy.weixin4j.http.HttpHeaders; +import com.foxinmy.weixin4j.http.HttpRequest; +import com.foxinmy.weixin4j.http.HttpResponse; +import com.foxinmy.weixin4j.http.entity.HttpEntity; +import com.foxinmy.weixin4j.util.StringUtil; + +/** + * OkHttp3 + * + * @className OkHttpClient3 + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月25日 + * @since JDK 1.6 + */ +public class OkHttpClient3 extends AbstractHttpClient { + + private final OkHttpClient okClient; + + public OkHttpClient3(OkHttpClient okClient) { + this.okClient = okClient; + } + + @Override + public HttpResponse execute(HttpRequest request) throws HttpClientException { + HttpResponse response = null; + try { + okhttp3.Request okRequest = createRequest(request); + okhttp3.Response okResponse = okClient.newCall(okRequest) + .execute(); + response = new OkHttpResponse3(okResponse, okResponse.body() + .bytes()); + handleResponse(response); + } catch (IOException e) { + throw new HttpClientException("I/O error on " + + request.getMethod().name() + " request for \"" + + request.getURI().toString() + "\":" + e.getMessage(), e); + } finally { + if (response != null) { + response.close(); + } + } + return response; + } + + /** + * create OkRequest + */ + protected okhttp3.Request createRequest(HttpRequest request) + throws HttpClientException { + okhttp3.Request.Builder requestBuilder = createBuilder(request); + resolveHeaders(requestBuilder, request); + resolveContent(requestBuilder, request); + return requestBuilder.build(); + } + + /** + * create Request.Builder + * + * @throws HttpClientException + */ + protected okhttp3.Request.Builder createBuilder(HttpRequest request) + throws HttpClientException { + okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); + try { + requestBuilder.url(request.getURI().toURL()); + } catch (MalformedURLException e) { + throw new HttpClientException("format URI error", e); + } + return requestBuilder; + } + + /** + * resolve Request.Headers + * */ + protected void resolveHeaders(okhttp3.Request.Builder builder, + HttpRequest request) { + com.foxinmy.weixin4j.http.HttpHeaders headers = request.getHeaders(); + if (headers == null) { + headers = new HttpHeaders(); + } + // Add default accept headers + if (!headers.containsKey(HttpHeaders.ACCEPT)) { + headers.set(HttpHeaders.ACCEPT, "*/*"); + } + // Add default user agent + if (!headers.containsKey(HttpHeaders.USER_AGENT)) { + headers.set(HttpHeaders.USER_AGENT, "square/okhttp3"); + } + for (Entry> header : headers.entrySet()) { + if (HttpHeaders.COOKIE.equalsIgnoreCase(header.getKey())) { + builder.header(header.getKey(), + StringUtil.join(header.getValue(), ';')); + } else { + for (String headerValue : header.getValue()) { + builder.header(header.getKey(), + headerValue != null ? headerValue : ""); + } + } + } + } + + /** + * resolve Request.Content + */ + protected void resolveContent(okhttp3.Request.Builder builder, + HttpRequest request) throws HttpClientException { + final HttpEntity entity = request.getEntity(); + okhttp3.RequestBody body = null; + if (entity != null) { + body = new RequestBody() { + + @Override + public long contentLength() throws IOException { + return entity.getContentLength(); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + entity.writeTo(sink.outputStream()); + } + + @Override + public MediaType contentType() { + return MediaType.parse(entity.getContentType().toString()); + } + }; + } + builder.method(request.getMethod().name(), body); + } +} \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient3Factory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient3Factory.java new file mode 100644 index 00000000..c773975c --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClient3Factory.java @@ -0,0 +1,108 @@ +package com.foxinmy.weixin4j.http.support.okhttp; + +import java.util.concurrent.TimeUnit; + +import okhttp3.Cache; +import okhttp3.ConnectionPool; +import okhttp3.CookieJar; +import okhttp3.Dispatcher; +import okhttp3.Dns; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; + +import com.foxinmy.weixin4j.http.HttpClient; +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; + +/** + * 使用OkHttp3 + * + * @className OkHttpClient3Factory + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月25日 + * @since JDK 1.6 + */ +public class OkHttpClient3Factory extends HttpClientFactory { + private volatile OkHttpClient okClient; + private final OkHttpClient.Builder clientBuilder; + + public OkHttpClient3Factory() { + this(new OkHttpClient.Builder()); + } + + public OkHttpClient3Factory(OkHttpClient.Builder clientBuilder) { + this.clientBuilder = clientBuilder; + } + + /** + * resolve Request.Parameter + * + * */ + @Override + protected void resolveHttpParams0(HttpParams params) { + clientBuilder.connectTimeout(params.getConnectTimeout(), + TimeUnit.MILLISECONDS); + clientBuilder.readTimeout(params.getReadTimeout(), + TimeUnit.MILLISECONDS); + if (params.getProxy() != null) { + clientBuilder.proxy(params.getProxy()); + } + if (params.getHostnameVerifier() != null) { + clientBuilder.hostnameVerifier(params.getHostnameVerifier()); + } + if (params.getSSLContext() != null) { + clientBuilder.sslSocketFactory(params.getSSLContext() + .getSocketFactory(), + HttpClientFactory.AllowX509TrustManager.GLOBAL); + } + } + + public OkHttpClient3Factory setWriteTimeout(int writeTimeout) { + clientBuilder.writeTimeout(writeTimeout, TimeUnit.MILLISECONDS); + return this; + } + + public OkHttpClient3Factory addInterceptor(Interceptor interceptor) { + clientBuilder.addInterceptor(interceptor); + return this; + } + + public OkHttpClient3Factory retryOnConnectionFailure( + boolean retryOnConnectionFailure) { + clientBuilder.retryOnConnectionFailure(retryOnConnectionFailure); + return this; + } + + public OkHttpClient3Factory setCookieJar(CookieJar cookieJar) { + clientBuilder.cookieJar(cookieJar); + return this; + } + + public OkHttpClient3Factory setCache(Cache cache) { + clientBuilder.cache(cache); + return this; + } + + public OkHttpClient3Factory setConnectionPool(ConnectionPool connectionPool) { + clientBuilder.connectionPool(connectionPool); + return this; + } + + public OkHttpClient3Factory setDispatcher(Dispatcher dispatcher) { + clientBuilder.dispatcher(dispatcher); + return this; + } + + public OkHttpClient3Factory setDns(Dns dns) { + clientBuilder.dns(dns); + return this; + } + + @Override + public HttpClient newInstance() { + if (okClient == null) { + this.okClient = clientBuilder.build(); + } + return new OkHttpClient3(okClient); + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClientFactory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClientFactory.java new file mode 100644 index 00000000..a14ea65f --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpClientFactory.java @@ -0,0 +1,38 @@ +package com.foxinmy.weixin4j.http.support.okhttp; + +import com.foxinmy.weixin4j.http.HttpClient; +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; + +/** + * 使用OkHttp + * + * @className OkHttpClientFactory + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月25日 + * @since JDK 1.6 + */ +public class OkHttpClientFactory extends HttpClientFactory { + private static HttpClientFactory okHttpClientFactory; + static { + try { + okHttpClientFactory = new OkHttpClient2Factory(); + } catch (Throwable e1) { + try { + okHttpClientFactory = new OkHttpClient3Factory(); + } catch (Throwable e2) { + throw e2; + } + } + } + + @Override + protected void resolveHttpParams0(HttpParams params) { + okHttpClientFactory.resolveHttpParams(params); + } + + @Override + public HttpClient newInstance() { + return okHttpClientFactory.newInstance(); + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpResponse2.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpResponse2.java new file mode 100644 index 00000000..b4135c23 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpResponse2.java @@ -0,0 +1,77 @@ +package com.foxinmy.weixin4j.http.support.okhttp; + + +import com.foxinmy.weixin4j.http.AbstractHttpResponse; +import com.foxinmy.weixin4j.http.HttpHeaders; +import com.foxinmy.weixin4j.http.HttpStatus; +import com.foxinmy.weixin4j.http.HttpVersion; +import com.squareup.okhttp.Headers; +import com.squareup.okhttp.Protocol; +import com.squareup.okhttp.Response; + +/** + * OkHttp Response:Requires OkHttp 2.x + * + * @className OkHttpResponse2 + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月25日 + * @since JDK 1.6 + */ +public class OkHttpResponse2 extends AbstractHttpResponse { + private final Response response; + private HttpHeaders headers; + private HttpVersion protocol; + private HttpStatus status; + + public OkHttpResponse2(Response response, byte[] content) { + super(content); + this.response = response; + } + + @Override + public HttpHeaders getHeaders() { + if (this.headers == null) { + this.headers = new HttpHeaders(); + Headers headers = this.response.headers(); + for (int i = 0; i < headers.size(); i++) { + this.headers.add(headers.name(i), headers.value(i)); + } + } + return this.headers; + } + + @Override + public HttpVersion getProtocol() { + if (protocol == null) { + String protocol = this.response.protocol().toString().split("/")[0]; + boolean keepAlive = KEEP_ALIVE.equalsIgnoreCase(this.response + .header("Connection")); + if (this.response.protocol() == Protocol.HTTP_1_0) { + return new HttpVersion(protocol, 1, 0, keepAlive); + } else if (this.response.protocol() == Protocol.HTTP_1_1) { + return new HttpVersion(protocol, 1, 1, keepAlive); + } else if (this.response.protocol() == Protocol.HTTP_2) { + return new HttpVersion(protocol, 2, 0, keepAlive); + } else if (this.response.protocol() == Protocol.SPDY_3) { + return new HttpVersion(protocol, 3, 0, keepAlive); + } else { + this.protocol = new HttpVersion(protocol, keepAlive); + } + } + return protocol; + } + + @Override + public HttpStatus getStatus() { + if (status == null) { + status = new HttpStatus(this.response.code(), + this.response.message()); + } + return status; + } + + @Override + public void close() { + // nothing + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpResponse3.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpResponse3.java new file mode 100644 index 00000000..d71d3cf7 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/support/okhttp/OkHttpResponse3.java @@ -0,0 +1,75 @@ +package com.foxinmy.weixin4j.http.support.okhttp; + +import okhttp3.Protocol; + +import com.foxinmy.weixin4j.http.AbstractHttpResponse; +import com.foxinmy.weixin4j.http.HttpHeaders; +import com.foxinmy.weixin4j.http.HttpStatus; +import com.foxinmy.weixin4j.http.HttpVersion; + +/** + * OkHttp Response:Requires OkHttp 3.x or higher + * + * @className OkHttpResponse3 + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月25日 + * @since JDK 1.6 + */ +public class OkHttpResponse3 extends AbstractHttpResponse { + private final okhttp3.Response response; + private HttpHeaders headers; + private HttpVersion protocol; + private HttpStatus status; + + public OkHttpResponse3(okhttp3.Response response, byte[] content) { + super(content); + this.response = response; + } + + @Override + public HttpHeaders getHeaders() { + if (this.headers == null) { + this.headers = new HttpHeaders(); + okhttp3.Headers headers = this.response.headers(); + for (int i = 0; i < headers.size(); i++) { + this.headers.add(headers.name(i), headers.value(i)); + } + } + return this.headers; + } + + @Override + public HttpVersion getProtocol() { + if (protocol == null) { + String protocol = this.response.protocol().toString().split("/")[0]; + boolean keepAlive = KEEP_ALIVE.equalsIgnoreCase(this.response + .header("Connection")); + if (this.response.protocol() == Protocol.HTTP_1_0) { + return new HttpVersion(protocol, 1, 0, keepAlive); + } else if (this.response.protocol() == Protocol.HTTP_1_1) { + return new HttpVersion(protocol, 1, 1, keepAlive); + } else if (this.response.protocol() == Protocol.HTTP_2) { + return new HttpVersion(protocol, 2, 0, keepAlive); + } else if (this.response.protocol() == Protocol.SPDY_3) { + return new HttpVersion(protocol, 3, 0, keepAlive); + } else { + this.protocol = new HttpVersion(protocol, keepAlive); + } + } + return protocol; + } + + @Override + public HttpStatus getStatus() { + if (status == null) { + status = new HttpStatus(this.response.code(), + this.response.message()); + } + return status; + } + + @Override + public void close() { + response.close(); + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java index 64000432..58846e33 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinRequestExecutor.java @@ -1,7 +1,12 @@ package com.foxinmy.weixin4j.http.weixin; import java.io.IOException; -import java.util.Map; +import java.io.InputStream; +import java.security.KeyStore; +import java.util.Arrays; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.HttpClient; @@ -10,6 +15,7 @@ import com.foxinmy.weixin4j.http.HttpMethod; import com.foxinmy.weixin4j.http.HttpParams; import com.foxinmy.weixin4j.http.HttpRequest; import com.foxinmy.weixin4j.http.HttpResponse; +import com.foxinmy.weixin4j.http.URLParameter; import com.foxinmy.weixin4j.http.apache.FormBodyPart; import com.foxinmy.weixin4j.http.apache.HttpMultipartMode; import com.foxinmy.weixin4j.http.apache.MultipartEntity; @@ -35,45 +41,31 @@ import com.foxinmy.weixin4j.model.Consts; */ public class WeixinRequestExecutor { - protected final InternalLogger logger = InternalLoggerFactory.getInstance(getClass()); + protected final InternalLogger logger = InternalLoggerFactory + .getInstance(getClass()); private static final String SUCCESS_CODE = ",0,success,"; - protected final HttpClient httpClient; - protected final HttpParams httpParams; + private final HttpClient httpClient; public WeixinRequestExecutor() { - this(new HttpParams()); - } - - public WeixinRequestExecutor(HttpParams httpParams) { this.httpClient = HttpClientFactory.getInstance(); - this.httpParams = httpParams; } - public WeixinResponse get(String url) throws WeixinException { - HttpRequest request = new HttpRequest(HttpMethod.GET, url); - return doRequest(request); - } - - public WeixinResponse get(String url, Map parameters) throws WeixinException { - StringBuilder buf = new StringBuilder(url); - if (parameters != null && !parameters.isEmpty()) { - if (url.indexOf("?") < 0) { - buf.append("?"); - } else { - buf.append("&"); - } - buf.append(FormUrlEntity.formatParameters(parameters)); - } - return doRequest(new HttpRequest(HttpMethod.GET, buf.toString())); - } - - public WeixinResponse post(String url) throws WeixinException { - HttpRequest request = new HttpRequest(HttpMethod.POST, url); - return doRequest(request); + public WeixinRequestExecutor(HttpParams params) { + this.httpClient = HttpClientFactory.getInstance(params); } + /** + * Post方法执行微信请求 + * + * @param url + * 请求URL + * @param body + * 参数内容 + * @return 微信响应 + * @throws WeixinException + */ public WeixinResponse post(String url, String body) throws WeixinException { HttpEntity entity = new StringEntity(body); HttpRequest request = new HttpRequest(HttpMethod.POST, url); @@ -81,8 +73,20 @@ public class WeixinRequestExecutor { return doRequest(request); } - public WeixinResponse post(String url, FormBodyPart... bodyParts) throws WeixinException { - MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null, Consts.UTF_8); + /** + * Post方法执行微信请求,用于文件上传 + * + * @param url + * 请求URL + * @param bodyParts + * 文件内容 + * @return 微信响应 + * @throws WeixinException + */ + public WeixinResponse post(String url, FormBodyPart... bodyParts) + throws WeixinException { + MultipartEntity entity = new MultipartEntity( + HttpMultipartMode.BROWSER_COMPATIBLE, null, Consts.UTF_8); for (FormBodyPart bodyPart : bodyParts) { entity.addPart(bodyPart); } @@ -91,31 +95,74 @@ public class WeixinRequestExecutor { return doRequest(request); } - protected WeixinResponse doRequest(HttpRequest request) throws WeixinException { - request.setParams(httpParams); + /** + * Get方法执行微信请求 + * + * @param url + * 请求URL,如:https://api.weixin.qq.com/cgi-bin/token + * @param parameters + * url上的参数,如:new URLParameter("appid",xxxxx) + * @return 微信响应 + * @throws WeixinException + */ + public WeixinResponse get(String url, URLParameter... parameters) + throws WeixinException { + // always contain the question mark + StringBuilder buf = new StringBuilder(url).append("&"); + if (parameters != null && parameters.length > 0) { + buf.append(FormUrlEntity.formatParameters(Arrays.asList(parameters))); + } + HttpRequest request = new HttpRequest(HttpMethod.GET, buf.toString()); + return doRequest(request); + } + + /** + * 执行微信请求 + * + * @param request + * 微信请求 + * @return 微信响应 + * @throws WeixinException + */ + protected WeixinResponse doRequest(HttpRequest request) + throws WeixinException { try { - logger.info("weixin request >> " + request.getMethod() + " " + request.getURI().toString()); + logger.info("weixin request >> " + request.getMethod() + " " + + request.getURI().toString()); HttpResponse httpResponse = httpClient.execute(request); WeixinResponse response = new WeixinResponse(httpResponse); - logger.info("weixin response << " + httpResponse.getProtocol() + httpResponse.getStatus() + ":" - + response.getAsString()); - handlResponse(response); + logger.info("weixin response << " + httpResponse.getProtocol() + + httpResponse.getStatus() + ":" + response.getAsString()); + handleResponse(response); return response; } catch (HttpClientException e) { throw new WeixinException(e); } } - protected void handlResponse(WeixinResponse response) throws WeixinException { + /** + * handle the weixin response + * + * @param response + * 微信请求响应 + * @throws WeixinException + */ + protected void handleResponse(WeixinResponse response) + throws WeixinException { ApiResult result = response.getAsResult(); - if (!SUCCESS_CODE.contains(String.format(",%s,", result.getReturnCode().toLowerCase()))) { - throw new WeixinException(result.getReturnCode(), result.getReturnMsg()); + if (!SUCCESS_CODE.contains(String.format(",%s,", result.getReturnCode() + .toLowerCase()))) { + throw new WeixinException(result.getReturnCode(), + result.getReturnMsg()); } if (XmlMessageConverter.GLOBAL.canConvert(XmlResult.class, response)) { try { - XmlResult xmlResult = XmlMessageConverter.GLOBAL.convert(XmlResult.class, response); - if (!SUCCESS_CODE.contains(String.format(",%s,", xmlResult.getResultCode().toLowerCase()))) { - throw new WeixinException(xmlResult.getErrCode(), xmlResult.getErrCodeDes()); + XmlResult xmlResult = XmlMessageConverter.GLOBAL.convert( + XmlResult.class, response); + if (!SUCCESS_CODE.contains(String.format(",%s,", xmlResult + .getResultCode().toLowerCase()))) { + throw new WeixinException(xmlResult.getErrCode(), + xmlResult.getErrCodeDes()); } } catch (IOException e) { ; @@ -127,7 +174,39 @@ public class WeixinRequestExecutor { return httpClient; } - public HttpParams getExecuteParams() { - return httpParams; + /** + * 创建 SSL微信请求对象 + * + * @param password + * 加载密钥 + * @param inputStream + * 密钥内容 + * @return 微信请求 + * @throws WeixinException + */ + public WeixinRequestExecutor createSSLRequestExecutor(String password, + InputStream inputStream) throws WeixinException { + try { + KeyStore keyStore = KeyStore.getInstance(Consts.PKCS12); + keyStore.load(inputStream, password.toCharArray()); + KeyManagerFactory kmf = KeyManagerFactory + .getInstance(Consts.SunX509); + kmf.init(keyStore, password.toCharArray()); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(kmf.getKeyManagers(), null, + new java.security.SecureRandom()); + return createSSLRequestExecutor(sslContext); + } catch (Exception e) { + throw new WeixinException("Key load error", e); + } + } + + public WeixinRequestExecutor createSSLRequestExecutor(SSLContext sslContext) { + if (sslContext == null) { + throw new IllegalArgumentException("sslContext must not be empty"); + } + HttpParams params = new HttpParams(); + params.setSSLContext(sslContext); + return new WeixinRequestExecutor(params); } } diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinSSLRequestExecutor.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinSSLRequestExecutor.java deleted file mode 100644 index aa088380..00000000 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/weixin/WeixinSSLRequestExecutor.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.foxinmy.weixin4j.http.weixin; - -import java.io.InputStream; -import java.security.KeyStore; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; - -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.http.HttpRequest; -import com.foxinmy.weixin4j.model.Consts; - -/** - * 微信ssl请求 - * - * @className WeixinSSLRequestExecutor - * @author jinyu(foxinmy@gmail.com) - * @date 2015年8月17日 - * @since JDK 1.6 - * @see - */ -public class WeixinSSLRequestExecutor extends WeixinRequestExecutor { - - private final SSLContext sslContext; - - public WeixinSSLRequestExecutor(String password, InputStream inputStream) - throws WeixinException { - try { - KeyStore keyStore = KeyStore.getInstance(Consts.PKCS12); - keyStore.load(inputStream, password.toCharArray()); - KeyManagerFactory kmf = KeyManagerFactory - .getInstance(Consts.SunX509); - kmf.init(keyStore, password.toCharArray()); - sslContext = SSLContext.getInstance("TLS"); - sslContext.init(kmf.getKeyManagers(), null, - new java.security.SecureRandom()); - } catch (Exception e) { - throw new WeixinException("Key load error", e); - } - } - - public WeixinSSLRequestExecutor(SSLContext sslContext) { - this.sslContext = sslContext; - } - - public SSLContext getSSLContext() { - return sslContext; - } - - @Override - protected WeixinResponse doRequest(HttpRequest request) - throws WeixinException { - httpParams.setSSLContext(sslContext); - return super.doRequest(request); - } -} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/setting/Weixin4jSettings.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/setting/Weixin4jSettings.java index b490f9c3..aa9d95dd 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/setting/Weixin4jSettings.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/setting/Weixin4jSettings.java @@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.setting; import com.foxinmy.weixin4j.cache.CacheStorager; import com.foxinmy.weixin4j.cache.FileCacheStorager; -import com.foxinmy.weixin4j.http.HttpParams; import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.util.StringUtil; import com.foxinmy.weixin4j.util.Weixin4jConfigUtil; @@ -21,10 +20,6 @@ public class Weixin4jSettings { * 账号信息 */ private final T account; - /** - * Http参数 - */ - private HttpParams httpParams; /** * 系统临时目录 */ @@ -46,18 +41,10 @@ public class Weixin4jSettings { return account; } - public HttpParams getHttpParams() { - return httpParams; - } - public String getTmpdir() { return tmpdir; } - public void setHttpParams(HttpParams httpParams) { - this.httpParams = httpParams; - } - public void setTmpdir(String tmpdir) { this.tmpdir = tmpdir; } @@ -103,8 +90,8 @@ public class Weixin4jSettings { @Override public String toString() { - return "Weixin4jSettings [account=" + account + ", httpParams=" - + httpParams + ", tmpdir=" + tmpdir + ", cacheStorager=" - + cacheStorager + ", certificateFile=" + certificateFile + "]"; + return "Weixin4jSettings [account=" + account + ", tmpdir=" + tmpdir + + ", cacheStorager=" + cacheStorager + ", certificateFile=" + + certificateFile + "]"; } } \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java index 23d55223..b05cddc2 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -41,6 +41,27 @@ public class IOUtil { out.flush(); } + public static int copy(InputStream input, OutputStream output) + throws IOException { + long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; + } + + private static long copyLarge(InputStream input, OutputStream output) + throws IOException { + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + long count = 0; + int n = 0; + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + public static byte[] toByteArray(InputStream input) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/HttpClientTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/HttpClientTest.java deleted file mode 100644 index aee8a211..00000000 --- a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/HttpClientTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.foxinmy.weixin4j.base.test; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.Proxy.Type; - -import com.foxinmy.weixin4j.http.HttpClient; -import com.foxinmy.weixin4j.http.HttpClientException; -import com.foxinmy.weixin4j.http.HttpMethod; -import com.foxinmy.weixin4j.http.HttpParams; -import com.foxinmy.weixin4j.http.HttpRequest; -import com.foxinmy.weixin4j.http.HttpResponse; -import com.foxinmy.weixin4j.http.factory.HttpClientFactory; -import com.foxinmy.weixin4j.http.factory.HttpComponent3Factory; -import com.foxinmy.weixin4j.http.factory.HttpComponent4Factory; -import com.foxinmy.weixin4j.http.factory.Netty4HttpClientFactory; -import com.foxinmy.weixin4j.http.factory.SimpleHttpClientFactory; -import com.foxinmy.weixin4j.util.IOUtil; - -public class HttpClientTest { - - static HttpRequest request = new HttpRequest(HttpMethod.GET, - "http://www.iteye.com/"); - static { - HttpParams params = new HttpParams().setProxy(new Proxy(Type.HTTP, - new InetSocketAddress("117.136.234.9", 80))); - // request.setParams(params); - } - - public static void test1() throws HttpClientException { - HttpClientFactory.setDefaultFactory(new SimpleHttpClientFactory()); - HttpClient httpClient = HttpClientFactory.getInstance(); - HttpResponse response = httpClient.execute(request); - print(response); - } - - public static void test2() throws HttpClientException { - HttpClientFactory.setDefaultFactory(new HttpComponent3Factory()); - HttpClient httpClient = HttpClientFactory.getInstance(); - HttpResponse response = httpClient.execute(request); - print(response); - } - - public static void test3() throws HttpClientException { - HttpClientFactory.setDefaultFactory(new HttpComponent4Factory()); - HttpClient httpClient = HttpClientFactory.getInstance(); - HttpResponse response = httpClient.execute(request); - print(response); - } - - public static void test4() throws HttpClientException { - HttpClientFactory.setDefaultFactory(new Netty4HttpClientFactory()); - HttpClient httpClient = HttpClientFactory.getInstance(); - HttpResponse response = httpClient.execute(request); - print(response); - } - - public static void print(HttpResponse response) throws HttpClientException { - try { - System.err.println(new String( - IOUtil.toByteArray(response.getBody()))); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static void main(String[] args) throws Exception { - test1(); - - } -} diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/PayTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/PayTest.java index 95194950..86b5c551 100644 --- a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/PayTest.java +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/PayTest.java @@ -34,7 +34,7 @@ import com.foxinmy.weixin4j.type.TradeType; * @className PayTest * @author jinyu(foxinmy@gmail.com) * @date 2016年1月30日 - * @since JDK 1.6 + * @since JDK 1.7 * @see */ public class PayTest { @@ -43,18 +43,18 @@ public class PayTest { protected final static WeixinPayProxy PAY; static { - ACCOUNT = new WeixinPayAccount("appid", "paysignkey", "mchid"); + ACCOUNT = new WeixinPayAccount("wx0d1d598c0c03c999", "GATFzDwbQdbbci3QEQxX2rUBvwTrsMiZ", "10020674"); SIGNATURE = new WeixinPaymentSignature(ACCOUNT.getPaySignKey()); PAY = new WeixinPayProxy(new Weixin4jSettings(ACCOUNT)); } /** * 商户证书文件 */ - protected File caFile = new File("*.p12"); + protected File caFile = new File("/Users/jy/workspace/feican/canyi-weixin-parent/canyi-weixin-service/src/main/resources/10020674.p12"); @Test public void queryOrder() throws WeixinException { - Order order = PAY.queryOrder(new IdQuery("201601131632321", + Order order = PAY.queryOrder(new IdQuery("BY2016010800025", IdType.TRADENO)); System.err.println(order); String sign = order.getSign(); @@ -70,6 +70,7 @@ public class PayTest { RefundRecord record = PAY.queryRefund(new IdQuery("TT_1427183696238", IdType.TRADENO)); System.err.println(record); + // 这里的验证签名需要把details循环拼接 String sign = record.getSign(); record.setSign(null); String valiSign = SIGNATURE.sign(record); @@ -138,7 +139,7 @@ public class PayTest { } @Test - public void reportInterface() throws WeixinException { + public void interfaceReport() throws WeixinException { String interfaceUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; int executeTime = 2500; String outTradeNo = null; diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache3HttpClientTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache3HttpClientTest.java new file mode 100644 index 00000000..1c3a07ba --- /dev/null +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache3HttpClientTest.java @@ -0,0 +1,20 @@ +package com.foxinmy.weixin4j.base.test.http; + +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.apache3.HttpComponent3Factory; + +/** + * Apache3 for http test + * + * @className Apache3HttpClientTest + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月28日 + * @since JDK 1.6 + */ +public class Apache3HttpClientTest extends HttpClientTest { + + @Override + protected HttpClientFactory createHttpFactory() { + return new HttpComponent3Factory(); + } +} diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache4_1HttpClientTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache4_1HttpClientTest.java new file mode 100644 index 00000000..57fb4bed --- /dev/null +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache4_1HttpClientTest.java @@ -0,0 +1,19 @@ +package com.foxinmy.weixin4j.base.test.http; + +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.apache4.HttpComponent4_1Factory; + +/** + * Apache4 for http test + * @className Apache4HttpClientTest + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月28日 + * @since JDK 1.6 + */ +public class Apache4_1HttpClientTest extends HttpClientTest { + + @Override + protected HttpClientFactory createHttpFactory() { + return new HttpComponent4_1Factory(); + } +} diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache4_2HttpClientTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache4_2HttpClientTest.java new file mode 100644 index 00000000..57609333 --- /dev/null +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/Apache4_2HttpClientTest.java @@ -0,0 +1,19 @@ +package com.foxinmy.weixin4j.base.test.http; + +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.apache4.HttpComponent4_2Factory; + +/** + * Apache4 for http test + * @className Apache4HttpClientTest + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月28日 + * @since JDK 1.6 + */ +public class Apache4_2HttpClientTest extends HttpClientTest { + + @Override + protected HttpClientFactory createHttpFactory() { + return new HttpComponent4_2Factory(); + } +} diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/HttpClientTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/HttpClientTest.java new file mode 100644 index 00000000..87e5a90f --- /dev/null +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/HttpClientTest.java @@ -0,0 +1,124 @@ +package com.foxinmy.weixin4j.base.test.http; + +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Proxy.Type; + +import org.junit.Assert; +import org.junit.Test; + +import com.foxinmy.weixin4j.http.HttpClient; +import com.foxinmy.weixin4j.http.HttpClientException; +import com.foxinmy.weixin4j.http.HttpParams; +import com.foxinmy.weixin4j.http.HttpResponse; +import com.foxinmy.weixin4j.http.URLParameter; +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.netty.Netty4HttpClientFactory; + +/** + * HttpClient Test + * + * @className HttpClientTest + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月28日 + * @since JDK 1.6 + */ +public abstract class HttpClientTest { + + private static final String GET_URL = "http://www.iteye.com/"; + private static final String POST_URL = "http://223.72.192.176:8080/YuJia/LoginServlet"; + private static final String HTTPS_URL = "https://www.baidu.com/"; + protected static final Proxy PROXY = new Proxy(Type.HTTP, + new InetSocketAddress("219.141.225.108", 80)); + + protected abstract HttpClientFactory createHttpFactory(); + + protected HttpClient createHttpClient() { + return createHttpFactory().newInstance(); + } + + protected HttpClient createProxyHttpClient() { + HttpParams params = new HttpParams(); + params.setProxy(PROXY); + return createHttpClient(params); + } + + protected HttpClient createSSLHttpClient() throws HttpClientException { + HttpParams params = new HttpParams(); + params.setHostnameVerifier(HttpClientFactory.AllowHostnameVerifier.GLOBAL); + params.setSSLContext(HttpClientFactory.allowSSLContext()); + return createHttpClient(params); + } + + protected HttpClient createProxyAndSSLHttpClient() + throws HttpClientException { + HttpParams params = new HttpParams(); + params.setHostnameVerifier(HttpClientFactory.AllowHostnameVerifier.GLOBAL); + params.setSSLContext(HttpClientFactory.allowSSLContext()); + params.setProxy(PROXY); + return createHttpClient(params); + } + + protected HttpClient createHttpClient(HttpParams params) { + HttpClientFactory httpClientFactory = createHttpFactory(); + httpClientFactory.resolveHttpParams(params); + return httpClientFactory.newInstance(); + } + + @Test + public void getDefaultHttpClientFactoryTest() { + HttpClientFactory httpClientFactory = HttpClientFactory + .getDefaultFactory(); + Assert.assertTrue(httpClientFactory.getClass().isAssignableFrom( + Netty4HttpClientFactory.class)); + } + + @Test + public void getRequestTest() throws HttpClientException { + HttpClient httpClient = createHttpClient(); + HttpResponse response = httpClient.get(GET_URL); + Assert.assertEquals(200, response.getStatus().getStatusCode()); + } + + @Test + public void postRequestTest() throws HttpClientException { + HttpClient httpClient = createHttpClient(); + URLParameter parameter = new URLParameter("query", "java"); + HttpResponse response = httpClient.post(POST_URL, parameter); + Assert.assertEquals(200, response.getStatus().getStatusCode()); + } + + @Test + public void httpsRequestTest() throws HttpClientException { + HttpClient httpClient = createHttpClient(); + HttpResponse response = httpClient.get(HTTPS_URL); + Assert.assertEquals(200, response.getStatus().getStatusCode()); + } + + @Test + public void proxyRequestTest() throws HttpClientException { + HttpClient httpClient = createProxyHttpClient(); + HttpResponse response = httpClient.get(GET_URL); + Assert.assertEquals(200, response.getStatus().getStatusCode()); + response = httpClient.get(HTTPS_URL); + Assert.assertEquals(200, response.getStatus().getStatusCode()); + } + + @Test + public void sslRequestTest() throws HttpClientException { + HttpClient httpClient = createSSLHttpClient(); + HttpResponse response = httpClient.get(GET_URL); + Assert.assertEquals(200, response.getStatus().getStatusCode()); + response = httpClient.get(HTTPS_URL); + Assert.assertEquals(200, response.getStatus().getStatusCode()); + } + + @Test + public void proxyAndSSLRequestTest() throws HttpClientException { + HttpClient httpClient = createProxyAndSSLHttpClient(); + HttpResponse response = httpClient.get(GET_URL); + Assert.assertEquals(200, response.getStatus().getStatusCode()); + response = httpClient.get(HTTPS_URL); + Assert.assertEquals(200, response.getStatus().getStatusCode()); + } +} diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/NettyHttpClientTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/NettyHttpClientTest.java new file mode 100644 index 00000000..6158e737 --- /dev/null +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/NettyHttpClientTest.java @@ -0,0 +1,19 @@ +package com.foxinmy.weixin4j.base.test.http; + +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.netty.Netty4HttpClientFactory; + +/** + * Netty for http test + * @className NettyHttpClientTest + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月28日 + * @since JDK 1.6 + */ +public class NettyHttpClientTest extends HttpClientTest { + + @Override + protected HttpClientFactory createHttpFactory() { + return new Netty4HttpClientFactory(); + } +} diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/OkHttp2ClinetTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/OkHttp2ClinetTest.java new file mode 100644 index 00000000..46de85dd --- /dev/null +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/OkHttp2ClinetTest.java @@ -0,0 +1,19 @@ +package com.foxinmy.weixin4j.base.test.http; + +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.okhttp.OkHttpClient2Factory; + +/** + * OkHttp for test + * + * @className OkHttpClinetTest + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月28日 + * @since JDK 1.6 + */ +public class OkHttp2ClinetTest extends HttpClientTest { + @Override + protected HttpClientFactory createHttpFactory() { + return new OkHttpClient2Factory(); + } +} diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/OkHttp3ClinetTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/OkHttp3ClinetTest.java new file mode 100644 index 00000000..b62d11d8 --- /dev/null +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/OkHttp3ClinetTest.java @@ -0,0 +1,19 @@ +package com.foxinmy.weixin4j.base.test.http; + +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.support.okhttp.OkHttpClient3Factory; + +/** + * OkHttp for test + * + * @className OkHttpClinetTest + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月28日 + * @since JDK 1.6 + */ +public class OkHttp3ClinetTest extends HttpClientTest { + @Override + protected HttpClientFactory createHttpFactory() { + return new OkHttpClient3Factory(); + } +} diff --git a/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/SimpleHttpTest.java b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/SimpleHttpTest.java new file mode 100644 index 00000000..ab189784 --- /dev/null +++ b/weixin4j-base/src/test/java/com/foxinmy/weixin4j/base/test/http/SimpleHttpTest.java @@ -0,0 +1,19 @@ +package com.foxinmy.weixin4j.base.test.http; + +import com.foxinmy.weixin4j.http.factory.HttpClientFactory; +import com.foxinmy.weixin4j.http.factory.SimpleHttpClientFactory; + +/** + * SimpleClient for test + * @className SimpleHttpTest + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月28日 + * @since JDK 1.6 + */ +public class SimpleHttpTest extends HttpClientTest { + + @Override + protected HttpClientFactory createHttpFactory() { + return new SimpleHttpClientFactory(); + } +} diff --git a/weixin4j-example/src/main/resources/spring-bean.xml b/weixin4j-example/src/main/resources/spring-bean.xml index 7da1e329..a25626ac 100644 --- a/weixin4j-example/src/main/resources/spring-bean.xml +++ b/weixin4j-example/src/main/resources/spring-bean.xml @@ -37,10 +37,6 @@ - - - - @@ -62,10 +58,6 @@ - - - - diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java index b679f3ac..fabac4e8 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java @@ -234,7 +234,6 @@ public class MediaApi extends MpApi { request = new HttpRequest(HttpMethod.GET, String.format(meida_download_uri, token.getAccessToken(), mediaId)); } - request.setParams(weixinExecutor.getExecuteParams()); logger.info("weixin request >> " + request.getMethod() + " " + request.getURI().toString()); HttpResponse response = weixinExecutor.getExecuteClient().execute(request); byte[] content = IOUtil.toByteArray(response.getBody()); diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/PayOldApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/PayOldApi.java index 187dd879..9821c711 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/PayOldApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/PayOldApi.java @@ -26,10 +26,9 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.parser.Feature; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.entity.FormUrlEntity; import com.foxinmy.weixin4j.http.message.ApiResult; -import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor; import com.foxinmy.weixin4j.http.weixin.WeixinResponse; -import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor; import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.mp.oldpayment.OrderV2; @@ -312,10 +311,9 @@ public class PayOldApi extends MpApi { ctx = SSLContext.getInstance(Consts.TLS); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); - - WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor( - ctx); - response = weixinExecutor.get(refund_uri, map); + response = weixinExecutor.createSSLRequestExecutor(ctx).get( + String.format("%s?%s", refund_uri, + FormUrlEntity.formatParameters(map))); } catch (WeixinException e) { throw e; } catch (Exception e) { @@ -459,7 +457,8 @@ public class PayOldApi extends MpApi { map.put("key", weixinAccount.getPartnerKey()); String sign = DigestUtil.MD5(MapUtil.toJoinString(map, false, false)); map.put("sign", sign.toLowerCase()); - WeixinResponse response = weixinExecutor.get(downloadbill_uri, map); + WeixinResponse response = weixinExecutor.get(String.format("%s?%s", + downloadbill_uri, FormUrlEntity.formatParameters(map))); BufferedReader reader = null; BufferedWriter writer = null; try { @@ -510,7 +509,8 @@ public class PayOldApi extends MpApi { map.put(idQuery.getType().getName(), idQuery.getId()); String sign = weixinMD5Signature.sign(map); map.put("sign", sign.toLowerCase()); - WeixinResponse response = weixinExecutor.get(refundquery_uri, map); + WeixinResponse response = weixinExecutor.get(String.format( + refundquery_uri, FormUrlEntity.formatParameters(map))); return ListsuffixResultDeserializer.deserialize(response.getAsString(), RefundRecordV2.class); } diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/OauthToken.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/OauthToken.java index d752c773..690725e2 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/OauthToken.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/OauthToken.java @@ -1,6 +1,5 @@ package com.foxinmy.weixin4j.mp.model; -import com.alibaba.fastjson.annotation.JSONCreator; import com.alibaba.fastjson.annotation.JSONField; import com.foxinmy.weixin4j.model.Token; diff --git a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/NotifyTest.java b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/NotifyTest.java index 775371a0..cb1696a7 100644 --- a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/NotifyTest.java +++ b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/NotifyTest.java @@ -93,13 +93,13 @@ public class NotifyTest extends TokenTest { @Test public void send2() throws WeixinException, IOException { - File file = new File("/tmp/test.jpg"); + File file = new File("/Users/jy/Downloads/weixin4j.png"); MediaUploadResult mediaResult = mediaApi.uploadMedia(false, new FileInputStream(file), file.getName()); NotifyMessage imageNotify = new NotifyMessage( "owGBft_vbBbOaQOmpEUE4xDLeRSU", new Image( mediaResult.getMediaId())); ApiResult result = notifyApi.sendNotify(imageNotify); - Assert.assertEquals(0, result.getReturnCode()); + Assert.assertEquals("0", result.getReturnCode()); } } diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java index 4ea53a70..45cfd130 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java @@ -199,7 +199,6 @@ public class MediaApi extends QyApi { request = new HttpRequest(HttpMethod.GET, String.format(media_download_uri, token.getAccessToken(), mediaId)); } - request.setParams(weixinExecutor.getExecuteParams()); logger.info("weixin request >> " + request.getMethod() + " " + request.getURI().toString()); HttpResponse response = weixinExecutor.getExecuteClient().execute(request); byte[] content = IOUtil.toByteArray(response.getBody()); diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/PartyApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/PartyApi.java index 1bb9a7bc..c0ec0c19 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/PartyApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/PartyApi.java @@ -122,7 +122,7 @@ public class PartyApi extends QyApi { public ApiResult deleteParty(int partId) throws WeixinException { String department_delete_uri = getRequestUri("department_delete_uri"); Token token = tokenManager.getCache(); - WeixinResponse response = weixinExecutor.post(String.format( + WeixinResponse response = weixinExecutor.get(String.format( department_delete_uri, token.getAccessToken(), partId)); return response.getAsResult(); } diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java index bb2e5730..a488e41a 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java @@ -339,8 +339,9 @@ public class UserApi extends QyApi { obj.put("useridlist", userIds); String user_delete_uri = getRequestUri("user_batchdelete_uri"); Token token = tokenManager.getCache(); - WeixinResponse response = weixinExecutor.post(String.format( - user_delete_uri, token.getAccessToken(), obj.toJSONString())); + WeixinResponse response = weixinExecutor.post( + String.format(user_delete_uri, token.getAccessToken()), + obj.toJSONString()); return response.getAsResult(); } @@ -418,9 +419,9 @@ public class UserApi extends QyApi { obj.put("agentid", agentid); } String userid2openid_uri = getRequestUri("userid2openid_uri"); - WeixinResponse response = weixinExecutor.post( - String.format(userid2openid_uri, tokenManager.getAccessToken()), - obj.toJSONString()); + WeixinResponse response = weixinExecutor + .post(String.format(userid2openid_uri, + tokenManager.getAccessToken()), obj.toJSONString()); obj = response.getAsJson(); return new String[] { obj.getString("openid"), obj.getString("appid") }; } @@ -439,9 +440,10 @@ public class UserApi extends QyApi { */ public String openid2userid(String openid) throws WeixinException { String openid2userid_uri = getRequestUri("openid2userid_uri"); - WeixinResponse response = weixinExecutor.post( - String.format(openid2userid_uri, tokenManager.getAccessToken()), - String.format("{\"openid\": \"%s\"}", openid)); + WeixinResponse response = weixinExecutor + .post(String.format(openid2userid_uri, + tokenManager.getAccessToken()), + String.format("{\"openid\": \"%s\"}", openid)); return response.getAsJson().getString("userid"); } }