Skip to content

Commit d0c46e3

Browse files
author
liuyj
committed
[fix]
1. 修复jdk11 json反序列化报错问题: ParameterizedTypeImpl 类找不到 2. 修复jdk1.6 https证书错误问题 3. 服务端返回500支持重试 4. 修复首次鉴权失败后空指针异常 [update] 1. ios支持自定义参数
1 parent f4fe13d commit d0c46e3

13 files changed

Lines changed: 359 additions & 161 deletions

File tree

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Eclipse project files
2+
.classpath
3+
.project
4+
.settings/
5+
6+
7+
# Intellij project files
8+
*.iml
9+
.idea/
10+
11+
# Others
12+
target/
13+
logs/

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<dependency>
2323
<groupId>com.getui.push</groupId>
2424
<artifactId>restful-sdk</artifactId>
25-
<version>1.0.0.1</version>
25+
<version>1.0.0.3</version>
2626
</dependency>
2727
```
2828

@@ -52,8 +52,8 @@ public class TestCreatApi {
5252
ApiHelper apiHelper = ApiHelper.build(apiConfiguration);
5353
// 创建对象,建议复用。目前有PushApi、StatisticApi、UserApi
5454
PushApi pushApi = apiHelper.creatApi(PushApi.class);
55-
}
5655
}
56+
}
5757
```
5858

5959
##### 使用示例:**推送API**_根据cid进行单推

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<groupId>com.getui.push</groupId>
88
<artifactId>restful-sdk</artifactId>
99
<packaging>jar</packaging>
10-
<version>1.0.0.2</version>
10+
<version>1.0.0.3</version>
1111
<url>https://github.com/GetuiLaboratory/getui-pushapi-java-client-v2</url>
1212
<name>Getui Push API Java Client</name>
1313
<description>Getui's officially supported Java client library for accessing Getui APIs.</description>

src/main/java/com/getui/push/v2/sdk/GtApiConfiguration.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ public class GtApiConfiguration {
6666
*/
6767
private int maxHttpTryTime = 1;
6868

69+
/**
70+
* http请求时是否需要信任https
71+
*/
72+
private boolean trustSSL = false;
73+
6974
/**
7075
* http请求设置代理,默认不设置
7176
*/
@@ -86,6 +91,14 @@ public void check() {
8691
Assert.notBlank(domain, true);
8792
}
8893

94+
public boolean isTrustSSL() {
95+
return trustSSL;
96+
}
97+
98+
public void setTrustSSL(boolean trustSSL) {
99+
this.trustSSL = trustSSL;
100+
}
101+
89102
public String getAppId() {
90103
return appId;
91104
}

src/main/java/com/getui/push/v2/sdk/common/http/GtHttpClient.java

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,21 @@
2121
import org.apache.http.impl.client.HttpClients;
2222
import org.apache.http.util.EntityUtils;
2323

24+
import javax.net.ssl.SSLContext;
25+
import javax.net.ssl.TrustManager;
26+
import javax.net.ssl.X509TrustManager;
2427
import java.io.IOException;
2528
import java.io.UnsupportedEncodingException;
2629
import java.net.HttpURLConnection;
30+
import java.security.cert.CertificateException;
31+
import java.security.cert.X509Certificate;
2732
import java.util.Map;
2833

2934
public class GtHttpClient {
3035
private int maxHttpTryTime;
3136
CloseableHttpClient httpclient;
3237

33-
public GtHttpClient(int connectTimeout, int soTimeout, int maxHttpTryTime, GtHttpProxyConfig proxyConfig) {
38+
public GtHttpClient(int connectTimeout, int soTimeout, int maxHttpTryTime, GtHttpProxyConfig proxyConfig, boolean trustSSL) {
3439
if (connectTimeout <= 0) {
3540
throw new IllegalArgumentException("connectTimeout must be > 0.");
3641
}
@@ -49,6 +54,10 @@ public GtHttpClient(int connectTimeout, int soTimeout, int maxHttpTryTime, GtHtt
4954
}
5055
builder.setProxy(new HttpHost(proxyConfig.getHost(), proxyConfig.getPort()));
5156
}
57+
// jvm1.6 如果不设置信任证书,会报错
58+
if (System.getProperty("java.version").startsWith("1.6") || trustSSL) {
59+
builder.setSSLContext(createSSLContext());
60+
}
5261
RequestConfig config = RequestConfig.custom()
5362
.setConnectTimeout(connectTimeout)
5463
.setSocketTimeout(soTimeout)
@@ -81,6 +90,30 @@ public String execute(String url, String method, Map<String, Object> headers, St
8190
return doRequest(request, 0);
8291
}
8392

93+
public static SSLContext createSSLContext() {
94+
try {
95+
SSLContext sslContext = SSLContext.getInstance("SSLv3");
96+
X509TrustManager trustManager = new X509TrustManager() {
97+
@Override
98+
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
99+
}
100+
101+
@Override
102+
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
103+
}
104+
105+
@Override
106+
public X509Certificate[] getAcceptedIssuers() {
107+
return new X509Certificate[0];
108+
}
109+
};
110+
sslContext.init(null, new TrustManager[]{trustManager}, null);
111+
return sslContext;
112+
} catch (Exception e) {
113+
throw new ApiException("create httpClient error.", e);
114+
}
115+
}
116+
84117
private String doRequest(HttpUriRequest request, int tryTimes) {
85118
CloseableHttpResponse response = null;
86119
int code = 5000;
@@ -95,8 +128,14 @@ private String doRequest(HttpUriRequest request, int tryTimes) {
95128
return EntityUtils.toString(response.getEntity());
96129
} else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
97130
throw new ApiException("not found.", code);
98-
} else if (code == HttpURLConnection.HTTP_GATEWAY_TIMEOUT) {
99-
throw new ApiException("timeout.", code);
131+
}
132+
// >=500 异常重试
133+
else if (code >= HttpURLConnection.HTTP_INTERNAL_ERROR) {
134+
if (tryTimes > maxHttpTryTime) {
135+
throw new ApiException("http error", code);
136+
} else {
137+
return doRequest(request, ++tryTimes);
138+
}
100139
} else {
101140
throw new ApiException("Http Response Error.", code);
102141
}

src/main/java/com/getui/push/v2/sdk/common/http/HttpManager.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ public class HttpManager {
1919
* @param connectionTimeOut 连接超时时间
2020
* @param readTimeout 读超时时间
2121
* @param maxHttpTryTime 失败最大尝试次数
22+
* @param trustSSL
2223
*/
23-
public HttpManager(int connectionTimeOut, int readTimeout, int maxHttpTryTime, GtHttpProxyConfig proxyConfig) {
24-
this.client = new GtHttpClient(connectionTimeOut, readTimeout, maxHttpTryTime, proxyConfig);
24+
public HttpManager(int connectionTimeOut, int readTimeout, int maxHttpTryTime, GtHttpProxyConfig proxyConfig, boolean trustSSL) {
25+
this.client = new GtHttpClient(connectionTimeOut, readTimeout, maxHttpTryTime, proxyConfig, trustSSL);
2526
}
2627

2728
public String syncHttps(String url, String method, Map<String, Object> headers, String body, String contentType) {
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package com.getui.push.v2.sdk.common.type;
2+
3+
import java.lang.reflect.MalformedParameterizedTypeException;
4+
import java.lang.reflect.ParameterizedType;
5+
import java.lang.reflect.Type;
6+
import java.lang.reflect.TypeVariable;
7+
import java.util.Arrays;
8+
9+
/**
10+
* Implementing class for ParameterizedType interface.
11+
* 具体请看 {@link sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl}
12+
*/
13+
public class ParameterizedTypeImpl implements ParameterizedType {
14+
private final Type[] actualTypeArguments;
15+
private final Class<?> rawType;
16+
private final Type ownerType;
17+
18+
private ParameterizedTypeImpl(Class<?> rawType,
19+
Type[] actualTypeArguments,
20+
Type ownerType) {
21+
this.actualTypeArguments = actualTypeArguments;
22+
this.rawType = rawType;
23+
this.ownerType = (ownerType != null) ? ownerType : rawType.getDeclaringClass();
24+
validateConstructorArguments();
25+
}
26+
27+
private void validateConstructorArguments() {
28+
TypeVariable<?>[] formals = rawType.getTypeParameters();
29+
// check correct arity of actual type args
30+
if (formals.length != actualTypeArguments.length) {
31+
throw new MalformedParameterizedTypeException();
32+
}
33+
for (int i = 0; i < actualTypeArguments.length; i++) {
34+
// check actuals against formals' bounds
35+
}
36+
}
37+
38+
/**
39+
* Static factory. Given a (generic) class, actual type arguments
40+
* and an owner type, creates a parameterized type.
41+
* This class can be instantiated with a raw type that does not
42+
* represent a generic type, provided the list of actual type
43+
* arguments is empty.
44+
* If the ownerType argument is null, the declaring class of the
45+
* raw type is used as the owner type.
46+
* <p> This method throws a MalformedParameterizedTypeException
47+
* under the following circumstances:
48+
* If the number of actual type arguments (i.e., the size of the
49+
* array {@code typeArgs}) does not correspond to the number of
50+
* formal type arguments.
51+
* If any of the actual type arguments is not an instance of the
52+
* bounds on the corresponding formal.
53+
*
54+
* @param rawType the Class representing the generic type declaration being
55+
* instantiated
56+
* @param actualTypeArguments a (possibly empty) array of types
57+
* representing the actual type arguments to the parameterized type
58+
* @param ownerType the enclosing type, if known.
59+
* @return An instance of {@code ParameterizedType}
60+
* @throws MalformedParameterizedTypeException if the instantiation
61+
* is invalid
62+
*/
63+
public static ParameterizedTypeImpl make(Class<?> rawType,
64+
Type[] actualTypeArguments,
65+
Type ownerType) {
66+
return new ParameterizedTypeImpl(rawType, actualTypeArguments,
67+
ownerType);
68+
}
69+
70+
71+
/**
72+
* Returns an array of {@code Type} objects representing the actual type
73+
* arguments to this type.
74+
*
75+
* <p>Note that in some cases, the returned array be empty. This can occur
76+
* if this type represents a non-parameterized type nested within
77+
* a parameterized type.
78+
*
79+
* @return an array of {@code Type} objects representing the actual type
80+
* arguments to this type
81+
* @throws TypeNotPresentException if any of the
82+
* actual type arguments refers to a non-existent type declaration
83+
* @throws MalformedParameterizedTypeException if any of the
84+
* actual type parameters refer to a parameterized type that cannot
85+
* be instantiated for any reason
86+
* @since 1.5
87+
*/
88+
@Override
89+
public Type[] getActualTypeArguments() {
90+
return actualTypeArguments.clone();
91+
}
92+
93+
/**
94+
* Returns the {@code Type} object representing the class or interface
95+
* that declared this type.
96+
*
97+
* @return the {@code Type} object representing the class or interface
98+
* that declared this type
99+
*/
100+
@Override
101+
public Class<?> getRawType() {
102+
return rawType;
103+
}
104+
105+
106+
/**
107+
* Returns a {@code Type} object representing the type that this type
108+
* is a member of. For example, if this type is {@code O<T>.I<S>},
109+
* return a representation of {@code O<T>}.
110+
*
111+
* <p>If this type is a top-level type, {@code null} is returned.
112+
*
113+
* @return a {@code Type} object representing the type that
114+
* this type is a member of. If this type is a top-level type,
115+
* {@code null} is returned
116+
* @throws TypeNotPresentException if the owner type
117+
* refers to a non-existent type declaration
118+
* @throws MalformedParameterizedTypeException if the owner type
119+
* refers to a parameterized type that cannot be instantiated
120+
* for any reason
121+
*/
122+
@Override
123+
public Type getOwnerType() {
124+
return ownerType;
125+
}
126+
127+
/**
128+
* From the JavaDoc for java.lang.reflect.ParameterizedType
129+
* "Instances of classes that implement this interface must
130+
* implement an equals() method that equates any two instances
131+
* that share the same generic type declaration and have equal
132+
* type parameters."
133+
*/
134+
@Override
135+
public boolean equals(Object o) {
136+
if (o instanceof ParameterizedType) {
137+
// Check that information is equivalent
138+
ParameterizedType that = (ParameterizedType) o;
139+
140+
if (this == that) {
141+
return true;
142+
}
143+
144+
Type thatOwner = that.getOwnerType();
145+
Type thatRawType = that.getRawType();
146+
147+
return
148+
equals(ownerType, thatOwner) &&
149+
equals(rawType, thatRawType) &&
150+
Arrays.equals(actualTypeArguments,
151+
that.getActualTypeArguments());
152+
} else {
153+
return false;
154+
}
155+
}
156+
157+
@Override
158+
public int hashCode() {
159+
return
160+
Arrays.hashCode(actualTypeArguments) ^
161+
hashCode(ownerType) ^
162+
hashCode(rawType);
163+
}
164+
165+
boolean equals(Object a, Object b) {
166+
return (a == b) || (a != null && a.equals(b));
167+
}
168+
169+
int hashCode(Object o) {
170+
return o != null ? o.hashCode() : 0;
171+
}
172+
}

src/main/java/com/getui/push/v2/sdk/core/client/DefaultApiClient.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ private DefaultApiClient(GtApiConfiguration apiConfiguration, IJson json) {
131131

132132
this.httpManager = new HttpManager(apiConfiguration.getConnectTimeout(),
133133
apiConfiguration.getSoTimeout(), apiConfiguration.getMaxHttpTryTime(),
134-
apiConfiguration.getProxyConfig());
134+
apiConfiguration.getProxyConfig(), apiConfiguration.isTrustSSL());
135135

136136
this.hostManager = new HostManager(apiConfiguration, this.httpManager);
137137
// 分析最稳定域名
@@ -288,7 +288,11 @@ else if (apiResult.getCode() == 301) {
288288
private ApiResult<?> doExecute(GtApiProxyFactory.ApiParam apiParam, TokenDTO token) {
289289
Map<String, Object> header = new HashMap<String, Object>(4);
290290
if (apiParam.getNeedToken()) {
291-
header.put("token", token.getToken());
291+
if (token == null) {
292+
header.put("token", refreshTokenAndGet(token));
293+
} else {
294+
header.put("token", token.getToken());
295+
}
292296
}
293297
String body = null;
294298
if (apiParam.getBody() != null) {
@@ -308,16 +312,26 @@ private ApiResult<?> doExecute(GtApiProxyFactory.ApiParam apiParam, TokenDTO tok
308312
} finally {
309313
afterDoExecute(apiParam, header, body, result);
310314
}
315+
if (result == null) {
316+
throw new ApiException(String.format("请求失败,返回值为空。url:%s, body: %s.", fullUrl, body));
317+
}
311318
try {
312-
final ApiResult<?> apiResult = json.fromJson(result, apiParam.getReturnType());
319+
ApiResult<?> apiResult = json.fromJson(result, apiParam.getReturnType());
313320
if (apiResult.getCode() == 301) {
314321
// 兼容域名改变
315-
return json.fromJson(result, ApiResult.class);
322+
apiResult = json.fromJson(result, ApiResult.class);
323+
}
324+
if (apiResult == null) {
325+
throw new ApiException(String.format("请求失败,解析返回值失败。url:%s, body: %s, result: %s.", fullUrl, body, result));
316326
}
317327
return apiResult;
318328
} catch (Exception e) {
319329
// 兼容域名改变
320-
return json.fromJson(result, ApiResult.class);
330+
ApiResult<?> apiResult = json.fromJson(result, ApiResult.class);
331+
if (apiResult == null) {
332+
throw new ApiException(String.format("请求失败,解析返回值失败。url:%s, body: %s, result: %s.", fullUrl, body, result));
333+
}
334+
return apiResult;
321335
}
322336
}
323337

@@ -481,6 +495,7 @@ public void setAuthApiAndAuth(AuthApi authApi) {
481495
refreshTokenAndGet(null);
482496
} catch (ApiException e) {
483497
log.error("refresh token failed.", e);
498+
throw e;
484499
}
485500
}
486501
}

0 commit comments

Comments
 (0)