【Android】使用Retrofit网络请求的URL的参数有【/】的转义问题

问题

在进行一个http的post请求时,使用Retrofit+okhttp3发起网络请求,但是这个post请求有点特殊,因为在请求头上要带个参数,而且参数里面还有【/】,刚开始没重视,然后就按照平时的请求方式进行实现,但是出现问题了,因为参数传的是错误的。在使用get请求获取到传入的参数的后,发现我本来传入的是一个【/】,但是获取到的参数是【//】,例如我传入的参数为【data/user】,返回的是【data//user】。
我:
在这里插入图片描述

问题分析

这是因为在 HTTP URL 中,斜杠 (/) 被视为分隔符,用于分隔 URL 的各个部分。在 URL中,每个斜杠字符都表示一个新的路径段。当将包含单个斜杠字符的路径作为 URL 参数传递时,它会被视为新的路径段,并且由于URL编码的原因,每个斜杠字符都会被编码为 %2F,因此单个斜杠字符会被编码为%2F%2F。当在多个路径段中传递多个斜杠字符时,它们也会被编码为多个 %2F,从而导致在查询时看到多个斜杠字符。

问题解决

为了避免这种情况,可以在将路径作为 URL 参数传递之前,对其进行 URL 编码。在Java 中,可以使用 URLEncoder.encode()方法来对路径进行 URL编码。这将会将斜字符和其他特殊字符编码为它们的 URL 编码形式,从而避免它们被解释为 URL 的分隔符.在收到编码后的路径时,可以使用 URLDecoder.decode() 方法对其进行解码。这将会还原路径中的所有特殊字符,包括斜杠字符

其中这个 URLEncoder.encode()的使用
在这里插入图片描述
这个一个参数的方法已经被废弃了,可以使用两个参数的方法。

//第二个参数可以传入UTF-8或者GBK等一种编码方式
 val valueEncoder = URLEncoder.encode("传入的需要转义的参数", "UTF-8")

但是当我在Retrofit中使用这个时,并没有获得预期的效果,最后还是传入错误的参数,没办法,打印了上传的URL地址,发现当我没有使用【 URLEncoder.encode()】方法的时候,Retrofit里面已经将【/】转义为了【%2F】,相当于Retrofit已经自动帮我实现了【/】的转义,而我在使用这个方法后,又转义了一次,将【%2F】转义成了【%252F】,相当于转义了两次。

最终解决方式

因为Retrofit会自动帮我们进行字符串的转义,但是我这次的http请求是不需要进行转义的,因为没有对应的【URLDecoder.decode() 】进行解码,所以我们不能再让Retrofit帮我们进行组装URL地址了,需要我们自己确定一个URL,然后我使用【@URL】注解来解决这个问题

    @POST()
    suspend fun postLamp2(@Url url: String): ResponseBody

然后我们自己组装一个URL使用

"http://${lampIP}/cgi-bin/Config.cgi?action=set&property=${property}&value=${value}"

这样就不会有转义的出现了。

注意

使用此方式的时候,虽然我们不需要再使用Retrofit的BASE_URL

private const val BASE_URL = "http://"

但是这个【BASE_URL 】也还是要加上的,而且这个【“http://”】后面也是要有东西的,像上面这个是要报错的,我们可以随便加点什么。
这里我加上了这些东西,但是没什么用,因为我们并不会用到

.baseUrl(BASE_URL + "cgi-bin/")

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你可以使用OkHttp的Interceptor来拦截参数。在使用Retrofit时,可以通过自定义OkHttpClient并添加Interceptor来实现。以下是一个示例: ``` OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); Request requestWithNewParameter = originalRequest.newBuilder() .addHeader("Your-Header-Name", "Your-Header-Value") .build(); return chain.proceed(requestWithNewParameter); } }) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build(); YourApiService apiService = retrofit.create(YourApiService.class); ``` 在上面的示例中,我们添加了一个Interceptor来拦截每个请求并添加一个自定义的Header。你可以根据需要修改拦截器的实现来拦截并修改请求参数。 ### 回答2: 在Android开发中,Retrofit是一个非常流行的网络请求库。它提供了拦截器(Interceptor)的功能,可以对网络请求参数进行拦截和修改。 拦截器是一个接口,可以在请求之前或者响应之后对请求进行处理。在Retrofit中,可以通过实现Interceptor接口来自定义拦截器。 通过拦截器,我们可以对请求进行一些通用的处理,比如对请求头进行添加、修改、删除等操作。我们可以在拦截器的intercept方法中获取到请求参数,然后根据需求进行修改。 拦截器可以被添加到OkHttpClient的拦截器链中,通过addInterceptor()方法来添加。当发起网络请求时,拦截器按照添加的顺序进行拦截。这样,我们就可以在请求中添加或修改参数。 拦截器还可以对响应进行处理,比如对返回的数据进行解析、转换等操作。拦截器可以获取到响应的数据,然后可以对数据进行一些处理,并返回给调用方。 通过使用拦截器,我们可以在不修改原有的网络请求代码的情况下,对请求和响应进行一些通用的处理。这样可以提高开发的效率,并且可以保持代码的整洁和可维护性。 总的来说,Android Retrofit的拦截器功能非常强大,可以非常方便地对网络请求参数进行拦截和修改,提供了非常灵活的扩展性。 ### 回答3: 在Android中,Retrofit是一个广泛使用网络请求库,用于方便地从服务器获取数据。拦截参数是指在使用Retrofit发送网络请求之前,可以通过拦截器对请求参数进行修改或添加一些额外的信息。 在Retrofit中,可以通过自定义拦截器来实现对参数的拦截操作。拦截器是一个接口,它提供了两个方法:intercept和proceed。 intercept方法用于处理拦截逻辑,我们可以在这个方法中获取到请求参数信息,并对其进行修改或添加额外信息。可以使用request.body()方法获取请求体,再通过request.newBuilder()方法创建一个新的请求,最后通过chain.proceed()方法继续请求发送。 proceed方法表示继续发送原始请求,如果不调用该方法,请求被拦截,不发送到服务器。 要使用拦截器,首先需要创建一个OkHttpClient对象,并通过addInterceptor方法将拦截器添加到OkHttpClient中。然后将创建的OkHttpClient对象传递给Retrofit.Builder的client方法。 以下是一个示例代码,演示如何使用拦截器对请求参数进行拦截: ``` OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); // 获取原始请求参数 HttpUrl url = request.url().newBuilder() .addQueryParameter("key", "value") .build(); Request newRequest = request.newBuilder() .url(url) .build(); return chain.proceed(newRequest); } }); OkHttpClient client = builder.build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://example.com/") .client(client) .build(); ``` 上述代码创建了一个OkHttpClient对象,并添加了一个拦截器。在拦截器的intercept方法中,获取了原始请求参数,然后对其进行了修改(添加了一个名为key值为value的参数),最后调用chain.proceed方法继续发送请求。 通过拦截器,我们可以对请求参数进行灵活处理,例如对请求进行签名、添加公共参数等操作,提高了开发的灵活性和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值