提交之后就是解析不出来 不知道是因为什么 有没有人做过这种的帮忙看一下
不知道你这个问题是否已经解决, 如果还没有解决的话:RequestFactory.Builder::parseMethodAnnotation
方法:
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
这里对方法注解的处理方式主要可以分为三类:
GET
、POST
等请求方法:调用RequestFactory.Builder::parseHttpMethodAndPath
方法进行处理Headers
的注解:调用RequestFactory.Builder::parseHeaders
方法进行处理Multipart
、FormUrlEncoded
注解:主要是在标记变量中进行记录我们看下第1
和2
步是如何处理的。
对GET
、POST
等请求方法的注解解析,使用RequestFactory.Builder::parseHttpMethodAndPath
:
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
// 1.若已设置过httpMethod,则抛出异常
if (this.httpMethod != null) {
throw methodError(
method,
"Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod,
httpMethod);
}
// 记录 请求方法 及 是否有请求体
this.httpMethod = httpMethod;
this.hasBody = hasBody;
// 若请求方法的注解(如GET)里面没有写值,则结束
if (value.isEmpty()) {
return;
}
// Get the relative URL path and existing query string, if present.
// 2.判断请求方法的注解中的值是否合理,不合理则抛出异常
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
// 使用正则表达式匹配
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError(
method,
"URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.",
queryParams);
}
}
// 3.记录相对Url;解析并记录注解中的占位符(parsePathParameters方法内部使用了正则表达式)
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
该方法主要做了下面的几件事情:
我们以GET
请求方法注解为例,第2
步主要是防止GET
的出现类似"users?sortby={sortby}"
这种值,它希望我们动态设置的参数使用@Query
注解来实现,举一个例子:
@GET("/banner")
fun getBanners(@Query("type") type: Int): Call<BannerJson>
而不是
@GET("/banner?type={type}")
fun getBanners(@Path("type") type: Int): Call<BannerJson>
第3
步,例如我们的请求方法为
interface IUser {
@GET("/users/{nickname}")
fun getUser(@Path("nickname") nickname: String): Call<User>
}
那么计算后的值为
// 相对url
this.relativeUrl = "/users/{nickname}"
// 也就是{}包裹的值,如果有多个{},那么Set<String>会有多个值
this.relativeUrlParamNames = 包含"nickname"的Set<String>
对Headers
注解的解析,使用RequestFactory.Builder::parseHeaders
方法:
private Headers parseHeaders(String[] headers) {
// 这是okhttp3的Headers.Builder
Headers.Builder builder = new Headers.Builder();
// 遍历传入的headers
for (String header : headers) {
int colon = header.indexOf(':');
if (colon == -1 || colon == 0 || colon == header.length() - 1) {
throw methodError(
method, "@Headers value must be in the form \"Name: Value\". Found: \"%s\"", header);
}
// 获取Header名和Header值
String headerName = header.substring(0, colon);
String headerValue = header.substring(colon + 1).trim();
// 如果Header是"Content-Type",则会进行一些特殊处理
if ("Content-Type".equalsIgnoreCase(headerName)) {
try {
contentType = MediaType.get(headerValue);
} catch (IllegalArgumentException e) {
throw methodError(method, e, "Malformed content type: %s", headerValue);
}
} else {
// 将Header添加到builder中
builder.add(headerName, headerValue);
}
}
// 返回okhttp3.Headers
return builder.build();
}
该方法主要做的事情:将传入的字符串数组headers
,构造为okhttp3.Headers
并返回,对于Content-Type
类型的Header
,会进行一些特殊的处理。