- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 API 的改造方法:
@POST("/searchCity/byname")
Call<Cities> searchCityByName(@Query("name") String name);
从代码中以这种方式调用它:
final String cityName ="City"
restClient.getApiService().searchCityByName(cityName);
每当我使用retrofit 2.1.0 发送请求时,url 是以下一个(正确):
searchCity/byname?name=City
但是,当我使用retrofit 2.2.0 及更高版本 发送相同的请求时,url 更改为(不正确):
searchCity/byname?name=%22City%22
至此,由于编码的双引号(%22 解码为 "),服务器在处理请求时失败。
我已经按照程序流程进行操作,但我什么也没发现...可能发生了什么?
我需要在拥有第一个 URL(没有引号的那个)的同时使用 retrofit 2.3.0。有什么办法可以实现吗?
编辑 - 2018 年 4 月 3 日:
这里是用到的类:
RetrofitClient.java
@EBean(scope = EBean.Scope.Singleton)
public class RetrofitClient {
private static volatile Retrofit retrofit;
private static Retrofit.Builder builder = new Retrofit.Builder().baseUrl("https://exampleserver.com/");
private PrivateApi apiService;
public static <S> S createService(Class<S> serviceClass) {
final GsonBuilder gsonBuilder = new GsonBuilder();
final Gson gson = gsonBuilder.create();
retrofit = builder.client(new WebClient().getClient())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
return retrofit.create(serviceClass);
}
@AfterInject
public void privateRestClientAfterInject() {
final PrivateApi apiService = createService(PrivateApi.class);
final PrivateApiServiceInvocationHandler publicApiServiceInvocationHandler = new
PrivateApiServiceInvocationHandler(apiService);
this.apiService = (PrivateApi) Proxy.newProxyInstance(PrivateApi.class.getClassLoader(),
new Class[]{PrivateApi.class}, publicApiServiceInvocationHandler);
}
public PrivateApi getApiService() {
if (apiService == null) {
privateRestClientAfterInject();
}
return apiService;
}
}
WebClient.java
public class WebClient {
public OkHttpClient getClient() {
final HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor
.Level.BODY);
final OkHttpClient.Builder builder = new OkHttpClient.Builder().readTimeout
(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.addInterceptor(logging)
.followRedirects(false)
.followSslRedirects(false);
builder.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
final Request originalRequest = chain.request();
final HttpUrl newurl = originalRequest.url().newBuilder().build();
final Request newRequest = originalRequest.newBuilder()
.url(newurl)
.headers(originalRequest.headers())
.header("Connection", "close")
.header("User-Agent",
getUserAgentAndKeyboard())
.method(originalRequest.method(), originalRequest.body())
.build();
return chain.proceed(newRequest);
}
});
return builder.build();
}
/**
* Returns the standard user-agent with the default input method brand name
*
* @return The concatenated "user-agent; keyboard" string
*/
private static String getUserAgentAndKeyboard() {
// WEWE-857
ContentResolver contentResolver = BaseApplication.getInstance().getContentResolver();
if (contentResolver != null) {
String keyboard = Settings.Secure.getString(contentResolver, Settings.Secure
.DEFAULT_INPUT_METHOD);
return String.format(Locale.getDefault(), "%s;%s", System.getProperty("http.agent"),
keyboard);
}
return System.getProperty("http.agent");
}
}
RetrofitInvocationHandler.java
public class RetofitInvocationHandler implements InvocationHandler {
private final Object target;
public RetofitInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(target, args);
}
}
PrivateApi.java
public interface PrivateApi {
@Headers({
"Content-Type:application/json"
})
@POST("/searchCity/byname")
Call<Cities> searchCityByName(@Query("name") String name);
}
最佳答案
最后我得到了解决方案:
只需添加一个自定义转换器来重写查询参数:
public static <S> S createService(Class<S> serviceClass) {
final GsonBuilder gsonBuilder = new GsonBuilder();
final Gson gson = gsonBuilder.create();
retrofit = builder.client(new WebClient().getClient())
.addConverterFactory(GsonConverterFactory.create(gson))
// custom interceptor
.addConverterFactory(new StringConverterFactory(GsonConverterFactory.create(gson)))
// custom interceptor
.build();
return retrofit.create(serviceClass);
}
StringCoverterFactory.java
public class DateStringConverterFactory extends Converter.Factory {
private final Converter.Factory delegateFactory;
DateStringConverterFactory(Converter.Factory delegateFactory) {
super();
this.delegateFactory = delegateFactory;
}
@Override
public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit
retrofit) {
for (final Annotation annotation : annotations) {
if (annotation instanceof Query) {
final Converter<?, RequestBody> delegate = delegateFactory
.requestBodyConverter(type, annotations, new Annotation[0], retrofit);
return new DelegateToStringConverter<>(delegate);
}
}
return null;
}
static class DelegateToStringConverter<T> implements Converter<T, String> {
private final Converter<T, RequestBody> delegate;
DelegateToStringConverter(Converter<T, RequestBody> delegate) {
this.delegate = delegate;
}
@Override
public String convert(T value) throws IOException {
final okio.Buffer buffer = new okio.Buffer();
delegate.convert(value).writeTo(buffer);
if(value instanceof String){
return value.toString();
}
else {
return buffer.readUtf8();
}
}
}
}
感谢所有尝试做出贡献的人!!
关于Android 在较新版本中使用 String Query param 双引号改造 POST 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49613331/
我经常看到这个,但我一直不明白。为什么这么多函数在函数定义中有这些嵌套的括号和奇怪的逗号? 有点像 function name(param, param param) 对我来说有意义,或者 funct
为什么参数输入有两种不同的格式?除了个人品味之外,还有其他好处吗? 例如,我正在使用它,因为那是我第一次阅读有关Powershell的文档时所看到的 function MyAwesomeFunctio
当我转到角色 Controller 时,显示操作,所有正常的 params[:id] 都是根据 REST 应该如何。 在显示 View 中,我渲染了部分。在该部分中,我有一个指向 vote_socio
我正在尝试在我的 Express 应用程序中使用 Sequelize 获取数据,并使用 MSSQL 获取数据库。这是我的代码: getInstitution: function (req, res)
从 ASP.NET 中的代码隐藏访问表单或查询字符串值时,使用的优缺点是什么,例如: // short way string p = Request["param"]; 代替: // long way
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: What is it called when you use object… as a parameter? 我在
在代码示例中,我看到了以下代码: SomeClass.Columns(columns => { columns.Add() .Text("Product")
我是 PySpark 的初学者。我在 PySpark 中使用 FPgrowth 计算关联。我按照以下步骤操作。 数据示例 from pyspark.sql.session import SparkSe
我想记录一个类,我在 PyCharm 中看到当自动添加文档字符串时它会添加 :param param_name1: :param param_name2: 不过,我看到有人用 @param param
我正在为一个网站设计 Android 客户端。所以我必须实现很多不同的网络操作。例如用户授权或在服务器上搜索。为此,我必须向 REST Web 服务器发送带有一些参数和 URL 的 JSON 请求。因
我对 Jersey 和 Grizzly 有疑问。这个问题可能非常基本,但我正在努力解决它。我的想法是,我正在创建一个需要存储书籍的练习应用程序。一切似乎都很好,但并没有按预期进行。这是源代码: @Pa
假设我有一个带有虚方法的接口(interface),但参数之一是: virtual void Delete(ParentClass *parentClass) = 0; 如果我稍后在子类中实现它 vo
需要一些 Python 语法方面的帮助 伪代码 if param is not None in params, param replace('xx', 'x') 我走到这一步了: param.repl
我刚开始使用 JSDocs,找不到这个问题的答案。 假设我想写这个简单的函数: function hasQ(array, item) {return array.includes(item);} 对于
我对doInBackground(Params...params)中的参数语法不熟悉 这种东西叫什么,我该如何使用它? 最佳答案 正如 devA 和 VVV 所说,这就是所谓的“可变参数”。实际上,以
我很难在两个 perl 模块之间做出选择——Params::Validate 和 Params::Check。 我正在编写一个应该易于分发的 Mojolicious 应用程序。 一般来说,我的意思是在
这个问题已经有答案了: What does [param: NotNull] mean in C#? (2 个回答) 已关闭 7 年前。 我发现了以下属性声明。 [param: Marsha
我正在阅读有关 $params 的 CakePHP 手册,并且想知道每个参数的适当用法是什么?我知道返回的数组略有不同(“url”实际上有一个名为“url”的数组键,它返回 Controller /操
我见过处理 *param1 和 ¶m2 的 C 函数调用 func1(*param1); func2(¶m2); 我知道 * 和 & 必须与指针相关。那么这两种不同的方式有
特别是,为什么对 *param 这样的参数的更改不会传播回函数的调用者,但对 **param 这样的参数的更改却会传播回来? 最佳答案 在这两种情况下,更改都会被传播,但这取决于调用函数。 请参阅下面
我是一名优秀的程序员,十分优秀!