Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wd1105040417
retrofit
提交
fe0d2bbf
R
retrofit
项目概览
wd1105040417
/
retrofit
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
retrofit
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
fe0d2bbf
编写于
1月 20, 2011
作者:
R
Rob Dickerson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refactoring RestAdapter HTTP request construction.
上级
97ad14dc
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
292 addition
and
165 deletion
+292
-165
modules/http/src/retrofit/http/GET.java
modules/http/src/retrofit/http/GET.java
+3
-3
modules/http/src/retrofit/http/Headers.java
modules/http/src/retrofit/http/Headers.java
+1
-1
modules/http/src/retrofit/http/POST.java
modules/http/src/retrofit/http/POST.java
+18
-0
modules/http/src/retrofit/http/RestAdapter.java
modules/http/src/retrofit/http/RestAdapter.java
+270
-161
未找到文件。
modules/http/src/retrofit/http/
Path
.java
→
modules/http/src/retrofit/http/
GET
.java
浏览文件 @
fe0d2bbf
...
...
@@ -7,12 +7,12 @@ import static java.lang.annotation.ElementType.METHOD;
import
static
java
.
lang
.
annotation
.
RetentionPolicy
.
RUNTIME
;
/**
*
REST URL
path relative to base URL.
*
Make a GET request to a REST
path relative to base URL.
*
* @author
Bob Lee (bob@squareup.com)
* @author
Rob Dickerson
*/
@Target
({
METHOD
})
@Retention
(
RUNTIME
)
public
@interface
Path
{
public
@interface
GET
{
String
value
();
}
modules/http/src/retrofit/http/Headers.java
浏览文件 @
fe0d2bbf
...
...
@@ -11,5 +11,5 @@ import org.apache.http.HttpMessage;
public
interface
Headers
{
/** Sets headers on the given message. */
public
void
set
Headers
(
HttpMessage
message
);
public
void
set
On
(
HttpMessage
message
);
}
modules/http/src/retrofit/http/POST.java
0 → 100644
浏览文件 @
fe0d2bbf
package
retrofit.http
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.Target
;
import
static
java
.
lang
.
annotation
.
ElementType
.
METHOD
;
import
static
java
.
lang
.
annotation
.
RetentionPolicy
.
RUNTIME
;
/**
* Make a POST request to a REST path relative to base URL.
*
* @author Rob Dickerson
*/
@Target
({
METHOD
})
@Retention
(
RUNTIME
)
public
@interface
POST
{
String
value
();
}
modules/http/src/retrofit/http/RestAdapter.java
浏览文件 @
fe0d2bbf
...
...
@@ -68,9 +68,10 @@ import java.util.logging.Logger;
* Adapts a Java interface to a REST API. HTTP requests happen in a
* background thread. Callbacks happen in the UI thread.
*
* <p>Gets the relative path for a given method from a {@link Path}
* annotation on the method. Gets the names of URL parameters from {@link
* com.google.inject.name.Named} annotations on the method parameters.
* <p>Gets the relative path for a given method from a {@link GET} or
* {@link POST} annotation on the method. Gets the names of URL parameters
* from {@link com.google.inject.name.Named} annotations on the method
* parameters.
*
* <p>The last method parameter should be of type {@link Callback}. The
* JSON HTTP response will be converted to the callback's parameter type
...
...
@@ -81,7 +82,7 @@ import java.util.logging.Logger;
*
* <pre>
* public interface MyApi {
* @P
ath
("go") public void go(@Named("a") String a, @Named("b") int b,
* @P
OST
("go") public void go(@Named("a") String a, @Named("b") int b,
* Callback<? super MyResult> callback);
* }
* </pre>
...
...
@@ -105,6 +106,243 @@ import java.util.logging.Logger;
};
}
private
static
final
class
RequestLine
{
private
final
String
relativePath
;
private
final
HttpMethod
httpMethod
;
public
RequestLine
(
String
relativePath
,
HttpMethod
method
)
{
this
.
relativePath
=
relativePath
;
this
.
httpMethod
=
method
;
}
public
String
getRelativePath
()
{
return
relativePath
;
}
public
HttpMethod
getHttpMethod
()
{
return
httpMethod
;
}
}
private
static
RequestLine
readHttpMethodAnnotation
(
Method
method
)
{
GET
getAnnotation
=
method
.
getAnnotation
(
GET
.
class
);
boolean
hasGet
=
getAnnotation
!=
null
;
POST
postAnnotation
=
method
.
getAnnotation
(
POST
.
class
);
boolean
hasPost
=
postAnnotation
!=
null
;
if
(
hasGet
&&
hasPost
)
{
throw
new
IllegalArgumentException
(
"Method annotated with both GET and POST: "
+
method
.
getName
());
}
if
(
hasGet
)
{
return
new
RequestLine
(
getAnnotation
.
value
(),
HttpMethod
.
GET
);
}
else
if
(
hasPost
)
{
return
new
RequestLine
(
postAnnotation
.
value
(),
HttpMethod
.
POST
);
}
else
{
throw
new
IllegalArgumentException
(
"Method not annotated with GET or POST: "
+
method
.
getName
());
}
}
/** Gets the parameter name from the @Named annotation. */
private
static
String
getName
(
Annotation
[]
annotations
,
Method
method
,
int
parameterIndex
)
{
return
findAnnotation
(
annotations
,
Named
.
class
,
method
,
parameterIndex
).
value
();
}
/**
* Finds a parameter annotation.
*
* @throws IllegalArgumentException if the annotation isn't found
*/
private
static
<
A
extends
Annotation
>
A
findAnnotation
(
Annotation
[]
annotations
,
Class
<
A
>
annotationType
,
Method
method
,
int
parameterIndex
)
{
for
(
Annotation
annotation
:
annotations
)
{
if
(
annotation
.
annotationType
()
==
annotationType
)
{
return
annotationType
.
cast
(
annotation
);
}
}
throw
new
IllegalArgumentException
(
annotationType
+
" missing on"
+
" parameter #"
+
parameterIndex
+
" of "
+
method
+
"."
);
}
private
static
enum
HttpMethod
{
GET
{
HttpUriRequest
createFrom
(
HttpRequestBuilder
builder
)
throws
URISyntaxException
{
List
<
NameValuePair
>
queryParams
=
builder
.
createParamList
();
String
queryString
=
URLEncodedUtils
.
format
(
queryParams
,
"UTF-8"
);
URI
uri
=
URIUtils
.
createURI
(
builder
.
getScheme
(),
builder
.
getHost
(),
-
1
,
builder
.
getRelativePath
(),
queryString
,
null
);
HttpGet
httpGet
=
new
HttpGet
(
uri
);
builder
.
getHeaders
().
setOn
(
httpGet
);
return
httpGet
;
}
},
POST
{
HttpUriRequest
createFrom
(
HttpRequestBuilder
builder
)
throws
URISyntaxException
{
URI
uri
=
URIUtils
.
createURI
(
builder
.
getScheme
(),
builder
.
getHost
(),
-
1
,
builder
.
getRelativePath
(),
null
,
null
);
HttpPost
post
=
new
HttpPost
(
uri
);
addParamsToPost
(
post
,
builder
);
builder
.
getHeaders
().
setOn
(
post
);
return
post
;
}
/**
* Adds all but the last method argument as parameters of HTTP post
* object.
*/
private
void
addParamsToPost
(
HttpPost
post
,
HttpRequestBuilder
builder
)
{
Method
method
=
builder
.
getMethod
();
Object
[]
args
=
builder
.
getArgs
();
Class
<?>[]
parameterTypes
=
method
.
getParameterTypes
();
Annotation
[][]
parameterAnnotations
=
method
.
getParameterAnnotations
();
int
count
=
parameterAnnotations
.
length
-
1
;
if
(
useMultipart
(
parameterTypes
))
{
MultipartEntity
form
=
new
MultipartEntity
(
HttpMultipartMode
.
BROWSER_COMPATIBLE
);
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Object
arg
=
args
[
i
];
if
(
arg
==
null
)
continue
;
Annotation
[]
annotations
=
parameterAnnotations
[
i
];
String
name
=
getName
(
annotations
,
method
,
i
);
Class
<?>
type
=
parameterTypes
[
i
];
if
(
TypedBytes
.
class
.
isAssignableFrom
(
type
))
{
TypedBytes
typedBytes
=
(
TypedBytes
)
arg
;
form
.
addPart
(
name
,
new
TypedBytesBody
(
typedBytes
,
name
));
}
else
{
try
{
form
.
addPart
(
name
,
new
StringBody
(
String
.
valueOf
(
arg
)));
}
catch
(
UnsupportedEncodingException
e
)
{
throw
new
AssertionError
(
e
);
}
}
}
post
.
setEntity
(
form
);
}
else
{
try
{
List
<
NameValuePair
>
paramList
=
builder
.
createParamList
();
post
.
setEntity
(
new
UrlEncodedFormEntity
(
paramList
));
}
catch
(
UnsupportedEncodingException
e
)
{
throw
new
AssertionError
(
e
);
}
}
}
/** Returns true if the post contains a file upload. */
private
boolean
useMultipart
(
Class
<?>[]
parameterTypes
)
{
for
(
Class
<?>
parameterType
:
parameterTypes
)
{
if
(
TypedBytes
.
class
.
isAssignableFrom
(
parameterType
))
return
true
;
}
return
false
;
}
};
/**
* Create a request object from HttpRequestBuilder.
*/
abstract
HttpUriRequest
createFrom
(
HttpRequestBuilder
builder
)
throws
URISyntaxException
;
}
/**
* Builds HTTP requests from Java method invocations.
*/
private
static
final
class
HttpRequestBuilder
{
private
Method
javaMethod
;
private
Object
[]
args
;
private
HttpMethod
httpMethod
;
private
String
apiUrl
;
private
String
relativePath
;
private
Headers
headers
;
public
HttpRequestBuilder
setMethod
(
Method
method
)
{
this
.
javaMethod
=
method
;
RequestLine
requestLine
=
readHttpMethodAnnotation
(
method
);
this
.
relativePath
=
requestLine
.
getRelativePath
();
this
.
httpMethod
=
requestLine
.
getHttpMethod
();
return
this
;
}
public
Method
getMethod
()
{
return
javaMethod
;
}
public
String
getRelativePath
()
{
return
relativePath
;
}
public
HttpRequestBuilder
setApiUrl
(
String
apiUrl
)
{
this
.
apiUrl
=
apiUrl
;
return
this
;
}
/** The last argument is assumed to be the Callback and is ignored. */
public
HttpRequestBuilder
setArgs
(
Object
[]
args
)
{
this
.
args
=
args
;
return
this
;
}
public
Object
[]
getArgs
()
{
return
args
;
}
public
HttpRequestBuilder
setHeaders
(
Headers
headers
)
{
this
.
headers
=
headers
;
return
this
;
}
public
Headers
getHeaders
()
{
return
headers
;
}
public
String
getScheme
()
{
return
apiUrl
.
substring
(
0
,
apiUrl
.
indexOf
(
"://"
));
}
public
String
getHost
()
{
String
host
=
apiUrl
.
substring
(
apiUrl
.
indexOf
(
"://"
)
+
3
,
apiUrl
.
length
());
if
(
host
.
endsWith
(
"/"
))
host
=
host
.
substring
(
0
,
host
.
length
()
-
1
);
return
host
;
}
/**
* Converts all but the last method argument to a list of HTTP request
* parameters.
*/
public
List
<
NameValuePair
>
createParamList
()
{
Annotation
[][]
parameterAnnotations
=
javaMethod
.
getParameterAnnotations
();
int
count
=
parameterAnnotations
.
length
-
1
;
List
<
NameValuePair
>
params
=
new
ArrayList
<
NameValuePair
>();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Object
arg
=
args
[
i
];
if
(
arg
==
null
)
continue
;
String
name
=
getName
(
parameterAnnotations
[
i
],
javaMethod
,
i
);
params
.
add
(
new
BasicNameValuePair
(
name
,
String
.
valueOf
(
arg
)));
}
return
params
;
}
public
HttpUriRequest
build
()
throws
URISyntaxException
{
return
httpMethod
.
createFrom
(
this
);
}
}
private
class
RestHandler
implements
InvocationHandler
{
public
Object
invoke
(
Object
proxy
,
final
Method
method
,
...
...
@@ -126,40 +364,29 @@ import java.util.logging.Logger;
(
Callback
<?>)
args
[
args
.
length
-
1
],
mainThread
);
try
{
String
relativePath
=
getRelativePath
(
method
);
final
String
apiUrl
=
server
.
apiUrl
();
// Construct HTTP request.
HttpUriRequest
request
;
HttpMethod
.
Type
requestType
=
getRequestType
(
method
);
switch
(
requestType
)
{
case
GET:
request
=
createGet
(
apiUrl
,
relativePath
,
method
,
args
);
break
;
case
POST:
request
=
createPost
(
apiUrl
,
relativePath
,
method
,
args
);
break
;
default
:
throw
new
IllegalStateException
(
"Unrecognized HTTP Method: "
+
requestType
);
}
headers
.
setHeaders
(
request
);
HttpUriRequest
request
=
new
HttpRequestBuilder
()
.
setMethod
(
method
)
.
setArgs
(
args
)
.
setApiUrl
(
server
.
apiUrl
())
.
setHeaders
(
headers
)
.
build
();
// The last parameter should be of type Callback<T>. Determine T.
Type
[]
genericParameterTypes
=
method
.
getGenericParameterTypes
();
final
Type
resultType
=
getCallbackParameterType
(
method
,
genericParameterTypes
);
logger
.
fine
(
String
.
format
(
"Sending "
+
requestType
+
" request to %s."
,
request
.
getURI
())
)
;
logger
.
fine
(
"Sending "
+
request
.
getMethod
()
+
" to "
+
request
.
getURI
());
final
GsonResponseHandler
<?>
gsonResponseHandler
=
GsonResponseHandler
.
create
(
resultType
,
callback
);
// Optionally wrap the response handler for server call profiling.
ResponseHandler
<?
extends
Void
>
rh
=
(
profiler
==
null
)
?
gsonResponseHandler
:
new
ProfilingResponseHandler
(
gsonResponseHandler
,
profiler
,
HttpProfiler
.
Method
.
POST
,
apiUrl
,
relativePath
);
ResponseHandler
<?
extends
Void
>
rh
=
(
profiler
==
null
)
?
gsonResponseHandler
:
createProfiler
(
gsonResponseHandler
,
profiler
,
method
,
server
.
apiUrl
());
httpClientProvider
.
get
().
execute
(
request
,
rh
);
}
catch
(
IOException
e
)
{
...
...
@@ -171,103 +398,26 @@ import java.util.logging.Logger;
}
/**
*
Converts all but the last method argument to a list of HTTP request
*
parameters
.
*
Wraps a {@code GsonResponseHandler} with a
*
{@code ProfilingResponseHandler}
.
*/
private
List
<
NameValuePair
>
createParamList
(
Method
method
,
Object
[]
args
)
{
Annotation
[][]
parameterAnnotations
=
method
.
getParameterAnnotations
();
int
count
=
parameterAnnotations
.
length
-
1
;
List
<
NameValuePair
>
params
=
new
ArrayList
<
NameValuePair
>();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Object
arg
=
args
[
i
];
if
(
arg
==
null
)
continue
;
String
name
=
getName
(
parameterAnnotations
[
i
],
method
,
i
);
params
.
add
(
new
BasicNameValuePair
(
name
,
String
.
valueOf
(
arg
)));
}
return
params
;
}
private
HttpGet
createGet
(
String
apiUrl
,
String
relativePath
,
Method
method
,
Object
[]
args
)
throws
URISyntaxException
{
List
<
NameValuePair
>
queryParams
=
createParamList
(
method
,
args
);
String
queryString
=
URLEncodedUtils
.
format
(
queryParams
,
"UTF-8"
);
URI
uri
=
URIUtils
.
createURI
(
scheme
(
apiUrl
),
host
(
apiUrl
),
-
1
,
relativePath
,
queryString
,
null
);
return
new
HttpGet
(
uri
);
}
private
HttpPost
createPost
(
String
apiUrl
,
String
relativePath
,
Method
method
,
Object
[]
args
)
throws
URISyntaxException
{
URI
uri
=
URIUtils
.
createURI
(
scheme
(
apiUrl
),
host
(
apiUrl
),
-
1
,
relativePath
,
null
,
null
);
HttpPost
post
=
new
HttpPost
(
uri
);
addParamsToPost
(
post
,
method
,
args
);
return
post
;
}
private
String
scheme
(
String
apiUrl
)
{
return
apiUrl
.
substring
(
0
,
apiUrl
.
indexOf
(
"://"
));
}
private
String
host
(
String
apiUrl
)
{
String
host
=
apiUrl
.
substring
(
apiUrl
.
indexOf
(
"://"
)
+
3
,
apiUrl
.
length
());
if
(
host
.
endsWith
(
"/"
))
host
=
host
.
substring
(
0
,
host
.
length
()
-
1
);
return
host
;
}
private
void
addParamsToPost
(
HttpPost
post
,
Method
method
,
Object
[]
args
)
{
// Convert all but the last method argument to HTTP request parameters.
Class
<?>[]
parameterTypes
=
method
.
getParameterTypes
();
Annotation
[][]
parameterAnnotations
=
method
.
getParameterAnnotations
();
int
count
=
parameterAnnotations
.
length
-
1
;
if
(
useMultipart
(
parameterTypes
))
{
MultipartEntity
form
=
new
MultipartEntity
(
HttpMultipartMode
.
BROWSER_COMPATIBLE
);
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Object
arg
=
args
[
i
];
if
(
arg
==
null
)
continue
;
Annotation
[]
annotations
=
parameterAnnotations
[
i
];
String
name
=
getName
(
annotations
,
method
,
i
);
Class
<?>
type
=
parameterTypes
[
i
];
if
(
TypedBytes
.
class
.
isAssignableFrom
(
type
))
{
TypedBytes
typedBytes
=
(
TypedBytes
)
arg
;
form
.
addPart
(
name
,
new
TypedBytesBody
(
typedBytes
,
name
));
}
else
{
try
{
form
.
addPart
(
name
,
new
StringBody
(
String
.
valueOf
(
arg
)));
}
catch
(
UnsupportedEncodingException
e
)
{
throw
new
AssertionError
(
e
);
}
}
}
post
.
setEntity
(
form
);
private
ProfilingResponseHandler
createProfiler
(
ResponseHandler
<
Void
>
handlerToWrap
,
HttpProfiler
profiler
,
Method
method
,
String
apiUrl
)
{
RequestLine
requestLine
=
readHttpMethodAnnotation
(
method
);
HttpProfiler
.
Method
profilerMethod
;
HttpMethod
httpMethod
=
requestLine
.
getHttpMethod
();
if
(
httpMethod
==
RestAdapter
.
HttpMethod
.
GET
)
{
profilerMethod
=
HttpProfiler
.
Method
.
GET
;
}
else
if
(
httpMethod
==
HttpMethod
.
POST
)
{
profilerMethod
=
HttpProfiler
.
Method
.
POST
;
}
else
{
try
{
List
<
NameValuePair
>
paramList
=
createParamList
(
method
,
args
);
post
.
setEntity
(
new
UrlEncodedFormEntity
(
paramList
));
}
catch
(
UnsupportedEncodingException
e
)
{
throw
new
AssertionError
(
e
);
}
throw
new
IllegalStateException
(
"Unrecognized method: "
+
httpMethod
);
}
}
/** Returns true if the post contains a file upload. */
private
boolean
useMultipart
(
Class
<?>[]
parameterTypes
)
{
for
(
Class
<?>
parameterType
:
parameterTypes
)
{
if
(
TypedBytes
.
class
.
isAssignableFrom
(
parameterType
))
return
true
;
}
return
false
;
return
new
ProfilingResponseHandler
(
handlerToWrap
,
profiler
,
profilerMethod
,
apiUrl
,
requestLine
.
getRelativePath
());
}
private
static
final
String
NOT_CALLBACK
=
"Last parameter of %s must be"
...
...
@@ -309,47 +459,6 @@ import java.util.logging.Logger;
return
new
IllegalArgumentException
(
String
.
format
(
NOT_CALLBACK
,
method
));
}
/** Gets the parameter name from the @Named annotation. */
private
String
getName
(
Annotation
[]
annotations
,
Method
method
,
int
parameterIndex
)
{
return
findAnnotation
(
annotations
,
Named
.
class
,
method
,
parameterIndex
).
value
();
}
/**
* Finds a parameter annotation.
*
* @throws IllegalArgumentException if the annotation isn't found
*/
private
<
A
extends
Annotation
>
A
findAnnotation
(
Annotation
[]
annotations
,
Class
<
A
>
annotationType
,
Method
method
,
int
parameterIndex
)
{
for
(
Annotation
annotation
:
annotations
)
{
if
(
annotation
.
annotationType
()
==
annotationType
)
{
return
annotationType
.
cast
(
annotation
);
}
}
throw
new
IllegalArgumentException
(
annotationType
+
" missing on"
+
" parameter #"
+
parameterIndex
+
" of "
+
method
+
"."
);
}
/** Gets the relative path from the @Path annotation. */
private
String
getRelativePath
(
Method
method
)
{
Path
pathAnnotation
=
method
.
getAnnotation
(
Path
.
class
);
if
(
pathAnnotation
==
null
)
throw
new
IllegalArgumentException
(
method
+
" is missing an @Path annotation."
);
return
pathAnnotation
.
value
();
}
private
HttpMethod
.
Type
getRequestType
(
Method
method
)
{
HttpMethod
requestTypeAnnotation
=
method
.
getAnnotation
(
HttpMethod
.
class
);
// Default to POST.
return
requestTypeAnnotation
==
null
?
HttpMethod
.
Type
.
POST
:
requestTypeAnnotation
.
value
();
}
}
/** Adapts ContentBody to TypedBytes. */
...
...
@@ -472,4 +581,4 @@ import java.util.logging.Logger;
return
delegate
.
handleResponse
(
httpResponse
);
}
}
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录